GLSL:无法获取制服位置

Posted

技术标签:

【中文标题】GLSL:无法获取制服位置【英文标题】:GLSL: Can't get uniforms location 【发布时间】:2014-06-16 09:08:36 【问题描述】:

我的问题是我无法获得一些制服位置,而其他人的位置却没有问题。

例如,我穿着 VS 制服称为“MVP”和“Model”,并且“MVP”位置没有问题,但我没有对称使用的“Model”位置。 以同样的方式,我无法从 FS 中的 Light 结构中获取字段的位置。

它的代码将数据传递到着色器:

bool Shader::SetShaderParameters(mat4 MVPMatrix,mat4 Model,GLint textureUnit)

  GLuint matrixLocation = glGetUniformLocation(programID,"MVP");
  if(matrixLocation==-1)
    return false;
  glUniformMatrix4fv(matrixLocation,1,GL_FALSE,&MVPMatrix[0][0]);
  GLuint modelLocation = glGetUniformLocation(programID,"Model");
  if(modelLocation==-1)
    return false;
  glUniformMatrix4fv(modelLocation,1,GL_FALSE,&Model[0][0]);
  return true;


bool Shader::SetShaderLights(vec3 lightColor,vec3 ambientIntensity,vec3 direction,vec3 diffuseIntensity)

    GLuint lightColorLocation = glGetUniformLocation(programID,"light.lightColor");
    if(lightColorLocation==-1)
        return false;
    glUniform3fv(lightColorLocation,1,&lightColor[0]);
    GLuint ambientIntensityLocation = glGetUniformLocation(programID,"light.ambientIntensity");
    if(ambientIntensityLocation==-1)
        return false;
    glUniform3fv(ambientIntensityLocation,1,&ambientIntensity[0]);
    GLuint directionLocation = glGetUniformLocation(programID,"light.direction");
    if(directionLocation==-1)
        return false;
    glUniform3fv(directionLocation,1,&direction[0]);
    GLuint diffuseIntensityLocation = glGetUniformLocation(programID,"light.diffuseIntensity");
    if(diffuseIntensityLocation==-1)
        return false;
    glUniform3fv(diffuseIntensityLocation,1,&diffuseIntensity[0]);
    return true;

这是着色器的代码:

VS:

#version 440 core

layout(location=0) in vec3 vertexPosition;
layout(location=1) in vec2 vertexUV;
layout(location=2) in vec3 normal;

out vec2 uv;
out vec3 norm;

uniform mat4 Model;
uniform mat4 MVP;

void main()

  gl_Position = MVP*vec4(vertexPosition,1.0);
  uv = vertexUV;
  norm = (Model*vec4(normal,0.0)).xyz;

FS:

#version 440 core

struct Light

  vec3 lightColor;
  vec3 ambientIntensity;
  vec3 direction;
  vec3 diffuseIntensity;
;

in vec2 uv;
in vec3 norm;

out vec3 color;

uniform sampler2D texSamp;
uniform Light light;

void main()

  color = texture(texSamp,uv).rgb*light.ambientIntensity;

在获取制服位置时,各种行为可能会出现什么问题?也许我使用了不好的着色器版本,或者它类似于着色器中的数据优化。我正在调试我的解决方案,我很确定着色器程序 ID 是正确的。

[编辑]: 当我尝试在 FS 中使用 norm 时,没有任何变化,并且在无法获取位置的 glGetUniformLocation() 之后,我得到了零错误代码。

【问题讨论】:

您是否在调用过程中检查过 GL 错误? 尝试在片段着色器中使用norm 的值。如果Model 的值对最终结果没有贡献,则可以从着色器程序中删除它。 【参考方案1】:

允许编译器优化掉任何未使用的制服,这就是您收到此错误的原因。

您可以放心地忽略这一点。如果未找到制服,glGetUniformLocation 返回 -1。来自 OpenGL 4.3 规范,第 7.6.1 节:

如果 location 的值为 -1,Uniform* 命令将静默 忽略传入的数据,当前的统一值不会 改变了。

【讨论】:

其实是linker删除了未使用的uniform(它们是程序状态,编译器只处理shader)。它不一定是一种优化,而只是链接工作方式的结果。如果没有使用某些东西来生成程序输出,则它不会生成通过最终链接程序的代码路径,因此通常不会出现非活动制服和属性。 Seaparate Shader Objects 稍微改变了这种行为,因为每个阶段都可以是它自己的单独程序(该变量只需要在 当前 阶段中使用才能被认为是活动的)。 如果你想引用部分规范。这实际上解释了发生了什么,我建议7.6统一变量部分的第一段:“着色器可以声明命名的统一变量,如OpenGL中所述着色语言规范。如果编译器和链接器确定在执行可执行代码时将实际访问统一,则统一被认为是活动的。如果编译器和链接器无法做出决定性的决定,统一将被认为是活动的。” 那么你可以解释glGetUniformLocation (...)返回一个活动制服的位置,如果没有制服则返回-1这个名字是活跃的。但就目前而言,这个答案并不能真正解释实际发生的事情。【参考方案2】:

这是Andreas's answer的扩展。

就我而言,当我将glGetUniformLocationglUniform* 放在glUseProgram 之前时,我得到了-1;但是,当我将这两个放在glUseProgram 之后时,我可以获得正确的统一位置。

(我的版本是OpenGL 3.3, GLSL 3.30)

【讨论】:

以上是关于GLSL:无法获取制服位置的主要内容,如果未能解决你的问题,请参考以下文章

顶点着色器 -> 几何着色器,错误“获取非活动制服的位置”

c_cpp 设置GLSL制服

c_cpp 设置GLSL制服

无法获取在GLSL 1.5中工作的整数顶点属性

片段着色器不会在 OpenGL GLSL 中创建像光一样的渐变

如何使用GLSL和OpenGL ES 2.0从整数中获取一点