我正在开发一款适用于iPhone的OpenGL ES 1.1游戏;我在数据结构中有很多纹理四边形,其中每个节点都有一个子节点列表。所以我从根遍历结构,并对每个四边形进行渲染,然后对其子进行渲染等等。
问题是,对于每个四元组我都在调用glVertexPointer来设置顶点。
尝试最小化调用次数并不容易,因为每个节点可能有不同的四边形。我有很多相同的精灵与相同的顶点数据,但我不一定渲染一个接一个,因为我可能在它们之间绘制不同的精灵。
感谢。
答案 0 :(得分:10)
glVertexPointer只保留指针,但会导致OpenGL驱动程序的状态更改和显式同步,因此成本相当高。通常当你说'这是我的数据,请绘制'时,GPU开始绘图并继续与CPU上的任何内容并行执行,只要它可以。当您更改渲染状态时,它需要完成它在旧状态下执行的任何操作。因此,通过每个四元组更改一次,您可以有效地强制并发处理是连续的。因此,每个四边形避免glVertexPointer(可能是glDrawArrays或glDrawElements?)应该会给你带来很大的好处。
立即优化只是在数据结构中保持总数的数量,为至少大小的顶点分配单个目标缓冲区,并让所有四边形将其几何体复制到目标缓冲区而不是每次调用glVertexPointer。然后调用glVertexPointer和你的绘图调用(也希望只调用一个调用),最后一个大数组。它在CPU方面成本更高,但并行性和缺乏重复的GPU / CPU同步应该可以为您节省很多。
在围绕目前正在使用NDA的主题时,我强烈建议您查看Xcode 4测试版。 Apple拥有stated publicly to be present的其他功能是OpenGL ES分析器。所以你可以很容易地比较方法。
要将数据复制到GPU,您需要使用顶点缓冲区对象。这意味着创建一个glGenBuffers
的缓冲区,用glBufferData
将数据推送给它,然后发布一个地址为例如的glVertexPointer。如果您上传的数据中的第一个字节是顶点的第一个字节,则为0。在ES 1.x中,您可以将数据上传为GL_DYNAMIC_DRAW
,以标记您打算经常更新它并经常从中进行绘制。如果你能够进入比你上传更频繁的位置,那么这可能是值得的。
如果您曾切换到ES 2.x,还有GL_STREAM_DRAW
,这可能值得调查,但与您的问题没有直接关系。我提到它,因为如果你谷歌的顶点缓冲对象,可能会出现在桌面OpenGL上。 ES 1.x的选项仅为GL_STATIC_DRAW
和GL_DYNAMIC_DRAW。
我刚刚在iPad ES 1.x应用程序上工作,其中的对象会改变每一帧,但每次使用的渲染管道都会被绘制两次。屏幕上只有五个这样的对象,每个40个顶点,但从初始实现切换到VBO实现,可以减少总处理时间的20%。