2012-10-15 64 views
2

我正在使用以下代码在3D游戏中绘制一些多边形网格物体。绘制多边形网格时发生Opengl性能问题

void drawModelFace(const MeshFace *face, float *vertices, float *vertNormals, float *textureVerts) 
{ 
    glBegin(GL_POLYGON); 
    for (int i = 0; i < face->_numVertices; i++) 
    { 
     glNormal3fv(&vertNormals[3 * face->_vertices[i]]); 

     if (face->_texVertices) 
     { 
      glTexCoord2fv(&textureVerts[2 * face->_texVertices[i]]); 
     } 

     glVertex3fv(&vertices[3 * face->_vertices[i]]); 
    } 
    glEnd(); 
} 

我的问题是我遇到一些性能问题游戏时,这个函数被称为很多时间。

这个函数平均每秒调用50000次,这个函数给出了一个恒定的60fps,但是在一些地方,它被称为每秒100000次,它给出了15fps。 (我使用今天的电脑降频到1Ghz来模拟今天的手机性能)

我听说即时模式可能很慢,这就是为什么我尝试使用glDrawArrays代替。代码如下:

void drawModelFace(const MeshFace *face, float *vertices, float *vertNormals, float *textureVerts) 
{ 
    GLfloat vert[3*face->_numVertices]; 
    GLfloat normal[3*face->_numVertices]; 
    GLfloat tex[2*face->_numVertices]; 

    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
    glEnableClientState(GL_NORMAL_ARRAY); 
    glVertexPointer(3, GL_FLOAT, 0, vert); 
    glTexCoordPointer(2, GL_FLOAT, 0, tex); 
    glNormalPointer(GL_FLOAT, 0, normal); 

    for (int i = 0; i < face->_numVertices; i++) 
    { 
     vert[0 + (i*3)] = vertices[3 * face->_vertices[i]]; 
     vert[1 + (i*3)] = vertices[3 * face->_vertices[i]+1]; 
     vert[2 + (i*3)] = vertices[3 * face->_vertices[i]+2]; 

     normal[0 + (i*3)] = vertNormals[3 * face->_vertices[i]]; 
     normal[1 + (i*3)] = vertNormals[3 * face->_vertices[i]+1]; 
     normal[2 + (i*3)] = vertNormals[3 * face->_vertices[i]+2]; 

      if (face->_texVertices) 
      { 
       tex[0 + (i*2)] = textureVerts[2 * face->_texVertices[i]]; 
       tex[1 + (i*2)] = textureVerts[2 * face->_texVertices[i]+1]; 
      } 
    } 

    glDrawArrays(GL_TRIANGLE_FAN ,0, face->_numVertices); 
    glDisableClientState(GL_VERTEX_ARRAY); 
    glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
    glDisableClientState(GL_NORMAL_ARRAY); 
} 

但是性能结果完全一样。

如何优化我的代码以获得一些fps?

请注意,我的最终目标是使用此代码的Android设备,因此glBegin和glEnd不被允许了。

+1

您似乎在研究如何在实际绘图函数中绘制网格,而不是预先绘制网格。我的意思是你的绘图函数应该只是传递已经构建的数组。所以这里的问题更多的是你如何管理模型工作流程。我会确保你有一个VBO和每个网格的索引缓冲区。然后,您将不必在绘图中间迭代网格。你只需在显卡上挑选三角形和指标的汤。 – Robinson

+0

在ES 1.1中,您的选择非常有限。它是glDrawArrays和glDrawElements,就是这样。而且,PC架构与嵌入式设备有很大不同。具有x16 PCIe总线和NVIDIA板的降频CPU不太可能提供与PowerRV相同的性能。 – Calvin1602

回答

0

如果您的网格不会改变(即它是一个静态的模型),那么你可以使用display list

这可以让你预先撰写所有的顶点/纹理/正常呼叫到一个列表,你然后渲染通过一次函数调用glCallList。

+0

不幸的是,它不是一个静态模型,而且显示列表不是一个opengl-es 1.1的一部分,这是我的最终目标。有人告诉我有关顶点缓冲区对象,但我不知道如何在我的代码中实现这一点。 – user1746664

4

我认为glDrawArray可能是最好的选择。如果我没有记错,那么阵列中的数据将在每次迭代中从客户端发送到服务器。如果数据在每次迭代中都发生了变化,那么这并不是一个问题,因为无论如何,客户端每次都要将数据发送到服务器。这意味着由于实施了VBOs,将大量数据存储在服务器内存上并不会真正提高性能,因为无论如何您都必须重新发送数据。

你使用的是大物还是小的? 我相当有信心glDrawArrays在大对象情况下是最优的。

你对“性能结果是完全一样的”意味着什么?它是非常非常相似还是有区别?对我来说,如果表现完全一样,这听起来有点可疑。

+0

仅供参考,此答案中的后续问题更好地发布为原始问题的评论(而不是您的答案)。 –

+0

我使用很多小对象,因为每次调用函数时只有3或4个顶点。 – user1746664

+0

使用gldrawarrays可以减少性能,因为有很多对象。 gldrawarrays的最大优点是客户端可以非常快速地向服务器发送大量数据,然后继续处理下一行代码,并让服务器处理刚刚收到的大量数据。这与使用glBegin/glEnd相反,客户端需要在每个glvertex调用之间等待(至少这是我的理解,也许我错了)。 –