我真的需要多少个着色器程序?

时间:2014-11-24 15:50:45

标签: opengl glsl shader

让我说我有一个着色器设置为使用3个纹理,并且我需要渲染一些需要所有相同着色器属性的多边形,除了它只需要1个纹理。我已经注意到在我自己的显卡上我可以简单地调用glDisableVertexAttrib()来禁用其他两个纹理,这样做显然会导致片段着色器接收的禁用纹理数据全白(1.0f)。换句话说,如果我有片段着色器指令(伪代码)......

final_red = tex0.red * tex1.red * tex2.red

...无论我是否启用了1,2或3个纹理,操作都会产生所需的最终值。由此提出了许多问题:

  1. 禁用这样的预期纹理是否合法,或者我的特定显卡是否具有明显的数学保障是巧合?

  2. "最佳实践"创建一个单独的着色器程序,只需要一个纹理来进行单个纹理渲染?

  3. 如果任何一种方法都有效,创建第二个着色器程序是否有好处?我认为制作2次glDisableVertexAttrib()调用比制作glUseProgram()+ 5-6 glGetUniform()调用花费更少的时间,但可能会发出#4地址问题。

  4. 当使用glUseProgram()更改活动着色器程序时,我是否需要每次都调用glGetUniform ...函数来重新建立程序中每个制服的位置,或者是每个预期的位置一致,直到着色器程序被解除分配?

1 个答案:

答案 0 :(得分:2)

禁用顶点属性不会真正禁用纹理,它只会为您提供未定义的纹理坐标。 可能 会产生类似于禁用某个纹理的效果,但为了正确执行此操作,您应该使用统一或可能的子程序(如果您有相同着色器的数十种变体) )。

就禁用顶点数组状态所花费的时间而言,这可能比更改统一值更慢。设置统一值并不会真正影响渲染管道状态,它们只是对内存的微小更改。同样,不断交换当前的GLSL程序会使着色器缓存失效,因此这比设置统一值要贵得多。

如果您使用的是现代GL实现(GL 4.1+或实现GL_ARB_separate_shader_objects的实现),您甚至可以设置统一值而无需绑定GLSL程序,只需调用glProgramUniform* (...)

我最关心的事实是,每次设置制服的值时,您认为需要调用glGetUniformLocation (...)。 GLSL程序中制服的位置改变的唯一时间是链接它。假设您不经常重新链接您的GLSL程序,您只需要查询这些位置一次并持久存储它们。