我有很多精灵要渲染,并希望得到那些推动这方面表现的人的反馈。
所以我按着色器和纹理排序。并且在VBO中具有相同渲染设置的批量精灵以发送到着色器进行渲染。所有正常的东西。我的精灵都是方形的并且都具有相同的基本数据:中心位置(P),方向(O),比例(S),rgb颜色(Col)和全局不透明度(Alpha)。我必须更新CPU代码中的位置和方向,(虽然大约50%的精灵不会在任何给定的帧对之间发生变化)并且缩放,颜色和不透明度几乎从不改变精灵,但实际上从来没有变化。
我不能假设几何着色器(我会支持它们,但在这种情况下问题没有实际意义)。
我应该:
当我更新精灵位置时,计算CPU上的顶点位置。使顶点着色器成为一个简单的变换步骤。 (更新每帧的数据量明显减少的优点,但CPU必须做很多触发)。
将POS数据作为附加数据放入VBO中,复制4个顶点,然后将vert位置设置为简单的偏移量(-1,-1; -1,1; 1,1; 1, -1)并在着色器中执行trig(有利于GPU进行更多计算,但每个顶点有5个额外的数据字)。
哪个更好是不明显的,所以这两种方法都需要进行分析才能看到会发生什么。
显然我可以做3,但我认为问这个问题是否有用,看看我是否只是缺乏关于应该更快的格式。无论哪种方式,答案都可以帮助其他严重的精灵/粒子实施者。
答案 0 :(得分:3)
所以我做了(3)和描述。并且,正如克朗米所说,选项2令人信服地获胜。
表现最佳的结构是两个维也纳国际中心:
vec2 float pos
,float orientation
,float scale
(16字节/顶点)vec2 float tex
,vec4 ubyte color
,uint flags
(16字节/顶点)当标志编码精灵的角落时,我们右边有0x00000001,底部有0x00000002。这允许代码更新精灵位置以遍历第一个VBO并一次设置四个值,而不需要任何触发或其他逻辑。所有数学都在顶点着色器中进行。
在我的测试中,如果位置更新的数量与纹理/颜色更新的数量差别不大,则将两个VBO合并为一个会更好。我假设这是因为那时顶点是32字节对齐的。但是在我的应用程序中(我假设大多数人都是这样),位置会更新大多数帧,但其他的东西永远不会,并且有一个较小的缓冲区来推送到显卡似乎获胜。
答案 1 :(得分:2)
根据我对大量粒子的经验,我会使用选项(2.)。也许你可以将偏移量/方向的索引打包到你的数据中(例如,如果到目前为止你没有使用它,你的位置向量的w分量)? 0 =( - 1,-1); 1 =( - 1,1); 2 =(1,1); 3 =(1,-1)。
(正如Ian所建议的那样,我只是将我的评论复制到答案中!)
@Ian:如果我理解你,你说你有一个全局不透明度/ alpha,所以你应该可以使用uniform
并使用{{1}的w分量} vec4 color
。但是,我怀疑这会有什么不同......
顺便说一下,你提到的几何着色器解决方案不仅要更优雅,而且要快一点。
答案 2 :(得分: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*n
texcoords作为n
精灵状态,可通过标志定义对于简单的精灵,此设置每个顶点仅使用16B。