Android openGL ES glDrawArrays还是glDrawElements?

时间:2011-01-17 09:37:05

标签: android opengl-es

最好的方法是什么?如果我使用drawarrays,或者我使用drawelements?有什么不同的吗?

4 个答案:

答案 0 :(得分:31)

对于两者,您向OpenGL传递一些包含顶点数据的缓冲区。

glDrawArrays基本上是“使用我之前给你的数据绘制这个连续的顶点范围”。 好:

  • 您不需要构建索引缓冲区

为:

  • 如果将数据整理到GL_TRIANGLES中,则相邻三角形的顶点数据会重复。这显然是浪费。
  • 如果您使用GL_TRIANGLE_STRIP和GL_TRIANGLE_FAN尝试避免重复数据:它不是非常有效,您必须为每个条带和风扇进行渲染调用。 OpenGL调用很昂贵,应尽可能避免使用

使用glDrawElements,传入包含要绘制的顶点索引的缓冲区。

  • 没有重复的顶点数据 - 您只需为不同的三角形索引相同的数据
  • 您可以使用GL_TRIANGLES并依赖顶点缓存来避免两次处理相同的数据 - 无需重新组织几何数据或通过多次调用拆分渲染

  • 索引缓冲区的内存开销

我的建议是使用glDrawElements

答案 1 :(得分:6)

性能影响在iphone上可能类似,OpenGL ES Programming Guide for iOS建议使用三角形条带并通过退化三角形连接多个条带。

这个链接很好地说明了这个概念。通过这种方式,您可以重复使用一些顶点并仍然可以一步完成所有绘图。

  

为获得最佳性能,您的模型应使用glDrawArrays作为单个无索引三角形条提交,并尽可能少复制顶点。如果您的模型需要复制许多顶点(因为许多顶点由三角形共享,或者因为您的应用程序合并了许多较小的三角形条),您可以使用单独的索引缓冲区并调用glDrawElements获得更好的性能代替。有一个权衡:未编制索引的三角形条必须定期复制整个顶点,而索引三角形列表需要额外的索引内存,并增加查找顶点的开销。为获得最佳效果,请使用索引和未索引的三角形条测试模型,并使用速度最快的模型。

     

在可能的情况下,对顶点和索引数据进行排序,以便共享公共顶点的三角形在三角形条带中相互接近地绘制。图形硬件通常会缓存最近的顶点计算,因此引用的局部性可能允许硬件避免多次计算顶点。

缺点是您可能需要一个预处理步骤来对网格进行排序,以获得足够长的条带。 我还没有想出一个很好的算法,所以与GL_TRIANGLES相比,我不能给出任何性能或空格数。当然,这也高度依赖于你想要绘制的网格。

答案 2 :(得分:1)

实际上,您可以退化三角形条以创建连续条带,这样您就不必在使用glDrawArray时将其拆分。

我一直在使用glDrawElements和GL_TRIANGLES,但考虑使用glDrawArray而不是GL_TRIANGLE_STRIP。这样就不需要创建inidices矢量。

任何了解上述帖子中上面提到的顶点缓存事项的人都有?考虑glDrawElements / GL_TRIANGLE与glDrawArray / GL_TRIANGLE_STRIP之间的表现。

答案 3 :(得分:1)

接受的答案有点过时了。按照Jorn Horstmann的答案OpenGL ES Programming Guide for iOS中的文档链接,Apple描述如何使用DrawElements 使用“退化三角形”技巧,从而获得两全其美的效果。

使用DrawArrays通过将所有数据组合到单个GL调用DrawElements中,可以节省少量索引。 (你可以使用DrawArrays组合所有,但是任何“浪费的元素”都会浪费顶点,这些顶点比索引大得多,并且需要更多的渲染时间。)

这也意味着您不需要仔细考虑所有模型,无论它们中的大多数都可以渲染为最小数量的条带,还是它们太复杂。一个统一的解决方案,处理一切。 (但是尽可能尝试组织成条带,以最小化发送的数据,并最大化GPU重新使用最近缓存的顶点计算的可能性。)

BEST:使用GL_TRIANGLE_STRIP进行一次DrawElements调用,其中包含 所有 您的数据(每帧都在变化)。