VBO

顶点数据被存储在客户端内存中,调用glDrawArrays或glDrawElements就可以将数据拷贝到绘图内存中,用于绘制。如果不用每次进行拷贝数据将显著提高渲染效率。这就要用到VBO(vectex buffer objects)。VBO允许GLES应用去分配和存储顶点数据到高效的绘制内存中,从这里直接渲染。不仅是顶点数据,甚至描述的顶点原始索引也能使用glDrawElements去存储。

GLES支持两中缓冲区对象:数组缓冲对象array buffer objects,元素数组缓冲对象element array buffer objects。数组缓冲对象是使用GL_ARRAY_BUFFER创建的存储顶点数据的缓冲对象;元素数组缓冲对象是使用GL_ELEMENT_ARRAY_BUFFER创建的存储原始索引的缓冲对象。

为了更好的执行程序,我们推荐GLES2应用应该尽可能的对顶点数据使用顶点缓冲区和元素索引。

void glGenBuffers(GLsizei n, GLuint *buffers)
void glDeleteBuffers (GLsizei n, const GLuint* buffers);

使用glGenBuffers分配n个缓冲区对象,在buffers返回它们。被glGenBuffers返回的缓冲区对象名是未使用的非0整型数。如果不再使用缓冲区glDeleteBuffers释放。

void glBindBuffer(GLenum target, GLuint buffer)

glBindBuffer函数使一个缓冲区对象成为当前数组缓冲对象或当前元素数组缓冲对象。一个缓冲对象被第一次使用glBindBuffer绑定时,缓冲对象将被分配合适的默认状态,如果分配成功,分配的对象被绑定成为渲染上下文的当前数组缓冲区对象或当前元素数组缓冲对象。

void glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);

为顶点缓存对象分配空间,target与glBindBuffer中的参数target相同;size指定顶点缓存区的大小,以字节为单位计数;data用于初始化顶点缓存区的数据,可以为NULL,表示只分配空间,之后再由glBufferSubData进行初始化;usage表示该缓存区域将会被如何使用,它的主要目的是用于提示GLES应该对缓存区域做何种程度的优化。其参数为以下三个之一:GL_STATIC_DRAW:表示该缓存区不会被修改;GL_DYNAMIC_DRAW:表示该缓存区会被周期性更改;GL_STREAM_DRAW:表示该缓存区会被频繁更改;

如果顶点数据一经初始化就不会被修改,那么就应该尽量使用GL_STATIC_DRAW,这样能获得更好的性能。

void glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);

用于更新顶点缓冲区数据,offset表示需要更新的数据的起始偏移量;size表示需要更新的数据的个数,也是以字节为计数单位;data即用于更新的数据。

栗子

我们这里分别采用VBO和不采用的方式去创建上一节的那个黄色三角形。工程代码的tag:lesson6

void Director::mainLoop()
{
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // use white color as background
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

    GLint idxColor = glGetAttribLocation(_glProgram->getProgramHandle(), "a_color");
    GLint idxPos = glGetAttribLocation(_glProgram->getProgramHandle(), "a_position");

    glVertexAttrib4fv(idxColor, gColor);

    //// not use VBO's code  ////
    // glVertexAttribPointer(idxPos, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices); 
    // glEnableVertexAttribArray(idxPos);
    //// not use VBO's code  ////

    //// use VBO ////
    GLuint arrayBuff[1];
    glGenBuffers(1, arrayBuff);
    glBindBuffer(GL_ARRAY_BUFFER, arrayBuff[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GL_FLOAT)*6, gTriangleVertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray(idxPos);
    glVertexAttribPointer(idxPos, 2, GL_FLOAT, GL_FALSE, 0, 0);
    //// use VBO ////

    glDrawArrays(GL_TRIANGLES, 0, 3);
}

运行效果:

clipboard.png


RichardXG
337 声望19 粉丝

引用和评论

0 条评论