蒂姆正确地指出,这取决于你的应用程序,让我们来谈谈一些数字,你提到的所有帧到一个VBO两个国际文凭组织和插入纹理坐标,所以让我们来看看各的影响。
假设一个典型的顶点看起来是这样的:
struct vertex
{
float x,y,z; //position
float tx,ty; //Texture coordinates
}
我添加了一个z分量,但计算是类似的,如果你不使用它,或者如果你有更多的属性。所以很明显这个属性需要20个字节。
让我们假设一个简单的精灵:一个由2个三角形组成的四边形。在非常天真的模式下,您只需发送2x3顶点并将6*20=120
字节发送到GPU。
在自带的索引,你知道你有实际只有四个顶点:1,2,3,4
和两个三角形1,2,3
和2,3,4
。所以我们向GPU发送两个缓冲区:一个包含4个顶点(4*20=80
字节),另一个包含三角形索引列表([1,2,3,2,3,4]
),假设我们可以在2个字节(65535个索引应该足够)中做到这一点,所以这个归结为6*2=12
字节。总共92
字节,我们保存28
字节或约23%
。另外,渲染GPU的时候很可能是only process each vertex once in the vertex shader,它也为我们节省了一些处理能力。
因此,现在您想要为所有动画一次添加所有纹理坐标。首先要注意的是,索引渲染中的顶点由其所有属性定义,不能将其分割为位置索引和纹理坐标索引。所以如果你想添加额外的纹理坐标,你将不得不重复这个位置。因此,您添加的每个“帧”都将向IBO添加80
字节,并向IBO添加12
字节。假设你有64帧,你最终会得到64*(80+12)=5888
字节。假设你有1000个精灵,那么这将变成约6MB
。这看起来不算太坏,但请注意,它的缩放比例非常快,每一帧都增加了大小,但也增加了每个属性(因为它们必须重复)。
那么,它会给你带来什么?
- 您不必动态发送数据到GPU。请注意,更新整个VBO需要发送
80
字节或640
位。假设您需要为每帧30
帧每秒1000
精灵执行此操作,您将获得19200000
bps或19.2Mbps
(不包括任何开销)。这是相当低的(例如,16xPCI-e可以处理32Gbps
),但如果您有其他带宽问题(例如由于纹理化),则可能值得一提。另外,如果您仔细地构建VBO(例如,单独的VBO或非交错),您可以将其更改为仅更新纹理部分,在上面的示例中,每个sprite只有16
字节,这可能会降低带宽。
- 您不必浪费时间计算下一帧的位置。但是,这通常只是一些添加,很少处理纹理的边缘。我怀疑你会在这里获得很多CPU的能力。
最后,您还可以将动画图像简单地分割为很多纹理。我完全不知道这是如何缩放的,但在这种情况下,您甚至不必使用更复杂的顶点属性,只需为每个动画帧激活另一个纹理。
编辑:另一种方法可以是在统一中传递帧号并在采样之前在片段着色器中进行计算。设置一个整数统一应该是那么多开销。
预计算=更多的内存使用量和更大的缓冲区。它不好或不好,它只是*不同*。分析您的应用,看看是否值得花时间在这里投资更高的性能。只有你知道速度/记忆权衡是否适合你。 – Tim 2012-08-13 17:41:47
为什么你甚至需要用这种技术来更新任何东西?您只需为['glDrawElements'](http://www.opengl.org/wiki/GLAPI/glDrawElements)提供不同的起始索引或使用['BaseVertex'](http://www.opengl.org/wiki/GLAPI/glDrawElementsBaseVertex)变体。 – KillianDS 2012-08-13 19:07:27
是的,没错。 – Aristarhys 2012-08-13 19:45:45