glDrawElements行为

时间:2014-01-21 06:03:18

标签: iphone opengl-es

我目前正在阅读一个iPhone OpenGL ES项目,该项目绘制了一些3D形状(shpere,cone,..)。我对glDrawElements的行为有点困惑。

将vertexbuffer绑定到GL_ARRAY_BUFFER,将indexbuffer绑定到GL_ELEMENT_ARRAY_BUFFER后,调用函数glDrawElements:

glDrawElements(GL_TRIANGLES, IndexCount, GL_UNSIGNED_SHORT, 0);

起初我认为这个功能在屏幕上绘制形状,但实际上这些形状随后会在屏幕上绘制:

[m_context presentRenderbuffer:GL_RENDERBUFFER];

那么glDrawElements做了什么?手册将其描述为render primitives from array data。但我不明白render&的真正含义。它与draw的区别(我的母语不是英语)

2 个答案:

答案 0 :(得分:1)

DrawElements调用实际上是绘图的“做”。或者说它告诉GPU绘制。 GPU最终会做到这一点。 仅需要当前调用,因为GPU通常工作为双缓冲:一个缓冲区,您看不到但是绘制到,以及一个当前在屏幕上显示的缓冲区。完成所有绘图后,您可以翻转它们。 如果你不这样做,你会在绘图时看到闪烁。 它还允许并行操作。当您调用DrawElements时,您可以多次调用一帧。只有当你调用present时,GPU才能等待所有这些完成。

答案 1 :(得分:-1)

glDraw命令对您的绘图负责,并且在您调用presentRenderbuffer:方法之前看不到任何可见结果,这是正确的,但它是正确的不是关于双重缓冲。

所有iOS设备都使用围绕基于平铺的延迟渲染(TBDR)设计的GPU。这种算法在嵌入式环境中运行良好,与桌面GPU相比,计算资源,内存和功耗预算更少。在桌面(基于流)的GPU上,每个绘图命令都会立即起作用(通常),其中一些像素被绘制到渲染缓冲区中。 (通常,您不会看到这一点,因为通常情况下,桌面GL应用程序设置为使用双重或三重缓冲,将完整的帧绘制到屏幕外缓冲区,然后将其交换到屏幕上。)

TBDR与众不同。你可以认为它有点像激光打印机:为此,你把一堆PostScript命令放在一起(设置状态,绘制它,设置不同的状态,绘制它等等),但打印机没有&#39做任何工作,直到你发送了所有的绘图命令并完成了那个说'#34;好的,开始放下墨水!"然后打印机计算需要黑色的区域并一次性打印所有区域(而不是在页面上下打印已打印的区域)。

TBDR的优势在于GPU在开始绘画之前就知道整个场景 - 这使得它可以使用隐藏表面移除等技巧来避免做不会导致可见像素被绘制的工作。

因此,在iOS设备上,glDraw仍然"确实"绘图,但这项工作不会发生,直到GPU需要它发生。在简单的情况下,GPU不需要开始工作,直到您致电presentRenderbuffer:(或者,如果您正在使用GLKView,直到您从其drawRect:返回为止或其委托的glkView:drawInRect:方法,隐式呈现渲染缓冲区)。如果你正在使用更高级的技巧,比如渲染到纹理然后使用这些纹理渲染到屏幕,那么只要切换到另一个渲染目标,GPU就会开始为一个渲染目标工作(使用glBindFramebuffer或类似)。

有关TBDR如何在Advances in OpenGL ES talk from WWDC 2013中发挥作用的一个很好的解释。