4

我有很多精灵要渲染,并且想从推动该领域性能的人们那里获得任何反馈。

所以我按着色器和纹理排序。并在 VBO 中将具有相同渲染设置的多批精灵发送到着色器进行渲染。都是正常的东西。我的精灵都是正方形的,并且都具有相同的基本数据:中心位置 (P)、方向 (O)、比例 (S)、rgb 颜色 (Col) 和全局不透明度 (Alpha)。我必须更新 CPU 代码中的位置和方向(尽管大约 50% 的精灵在任何给定的帧之间都不会改变),并且比例、颜色和不透明度对于精灵来说几乎永远不会改变,但实际上并非永远不会改变。

我不能假设几何着色器(我会支持它们,但在这种情况下问题是没有实际意义的)。

我是不是该:

  1. 当我更新精灵位置时,计算 CPU 上的顶点位置。使顶点着色器成为一个简单的变换步骤。(优点是每帧更新的数据量显着减少,但 CPU 必须做很多触发)。

  2. 将 POS 数据作为附加数据放入 VBO,为 4 个顶点复制,然后将顶点位置设置为简单的偏移量 (-1,-1;-1,1;1,1;1,-1) 并执行着色器中的触发(优势是 GPU 进行更多计算,但每个顶点有 5 个额外的数据字)。

  3. 哪个更好并不明显,因此这两种方法都需要分析以查看会发生什么。

显然我可以做 3,但我认为问这个问题会很有用,看看我是否只是缺乏关于应该更快的格式塔。无论哪种方式,答案都可以在以后帮助其他认真的精灵/粒子实现者。

4

3 回答 3

3

所以我做了(3)并进行了分析。而且,正如 kronemi 所说,选项 2 令人信服地获胜。

表现最好的结构是两个 VBO:

  1. vec2 float pos, float orientation, float scale(16 字节/顶点)
  2. vec2 float tex, vec4 ubyte color, uint flags(16 字节/顶点)

其中标志编码精灵的角,所以我们有右边的 0x00000001 和底部的 0x00000002。这允许代码更新精灵位置以遍历第一个 VBO 并一次设置四个值,而无需任何触发或其他逻辑。所有的数学运算都发生在顶点着色器中。

在我的测试中,如果位置更新的数量与纹理/颜色更新的数量差别不大,那么将两个 VBO 合并为一个效果会更好。我认为这是因为顶点是 32 字节对齐的。但是在我的应用程序(我假设大多数人的应用程序)中,大多数帧都会更新位置,但其他事情从来没有,并且有一个较小的缓冲区来下推到显卡似乎会赢。

于 2012-07-17T11:55:58.783 回答
2

根据我对大量粒子的经验,我会使用选项 (2.)。也许您可以将偏移量/方向的索引打包到您的数据中(例如,作为您的位置向量的 w 分量,如果您到目前为止不使用它)?0 = (-1,-1); 1 = (-1,1); 2 = (1,1); 3 = (1,-1)。

(正如 Ian 所建议的,我只是将我的评论复制到一个答案中!)

@Ian:如果我正确理解你,你说你有一个全局不透明度/alpha,所以你应该能够使用 auniform并使用你的 w 组件vec4 colorfor flag。但是,我怀疑这会有所不同...

顺便说一句,您已经提到的几何着色器解决方案不仅应该更优雅,而且应该更快一些。

于 2012-07-18T11:49:08.237 回答
1

我发现带宽几乎没有改善。我假设你的每个精灵都有 4 个顶点(6 个索引),那么你可以简单地使用gl_VertexID % 4而不是flags.

每个顶点属性:

  • vec2 float position, float orientation, float scale- 精灵几何数据 (16B)
  • uint flags- 特殊精灵的可选标志(4B)
  • float param- 平滑精灵变换的可选参数 (4B)

制服:

  • vec2 vertexPosition[4]- 每个角的相对位置 - 你可以用它来指定中心
  • vec2 textureCoord[4]- 每个角落的纹理坐标,您还可以使用4*ntexcoordsn来定义可以通过标志定义的精灵状态

对于简单的 sprite,此设置每个顶点仅使用 16B。

于 2013-02-04T19:35:52.437 回答