在OpenGL ES(iPhone)中使用顶点缓冲对象(VBO)以提高性能

5
我正在为iPhone编写一个简单的应用程序,它显示旋转的立方体。我使用glDrawElements(OpenGl ES)来绘制立方体的三角形并旋转它。我注意到当我将立方体的大小增加到100*100*100个体素时,显示性能变得很差(澄清:我不绘制整个立方体,我只绘制它的轮廓(网格)。我通过在立方体上应用Marching Cubes算法来获得所有网格的三角形...最终我获得大约120k个要绘制的三角形,由40k个顶点表示)...

为了绘制立方体,我持有一个顶点数组、一个颜色数组和一个指向顶点的索引数组。索引数组定义要绘制的顶点三角形。它被传递给glDrawElements作为参数。

最近我读到了一种使用顶点缓冲对象(VBO)绘制立方体的不同技术。我实现了它,但性能甚至比以前的技术更差。

这是我的代码,也许我犯了一个愚蠢的错误,任何改进建议都将受到欢迎:)

顺便说一下,我使用了以下文章作为参考:

这是一个包含两个链接的块引用:
- 第一个链接指向http://playcontrol.net/ewing/jibberjabber/opengl_vertex_buffer_object.html - 第二个链接指向http://iphonedevelopment.blogspot.com/2009/05/opengl-es-from-ground-up-table-of.html
//all the 7 variables down are initialized by other function at the beginning 
GLushort* meshIndices;    //array of indices (ushort)
MeshVertex* meshVertices; //array of vertices (floats)
Color3D* meshColors;      //array of colors  (floats)

int numberOfTriangles; //number of Triangle to draw the cube
int numberOfVertices;  //number of all Vertices to draw the cube
int numberOfIndices;   //number of all Indices to draw the cube, each 3 indices define 3 vertices which define 1 triangle
int numberOfColors;    //number of colors used to draw the cube. each color is of tip Color3D

//in this function i initializing the VBOs 
- (void) setupMeshVBOs { 

    glGenBuffers(1, &triangleVBO);
    glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);

    const GLsizeiptr vertex_size = numberOfVertices * sizeof(MeshVertex);
    const GLsizeiptr color_size = numberOfColors * sizeof(Color3D);

    glBufferData(GL_ARRAY_BUFFER, vertex_size + color_size, 0, GL_STATIC_DRAW);

    GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES); 
    memcpy(vbo_buffer, meshVertices, vertex_size);

    GLbyte* temp = (GLbyte*)vbo_buffer;
    temp += vertex_size;
    memcpy((GLvoid*)temp, meshColors, color_size);

    glUnmapBufferOES(GL_ARRAY_BUFFER); 

    glVertexPointer(3, GL_FLOAT, 0, (GLvoid*)((char*)NULL));

    glColorPointer(4, GL_FLOAT, 0, (GLvoid*)((char*)NULL+vertex_size));

    glGenBuffers(1, &triangleIBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangleIBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, numberOfIndices * sizeof(GLushort), meshIndices, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

//this function is the one which draws the VBOs
- (void)drawView:(GLView*)view;
{

    static GLfloat rot = 0.0;


    glLoadIdentity();
    glTranslatef(-1.0f,-2.0f,-20.0f);
    glRotatef(rot,1.0f,1.0f,1.0f);
    glClearColor(0.7, 0.7, 0.7, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangleIBO);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);

        glDrawElements(GL_TRIANGLE_STRIP, numberOfIndices, GL_UNSIGNED_SHORT, (GLvoid*)((char*)NULL));

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);

    static NSTimeInterval lastDrawTime;
    if (lastDrawTime)
    {
        NSTimeInterval timeSinceLastDraw = [NSDate timeIntervalSinceReferenceDate] - lastDrawTime;
        rot+=50 * timeSinceLastDraw;                
    }
    lastDrawTime = [NSDate timeIntervalSinceReferenceDate];
}

2
首先,你说在100^3个像素的情况下性能变差。这一点并不令人意外,因为那将是1百万个像素。我假设每个像素都是一个立方体,由12个三角形组成。那就是每次呈现调用1200万个三角形。真的非常多。另外请注意,当顶点和颜色数据交错时,VBO可能更有效率。但是对于iPhone(PowerVR)而言,我不知道是否是这种情况。 - Arne
是的,我没有解释清楚,我已经相应地编辑了问题。这个立方体是100100100的,但我不绘制整个立方体,只绘制它的轮廓(网格)。我通过在立方体上应用Marching Cubes算法来获取网格的所有三角形...最终我得到大约120k个要绘制的三角形,由40k个顶点表示... - alexpov
1个回答

5
首先,要绘制一个100x100x100的立方体地图,您不应该单独绘制每个立方体。如果有一排六个方块,则应将它们绘制为一个长方体,总共十二个三角形。任何被六面包围的立方体肯定不需要考虑。您应该采用这些策略来显著减少几何数量。
苹果关于GL优化的建议在这里。简要版本是,您应该使用具有对齐的交错数据的VBO,并使用最小可接受的类型。因此,隐含地,读取数据是瓶颈。使用两个分开的列表可能会将几何输入速率减半,并且使用浮点数可能会进一步减慢速度。

你好,我已经阅读了你建议的文档,它包含了所有的答案...谢谢 :) - alexpov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接