11

在我的应用程序中,我通过 OpenGL ES Api 绘制了很多立方体。所有立方体的尺寸相同,只是它们位于不同的空间坐标。我可以想到两种绘制它们的方法,但我不确定哪种方法最有效。我不是OpenGL专家,所以我决定在这里问。

方法1,也就是我现在使用的方法:由于所有立方体的尺寸都相同,所以我只计算了一次顶点缓冲区、索引缓冲区、法线缓冲区和颜色缓冲区。在刷新场景期间,我遍历所有立方体,对同一组缓冲区执行 bufferData(),然后使用 drawElements() 调用绘制立方体的三角形网格。由于每个立方体位于不同的位置,因此我在绘制之前翻译了 mvMatrix。为每个立方体执行 bufferData() 和 drawElements()。在这种方法中,我可能节省了大量内存,因为不是每次都计算缓冲区。但我打了很多 drawElements() 电话。

方法 2 是:将所有立方体视为遍布场景的一组多边形。计算每个多边形(实际上是多边形内的三角形)的顶点、索引、颜色、法线缓冲区,并在一次调用 bufferData() 时将它们推送到显卡内存。然后通过一次调用 drawElements() 来绘制它们。这种方法的优点是,我只调用了一次 bindBuffer 和 drawElements。缺点是,我使用大量内存来创建缓冲区。

我对 OpenGL 的经验非常有限,从性能的角度来看,不知道上述哪种方法更好。

我在 WebGL 应用程序中使用它,但这是一个通用的 OpenGL ES 问题。

4

3 回答 3

14

我实施了方法 2,它以压倒性优势获胜。高内存的所谓缺点似乎只是我的想象。事实上,垃圾收集器在方法 2 中只被调用了一次,而在方法 1 中被调用了 4-5 次。

您的 OpenGL 场景可能与我的不同,但如果您来到这里是为了寻找性能提示,那么这个问题的教训是:识别场景中不经常更改的部分。无论它们有多大,都将它们放在单个缓冲区集 (VBO) 中,并以最少次数上传到图形内存。这就是 VBO 的用途。客户端(即您的应用程序)和显卡之间的内存带宽非常宝贵,您不想经常无故消耗它。

阅读章节中的“顶点缓冲区对象”部分。“OpenGL ES 2.0 Programming Guide”的第 6 节,以了解它们应该如何使用。http://opengles-book.com/

于 2010-10-13T13:50:12.330 回答
6

我知道这个问题已经得到解答,但我认为值得指出的是关于 WebGL 优化的 Google IO 演示文稿:

http://www.youtube.com/watch?v=rfQ8rKGTVlg

他们基本上涵盖了这个完全相同的问题(许多具有不同颜色/位置的相同形状)并讨论了一些优化这种场景的好方法(他们的也是动态的!)

于 2011-10-04T22:28:57.693 回答
-1

我提出以下方法:

负载:

  1. 生成坐标缓冲区(用于一个立方体)并将其加载到 VBO ( gl.glGenBuffers, gl.glBindBuffer)

抽奖时:

  1. 绑定缓冲区 ( gl.glBindBuffer)

  2. 绘制每个单元格(循环)

    2.1。将当前位置移动到当前立方体的中心 ( gl.glTranslatef(position.x, position.y, position.z)

    2.2. 绘制当前立方体 ( gl.glDrawArrays)

    2.3. 向后移动位置 ( gl.glTranslatef(-position.x, -position.y, -position.z))

于 2010-10-13T14:06:58.140 回答