PDA

View Full Version : glGetUniformLocation always causes GL_INVALID_VALUE



LReiter
04-15-2014, 03:56 AM
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 (http://pastebin.com/2VEasjbu), 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 << "\n"; returns
OpenGL version supported: 3.3.11672 Compatibility Profile Context.
Thanks in advance, if you need any more information let me know.

Brokenmind
04-15-2014, 04:19 AM
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 :) 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.

LReiter
04-15-2014, 05:02 AM
Thanks very much so far. :) Excuse my tediousness. ;)
The shaders are stored in strings:

const char* gl_vertex_shader_code =
"#version 330 core\n"
"\n"
"layout(location = 0) in vec3 Position;\n"
"layout(location = 1) in vec2 TexCoord;\n"
"out vec2 oTexCoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = vec4(Position, 1);\n"
" oTexCoord = TexCoord;\n"
"};\n";

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

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.

Brokenmind
04-15-2014, 05:20 AM
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 :)

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?

LReiter
04-15-2014, 06:32 AM
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. :)

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(). :) Anyway, it's solved now!