从效率的角度(或其他观点,如果重要的话),什么是可取的?
场合
一个OpenGL应用程序,每帧(60 fps)在不同位置绘制许多行。可以说有10行。或100 000行。答案会有所不同吗?
每一帧每行都会有一个glDrawArrays调用,而在它们之间会有矩阵变换来定位我们的一行
每一帧都有一次平局调用
答案 0 :(得分:28)
第二种效率非常高。
改变状态,特别是转换和矩阵,往往会导致重新计算其他状态,并且通常会产生更多的数学。
然而,更新几何图形只需要覆盖缓冲区。
在相当庞大的带宽总线上使用现代视频硬件,发送几个浮点数是微不足道的。它们旨在快速移动大量数据,这是工作的副作用。更新顶点缓冲区正是它们经常和快速执行的操作。如果我们假设每个点32个字节(float4位置和颜色),100000个线段小于6 MB,而PCIe 2.0 x16大约是8 GB / s,我相信。
在某些情况下,根据驱动程序或卡处理变换的方式,更改一个可能会导致某些矩阵乘法并重新计算其他值,包括变换,剔除和剪裁平面等。如果您更改了这个值,这不是问题。状态,画出几千个多边形,并重复,但是当状态经常发生变化时,它们将会产生很大的成本。
之前解决的一个很好的例子是批处理的概念,最小化状态变化,因此可以在它们之间绘制更多的几何。这用于更有效地绘制大量几何体。
作为一个非常明显的例子,考虑#1的最佳情况:变换集触发无额外计算,驱动程序热情且完美地缓冲。要绘制100000行,您需要:
单独的函数调用开销将 kill 性能。
另一方面,批处理涉及:
您可以复制更多数据,但VBO内容很可能不像复制矩阵数据那样昂贵。另外,在函数调用中可以节省大量的CPU时间(200000到2)。这简化了您的生活,驱动程序(必须缓冲所有内容并检查冗余调用并优化和处理下载)以及可能的视频卡(可能必须重新计算)。为了使其清晰,可视化简单的代码:
for (i = 0; i < 100000; ++i)
{
matrix = calcMatrix(i);
setMatrix(matrix);
drawLines(1, vbo);
}
(现在解开)
matrix = calcMatrix();
setMatrix(matrix);
for (i = 0; i < 100000; ++i)
{
localVBO[i] = point[i];
}
setVBO(localVBO);
drawLines(100000, vbo);