Cannot get uniform location

My problem is: glGetUniformLocation() always give me -1.
Althogh it fails to set the sampler, the shader program works almost correct, excepts only the first texture is working.

Thanks a lot!

This is the vertex program:

#version 130

uniform int test_var;

uniform sampler2D sp_surface;
uniform sampler2D sp_cloud;
uniform sampler2D sp_bump;

out vec3 normal_v;
out vec3 light_v;
out vec3 eye_v;

void main() {
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_FrontColor = gl_Color;
    
    vec4 vertex_p = gl_ModelViewMatrix * gl_Vertex;
    vec4 light_p  = gl_LightSource[0].position;
    
    normal_v = normalize(gl_NormalMatrix * gl_Normal);
    light_v  = normalize(gl_LightSource[0].position.xyz - vertex_p.xyz);
    eye_v    = normalize(-vertex_p.xyz);
    
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_TexCoord[1] = gl_MultiTexCoord1;
}

And the fragment program:

#version 130
uniform sampler2D sp_surface;
uniform sampler2D sp_cloud;
uniform sampler2D sp_bump;

const vec3 atm_color = vec3(1,1,1);

in vec3 normal_v;
in vec3 light_v;
in vec3 eye_v;

void main() {
    float Kd = max( dot(light_v,normal_v), 0.0 );
    vec4 diffuse = Kd * gl_FrontLightProduct[0].diffuse;
    
    vec3 half_v = normalize(light_v + eye_v);
    float Ks = pow( max(dot(half_v,normal_v),0.0), gl_FrontMaterial.shininess );
    float f = 1.0;
    if (dot(normal_v,light_v)<0) f = 0;
    vec4 specular = f * Ks * gl_FrontLightProduct[0].specular;
    
    vec4 ambient = gl_FrontLightProduct[0].ambient;

    // atmosphere effect
    float atm_alpha = length(cross(normal_v,eye_v))/length(normal_v)/length(eye_v);
    atm_alpha = pow(atm_alpha,100);

    // calculate color
    vec4 ground_color = texture(sp_surface,gl_TexCoord[0].st);
    ground_color.rgb = ground_color.rgb*(1-atm_alpha) + atm_color*atm_alpha;
    
    gl_FragColor = (ambient+diffuse) * ground_color + specular + gl_FrontMaterial.emission;
}

This is the part where uniforms are fetched and set.


    // DBG
    GLint addr_test = glGetUniformLocation(program,"test_var ");
    cout<<"test variable addr: "<<addr_test<<endl;
    
    // set texture sampler
    // assume the surface is 0, cloud is 1, bump is 2
    GLint addr_sampler_surface = glGetUniformLocation(program,"sp_surface");
    GLint addr_sampler_cloud   = glGetUniformLocation(program,"sp_cloud");
    GLint addr_sampler_bump    = glGetUniformLocation(program,"sp_bump");
    if ( (addr_sampler_surface==-1)
        || (addr_sampler_cloud==-1)
        || (addr_sampler_bump==-1) )
    {
        cerr<<"invalid uniform address:
";
        cerr<<"	surface addr: "<<addr_sampler_surface<<"
";
        cerr<<"	cloud addr: "<<addr_sampler_cloud<<"
";
        cerr<<"	bump addr: "<<addr_sampler_bump<<"
";
        //throw "";
    }
    glUniform1i(addr_sampler_surface,GL_TEXTURE0);
    glUniform1i(addr_sampler_cloud,GL_TEXTURE1);
    glUniform1i(addr_sampler_bump,GL_TEXTURE2);

The glslcompiler would strip out the unused variables hence their locations will be -1. To resolve this, you must use the variable at hand. In your case, you are not using the sp_cloud and sp_bump samplers hence their locations will be -1.

To resolve this, u must use the sampler in the shader.
Another thing, you dont have to declare a uniform in the vertex shader if that uniform is only used in the fragment shader.

1 Like

Did the shader compile correctly? Also, the trailing space in "test_var " should be removed.

In a book I read, it provides an demo that has space after that…

Thanks a lot!
So my problem would be another one, that the sampler seems not working properly. I will do some work around that.

But what Alfonse is saying is correct. Perhaps the book has a typo and adding in a space to the variable name will also give that variables location as -1 since the variable does not exist. Remove the trailing space.

From the spec:

So you should have:

glUniform1i(addr_sampler_surface, 0);
glUniform1i(addr_sampler_cloud, 1);
glUniform1i(addr_sampler_bump, 2);

So you should have:

glUniform1i(addr_sampler_surface, 0);
glUniform1i(addr_sampler_cloud, 1);
glUniform1i(addr_sampler_bump, 2);

[/QUOTE]

My multilayer texture is still not working.

First of all, I’m sure the image is loaded correctly.
And the mixture mechanism in fragment shader is working correctly, while I’ve tested it using a const vec4 as cloud color.

But when I use the sampler of the cloud (should be GL_TEXTURE1), it always give me the color on the ground (GL_TEXTURE0). Is there anything wrong on the texture object?

This is the code when I draw a planet:


    texture_ground.apply();
    texture_cloud.apply();
    texture_bump.apply();

    glCallList(obj_id);
    
    texture_ground.decline();
    texture_cloud.decline();
    texture_bump.decline();

And this is what my texture object looks like:


class SolarTexture
{
public:
    SolarTexture(GLuint layer);
    ~SolarTexture();
    
    void load_texture(FREE_IMAGE_FORMAT format, string file);
    void apply();
    void decline();
    
protected:
    GLuint layer;
    GLuint id;
};

void SolarTexture::apply() {
    if (id!=0) {
        glActiveTexture(layer);
        glEnable(GL_TEXTURE_2D);
        glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ALPHA);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR);
        glBindTexture(GL_TEXTURE_2D,id);
    }
}

THe reason why your multitexturing is not working is b/c u have multiple textures. Now u r setting the sampler uniform locations to 0,1 and 2 so u must bind the textures to the texture targets 0 1 and 2 like this if ur shader is using three samplers,


glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, firstTexID);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, secondTexID);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, thirdTexID);


glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR);

GL_LINEAR_MIPMAP_LINEAR is not a valid magnification filter. Your choices are GL_NEAREST or GL_LINEAR.

glTexParameteri affects the currently bound texture object for the active texture unit (ie. not the texture unit by itself), so you will need to bind the texture you want to modify before calling it.


glActiveTexture(GL_TEXTURE0+layer);
glBindTexture(GL_TEXTURE_2D,id);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

Because texture parameters are stored with the texture object, you don’t need to re-apply every time you bind the texture object in this way either, just once at texture initialization will do.

glEnable(GL_TEXTURE_2D) is no longer needed for shaders, since shader programs will use the texture bound to the texture unit whether you have enabled or disabled the texture unit for fixed-function. glTexEnvi is also deprecated in core OpenGL, and probably isn’t needed if you are solely using shaders.

I have binded different layers, in a different way.
In my texture class, it has a layer property and a id property. In the “apply()” method of texture class, it has things like this:


glActiveTexture(layer);
glBindTexture(GL_TEXTURE_2D,id);

So if I call "apply()"method on 3 different texture objects that has different layer, they should be activated to those layers.

So if I call "apply()"method on 3 different texture objects that has different layer, they should be activated to those layers.

Is “layer” an OpenGL enumerator, or is it an integer starting at 0? Because if it’s the latter, you need to do what Dan said and add GL_TEXTURE0 to the layer in your glActiveTexture call.

“layer” is an OpenGL enum.

This is where the texture objects were initialized:


SolarObj::SolarObj(lots_of_arguments):
    ...
    texture_ground(GL_TEXTURE0),
    texture_cloud(GL_TEXTURE1),
    texture_bump(GL_TEXTURE2),
    ...
{
    body
}

This is the constructor of SolarTexture:


SolarTexture::SolarTexture(GLuint layer):
        id(0),
        layer(layer)
{}

So you can see it should have provided correct value to glActiveTexture()

Are you correctly passing the values 0 to 2 as uniform values (layer - GL_TEXTURE0), rather than “layer” which is GL_TEXTURE0…GL_TEXTURE2.
ps. The OpenGL spec guarantees that

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.