openGL 学习笔记 (一) 了解 OpenGL,创建第一个OpenGL窗口
// 序章
最开始我以为OpenGL是一系列的API,他给出了一系列对计算机图像的操作接口。
但其实OpenGL其实并不是一个API,他是由khronos组织制定并维护的规范。
早期的OpenGL使用立即渲染模式(固定渲染管线),后期使用核心渲染模式。 -- TODO 以后要深入了解两种渲染方式的区别。
OpenGL自身其实是一个巨大的状态机:使用一系列变量来改变OpenGL的状态。从而改变OpenGl的绘制方式。我们使用OpenGL状态设置函数去改变OpenGL的上下文(既状态);使用状态使用函数,根据当前的OpenGl状态执行一些操作。
OpenGL内核是用C写的,因为C的一些语言结构不易被翻译到其他高级语言,所以在开发时引入了一些抽象层如对象(Object)。
在OpenGL中对象是被作用于一些状态的集合,他代表GL状态的一个子集,其实就可以把OpenGL的状态看做是一个巨大的结构体:
1 struct OpenGl_Context { 2 ... 3 float stat_1 4 int stat_2 5 char[] stat_3 6 object* object_Window_Target; 7 ... 8 }
// 创建窗口
需要 GLFW GLAD
配置 GLFW 的链接库,文件包含, LINK链接器
配置 GLAD 的文件包含,将glad.c 加入到项目中去
VS环境下需要有main函数编译才能完全成功。
GLAD: 用来管理OpenGL的函数指针,在调用任何OpenGL的函数之前需要初始化GLAD,他会根据不同的编译系统返回可使用的正确的函数。
双缓冲:应用程序使用单缓冲绘图时可能会存在图像闪烁的问题。因为单缓冲状态下图像不是一下子就绘制出来的,是按照从左到右,从上到下一步步绘制而成。为了解决这个问题一般会使用双缓冲绘制方式解决问题,前缓冲区保存着最终输出的成像,并在屏幕上显示,所有的渲染指令都会在后缓冲上绘制,在所有渲染指令执行完毕后,交换(swap)前后缓冲,图像就可以立即显示出来。
1 #include <iostream> 2 #include <glad/glad.h> 3 #include <GLFW/glfw3.h> 4 #include <Windows.h> 5 #include <ctime> 6 7 using namespace std; 8 9 const unsigned int SCR_WIDTH = 800; 10 const unsigned int SCR_HEIGHT = 600; 11 12 void framebuffer_size_callback(GLFWwindow* windos, int width, int height) 13 { 14 glViewport(0, 0, width, height); 15 } 16 17 void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) 18 { 19 if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) 20 { 21 glfwSetWindowShouldClose(window, GL_TRUE); 22 } 23 else if (key == GLFW_KEY_C && action == GLFW_PRESS) 24 { 25 srand(time(0)); 26 float r = ((rand() % 10) + 1) / 10.0f; 27 float g = ((rand() % 10) + 1) / 10.0f; 28 float b = ((rand() % 10) + 1) / 10.0f; 29 glClearColor(r, g, b, 1.0f); 30 glClear(GL_COLOR_BUFFER_BIT); 31 glfwSwapBuffers(window); 32 } 33 } 34 35 int main() 36 { 37 //初始化GLFW 38 glfwInit(); 39 40 //设置OpenGL版本号为3.3 41 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 42 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 43 44 //设置OpenGL渲染方式为核心渲染 45 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 46 47 // 创建一个宽800,高600,的窗口,窗口名字为"myGLWindow". 48 GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "myGLWindow", NULL, NULL); 49 if (window == NULL) 50 { 51 std::cout << "Failed to create GLFW window" << std::endl; 52 glfwTerminate(); // 销毁窗口和资源 53 return -1; 54 } 55 56 // 设置该窗口为GLFW的主当前线程的主上下文 57 glfwMakeContextCurrent(window); 58 59 //初始化GLAD, 其实是用加载系统相关的OpenGL函数指针地址的函数的返回值判断GLAD是否初始化成功 60 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) 61 { 62 std::cout << "Failed to initialize GLAD" << std::endl; 63 return -1; 64 } 65 66 // 获取窗口windows的宽高 67 int width, height; 68 glfwGetFramebufferSize(window, &width, &height); 69 70 71 // 设置OpenGL渲染窗口的尺寸大小, 前两个参数控制左下角原点的位置 72 glViewport(0, 0, width, height); 73 74 // 注册窗口大小改变的回调 75 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); 76 77 //添加键盘输入回调 78 glfwSetKeyCallback(window, key_callback); 79 80 // 循环渲染 81 while (!glfwWindowShouldClose(window)) 82 { 83 //glClearColor(0.2f, 0.3f, 0.5f, 1.0f); 84 //glClear(GL_COLOR_BUFFER_BIT); 85 //glfwSwapBuffers(window); // 交换窗口颜色缓冲 86 87 glfwPollEvents(); // 检查事件触发,更新窗口状态,调用已经注册的回调函数 88 } 89 90 glfwTerminate(); 91 92 return 0; 93 }
祝我无坚不摧,祝我百毒不侵,祝我狼心狗肺,祝我逍遥快活。