OpenGL- drawarrays或drawelements?

时间:2013-10-28 13:26:31

标签: opengl

我正在制作一个小型2D游戏演示,根据我的阅读,最好使用drawElements()绘制索引三角形列表,而不是使用drawArrays()绘制未编制索引的三角形列表。< / p>

但据我所知,似乎不可能在drawElements()的单个绘图调用中绘制多个未连接的元素。

所以对于我的2D游戏演示,我只打算绘制由两个三角形组成的正方形,那么最好的方法是什么,所以我不会每个对象都有一个绘图调用?

1 个答案:

答案 0 :(得分:4)

是的,在许多情况下最好使用索引,因为您不必存储或传输重复的顶点,并且您不必处理重复的顶点(顶点着色器只需要在每个顶点运行一次)。对于四边形,您将6个顶点减少到4,再加上少量索引数据。三分之二是非常好的改进,特别是如果您的顶点数据不仅仅是位置。

总之,glDrawElements会产生

  • 较少的数据(大多数),这意味着更多的GPU内存用于其他事情
  • 如果数据更改,则更新更快
  • 更快地转移到GPU
  • 更快的顶点处理(无重复)

如果参考顶点在内存中彼此不相近,则索引会影响缓存性能。建模者通常会生成网格,并考虑到这一点进行了优化。

对于多个元素,如果您引用的是GL_TRIANGLE_STRIP,则可以使用glPrimitiveRestartIndex通过一次glDrawElements调用绘制多条三角形条带。在您的情况下,使用GL_TRIANGLES和引用4个顶点以及每个四边形的6个索引很容易。然后,您的顶点数组需要存储所有四边形的所有顶点。如果它们正在移动,您仍需要每帧将该数据发送到GPU。您可以将所有移动的四边形放置在阵列的前面,只更新活动的四边形。您还可以将静态顶点数据存储在单独的数组中。

绘制3D模型的典型方法是提供几何体的固定顶点列表,并使用模型矩阵(作为模型视图的一部分)移动整个事物。这里令人困惑的部分是网格数据太小,正如你所说,绘制调用的开销可能变得非常突出。我认为你必须先得到一个 LOT 的四边形,然后才能进入一个问题的阶段。但是,如果你这样做,实例化或类似的想法,如粒子系统,你应该看。

如果绘图调用或数据传输成为问题,可能只会沿着下面的轨道走下去,因为涉及很多。完全在GPU上实现粒子系统的一种好方法是在纹理中存储实例属性,例如位置/颜色。您使用FBO /渲染到纹理的每个帧在另一个纹理之间“乒乓”此数据并更新片段着色器中的属性。要绘制粒子,可以设置一个静态VBO,它存储带有属性 - 数据纹理坐标的四边形,以便在顶点着色器中使用,可以读取和应用粒子位置。我确信有一堆很好的教程/实现可以跟随out there(如果你知道一个好的教程/实施,请发表评论)。