2

我只是看着我的动画精灵代码,并得到一些想法。
动画是通过改变 tex 坐标制作的。它有缓冲区对象,它保存当前帧纹理坐标,当新帧请求时,新的纹理坐标由glBufferData()输入缓冲区。

如果我们预先计算所有动画帧的纹理坐标,将它们放在 BO 中并创建只有一些帧的索引缓冲区对象,我们需要绘制

 GLbyte cur_frames = 0; //1,2,3 etc

现在,当我们需要更新动画时,我们只需要使用 glBufferData 更新 IBO 帧的 1 个字节(而不是 4 / quad vertex count / * 2 / s, t / * sizeof(GLfloat) bytes 用于使用 TRIANGLE_STRIP 进行四边形绘制) ,我们不需要在我们的 BO 初始化后保存任何纹理坐标。

我错过了什么?什么是反派?

编辑:当然,例如,您的顶点数据可能不是 gl_float 。

4

2 回答 2

1

正如 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,32,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。这似乎并不算太​​糟糕,但请注意它的缩放速度非常快,每一帧都会增加大小,而且还会增加每个属性(因为它们必须重复)。

那么,它能给你带来什么?

  1. 您不必动态地将数据发送到 GPU。请注意,更新整个 VBO 需要发送80字节或640位。假设您需要以每秒帧数对1000每帧精灵执行此操作30,您将达到19200000bps 或19.2Mbps(不包括开销)。这是相当低的(例如 16xPCI-e 可以处理32Gbps),但如果您有其他带宽问题(例如由于纹理),它可能是值得的。此外,如果您仔细构建您的 VBO(例如,单独的 VBO 或非交错的),您可以将其减少为仅更新纹理部分,16在上面的示例中每个精灵只有一个字节,这可能会进一步减少带宽。
  2. 您不必浪费时间计算下一帧位置。然而,这通常只是一些添加,很少有处理纹理边缘的方法。我怀疑你会在这里获得很多 CPU 能力。

最后,您还可以将动画图像简单地分割成许多纹理。我完全不知道它是如何缩放的,但在这种情况下,您甚至不必使用更复杂的顶点属性,您只需为每一帧动画激活另一个纹理。

编辑:另一种方法可能是在采样之前以统一的方式传递帧号并在片段着色器中进行计算。设置一个整数统一应该是一个很大的开销。

于 2012-08-13T22:59:35.117 回答
1

对于现代 GPU,访问/解包单个字节不一定比访问整数类型甚至向量(寄存器大小和加载指令等)更快。您可以只节省内存,从而节省内存带宽,但我不希望这与所有其他顶点属性数组访问有很大不同。

我认为,为动画精灵提供帧索引的最快方法是统一,或者如果必须使用一次绘制调用渲染多个精灵,则使用实例化顶点属性数组。使用后者,您可以为固定大小的顶点子序列提供单个索引。例如,在绘制“sprite-quads”时,您将每 4 个顶点获取一帧索引。当使用实例渲染时,第三种方法是缓冲区纹理。

我建议为时间/帧索引计算使用全局(共享)统一,这样您就可以在着色器中动态计算动画索引,这不需要您更新索引缓冲区(然后它只表示之间的相对动画状态精灵)

于 2012-08-13T23:06:03.483 回答