uniform变量和顶点数组
uniform让我们可以从CPU向GPU中的着色器发送数据,它与顶点属性都能向着色器发送数据,不同之处在于,第一,uniform是全局的,意味着uniform变量必须在每个着色器程序对象中都是独一无二的,而且它可以被着色器程序的任意着色器在任意阶段访问。第二,无论你把uniform值设置成什么,uniform会一直保存它们的数据,直到它们被重置或更新。
我们先在着色器文件中的片段着色器中添加uniform变量u_Color

在C++文件中为其赋值,我们通过glGetUniformLocation找到u_Color的索引,如果找不到就会返回-1,但这并不意味着我们一定犯了错误,比如变量名称拼写错误之类的,因为如果我们在着色器中声明了uniform变量,但在整个着色器中没有使用这个uniform变量,那么OpenGL在编译着色器时就会静默移除这个变量,这也会导致返回-1。找到索引后,最后通过glUniform4f来设置u_Color的值,这里需要注意,在设置一个uniform变量之前必须先调用glUseProgram,因为glUniform4f是在当前激活的着色器程序中设置uniform的。

这里我们举个例子来感受一下uniform变量存在的好处,我们将glUniform4f放到while中,来每一帧都对颜色进行设置,将第二个参数设置为随时间变化的值,这样就能得到一个颜色不断变化的正方形。

设置glfwSwapInterval可以让颜色变换更加平滑一些
glfwSwapInterval
设置当前OpenGL上下文的交换间隔,即在交换缓冲区并返回之前,从调用glfwSwapBuffers开始等待的屏幕更新次数。这有时被称为垂直同步、垂直回扫同步或简称为vsync。
调用线程上的上下文必须是当前的。在没有当前上下文的情况下调用此函数将导致GLFW_NO_CURRENT_CONTEXT错误。

目前为此我们讨论了顶点缓冲区,索引缓冲区,着色器,这里还有一个顶点数组的概念,顶点数组和顶点缓冲区听起来有些相似,它并不是DirectX等其他渲染接口中有的东西,顶点数组是在OpenGL特殊存在的东西,它通过一种特定的规范绑定顶点缓冲区,用于顶点缓冲区的布局。
回顾一下,顶点缓冲区只包含了一些顶点位置,

我们创建缓冲区,绑定缓冲区,设置了数据

然后激活顶点属性,指定实际数据的布局

这是顶点缓冲区的设置流程,在每次绘制之前我们都需要做这些操作,而顶点数组对象(Vertex Array Object, VAO)可以帮我们简化某些部分。
绑定着色器->绑定顶点缓冲区->设置顶点布局->绑定索引缓冲区->DrawCall指令
绑定着色器->绑定顶点数组->绑定索引缓冲区->DrawCall指令
顶点数组对象可以像顶点缓冲对象那样绑定,任何随后的顶点属性调用都会储存在这个VAO中,比如glVertexAttribPointer、与顶点属性关联的顶点缓冲对象、glEnableVertexAttribArray和glDisableVertexAttribArray。这样的好处就是,当配置顶点属性指针时,我们只需要将那些设置执行一次,之后再绘制物体的时候只需要绑定相应的VAO就行了,而不用每次绘制之前都做一系列操作,这使得在不同顶点数据和属性配置之间切换变得非常简单,只需要绑定不同的VAO就行了
