glGetUniformLocation always causes GL_INVALID_VALUE

Hey everyone,
I’m trying to get my openGL code to work with the Oculus Rift.
I’m using a (slightly) modified version of this code, particularly regarding the shaders.
However, the calls to glGetUniformLocation in the gl_uniform_2f/4f/1i (which I didn’t change) always cause the error 1281 (GL_INVALID_VALUE).
As far as I understand (from http://www.opengl.org/sdk/docs/man/docbook4/xhtml/glGetUniformLocation.xml), this is caused by:

GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.

But this error can not (as I see it, but I’m just a beginner) be true, since gl_fragment_shader_program is definitely the correct handle/name for my shader program (which compiled & linked correctly) and should also be accessible for the functions since it’s a member variable of my class (which contains all of this). So how could this be?

I’m using Qt 5.2.0 and the MSVC compiler, as well as an ATI Radeon HD 3400.

qDebug() << "OpenGL version supported:" << (const char*)version << "
";

returns

OpenGL version supported: 3.3.11672 Compatibility Profile Context
.
Thanks in advance, if you need any more information let me know.

You might get a much faster solution to your problem if you could post the relevant code snippets here, searching through over 1000 LOC is a little tedious :slight_smile: and you might have as well made a typo in your specific code.

So the information necessary would be: Generation of the shader, how it is stored (i.e. in which variable) and the glGetUniformLocation call.

Thanks very much so far. :slight_smile: Excuse my tediousness. :wink:
The shaders are stored in strings:

const char* gl_vertex_shader_code =
"#version 330 core
"
"
"
"layout(location = 0) in vec3 Position;
"
"layout(location = 1) in vec2 TexCoord;
"
"out vec2 oTexCoord;
"
"
"
"void main()
"
"{
"
"   gl_Position = vec4(Position, 1);
"
"   oTexCoord = TexCoord;
"
"};
";
 
const char* gl_fragment_shader_code =
"#version 330
"
"
"
"uniform vec2 LensCenter;
"
"uniform vec2 ScreenCenter;
"
"uniform vec2 Scale;
"
"uniform vec2 ScaleIn;
"
"uniform vec4 HmdWarpParam;
"
"uniform sampler2D texture0;
"
"varying vec2 oTexCoord;
"
"out vec4 outcolor;
"
"
"
"vec2 HmdWarp(vec2 in01)
"
"{
"
"   vec2  theta = (in01 - LensCenter) * ScaleIn; // Scales to [-1, 1]
"
"   float rSq = theta.x * theta.x + theta.y * theta.y;
"
"   vec2  theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + 
"
"                           HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);
"
"   return LensCenter + Scale * theta1;
"
"}
"
"void main()
"
"{
"
"   vec2 tc = HmdWarp(oTexCoord);
"
"   if (!all(equal(clamp(tc, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)), tc)))
"
"       outcolor = vec4(0);
"
"   else
"
"          outcolor = texture2D(texture0, tc);
"
"};
";

An example for the uniform functions (the other ones work just the same) is:

void MainWindow::gl_uniform_1i(const char* varname, int value)
{
    GLuint varid = glGetUniformLocation(gl_fragment_shader_program, varname); // Error is caused here
    glUniform1i(varid, value);
}

Shaders are compiled etc. in

    qDebug() <<" Compiling Vertex Shader";
    glShaderSource(VertexShaderID, 1, &gl_vertex_shader_code , NULL);
    glCompileShader(VertexShaderID);

    // Check Vertex Shader
    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if ( InfoLogLength > 0 ){
        std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
        glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
//        printf("%s", &VertexShaderErrorMessage[0]);
        qDebug() << &VertexShaderErrorMessage[0];
    }

    // Compile Fragment Shader
    qDebug() << "Compiling fragment shader";
    glShaderSource(FragmentShaderID, 1, &gl_fragment_shader_code , NULL);
    glCompileShader(FragmentShaderID);

    // Check Fragment Shader
    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if ( InfoLogLength > 0 ){
        std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
        glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
//        printf("%s", &FragmentShaderErrorMessage[0]);
        qDebug() << &FragmentShaderErrorMessage[0];
    }

    // Link the program
    qDebug() << "Linking program";
    gl_fragment_shader_program = glCreateProgram();
    glAttachShader(gl_fragment_shader_program, VertexShaderID);
    glAttachShader(gl_fragment_shader_program, FragmentShaderID);
    glLinkProgram(gl_fragment_shader_program);

    // Check the program
    glGetProgramiv(gl_fragment_shader_program, GL_LINK_STATUS, &Result);
    glGetProgramiv(gl_fragment_shader_program, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if ( InfoLogLength > 0 ){
        std::vector<char> ProgramErrorMessage(InfoLogLength+1);
        glGetProgramInfoLog(gl_fragment_shader_program, InfoLogLength, NULL, &ProgramErrorMessage[0]);
        qDebug() << &ProgramErrorMessage[0];
    }

And the qDebug() calls (like cout, I think, in case you’re not familiar) give:

Compiling Vertex Shader
Vertex shader was successfully compiled to run on hardware.

Compiling fragment shader
Fragment shader was successfully compiled to run on hardware.

Linking program
Vertex shader(s) linked, fragment shader(s) linked.

Also, the glGetUniformLocation returns a huge number (4294967295 for example), but I don’t think that’s a problem. I’m just curious why it doesn’t return -1, since it’s causing an error.

As for the last question, it has an easy answer:
You assign the function’s return value to an unsigned int, which doesn’t have a sign (duh). It isn’t returning (int)-1 but (uint)4294967295, which is internally the same as -1 :slight_smile:

What I’d need aditionally is the code where you actually call your glGetUniformLocation (the calling function of that). Keep in mind that the shader must be bound for that (glRunProgram), did you do that?

Do you mean glUseProgram()? I’m doing that. It’s basically

    glUseProgram(gl_fragment_shader_program);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, gl_frame_buffer_texture);

    gl_uniform_1i("texture0", 0); // Error occurs here

    // render left eye with distortion shader
    renderEyePatch(OVR::Util::Render::StereoEye_Left);
    // render other eye etc.

with (a part of) renderEyePatch() being

    
    // fragment shader.
    gl_uniform_2f("LensCenter", LensCenter.x, LensCenter.y); qDebug() << "Lenscenter x y:" << LensCenter.x << LensCenter.y;
    gl_uniform_2f("ScreenCenter", ScreenCenter.x, ScreenCenter.y);
    gl_uniform_2f("Scale", Scale.x, Scale.y);
    gl_uniform_2f("ScaleIn", ScaleIn.x, ScaleIn.y);
    gl_uniform_4f("HmdWarpParam", HmdWarpParam[0], HmdWarpParam[1], HmdWarpParam[2], HmdWarpParam[3]);
    gl_uniform_4f("ChromAbParam", ChromAbParam[0], ChromAbParam[1], ChromAbParam[2], ChromAbParam[3]);

    //some stuff

    glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_eye_1);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glBindBuffer(GL_ARRAY_BUFFER, m_uv_buffer_eye_1);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glDrawArrays(GL_QUADS, 0, 4);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

BTW, thanks for the hint with unsigned ints. I feel stupid now. :slight_smile:

EDIT:
So I seem to have no active shader program at the time of calling glGetUniformLocation after all. I put

    GLint id;
    glGetIntegerv(GL_CURRENT_PROGRAM,&id);
    qDebug() << "current program:" << id << " - while gl_fragment_shader_program is:" << gl_fragment_shader_program;

before the glGetUniformLocation call. It spits out

current program: 0 - while gl_fragment_shader_program is: 0

while putting


    qDebug() << "gl_fragment_shader_program is" << gl_fragment_shader_program;

behind

    gl_fragment_shader_program = glCreateProgram();

returns

gl_fragment_shader_program is 6

But why would it do that? I made the program current, didn’t I?

EDIT2:
So apparently I thought it was a good idea to initialize the shader program handle to 0 after creating the program. In my defense, I didn’t know how fast the QGLWidget calls initializeGL(). :slight_smile: Anyway, it’s solved now!