Graphics Library Framework(图形库框架),可以让我们通过其封装好的 通用API 来正确创建 OpenGL context(上下文)
并显示出一个简单的 窗口
。
如果没有这个跨平台工具,那么我们在 windows 上创建 OpenGL窗口 时需要调用显卡中提供的 windows 使用的 API,而在 Mac 上创建窗口时需要 MacOS 的 API。
从官网上下载GLFW macOS下64位二进制文件
因为 OpenGL 只是一个标准/规范,驱动开发商针对不同显卡有不同的具体实现,导致 OpenGL 驱动版本过于庞杂,大多数函数的位置都无法在编译时确定下来,需要在运行时查询。 因此开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用。
这里来看一个 LearnOpenGL CN 中所举的 Windows 下获取函数地址的例子:
// 定义函数原型
typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*);
// 找到正确的函数并赋值给函数指针
GL_GENBUFFERS glGenBuffers = (GL_GENBUFFERS)wglGetProcAddress("glGenBuffers");
// 现在函数可以被正常调用了
GLuint buffer;
glGenBuffers(1, &buffer);
对于开发人员而言,每使用一个函数就要经历这样的寻址过程无疑是极其痛苦的,因此需要通过 GLAD 库加载所有OpenGL函数指针,来简化使用函数的流程。
打开 GLAD 的在线服务:
Language
设置为 C/C++
;API
选项中,选择 3.3
以上的 OpenGL(gl)版本(更新的版本也能用);模式(Profile)
设置为Core
。
Compatibility
兼容旧版本,包含低版本中的 API 。Core
只包含当前版本必须支持的 API ,不考虑向下兼容旧版本,更为轻巧。生成加载器(Generate a loader)
选项。扩展(Extensions)
中的内容。生成(Generate)
按钮来生成库文件。下载得到一个 zip
压缩文件,包含两个头文件目录,里面分别放着一个和目录同名的 .h
文件,和一个放着 glad.c
文件的 src
目录:
Command Line Tool
。OpenGL
。glad/include文件夹
与 glfw-3.3.7.bin.MACOS/include文件夹
到弹出的方框中(对于这两个文件夹在访达中的所在位置,你可能与我不一样,因此按照你自己放置的路径来配置即可),配置头文件搜索路径:main.cpp
文件中添加以下代码,注意添加时两个 include 语句的顺序不能改变:#include
#include
请确认是在包含 GLFW 的头文件之前包含了 GLAD 的头文件。GLAD 的头文件包含了正确的 OpenGL 头文件(例如GL/gl.h),所以需要在其它依赖于 OpenGL 的头文件之前包含 GLAD。
libglfw3.a
、libglfw3.dylib
(静态库、动态库两者添加其一即可),以及 glad.c
是否参与编译:将下面的代码复制到 main.cpp 中并运行,如果能弹出一个墨绿色的窗口即证明配置成功。
以下代码源于 LearnOpenGL CN的创建窗口 ,代码中注释不够细致,如果不懂可以阅读文档了解更多。
#include
#include
#include
// 对窗口注册一个回调函数(Callback Function),它会在每次窗口大小被调整的时候被调用。
// 参数:window - 被改变大小的窗口,width、height-窗口的新维度。
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// 改变视口大小的函数
glViewport(0, 0, width, height);
}
// 实现输入控制的函数
void processInput(GLFWwindow *window)
{
// glfwGetKey两个参数:窗口,按键
// 没有被按下返回 GLFW_PRESS
std::cout << "是否点击ESC?" << std::endl;
std::cout << glfwGetKey(window, GLFW_KEY_ESCAPE) << std::endl;
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
// 被按下则将 WindowShouldClose 属性置为 true
// 以便于关闭 渲染循环
glfwSetWindowShouldClose(window, true);
}
int main()
{
glfwInit(); // 初始化GLFW
// glfwWindowHint函数的第一个参数代表选项的名称
// 第二个参数接受一个整型,用来设置这个选项的值
// 将主版本号(Major)和次版本号(Minor)都设为3
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// 使用的是核心模式(Core-profile)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// 参数依次为:宽、高、窗口的名称,显示器用于全屏模式,设为NULL是为窗口
// 窗口的上下文为共享资源,NULL为不共享资源
GLFWwindow* window = glfwCreateWindow(800, 600, "FirstWindow", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
// 释放空间,防止内存溢出
glfwTerminate();
return -1;
}
// 创建完毕之后,需要让window的context成为当前线程的current context
glfwMakeContextCurrent(window);
// glfwGetProcAddress是glfw提供的用来加载 系统相关的OpenGL函数指针地址 的函数
// 用gladLoadGLLoader函数根据使用者的系统定义了正确的函数
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// 告诉OpenGL渲染窗口的尺寸大小,即视口(Viewport)
// 这样OpenGL才只能知道怎样根据窗口大小显示数据和坐标
// 调用glViewport函数来设置窗口的维度(Dimension)
// 前两个参数控制窗口左下角的位置。第三个和第四个参数控制渲染窗口的宽度和高度(像素)
glViewport(0, 0, 800, 600);
// 窗口大小改变时视口也要随之改变,这通过对窗口注册 framebuffer_size_callback 实现。
// 它会在每次窗口大小被调整时调用
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
/* 渲染循环(Render Loop) */
// glfwWindowShouldClose 检查一次GLFW是否被要求退出
// 为true时渲染循环结束
while(!glfwWindowShouldClose(window))
{
// 监测键盘输入
processInput(window);
/* 渲染 */
// 状态设置函数,设置清空屏幕所用的颜色
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
// 状态使用函数,使用设定好的颜色来清除旧的颜色缓冲
glClear(GL_COLOR_BUFFER_BIT);
// 上面两种函数起到的作用也可以用 glClearBufferfv 来现实
/*GLfloat color[] = {0.2, 0.3, 0.3, 1.0};
glClearBufferfv(GL_COLOR, 0, color);*/
// glfwSwapBuffers 交换颜色缓冲,用来绘制并作为输出显示在屏幕
glfwSwapBuffers(window);
// glfwPollEvents 检查是否有触发事件
glfwPollEvents();
}
glfwTerminate();
return 0;
}
接下来要讲的一点与配置关系不大,但是也给初使用 Xcode 的我带来了不小的麻烦。不同于 Windows 下的操作习惯,在 macOS 中尽量在访达中对文件进行移动、删除等操作,而非直接拖拽到 Xcode 的树形目录中进行移动,亦或直接在树形目录中进行删除。举个例子:
test
文件夹,并且其中有文件 test.sh
:Reremove reference
还是 Move to Trash
他们的文件夹都会在工程中(如果没有清除,下次添加重名的工程文件会弹出警告)。PS:还遇到过删除 OpenGL 目录下的 test 文件夹,结果导致与 OpenGL 同级的 test 文件夹也被删除的情况,但后来无法复现,因此在这里无法贴图证明。总而言之,对 macOS 使用尚不熟练时,尽量使用访达对文件进行移动删除操作(通过拖拽获得文件路径是简单且安全的方法,可以使用),即使是对 Xcode 树形目录进行操作也请尽可能通过 Show in Finder
跳转到访达中,以避免出现不必要的错误与文件损失。