2011-09-24 40 views
17

从效率的角度(或其他重要的观点来看)是什么更喜欢?OpenGL是更好的批量绘制或具有静态VBOs

现状
一个OpenGL应用程序,它在不同的位置绘制多行每帧(每秒60帧)。可以说有10条线。或100000行。答案会不同吗?

  • #1具有静态VBO永远不会改变,含有线

每帧将有一个调用glDrawArrays每行绘制调用的2个顶点,和在它们之间会有矩阵变换定位我们一行

  • #2更新的VBO与所有行的数据每帧

每一帧都会有一个平局呼叫

回答

27

第二个是令人难以置信的更高效。

更改状态,特别是转换和矩阵,往往会导致重新计算其他状态,并且通常会导致更多的数学运算。

但是,更新几何图形只涉及覆盖缓冲区。

随着现代视频硬件在相当大规模的带宽总线上,发送几个浮点数是微不足道的。它们旨在快速移动大量数据,这是该作业的副作用。更新顶点缓冲区正是他们经常和快速完成的。如果我们分别确定32个字节的点(float4位置和颜色),我相信100000个线段小于6 MB,PCIe 2.0 x16大约为8 GB/s。

在某些情况下,根据驱动程序或卡片如何处理转换,更改一个可能会导致一些矩阵乘法和重新计算其他值(包括转换,剔除和剪切平面等)。如果更改,则这不是问题这个状态,画出几千个多边形,然后重复,但是当状态经常变化时,它们将会有很大的成本。

以前解决此问题的一个很好的例子是配料的概念,最小化状态变化,因此可以在它们之间绘制更多的几何图形。这用于更有效地绘制大量的几何图形。

作为一个非常明确的例子,考虑#1的最佳情况:变换集触发器不需要额外的计算,并且驱动程序非常热情和完美地缓冲。要绘制10万株,您需要:

  • 100000矩阵集(系统内存)与函数调用的开销
  • 100000矩阵集电话(视频驱动器,矩阵复制到缓冲区有)
  • 100000矩阵复制到视频RAM,在一个单一肿块进行
  • 100000画线电话

函数调用的开销单是要性能。

在另一方面,配料包括:

  • 100000点计算,并在系统RAM
  • 1 VBO复制到视频RAM。这将是一个大块,但一个连续的大块,双方都知道会发生什么。它可以很好地处理。
  • 1点矩阵集呼叫
  • 1矩阵拷贝到视频RAM
  • 1战平呼叫

你做复制更多的数据,但有一个很好的机会VBO内容仍然不如复制为贵矩阵数据。另外,您可以在函数调用中节省大量的CPU时间(从200000降低到2)。这可以简化您的生活,驱动程序(它必须缓冲所有内容并检查是否有多余的呼叫,并优化和处理下载),也可能是视频卡(可能需要重新计算)。为了使它真正明确的,可视化的简单代码:

1:

for (i = 0; i < 100000; ++i) 
{ 
    matrix = calcMatrix(i); 
    setMatrix(matrix); 
    drawLines(1, vbo); 
} 

(现在打开那)

2:

​​
+3

好了,这是否意味着它是总是更好地烘烤到一个VBO然后绘制,而不是使用矩阵进行转换?如果我说了一些,也许是10,移动纹理四边形。计算对象的坐标,重新创建VBO,上传和绘制真的会更好吗?与在每个对象上使用矩阵平移(我优化为简单的2次加法而不是64次乘法和48次加法)然后绘制每个对象相反。 – mk12

+1

“如果我们分别确定32个字节的点(float4的位置和颜色)”并且几乎​​不需要将这一点减半:vec3的位置和vec4的无符号字节颜色。此外,你应该调查[缓冲区对象流](http://www.opengl.org/wiki/Buffer_Object_Streaming),以提高性能。 –

+1

@ Mk12你问了一个更复杂的问题。你的问题答案很简单,因为每个对象都非常小,即使你有很多对象,顶点数据也很小。一旦你有更多的对象,计算他们的头寸成本变得更加重要,上传成本也是如此。 –