在带着色器的OpenGL中,我想渲染两个已加载为两个网格的对象。每个对象由一组顶点位置,一组顶点颜色和一组三角形的顶点索引表示。
我可以通过三种方式来绘制这两个对象。哪种是最佳做法?
1)我将两个对象的顶点位置连接成一个长顶点顶点,并且顶点颜色和顶点索引类似。然后我创建一个顶点位置缓冲区,一个顶点颜色缓冲区和一个索引缓冲区。渲染时,我会调用glBindBuffer(...)
和glDrawElements(...)
。
2)我将两个对象的顶点位置连接成一个长顶点数组,并且类似于顶点颜色。然后我创建一个顶点位置缓冲区和一个顶点颜色缓冲区。渲染时,我会对glBindBuffer(...)
和glDrawElements(...)
进行两次调用,每个对象一次。
3)我创建了两个顶点位置缓冲区,两个顶点颜色缓冲区和两个索引缓冲区。渲染时,我会对glBindBuffer(...)
和glDrawElements(...)
进行两次调用,每个对象一次。
谢谢!
答案 0 :(得分:1)
OpenGL优化的一般规则是最小化状态更改的数量。绑定缓冲区是一种状态变化。
所以,所有其他条件相同,#1可能是最快的。
然而,它并不总是特别有用。通常,不同的对象相对于彼此具有不同的变换。通常情况下,您需要在呈现对象之间更改某些状态,因此#1不是一个选项。
即便如此,您也不必求助于选项2.您可以使用与选项1相同的缓冲区设置,但只需发出两个绘制调用。每次绘制都将使用部分数组进行渲染。
同样重要的是,对于顶点数组,问题不在于绑定缓冲区(尽管它们并不便宜)。它改变了你使用的vertex format,属性的相对安排。如果使用separate attribute format API,则可以轻松更改缓冲区绑定,而无需触及格式。通常,整个程序中只有5-6个顶点格式。
另一个问题是你没有在这里充分探索各种可能性。例如,在所有情况下,位置,颜色,法线和其他属性都位于不同的缓冲区中。那么......为什么他们在不同的缓冲区? Interleaving your vertex attributes通常会提供更好的效果。
所以,真正的最佳表现的答案是"以上都不是"。
答案 1 :(得分:1)
只渲染了2个对象,这些选项都不会让您接近任何类型的性能瓶颈。如果您将帧速率定位为与显示刷新率(通常约为60 fps)相匹配,则只需每秒渲染120个对象。
假设您需要为每个对象提供少量的状态设置调用,这使您可以在每秒1000次状态设置调用的范围内。虽然性能特征当然是高度平台/供应商特定的,但是中途不错的驱动程序将能够每秒处理几百万个简单的状态设置调用(如绑定缓冲区,设置顶点属性等)。因此,您至少要比我开始担心吞吐量的水平低3或4个数量级。
现在,如果你有数千个对象,事情就会开始变得有些不同了。我肯定会推荐两件事:
使用交错属性。这意味着您按顺序存储一个顶点的位置和颜色,然后是下一个顶点的属性。假设您有3个组件(xk, yk, pk)
用于位置,4个组件(rk, gk, bk, ak)
用于顶点k
的颜色,缓冲区的内存布局为:
x0 y0 z0 r0 g0 b0 a0 x1 y1 z1 r1 g1 b1 a1 x2 y2 z2 r2 g2 b2 a2 ...
使用VAO(顶点阵列对象)设置状态。这将允许您通过单个glBindVertexArray()
调用为对象设置整个顶点属性状态。
为每个对象分别使用单独的VBO,或者在对象之间共享更大的VBO,是否更好,一般很难说清楚。拥有大量的小型VBO肯定会对性能产生影响,如果您可以相当容易地进行安排,那么分享它们可能会有所帮助。但我也可以想象一下,如果有很大的维生素生态系统会产生不利影响。因此,如果您希望在拥有大量对象的情况下获得最大性能,则可能必须尝试不同的选项。不幸的是,结果很可能取决于平台。