绘制三角形
当我们把顶点数据发送给GPU后,我们还需要告诉GPU应该如何解读这些数据。顶点的数据中包含顶点的各种属性,这意味着我们必须手动指定输入数据的哪一个部分对应顶点着色器的哪一个顶点属性。
我们使用函数glVertexAttribPointer()告诉OpenGL该如何解析顶点数据。

index是顶点属性的索引。在顶点着色器中,我们使用layout (location = index)来声明对应的属性变量。
size是每个顶点属性的元素个数,比如使用三维坐标(vec3)作为位置属性,则size为3。
type是数据的类型,可以是GL_FLOAT、GL_INT等。
normalized指定是否将非浮点类型的数据规范化到范围 [0, 1](如果是无符号整数)或者 [-1, 1](如果是有符号整数)。一般情况下,对于浮点类型的数据,这个参数设置为GL_FALSE。
stride步长,即连续的顶点属性组之间的间隔(字节)。如果属性紧密排列在一起,可以设置为0,OpenGL会自动计算步长。
pointer表示位置数据在缓冲中起始位置的偏移量,并进行强制类型转换。
下一步要做的是启用对应的顶点属性——因为顶点属性默认是禁用的,通过函数glEnableVertexAttribArray()。

当然,有启用就有禁用,我们可以在不需要某个顶点属性数组时将其禁用,通过函数glDisableVertexAttribArray()。

顶点数组对象
在传统的固定渲染管线中,每次绘制之前都需要重新配置顶点属性,这样会导致重复的代码,并且容易出错。顶点数组对象的引入解决了这个问题。
顶点数组对象(Vertex Array Object,VAO)可以看作是一个容器,用于存储指向顶点数据的指针以及顶点属性的配置信息,它简化了顶点数据的管理和绘制过程。我们可以将所有顶点属性的配置信息存储在VAO中,然后在需要绘制的时候,只需绑定对应的VAO即可,OpenGL会自动恢复为相应的配置状态。
一个顶点数组对象会储存以下这些内容:
I. glEnableVertexAttribArray()和glDisableVertexAttribArray()的调用。
II. 通过glVertexAttribPointer()设置的顶点属性配置。
III. 通过glVertexAttribPointer()调用与顶点属性关联的顶点缓冲对象。
使用VAO的基本流程如下:创建对象—绑定对象—配置顶点—解绑对象。
I.用glGenVertexArrays()生成VAO。

II.使用glBindVertexArray()绑定VAO。

III.使用glVertexAttribPointer()等函数配置顶点属性数组。
IV.解绑VAO。
一个完整的流程示例:

绘制图形
我们使用函数glDrawArrays()绘制基本图元。

mode表示绘制的基本图元类型,包括点、线段、三角形等。绘制三角形我们使用GL_TRIANGLES。
first指定从哪个顶点开始绘制,即顶点数组的起始索引。
count是要绘制的顶点数量。
我们使用之前创建的vertices数组来绘制一个三角形:

收尾
在渲染循环结束后,我们需要调用glDeleteVertexArrays()、glDeleteBuffers()以及glDeleteProgram()进行资源清理,它们分别用来删除VAO、VBO和着色器程序对象。
