本文是OpenGL学习记录的第二篇,在上一篇我们完成了GLFW以及GLEW的安装,和CMakeLIst文件的设置。在本篇中,将使用OpenGL进行窗口的绘制,以校验相关支持库是否能正常工作。
头文件的引入
由于使用了GLFW和GLEW,因此需要先引入相关头文件:
1 2
| #include <GL/glew.h> #include <GLFW/glfw3.h>
|
为了将有关信息打印出来还需引入输入输出库:
GLFW以及GLEW的初始化
在使用GLFW和GLEW之前,需要先将他们进行初始化操作,并且进行GLFW相关信息的配置。
这一系列操作我们在main函数的开始进行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| int main() { if(!glfwInit()){ printf("Init GLFW failed."); return -1; } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glewExperimental = true; if (glewInit() != GLEW_OK) { printf("Init Glew failed."); glfwTerminate(); return -1; }
... return 0; }
|
其中,我们使用 glfwWindowHint
函数配置当前代码所运行的OpenGL最高版本以及最小版本,并且使用核心模式。
在GLEW的初始化中需要先将glewExperimental
置为true,然后再进行初始化。
窗口的创建
在初始化完毕后,我们可以使用glfwCreateWindow
函数创建一个窗口对象,并且将此窗口设置为当前线程的主上下文。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| int main() { if(!glfwInit()){ printf("Init GLFW failed."); return -1; } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glewExperimental = true; if (glewInit() != GLEW_OK) { printf("Init Glew failed."); glfwTerminate(); return -1; } GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL window", nullptr, nullptr);
if (window == nullptr) { printf("Open window failed."); glfwTerminate(); return -1; } glfwMakeContextCurrent(window); ... return 0; }
|
其中,glfwCreateWindow
函数的前两个参数表示窗口的宽和高,第三个参数表示窗口的标题,后两个参数在此暂时忽略。
视口及循环渲染
在创建完窗口后,还需设置视口(viewport)的大小,视口表示OpenGL渲染窗口的大小。
OpenGL幕后使用glViewport中定义的位置和宽高进行2D坐标的转换,将OpenGL中的位置坐标转换为你的屏幕坐标。例如,OpenGL中的坐标(-0.5, 0.5)有可能(最终)被映射为屏幕中的坐标(200,450)。注意,处理过的OpenGL坐标范围只为-1到1,因此我们事实上将(-1到1)范围内的坐标映射到(0, 800)和(0, 600)。
同时还可以增加一个回调函数,使得调整窗口大小后,视口的大小也相应做出改变。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); }
int main() { ... glViewport(0, 0, 800, 600); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
return 0; }
|
在完成视口的设置后,可以增加一个while循环使得窗口不会立即被关闭,从而在窗口中可以进行相应的画面渲染。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| int main() { ... glViewport(0, 0, 800, 600); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); while (!glfwWindowShouldClose(window)) { glfwSwapBuffers(window); glfwPollEvents(); }
glfwTerminate(); return 0; }
|
循环使用!glfwWindowShouldClose(window)
作为判断条件,在我们每次循环的开始前检查一次GLFW是否被要求退出,如果是的话该函数返回true然后渲染循环便结束了,之后为我们就可以关闭应用程序了。
glfwPollEvents
函数检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数(可以通过回调方法手动设置)。