初始化GLFW
什么是GLFW?
GLFW是一款轻量级、开源的c语言库,它提供了跨平台的窗口管理和输入处理功能,支持多个OpenGL版本和扩展。
-
首先我们使用glfwInit 函数初始化GLFW
-
在初始化时我们需要设置OpenGL上下文的主版本号:
使用glfwInitHint(GLFW_CONTEXT_VERSION_MAJOR, 4)函数:这里参数的意思是希望使用主版本为4的OpenGL上下文
-
使用glfwWindowHint函数来配置glfw:
这个函数的作用是用于设置窗口创建时的各种题实参数,以便GLFW在创建窗口是可以进行适当的配
-
先输入glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4):告诉GLFW在创建窗口时,希望使用的OpenGL版本的主要版本号是4
-
然后输入glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE):告诉GLFW我们使用的是核心模式(core - profile)
-
创建窗口对象
-
初始化完成后我们开始创建窗口对象
-
使用GLFWwindow类和glfwCreatWindow函数:
-
GLFWwindow* window = glfwCreateWindow(800, 600, "My OpenGL Game", NULL, NULL);
这段代码的意思是:使用使用
glfwCreateWindow
函数创建一个宽度为800像素、高度为600像素,标题为"My OpenGL Game"的窗口,并将返回的指针赋值给GLFWwindow* window
变量。这里需要注意的,在我们使用窗口完成操作后应该使用glfwDestroyWindow函数销毁窗口对象,并确保在程序结束前调用glfwTerminate函数释放相关资源 -
glfwCreateWindow函数所需的参数有:
-
1.窗口宽度:int
-
2.窗口高度:int
-
3.窗口标题:string
-
4.监视器(可选,不使用就输入NULL):GLFWmonitor类型的指针,用于全屏显示窗口时指定要使用的监视器。
-
5/共享上下文(可选,不使用就输入NULL):GLFWwindow类型的指针,表示与之共享OpenGL对象的上下文。
-
-
将窗口的上下文设置为当前线程的主上下文:
-
glfwMakeContextCurrent(window);
-
-
初始化GLEW
什么时GLEW?
GLEW是OpenGL扩展库的简称,是一个轻量级的库,它提供了一组C/C++函数用于查询和加载OpenGL的扩展函数。
-
初始化GLEW,打开实验性质的功能以及错误提醒
glewExperimental = true; if (glewInit() != GLEW_OK) { printf("Init GLFW failed."); glfwTerminate(); return -1; }
-
在开始渲染之前,需要告诉OpenGL渲染窗口的尺寸大小,即视口(Viewport)。可以通过调用glViewport函数来设置窗口的维度(Dimension)
-
glViewport(0, 0, 800, 600); 前两个参数X,Y————以像素为单位,指定了视口的左下角(在第一象限内,以(0,0)为原点的)位置。 后两个参数width,height————表示这个视口矩形的宽度和高度,根据窗口的实时变化重绘窗口。
-
进行VAO建立
-
只需要一个VAO的时候:
-
unsigned int VAO; glGenVertexArrays(1, &VAO);
-
-
多个VAO建立:
-
unsigned int VAO[10]; glGenVertexArrays(10, VAO);
-
-
将生成的VAO加入目前渲染管线需要的数据位置上:
-
glBindVertexArray(VAO);
-
进行VBO建立
-
只需要一个VBO时:
-
unsigned int VBO; glGenBuffers(1, &VBO);
-
-
多个VBO建立:
-
unsigned int VBO[10]; glGenBuffers(10, VBO);
-
-
将新建的VBO绑在ARRAY_BUFFER的位置上
-
glBindBuffer(GL_ARRAY_BUFFER, VBO);
-
-
将三角形的顶点放到VBO里,也就是让它进入到GPU的buffer里:
-
glBufferData(GL_ARRAY_BUFFER, sizeof(verticse), verticse, GL_STATIC_DRAW);
-
第一个参数:数值类型
-
第二个参数:需要绑定多少数据(bytes)
-
第三个参数:具体要发送的数组
-
第四个参数:显卡需要如何处理得到的数值
-
1.GL_STATIC_DRAW:得到的数据将几乎不动或者很少改
-
2.GL_DYNAMIC_DRAW:得到的数据将会频繁变动
-
3.GL_STREAM_DRAW: 得到的数据在每次绘制时都会变动
-
-
绘制三角形
-
链接顶点属性:
-
glVertexAribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);
第一个参数:指定要设置的顶点属性的索引。该索引对应于顶点着色器中的in变量的位置。这里写0是因为在vertexshader里location = 0,所以这里写0。
第二个参数:指定每个顶点属性的组件数量。这里的3指的是每个顶点的位置属性由三个浮点数构成(分别是x,y,z坐标)
第三个参数:指定组成顶点属性的数据类型。常见的数据类型有:GL_FLOAT(浮点数)、GL_INT(整型)、GL_SHORT(短整型)等。这里指定顶点属性的数据类型为浮点数
第四个参数:指定是否应该将非浮点数据类型的值映射到标准化范围,如果是GL_TRUE,则表示将非浮点数据类型映射到[ -1, 1] (有符号类型) 或 [0, 1] (无符号类型)的范围内。如果传入GL_FALSE,则表示不进行任何映射。
第五个参数:指定相邻顶点之间的偏移量(以字节为单位)。如果顶点属性在数组中是紧密排列的(即没有间隔),可以将此参数设置为0。否则,需要指定适当的偏移量。
-
-
启用顶点数组
-
glEnableVertexAttribArray(0);
-
该函数与glVertexAttribPointer()函数一同使用
-
-
添加渲染循环(Render Loop)
-
添加这个循环,目的是能让我们在GLFW退出之前一直保持运行
-
while (!glfwWindowShouldClose(window)){...}
while 函数中输入:
-
渲染指令
-
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//设定背景颜色
-
-
清空颜色缓冲区
-
glClear(GL_COLOR_BUFFER_BIT);
-
-
绑定顶点数组对象
-
glBindVertexArray(VAO);
-
-
使用shader程序
-
glUseProgram(shaderProgram);
-
这里需要注意的是,一般我们是不用这个函数的,但是因为我们现在没有学shader,所以我们使用课本上的vertexShade和fragmentShader并且将它们组合成一个program,最后在while函数中调用(一般不会使用这种方法)
-
-
-
绘制图形
-
使用glDrawArrays()函数绘制图形
-
glDrawArrays(GL_TRIANGLES, 0, 6);
-
该函数的第一个参数是我们打算绘制的图元类型,是一个三角形。这里可能有同学会问,如果我想绘制四边形或者其他多边形呢?回答是也是使用GL_TRIANGLES。因为多边形可以用多个三角形拼接而成
-
第二个参数指定了顶点数组的其实索引,我们这里是0
-
第三个参数指定我们打算绘制多少个顶点,这里我们明明绘制的是四边形,四边形只有四个顶点,为什么这里是6呢?因为OpenGL这里画的是三角形,将两个三角形拼接后可得到一个四边形,两个三角形就是六个顶点。
-
-
-
检查并调用事件,交换缓冲
-
glfwSwapBuffers(window); glfwPollEvents();
最后正确释放/删除之前的分配的所有资源
-
glfwTerminate();