正如 Tim 正确指出的那样,这取决于您的应用程序,让我们谈谈一些数字,您提到了 IBO和将所有帧的纹理坐标插入到一个 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
大约 byte 23%
。此外,当渲染 GPU 可能只在顶点着色器中处理每个顶点一次时,它也为我们节省了一些处理能力。
所以,现在您想一次为所有动画添加所有纹理坐标。首先要注意的是,索引渲染中的顶点由它的所有属性定义,您不能将其拆分为位置索引和纹理坐标索引。所以如果你想添加额外的纹理坐标,你将不得不重复这些位置。因此,您添加的每个“帧”都会将80
字节添加到 VBO 并将12
字节添加到 IBO。假设你有 64 帧,你最终得到64*(80+12)=5888
字节。假设你有 1000 个精灵,那么这将变成 about 6MB
。这似乎并不算太糟糕,但请注意它的缩放速度非常快,每一帧都会增加大小,而且还会增加每个属性(因为它们必须重复)。
那么,它能给你带来什么?
- 您不必动态地将数据发送到 GPU。请注意,更新整个 VBO 需要发送
80
字节或640
位。假设您需要以每秒帧数对1000
每帧精灵执行此操作30
,您将达到19200000
bps 或19.2Mbps
(不包括开销)。这是相当低的(例如 16xPCI-e 可以处理32Gbps
),但如果您有其他带宽问题(例如由于纹理),它可能是值得的。此外,如果您仔细构建您的 VBO(例如,单独的 VBO 或非交错的),您可以将其减少为仅更新纹理部分,16
在上面的示例中每个精灵只有一个字节,这可能会进一步减少带宽。
- 您不必浪费时间计算下一帧位置。然而,这通常只是一些添加,很少有处理纹理边缘的方法。我怀疑你会在这里获得很多 CPU 能力。
最后,您还可以将动画图像简单地分割成许多纹理。我完全不知道它是如何缩放的,但在这种情况下,您甚至不必使用更复杂的顶点属性,您只需为每一帧动画激活另一个纹理。
编辑:另一种方法可能是在采样之前以统一的方式传递帧号并在片段着色器中进行计算。设置一个整数统一应该是一个很大的开销。