使用IBO动画 - 好还是坏?

时间:2012-08-13 17:29:05

标签: opengl opengl-es

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

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

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

现在我们需要更新动画,我们所需要的只是更新1个字节(而不是4 / 四个顶点数 / * 2 / s,t / *用于使用glBufferData的IBO的TRIANGLE_STRIP框架进行四边形绘制的sizeof(GLfloat)字节,我们不需要在BO初始化之后保持任何纹理坐标。

我错过了什么?什么是对比?

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

2 个答案:

答案 0 :(得分:1)

正如Tim所说,这取决于你的应用程序,让我们谈谈一些数字,你提到IBO的将所有帧的纹理坐标插入到一个VBO中,所以让我们来看看每个人的影响。

假设一个典型的顶点如下所示:

struct vertex
{
    float x,y,z; //position
    float tx,ty; //Texture coordinates
}

我添加了一个z组件,但如果你不使用它,或者你有更多的属性,计算是相似的。所以很明显这个属性需要20个字节。

让我们假设一个简单的精灵:四边形,由2个三角形组成。在一个非常天真的模式中,您只需发送2x3顶点并将6*20=120个字节发送到GPU。

Triangulated quad

在索引编制中,您知道实际上只有四个顶点: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个字节或大约23%。此外,当渲染GPU可能only process each vertex once in the vertex shader时,它也为我们节省了一些处理能力。

所以,现在你想一次为所有动画添加所有纹理坐标。首先要注意的是,索引渲染中的顶点是由其所有属性定义的,您不能将其拆分为位置索引和纹理坐标索引。因此,如果要添加额外的纹理坐标,则必须重复这些位置。因此,您添加的每个“帧”将向VBO添加80个字节,向IBO添加12个字节。假设您有64个帧,最后得到64*(80+12)=5888个字节。假设你有1000个精灵,那么这将变成大约6MB。这似乎并不太糟糕,但请注意它的扩展速度非常快,每个帧都会增加大小,但也会增加每个属性(因为它们必须重复)。

那么,它有什么收获?

  1. 您不必动态地将数据发送到GPU。请注意,更新整个VBO需要发送80个字节或640位。假设您需要以每秒1000帧的速度每帧30精灵执行此操作,您将获得19200000个bps或19.2Mbps(不包括任何开销)。这是非常低的(例如16xPCI-e可以处理32Gbps),但如果你有其他带宽问题(例如由于纹理),它可能是值得的。此外,如果您仔细构建VBO(例如单独的VBO或非交错),您可以将其简化为仅更新纹理部分,在上面的示例中每个sprite只有16个字节,这可能会减少带宽更。
  2. 您不必浪费时间计算下一帧位置。但是,这通常只是一些补充,如果要处理纹理的边缘,则很少。我怀疑你在这里会获得多少CPU能力。
  3. 最后,您还可以简单地将动画图像分割为很多纹理。我完全不知道它如何缩放,但在这种情况下你甚至不必使用更复杂的顶点属性,你只需为每一帧动画激活另一个纹理。

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

答案 1 :(得分:1)

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

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

我推荐用于时间/帧索引计算的全局(共享)统一,因此您可以在着色器中动态计算动画索引,这不需要您更新索引缓冲区(然后只表示相对精灵中的动画状态)