每个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。
因此,请回答您的特定问题:
glDrawElements如何保存绘图调用...?在您使用的示例中,没有。每个都有一个抽奖电话。正如我上面讨论的那样,此示例对于比较这两个示例而言是非常糟糕的示例。
使用glDrawElements如何节省空间...?因为索引小于顶点。16位索引是两个字节,位置/颜色/ texcoord顶点是24个字节。6个顶点为144个字节,4个顶点加6个索引为108个字节。
如果从2个三角形绘制一个正方形...?一一。glDraw *调用是一个绘制调用,所使用的顶点或索引数与该度量无关。但是我必须再次强调,这是比较两者的非常不好的例子。
最后,只是使事情复杂一点,带有三角形的glDrawElements是台式机GPU上的最佳路径,而在移动设备上则可能大不相同。一些移动GPU可能更喜欢带有GL_TRIANGLE_STRIP的glDrawArrays(在这种情况下,您将添加退化三角形来连接图元),而我什至都没有涉及到更高级的主题,例如图元重启或多绘制。