2012-03-12 8 views
15

Estoy teniendo un poco de mala suerte tratando de unir una matriz 4x4 uniforme. Me estoy orientando a OpenGL 3.3 con este programa, pero mi entorno es OpenGL 4.2. Tengo una función que simplemente une una matriz de identidad a un uniforme en mi sombreador de vértices, pero la llamada a glUniformMatrix4fv falla con GL_INVALID_OPERATION.glUniformMatrix4fv falla con un código de error de GL_INVALID_OPERATION

Aquí es mi sombreado de vértices:

#version 330 
in vec4 in_vertex; 
uniform mat4 mvMatrix; 
void main(void) { 
    gl_Position = mvMatrix * in_vertex; 
} 

Soy consciente de las dificultades de la transposición de la matriz y la multiplicación izquierda/derecha, pero calculo que es una batalla para cuando realmente puedo pasar una matriz uniforme.

Aquí hay una función simple a la que se hace referencia en la función donde estoy teniendo problemas. Solo estoy usando esto por ahora para intentar localizar el lugar donde ocurre el error. Dado que la evaluación de glUniformMatrix4fv es todo en el lado del servidor, no tengo una manera de utilizar los puntos de interrupción, etc.

inline void die_on_gl_error(const char* location) { 
    GLenum error = GL_NO_ERROR; 
    error = glGetError(); 
    if (GL_NO_ERROR != error) { 
     printf("GL Error %x encountered in %s.\n", error, location); 
     exit(1); 
    } 
} 

El SDK docs decir que hay algunas razones por las glMatrixUniform4fv podría establecidos GL_INVALID_OPERATION:

  1. GL_INVALID_OPERATION se genera si no hay un objeto de programa actual.
  2. GL_INVALID_OPERATION se genera si el tamaño de la variable uniforme declarada en el sombreado no coincide con el tamaño indicado por el comando glUniform.
  3. GL_INVALID_OPERATION se genera si una de las variantes enteras de esta función se utiliza para cargar una variable uniforme de tipo float, vec2, vec3, vec4 o una matriz de estas, o si una de las variantes de coma flotante de esta función se usa para cargar una variable uniforme de tipo int, ivec2, ivec3 o ivec4, o una matriz de estos.
  4. GL_INVALID_OPERATION se genera si la ubicación es una ubicación uniforme no válida para el objeto de programa actual y la ubicación no es igual a -1.
  5. GL_INVALID_OPERATION se genera si count es mayor que 1 y la variable uniforme indicada no es una variable de matriz.
  6. GL_INVALID_OPERATION se genera si se carga una muestra utilizando un comando distinto de glUniform1i y glUniform1iv.
  7. GL_INVALID_OPERATION se genera si glUniform se ejecuta entre la ejecución de glBegin y la ejecución correspondiente de glEnd.

Para el contexto, el objeto desde el que se llama a esta función tiene un parámetro llamado active_program que almacena el número del programa GLSL actualmente activado. identity_matrix se declara como:

float identity_matrix[16]; 

y se define como:

identity_matrix = { 
      1.0f, 0.0f, 0.0f, 0.0f, 
      0.0f, 1.0f, 0.0f, 0.0f, 
      0.0f, 0.0f, 1.0f, 0.0f, 
      0.0f, 0.0f, 0.0f, 1.0f 
}; 

Sin más preámbulos, aquí es lo que me está dando problemas:

void VSGL::load_identity_matrix() { 
// GL_INVALID_OPERATION is generated if there is no current program object. 
if (!glIsProgram(active_program)) { 
    printf("Active program is not valid.\n"); 
    exit(1); 
} 

// ... active_program is a program, but is it valid? 
GLint program_valid = 0; 
glValidateProgram(active_program); 
glGetProgramiv(active_program, GL_VALIDATE_STATUS, &program_valid); 
if (GL_TRUE != program_valid) { 
    printf("Program validation failed.\n"); 
    exit(1); 
} 
die_on_gl_error("GetProgram (Validate Status)"); 

// ... makes sure there is a program active, and the current program matches 
// the value stored in active_program. 
GLint current_program = 0; 
glGetIntegerv(GL_CURRENT_PROGRAM, &current_program); 
if (0 == current_program) { 
    printf("Error, no current program is set.\n"); 
    exit(1); 
} else if (current_program != active_program) { 
    printf("Error, current program doesn't match active_program!\n"); 
} 
die_on_gl_error("GetInteger"); 

// ... ensures the program actually has an active uniform, as the docs 
// say that uniforms can be optimized out if they don't contribute to 
// out results. 
GLint num_active_uniforms = 0; 
glGetProgramiv(active_program, GL_ACTIVE_UNIFORMS, &num_active_uniforms); 
if (0 == num_active_uniforms) { 
    printf("There are 0 uniforms active in program %d.\n", active_program); 
    exit(1); 
} else { 
    printf("There are %d uniform(s) active in program %d.\n", num_active_uniforms, active_program); 
} 
die_on_gl_error("GetProgram (Active Uniforms)"); 

// GL_INVALID_OPERATION is generated if the size of the uniform variable 
// declared in the shader does not match the size indicated by the glUniform 
// command. 

// GL_INVALID_OPERATION is generated if location is an invalid uniform location 
// for the current program object and location is not equal to -1. 

// ... gets some basic information about the active uniforms, of which there 
// should be only one, a FLOAT_MAT4 of size 1. 
const GLchar *uniform_name = "mvMatrix"; 
GLint location = glGetUniformLocation(active_program, uniform_name); 
die_on_gl_error("GetUniformLocation"); 

GLchar *message; 
GLint max_uniform_length; 
glGetProgramiv(active_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_length); 
message = new GLchar[max_uniform_length]; 
GLint size; 
GLenum type; 
glGetActiveUniform(active_program, location, max_uniform_length, NULL, &size, &type, message); 
printf("Uniform %s:\tType:%x\tSize:%d\n", message, type, size); 
if (GL_FLOAT_MAT4 != type) { 
    printf("Active uniform at location is not a 4x4 float matrix.\n"); 
} 
die_on_gl_error("GetActiveUniform"); 

// GL_INVALID_OPERATION is generated if count is greater than 1 and the indicated 
// uniform variable is not an array variable. 

// GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than 
// glUniform1i and glUniform1iv. 

// GL_INVALID_OPERATION is generated if glUniform is executed between the execution 
// of glBegin and the corresponding execution of glEnd. 

// None of the above are true, and yet the following dies with GL_INVALID_OPERATION? 
glUniformMatrix4fv(location, 1, false, identity_matrix); 
die_on_gl_error("UniformMatrix4f"); 
} 

Después de todo esto, aquí está la salida:

There are 1 uniform(s) active in program 3. 
Uniform mvMatrix: Type:8b5c Size:1 
GL Error 502 encountered in UniformMatrix4f. 

Tipo 8b5c es GL_FLOAT_MAT4, por supuesto, y el tamaño es 1, por supuesto, ¡así que no puedo ver cuál de las condiciones de operación no válida me está mordiendo!

Editar:

Aquí está el bucle en el principal, donde se llaman UseProgram y esta función:

while (wm->update()) { 
     wm->poll_input(); 
     handle_input(viewingmatrix); 
     if (!gl->use_program(program)) 
      exit(-1); 
     gl->load_identity_matrix(); 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
     glDrawArrays(GL_TRIANGLES, 0, bananaNumVerts); 
     glFlush(); 
     usleep(16667); 
    } 

gl->use_program(program) es sólo un envoltorio que comprueba la validez de la int pasado y actualizaciones el parámetro active_program del objeto.

Edición 2: Mi agradecimiento a luke para mí que apunta a gDEBugger, que detectó el error GL también. En la información de la llamada en gDEBugger, noté que solo se enumeraban tres argumentos. Aunque supongo que esto podría deberse a que el cuarto era un puntero a una matriz (¿eso reside en el lado del cliente, o se pasa al lado del servidor cada vez que se llama glUniform?), Me hizo pensar en qué otra cosa podría ser la porque.

En caso de que sea probatorio, glUniformMatrix4fv es, por supuesto, en realidad un puntero de función que obtiene su dirección, así:

Declaración:

PFNGLUNIFORMMATRIX4FV glUniformMatrix4fv; 

Asignación:

glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)glXGetProcAddress((const GLubyte*)"glUniform4fv"); 

Este es evitando GLEW por razones académicas. Sin embargo, cuando estaba mirando a través de glext.h, noté que había también un PFNGLUNIFORMMATRIX4FVARBPROC, que supongo que está solo allí para las bases de código escritas antes de que esta función fuera adoptada en el núcleo. Si ese no es el caso, házmelo saber.

+0

Creo que esta pregunta no está tan localizada con más de 4000 comentarios. –

Respuesta

8

Tome un vistazo a su llamada glXGetProcAddress:

glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)glXGetProcAddress((const GLubyte*)"glUniform4fv"); 

Usted está solicitando glUniform4fv en lugar de glUniformMatrix4fv!

Sé que dijiste que no estás utilizando las bibliotecas de envoltorios de extensión por razones académicas, pero aún así las recomiendo.

+1

Muchas gracias por su ayuda. Incluso si el problema terminó siendo (ejem) un error tipográfico, ¡agradezco saber sobre gDEBugger y glsldevil! Quería hacer las cosas de la manera difícil, y ahora veo por qué cada libro, entrada de blog, tutorial, etc. dice que no. –

+1

Mi placer. He luchado con esto muchas veces, y sé lo útil que es un par de ojos extra. – luke

+0

Solo una actualización rápida: hay una nueva herramienta renderdoc, https://github.com/baldurk/renderdoc que es un depurador de gráficos extremadamente útil. – luke

Cuestiones relacionadas