1. 头文件
1 2 3 4
| #include <glad/glad.h> #include <GLFW/glfw3.h> #include <iostream> using namespace std;
|
引入glad加载库,glfw窗口库,iostream标准输入输出库
一定要在包含GLFW的头文件之前包含了GLAD的头文件,因为GLAD的头文件包含了正确的OpenGL头文件(例如GL/gl.h),所以需要在其它依赖于OpenGL的头文件之前包含GLAD
2. 初始化GLFW窗口
1 2 3 4
| glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwInit函数用来初始化GLFWglfwWindowHint函数来配置GLFW:第一个参数代表选项的名称(以GLFW_开头的枚举值),第二个参数接受一个整型用来设置这个选项的值(GLFW’s window handling)- 将主版本号(Major)和次版本号(Minor)都设为3:因为当前大部分驱动程序和显卡都是基于OpenGL3.3版本
- 使用核心模式:不包括旧版本中的向后兼容特性,只向前兼容,简化开发过程,处理更加高效
3. 创建窗口对象
1 2 3 4 5 6
| GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL); if (window == NULL) { cout << "Failed to create GLFW window" << endl; return -1; } glfwMakeContextCurrent(window);
|
glfwCreateWindow:创建一个窗口对象,参数分别是(宽度,高度,标题,监视器,监视器)glfwMakeContextCurrent:用于设置当前的OpenGL上下文,使后续的OpenGL操作作用于指定的窗口
4. 初始化GLAD
1 2 3 4
| if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { cout << "Failed to initialize GLAD" << endl; return -1; }
|
GLADloadproc:函数指针类型,这里将glfwGetProcAddress转换为GLADloadproc类型glfwGetProcAddress:用于获取OpenGL函数指针gladLoadGLLoader:用于根据OpenGL函数指针来加载OpenGL函数
5. 初始化视口和回调视口
视口(viewport):是窗口中渲染图形的实际尺寸大小,理论上不能大于窗口但可以小于等于窗口
回调(callback):用户可以改变窗口大小,而视口大小也应该跟着窗口大小的改变而改变
1 2 3 4 5 6
| void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); }
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
6. 渲染循环
1 2 3 4
| while(!glfwWindowShouldClose(window)) { glfwSwapBuffers(window); glfwPollEvents(); }
|
渲染循环(Render Loop):在GLFW退出前保持运行,从而能让开发者持续观察渲染效果
glfwWindowShouldClose:检查窗口关闭请求(如用户点击窗口关闭按钮)glfwSwapBuffers:交换前后缓冲,将渲染的图像显示到窗口上,在每次渲染循环的最后进行,以确保屏幕上显示的内容是最新的glfwPollEvents:检查有没有触发什么事件(如键盘输入,鼠标移动,窗口调整)
双缓冲(Double Buffer):通过交换前后缓冲,可以立即将图像呈现出来,从而消除逐渐渲染的图像闪烁问题
- 前缓冲:当前显示在屏幕窗口上的图像
- 后缓冲:正在被绘制的图像
7. 销毁窗口
1 2 3
| glfwDestroyWindow(window); glfwTerminate(); return 0;
|
glfwDestroyWindow:销毁指定的窗口,释放与窗口相关的所有资源glfwTerminate:清理GLFW库,终止使用GLFW,通常在程序结束或程序出错时调用
8. 键盘输入
1 2 3 4 5
| void processInput(GLFWwindow *window) { if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); }
|
glfwGetKey:用于检查特定键的当前状态,GLFW_PRESS表示当前被按下,GLFW_REPEAT表示当前被持续按住,GLFW_RELEASE表示当前未被按下glfwSetWindowShouldClose:明确告诉GLFW窗口应当关闭,常用于响应用户输入
9. 清空颜色
1 2 3
| glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT);
|
glClearColor:设置清除后的颜色(R,G,B,A)glClear:清除指定的缓冲区,GL_COLOR_BUFFER_BIT表示颜色缓冲区
10. 完整代码
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| #include <glad/glad.h> #include <GLFW/glfw3.h> #include <iostream> using namespace std;
void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); }
void processInput(GLFWwindow *window) { if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); }
int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 600, "Simple Triangle", nullptr, nullptr); if (!window) { cerr << "Failed to create GLFW window" << endl; return -1; } glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){ cout << "Failed to initialize GLAD" << endl; return -1; }
glViewport(0, 0, 800, 600); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
while (!glfwWindowShouldClose(window)) { processInput(window); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); glfwSwapBuffers(window); glfwPollEvents(); }
glfwDestroyWindow(window); glfwTerminate(); return 0; }
|