OpenGL中的精灵渲染架构

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,但我认为询问这个问题可能有用,以便确定哪种方法更快。无论哪种方式,答案都可以帮助其他严肃的精灵/粒子实现者。


1
根据我处理大量粒子的经验,我会选择选项(2.)。也许你可以将偏移/方向的索引打包到你的数据中(例如,作为位置向量的w分量,如果你迄今未使用它)?0 = (-1,-1);1 = (-1,1);2 = (1,1);3 = (1,-1)。 - kroneml
如果您想将其放入答案中,我会给您接受! - Ian
3个回答

3

所以我进行了(3)并进行了配置文件。正如kronemi所说,选项2赢得了胜利。

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

  1. vec2 float posfloat orientationfloat scale(每个顶点16字节)
  2. vec2 float texvec4 ubyte coloruint flags(每个顶点16字节)

其中标志编码精灵的角落,因此我们有0x00000001表示右侧,0x00000002表示底部。这使得代码可以通过第一个VBO遍历更新精灵位置,并每次设置四个值而无需任何三角函数或其他逻辑。所有数学计算都在顶点着色器中完成。

在我的测试中,如果位置更新的次数与纹理/颜色更新的次数不相差太多,则将两个VBO合并为一个会表现更好。我认为这是因为顶点是32字节对齐的。但在我的应用程序(我认为大多数人的应用程序也是如此),位置在大多数帧中都会更新,但其他事情从不更新,因此具有较小的缓冲区似乎更胜一筹。


2
从我处理大量粒子的经验来看,我会选择选项(2)。也许你可以将偏移/方向的索引打包到你的数据中(例如,作为你的位置向量的w分量,如果你迄今尚未使用它)?0 =(-1,-1); 1 =(-1,1); 2 =(1,1); 3 =(1,-1)。
如 @Ian 所建议的那样,我刚刚将我的评论复制到了回答中!
@Ian:如果我理解正确,您说您有一个全局不透明度/阿尔法,因此您应该能够为此使用一个uniform,并将您的vec4颜色的w分量用于标志。但是,我怀疑这不会有任何区别......
顺便说一下,您已经提到的几何着色器解决方案不仅更加优雅,而且速度更快。

谢谢,你得到了接受!是的,不透明度可以是均匀的。我试过了,性能有一点下降(也许是因为第二个VBO现在只有12字节对齐?不知道)。不用担心。至于几何着色器,是的,它比两个选项都要好,我首先构建了它,但我需要一个适用于几何着色器卡之前的解决方案。最终,性能足够接近,我选择了2,完全忽略了几何着色器——以速度换取只有一个代码路径,因为具有几何着色器的卡通常更快。 - Ian

1
我发现带宽改进很小。我假设每个精灵都有4个顶点(6个索引),那么你可以简单地使用gl_VertexID % 4代替flags
每个顶点属性:
- vec2 float positionfloat orientationfloat scale——精灵几何数据(16B) - uint flags——特殊精灵的可选标志(4B) - float param——平滑精灵变换的可选参数(4B)
统一变量:
- vec2 vertexPosition[4]——每个角落的相对位置——您可以使用它来指定中心 - vec2 textureCoord[4]——每个角落的纹理坐标,您还可以使用4*n纹理坐标来定义通过标志可以定义的n个精灵状态
这种设置仅使用每个简单精灵的16B。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接