使用webgl我需要执行3次传递来渲染我的场景。每个过程都运行相同的几何体和着色器,但对于某些制服和纹理具有不同的值。
我似乎有两个选择。拥有一个“程序”并为每次传递设置所有制服和纹理。或者有3个“程序”,每个程序包含相同的着色器,并为每个程序设置所有必要的制服/着色器,然后只为每个过程切换程序。这意味着我将为每次传递执行一次useProgram调用,而不是每次传递的 man setUniform调用。
这第二种技术可能会更快,因为它会避免很多单一调用,或者正在改变程序非常昂贵吗?我已经完成了一些试验但是由于我目前只有非常简单的几何形状,所以我看不出任何性能上的差异,因为设置成本压倒了任何差异。
有没有理由更喜欢一种技术而不是另一种?
答案 0 :(得分:2)
如果着色器程序相同,只需通过glUniform发送不同的值。
程序之间的切换通常比统一的更改值慢。 无论如何,在大多数情况下,优步着色程序(带有使用照明,使用AlphaMap等制服的列表)并不好。
@gman 我们谈论的是WebGL(GLES 2.0),我们没有UBO。 (统一缓冲对象)
@top 总结尝试避免重新绑定着色器程序(但它不是世界末日)并且不创建一个超级着色器!
答案 1 :(得分:1)
当您需要大量纹理重新绑定时,纹理图谱应该是最快的解决方案,因此您不需要重新绑定纹理,也不需要重新绑定程序。可以通过修改表示texCoord偏移的制服来切换纹理。
可以进一步优化修改这些制服:
您应该考虑将经常修改的制服移动到属性。通常,他们的数据源是使用attribPointers提供的,但是当它们被禁用时你也可以使用常量值。而不是unformXXX()使用attribXXX()函数来指定它们的常量值。
我认为最好的例子是轻松的位置。 Normaly每次灯光位置改变使用它的所有程序时,你必须为它指定统一值。相反,当使用“属性”制服时,您可以在光线移动时指定属性值一次全局。
-pros: 当你有许多想要共享制服的程序时,这种方法最适合,因为我们知道我们不能在WebGL中使用统一缓冲区,它接缝是唯一合理的解决方案。
-cons:
当然,这种“归属”制服的可用尺寸将比使用普通制服小得多,但如果你对制服的某些部分做了这件事,它仍然可以加快速度。