我有几个带有统一变量的着色器,它们在所有着色器中具有相同的名称。一次更新所有着色器中具有相同名称的制服的最佳方法是什么?我考虑以下方法:
1)只需为每个程序存储该统一的位置,并在程序被指定为“已使用”程序(glUseProgram
)后立即更新。
缺点:
所有“共享”统一变量将在每次glUseProgram
调用后更新。此外,如果在当前帧期间不首次使用某个程序,则所有glUniform*
次呼叫都将是多余的。
或者,应该有一组标志,用于判断程序是否第一次使用。应该每帧重置“未使用”标志。
2)使用统一缓冲区和shared
(甚至std140
)布局。在这种方法中,我们可以立即设置一个统一,然后更改着色器程序而不更新缓冲区。但是,如果有一堆简单的着色器,其中唯一的共享变量是变换矩阵呢?是否可以为这么少的内存使用统一缓冲区?在一些论坛讨论中,我已经阅读了
glBindBuffer(GL_UNIFORM_BUFFER,buf);
glBufferSubData(/*just 16 floats*/);
glBindBuffer(GL_UNIFORM_BUFFER,0);
比glUniform*
调用慢得多。在这里我们可以注意到,第一种和第二种方法之间的选择取决于以下条件:
是否有任何妥协设计模式,无论这三个问题的答案如何,都会有良好的表现?
3)使用ubershader。这里在第二段中提到:GLSL multiple shaderprogram VS uniforms switches。我有两个问题:
什么有更好的性能:一个glUseProgram
电话或几个统一开关,这将改变ubershader的功能?
提出该问题的作者
作为ubershader的缺点之一。但为什么不好呢?性能不好吗?如果是这样,是否可以将转换矩阵和其他一些小尺寸的东西作为统一变量传递并在每帧中更新它们?每帧必须多次更换制服
总结以上所有的主要问题:您是否可以建议在几个不同的着色器程序中更新同名统一变量的任何其他技术或设计模式?
UPD:答案被接受了,但是如果你能提出一个非常重要的高级设计技术(用C ++或语言独立的话),那就把它留在这里。
答案 0 :(得分:8)
在一些论坛讨论中,我读过[...]比glUniform * call慢得多。
那么如果是(假设有证据表明它甚至是当然的话)?您每帧仅执行一次,而glUniform
调用每个修改的程序一次。
我会使用统一块(默认情况下始终使用std140
)来获取任何共享数据。更新它们需要固定的成本,而更新其他成本的成本可变。