glGetUniformLocation为第一个以外的采样器返回-1?

问题描述 投票:4回答:2

我一直在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()并且没有任何错误。

在此先感谢您的帮助。

c++ graphics opengl-es opengl-es-2.0
2个回答
2
投票

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

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

设置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);

最终的结果如下:

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

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


0
投票

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

  • 着色器中从未存在统一值。
  • 声明了统一值,但从未在着色器中使用。
  • 统一值在着色器/程序中声明并使用,但由编译器优化,因为编译器可以证明不需要该值。
© www.soinside.com 2019 - 2024. All rights reserved.