在顶点和片元着色器中访问同名统一变量失败

9
我在着色器方面还很不熟练,但我正在很好地攀登学习曲线。今天早上我发现的一个问题是试图在片段着色器和顶点着色器中使用同名的uniform。

uniform可以在两个着色器中定义,但只能在某一个着色器中单独访问,而不能同时使用。如果尝试在两个着色器中都访问该着色器,则程序无法编译。

我最后想到的一个想法是它们编译为单独的符号,但我不知道如何访问它们,除了通过glGetUniformLocation。使用相同字符串调用两次会返回相同的统一位置...没有什么帮助。

着色器非常简单,除了对渲染没有影响的单行工作或不工作测试之外,一切正常。

是否有一种特殊方法来使用两个着色器中具有相同值的同名的uniform?

也许我应该在gamedev.stackexchange.com上发布这个问题? - Tom Pace
1个回答

13
解决了!根据我的经验,精度限定符通常不是必需的。我没有使用它...因为我的制服是整数。
我在这里阅读到了一个确认,即顶点着色器和片段着色器之间可以使用相同名称的制服:

http://www.gamedev.net/topic/535321-glsl-the-same-named-uniform-in-vertex-and-fragment-shaders/

我认为这是我的错误。
最后,我尝试添加 highp 精度限定符,并解决了崩溃问题。
从技术上讲:
设置 1(崩溃
Vertex shader:
uniform int frameNum;

Fragment shader:
uniform int frameNum;

安装步骤 2 (崩溃)

Vertex shader:
uniform highp int frameNum;

Fragment shader:
uniform int frameNum;

设置 3 (成功)

Vertex shader:
uniform highp int frameNum;

Fragment shader:
uniform highp int frameNum;

设置 4 (成功)

Vertex shader:
uniform int frameNum;

Fragment shader:
uniform highp int frameNum;

1
说到精度限定符...你可能会受益于知道,在GLES 2.0中,highp是片段着色器中的可选精度。它在顶点着色器中保证可以工作,但在片段着色器中,实现允许不支持它(就像顶点纹理查找是可选的一样)。ES 3.0使其成为强制性的,但在ES 2.0中,您应该在使用片段着色器中的highp之前检查是否存在GL_FRAGMENT_PRECISION_HIGH的预处理器定义。至于您不使用精度限定符的理由,整数也支持它们。 - Andon M. Coleman
由于这个原因,在片元着色器中,你必须明确指定 "float" 精度 - 它没有像片元着色器中那样默认的 "highp" 精度。 参考:http://www.khronos.org/files/opengles_shading_language.pdf,第4.5.3段。 在某些硬件上,片元着色器无需指定精度即可有效,但为了完全符合标准,您必须在片元着色器中指定 "float" 精度。 对于任何GPU,“precision mediump float;”都可以正常使用。 - keaukraine
@keaukraine,这真是个惊喜...如果没有指定,似乎浮点数会自动预定义精度。我注意到你在第一句话中两次使用了“片元着色器”。你的意思是片元着色器必须指定浮点数,而顶点着色器具有highp吗?我正在参考OpenGL ES Shading Language 1.0快速参考卡来学习/练习。 - Tom Pace
@AndonM.Coleman 我看到了GLSL 1.0快速参考卡中有关highp是可选的说明。但整数需要精度修饰符才能支持同名uniform在我的使用案例中,这让我感到惊讶和反直觉。感谢您的建议! 我将研究GL_FRAGMENT_PRECISION_HIGH。 - Tom Pace
@TomPace 对不起,我引用了片段着色器的错误 - 感谢您指出这个错误。 顶点着色器具有默认的 precision highp float,而片段着色器没有任何默认的 float 精度。 - keaukraine
1
在计算gl_PointSize时,通过统一乘法计算后未能绘制点的奇怪问题中帮助了我。在我的情况下,将“mediump”添加到统一变量中起了作用。谢谢! - Rodia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接