【问题标题】:glGetUniformLocation returns -1 for samplers other than first?glGetUniformLocation 为除第一个以外的采样器返回-1?
【发布时间】:2020-06-14 14:49:31
【问题描述】:

我一直在用 OpenGL 开发一些应用程序。 在第一遍中,我将一些值写入我的 FBO,它附有 3 个颜色纹理。在第二遍中,我将这 3 个纹理附加为着色器中的采样器,并对颜色进行一些计算。以下是第二遍的着色器代码。

const char* final_fragment_source[] = {
    "uniform sampler2D rt1;\n"
    "uniform sampler2D rt2;\n"
    "uniform sampler2D rt3;\n"
    "out vec4 color;\n"
    "void main(){\n"
    "vec3 bg = vec3(0.0, 0.0, 0.0);\n"
    "vec4 RGB1 = texture2D(rt1,vec2(gl_FragCoord.xy));\n"
    "vec4 RGB2 = texture2D(rt2,vec2(gl_FragCoord.xy));\n"
    "vec4 RGB3 = texture2D(rt3,vec2(gl_FragCoord.xy));\n"
    "vec3 tempcolor = RGB1.rgb -  bg * RGB1.a + bg * RGB3.a + bg * RGB2.rgb * RGB3.a + RGB3.rgb * RGB2.a * 0.0f + bg;\n"
    "color = vec4(tempcolor,0.25);\n"
    "} \n"
};

问题是当我为 rt2 和 rt3 调用 glGetUniformLocation() 时,我得到 -1。我得到了 rt1 的正确位置。

这个我试过了

-- 我知道,如果您不使用在片段着色器中声明的任何统一变量,那么驱动程序可能会优化并为该变量返回 -1。很明显,我在计算最终颜色时使用了所有变量。

--此着色器代码中没有编译时间或链接错误。

以下是我得到错误的代码

glUseProgram(fp_render_prog);
err = glGetError();

rt1 = glGetUniformLocation(fp_render_prog, "rt1");
err = glGetError();

rt2 = glGetUniformLocation(fp_render_prog, "rt2");
err = glGetError();

rt3 = glGetUniformLocation(fp_render_prog, "rt3");
err = glGetError();

MVPLocation = glGetUniformLocation(render_prog, "MVP");
err = glGetError();``

--我试过放glGetError(),没有报错。

提前感谢您的帮助。

【问题讨论】:

  • 感谢您的评论我刚刚发现了问题,我在着色器中使用 bg 作为常量,并在最终乘法中使用它,所以很多项都变为零,导致驱动程序优化,只留下 RGB1 作为有效值。这与 rt1 ans 相关联,因此它只有活动制服。如果我将 bg 作为统一传递,问题就解决了。感谢您的评论。

标签: c++ graphics opengl-es glsl opengl-es-2.0


【解决方案1】:

glGetUniformLocation(fp_render_prog, "rt2")glGetUniformLocation(fp_render_prog, "rt3") 返回 -1,因为 rt2rt3 未激活。

注意,glGetUniformLocation 的第二个参数必须是 active 统一变量的名称:

rt2rt3在设置RGB2RGB3时使用:

vec4 RGB2 = texture2D(rt2,vec2(gl_FragCoord.xy));
vec4 RGB3 = texture2D(rt3,vec2(gl_FragCoord.xy));

RGB2RGB3 乘以 0.0:

vec3 bg = vec3(0.0, 0.0, 0.0);
vec3 tempcolor = 
    RGB1.rgb - 
    bg * RGB1.a +
    bg * RGB3.a +
    bg * RGB2.rgb * RGB3.a +
    RGB3.rgb * RGB2.a * 0.0f +
    bg;

编译器可能会优化:

vec3 tempcolor = 
    RGB1.rgb - 
    vec3(0.0) * RGB1.a +
    vec3(0.0) * RGB3.a +
    vec3(0.0) * RGB2.rgb * RGB3.a +
    RGB3.rgb * RGB2.a * 0.0f +
    vec3(0.0);

final 中的相同:

vec3 tempcolor = RGB1.rgb;

这导致rt2rt3 没有在可执行代码中使用,并且统一变量rt2rt3 处于不活动状态


请参阅 [OpenGL ES 2 规范 - 2.10.4 着色器变量 - p。 35] (https://www.khronos.org/registry/OpenGL/specs/es/2.0/es_full_spec_2.0.pdf):

如果编译器和链接器确定在执行可执行代码时将实际访问该统一,则该统一被认为是活动的。如果编译器和链接器无法做出决定性的决定,统一将被视为有效。

.....

要在程序对象中查找活动统一变量的位置,请使用命令

int GetUniformLocation( uint program, const char *name );


OpenGL ES 2.0 Online Manual Pages. - glGetActiveUniform:

如果在链接操作期间确定可以在程序执行期间访问统一变量(内置的或用户定义的),则认为它是活动的。

【讨论】:

    【解决方案2】:

    -1 的位置值不是错误条件,它只是意味着不需要给定的制服。这可能有多种原因,包括:

    • 着色器中从未存在统一值。
    • 已声明统一值,但从未在着色器中使用。
    • 在着色器/程序中声明和使用统一值,但由编译器优化,因为编译器可以证明不需要该值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多