opengl - 我真正需要多少个着色器程序?

标签 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... 函数来重新建立程序中每个统一的位置,或者每个预期的位置在着色器程序被释放之前保持一致?

最佳答案

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

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

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

我最关心的是你认为你需要打电话glGetUniformLocation (...)每次设置制服的值时。 GLSL 程序中统一位置唯一发生变化的时间是链接它时。假设您不经常重新链接 GLSL 程序,则只需查询这些位置一次并永久存储它们。

关于opengl - 我真正需要多少个着色器程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27108736/

相关文章:

c# - 是否可以使用着色器在两个纹理之间找到 "difference"? (XNA/HLSL)

c++ - 问题传递数组作为参数

opengl - 在顶点着色器中置换顶点

c++ - 如何将整个 C++ 过剩程序编写为可以在另一个程序中调用的函数?

c++ - 为什么 SSAO 仅在特定角度/距离下起作用?

android - 如何在 OpenGL ES 2.0 for Android 中对大纹理进行采样

optimization - GLSL-是否优化了纹理查找?

opengl - 在 OpenGL 顶点着色器中,gl_Position 不会被均匀化

c# - Unity 中的闪光效果

c++ - 为什么在使用 OpenGL 编译顶点着色器时会出现着色器编译器错误 #143、#160 和 #216?