glDrawArrays和glDrawElements的区别


12

在刷新OpenGL ES的想法时,我遇到了glDrawArraysglDrawElements

我了解它们的用法,并有点理解它们为何与众不同。

我似乎不明白的是,我看不到如何glDrawElements保存绘图调用(保存绘图调用是我所读过的大多数书籍都提到的描述,因此我在这里提到了)。

想象一个简单的场景,其中我尝试使用2个三角形绘制一个正方形。

使用glDrawArraysglDrawElements,我需要使用6个顶点的集合,除了具有6个元素的索引数组之外,我只需要4 个顶点。

鉴于以上所述,这是我不了解的内容:

  1. glDrawElements如果仍然需要使用索引数组(在正方形的情况下为6个索引)来索引具有4个元素(6次)的顶点数组,如何保存绘图调用?换句话说,这glDrawElements是否仍意味着总共需要进行6次抽签glDrawArrays
  2. glDrawElements如果一个仍然需要2个数组,即一个用于顶点,一个用于索引,该如何节省空间?
  3. 为了从2个三角形绘制一个正方形,为简单起见,分别需要多少次绘制调用glDrawElements(顶点数组中4个项目,而索引数组中glDrawArrays6个项目)和(顶点数组中仅6个项目)?

谢谢。

Answers:


16

每个glDraw *是一个绘制调用。

1 glDrawArrays是1个绘制调用。
1 glDrawElements是1个绘制调用。

无关紧要(就绘图调用次数而言),您使用多少个顶点或索引,1 glDraw *是1个绘图调用。

绘制四边形(假设您使用的GL版本没有删除四边形)或三角形的简单情况不是比较它们的好例子,因为可以通过一次调用来绘制四边形列表或三角形列表, glDrawArrays和glDrawArrays看起来效率更高,因为它没有索引的额外开销。

让我们来看一个稍微复杂一点的案例,但是这代表了一个更真实的场景。想象一下,您有一个由多个三角带和风扇组成的模型:

glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);

在此示例中,使用glDrawArrays可以为模型提供总共6个绘制调用。但是,条带和扇形都可以轻松地转换为索引三角形,因此添加索引,它将变为:

glDrawElements (GL_TRIANGLES, .....);

这是整个模型的一次抽签。


glDrawElements优于glDrawArrays的优点不仅仅是节省内存,这是衡量它的幼稚方式。由于索引通常比顶点小(因此即使您有很多平衡的索引也会更小),因此可以重复使用顶点有节省内存的潜力,但是其他优点包括:

  • 减少抽奖电话次数。每个draw调用都会因验证状态,进行设置等操作而产生一些开销,并且这些开销的大部分发生在CPU端。通过减少绘图调用次数,我们避免了很多此类开销。

  • 顶点重用。这不仅仅是节省内存。您的GPU可能具有硬件顶点缓存,可以在其中存储最近转换的顶点;如果相同的顶点再次出现,并且位于缓存中,则可以从缓存中重用它,而不必再次进行转换。您的硬件将通过比较索引来检查缓存,因此在OpenGL术语中,使用缓存的唯一方法是使用glDrawElements。


因此,请回答您的特定问题:

  1. glDrawElements如何保存绘图调用...?在您使用的示例中,没有。每个都有一个抽奖电话。正如我上面讨论的那样,此示例对于比较这两个示例而言是非常糟糕的示例。

  2. 使用glDrawElements如何节省空间...?因为索引小于顶点。16位索引是两个字节,位置/颜色/ texcoord顶点是24个字节。6个顶点为144个字节,4个顶点加6个索引为108个字节。

  3. 如果从2个三角形绘制一个正方形...?一一。glDraw *调用是一个绘制调用,所使用的顶点或索引数与该度量无关。但是我必须再次强调,这是比较两者的非常不好的例子。


最后,只是使事情复杂一点,带有三角形的glDrawElements是台式机GPU上的最佳路径,而在移动设备上则可能大不相同。一些移动GPU可能更喜欢带有GL_TRIANGLE_STRIP的glDrawArrays(在这种情况下,您将添加退化三角形来连接图元),而我什至都没有涉及到更高级的主题,例如图元重启或多绘制。


非常感谢您的反馈;我只花一点时间阅读您分享的内容。只是想让您知道我已确认您的回复。再次感谢。
Unheilig

在将6个DrawTriangleFans和DrawTriangleStrips调用转换为1个单个DrawTriangles调用的示例中。这真的会提高性能吗?我的理解画由100个三角形的三角形带是要比单独绘制三角形100更高效,效益很容易抵消任何惩罚使用6个函数调用,而不是1。发生
塞缪尔·李

@SamuelLi 6比1不会有很大的改进,仅是为了说明原理。而且,正如我指出的那样,在1998年后的台式机硬件上,条带化通常并不是性能优于索引表的优势。检查任何建议您使用试纸的文档上的日期。
Maximus Minimus

明白了,谢谢您的澄清!@MaximusMinimus
塞缪尔·李
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.