VBO(顶点缓冲区对象),允许应用程序迅速方便地将数据从一个渲染管线移动到另一个渲染管线,以及从一个对象绑定到另一个对象,数据也摆脱了强类型对象的束缚。所有对glBufferData的调用都和其他的绘制调用一起通过管线进行处理,so OpenGL实现不需要等待所有活动停止,就可以将数据发送到GPU。
1.VBO的由来
理解客户端状态和服务器状态。客户端状态可以理解为内存。服务器状态可以理解为显卡里面的OpenGL模块,乃至整张拥有OpenGL流水线,硬件实现OpenGL功能的显卡。glEnable是直接维护流水线处理的相关状态,而glEnableClientState维护的则是进入流水线前的状态。
在流水线早期的T&L阶段,程序的顶点数据就被获知而接受处理了。至于顶点数据是怎么来的,是glVertex还是glDrawArray来的,流水线没必要知道,这是客户端的任务,所以是否使用顶点数组(作为一种状态是否需要被启动)是由客户端决定的。正是由于VA(顶点数组)是由客户端决定的,所以执行glDrawArray或glDrawElement时,客户端还需要把顶点数据传递给服务器。为了解决这个二次传输的问题,出现了VBO。
VBO直接把顶点数据交给了流水线。可以把该帧到达了流水线的顶点数据捏回客户端修改(Vertex mapping),再提交回流水线(Vertex unmapping),(或者用glBufferData或glBufferSubData重新全部/部分提交更改了的顶点数据。
2.VBO的使用
初始化
1 - (void)createVBO { 2 const GLfloat vertices[] = { 3 -1.0, -1.0, -5.0, 4 1.0, -1.0, -5.0, 5 1.0, 1.0, -5.0, 6 }; 7 glGenBuffers(1, &vertexBuffer); 8 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 9 glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), vertices, GL_STATIC_DRAW); 10 }
使用
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, NULL); glColor4f(1.0, 0, 0, 1.0); glDrawArrays(GL_TRIANGLES, 0, 3); glDisableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0);
销毁
- (void)destroyVBO { if (vertexBuffer) { glDeleteBuffers(1, &vertexBuffer); vertexBuffer = 0; } }
3.
glVertexAttribPointer
void glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
参数 index :为顶点数据(如顶点,颜色,法线,纹理或点精灵大小)在着色器程序中的槽位;
参数 size :指定每一种数据的组成大小,比如顶点由 x, y, z 3个组成部分,纹理由 u, v 2个组成部分;
参数 type :表示每一个组成部分的数据格式;
参数 normalized : 表示当数据为法线数据时,是否需要将法线规范化为单位长度,对于其他顶点数据设置为 GL_FALSE 即可。如果法线向量已经为单位长度设置为 GL_FALSE 即可,这样可免去不必要的计算,提升效率;
stride : 表示上一个数据到下一个数据之间的间隔(同样是以字节为单位),OpenGL ES根据该间隔来从由多个顶点数据混合而成的数据块中跳跃地读取相应的顶点数据;
ptr :值得注意,这个参数是个多面手。如果没有使用 VBO,它指向 CPU 内存中的顶点数据数组;如果使用 VBO 绑定到 GL_ARRAY_BUFFER,那么它表示该种类型顶点数据在顶点缓存中的起始偏移量。
4.
glDrawElements
void glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
参数 mode :表示描绘的图元类型,如:GL_TRIANGLES,GL_LINES,GL_POINTS;
参数 count : 表示索引数据的个数;
参数 type : 表示索引数据的格式,必须是无符号整形值;
indices :这个参数也是个多面手,如果没有使用 VBO,它指向 CPU 内存中的索引数据数组;如果使用 VBO 绑定到 GL_ELEMENT_ARRAY_BUFFER,那么它表示索引数据在 VBO 中的偏移量。