2012-03-12 13 views
15

Sto avendo un po 'di sfortuna cercando di associare una matrice 4x4 uniforme. Sto prendendo di mira OpenGL 3.3 con questo programma, ma il mio ambiente è OpenGL 4.2. Ho una funzione che lega semplicemente una matrice di identità a una uniforme nel mio vertex shader, ma la chiamata a glUniformMatrix4fv fallisce con GL_INVALID_OPERATION.glUniformMatrix4fv non riesce con un codice di errore di GL_INVALID_OPERATION

Ecco il mio vertex shader:

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

Sono consapevole delle insidie ​​di matrice trasposizione e moltiplicando destra/sinistra, ma immagino che sia una battaglia per quando posso davvero passare una matrice uniforme.

Ecco una semplice funzione a cui si fa riferimento nella funzione in cui si verificano problemi. Sto solo usando questo per ora per cercare di individuare il punto in cui si verifica l'errore. Dal momento che la valutazione di glUniformMatrix4fv è tutto sul lato server, non ho un modo per utilizzare i punti di interruzione, ecc

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); 
    } 
} 

Il SDK docs dire che ci sono alcune ragioni per cui glMatrixUniform4fv potrebbe impostare GL_INVALID_OPERATION:

  1. GL_INVALID_OPERATION viene generato se non esiste un oggetto programma corrente.
  2. GL_INVALID_OPERATION viene generato se la dimensione della variabile uniforme dichiarata nello shader non corrisponde alla dimensione indicata dal comando glUniform.
  3. GL_INVALID_OPERATION viene generato se una delle varianti intere di questa funzione viene utilizzata per caricare una variabile uniforme di tipo float, vec2, vec3, vec4 o una matrice di questi, o se una delle varianti a virgola mobile di questa funzione è usato per caricare una variabile uniforme di tipo int, ivec2, ivec3 o ivec4, o una matrice di questi.
  4. GL_INVALID_OPERATION viene generato se la posizione è un percorso uniforme non valido per l'oggetto programma corrente e la posizione non è uguale a -1.
  5. GL_INVALID_OPERATION viene generato se il conteggio è maggiore di 1 e la variabile uniforme indicata non è una variabile di matrice.
  6. GL_INVALID_OPERATION viene generato se un campionatore viene caricato utilizzando un comando diverso da glUniform1i e glUniform1iv.
  7. GL_INVALID_OPERATION viene generato se glUniform viene eseguito tra l'esecuzione di glBegin e l'esecuzione corrispondente di glEnd.

Per il contesto, l'oggetto da cui viene chiamata questa funzione ha un parametro denominato programma_programma che memorizza il numero del programma GLSL attualmente attivato. identity_matrix è dichiarato come:

float identity_matrix[16]; 

e definito come:

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 
}; 

Senza ulteriori indugi, ecco quello che mi sta dando problemi:

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"); 
} 

Dopo tutto questo, ecco l'output:

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

Il tipo 8b5c è GL_FLOAT_MAT4, ovviamente, e la dimensione è 1, ovviamente, quindi non riesco a vedere quale delle condizioni operative non valide mi sta mordendo!

Edit:

Ecco il ciclo in principale dove UseProgram e questa funzione sono chiamati:

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) è solo un wrapper che verifica la validità del int passato in e aggiornamenti il parametro active_program dell'oggetto.

Edit 2: I miei ringraziamenti a luke per me indicando gDEBugger, che ha rilevato l'errore GL pure. Nelle informazioni sulla chiamata in gDEBugger, ho notato che erano elencati solo tre argomenti. Presumo che questo potrebbe essere dovuto al fatto che il quarto era un puntatore a un array (che risiede sul lato client, o è passato al lato server ogni volta che glUniform viene chiamato?), Mi ha fatto pensare a cos'altro potrebbe essere il causa.

Nel caso è probatorio, glUniformMatrix4fv è, naturalmente, in realtà un puntatore alla funzione che ottiene l'indirizzo in questo modo:

Dichiarazione:

PFNGLUNIFORMMATRIX4FV glUniformMatrix4fv; 

Assignment:

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

Questo è evito GLEW per ragioni accademiche. Tuttavia, quando stavo guardando attraverso glext.h, ho notato che c'era anche a PFNGLUNIFORMMATRIX4FVARBPROC, che presumo sia proprio lì per le basi di codice scritte prima che questa funzione venisse adottata nel core. Se questo non è il caso, per favore fatemelo sapere.

+0

Penso che questa domanda non sia così localizzata con oltre 4000 recensioni. –

risposta

8

Date un'occhiata al vostro glXGetProcAddress chiamata:

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

Stai chiedendo glUniform4fv invece di glUniformMatrix4fv!

So che hai detto che non stai utilizzando le librerie di estensione wrapper per ragioni accademiche, ma le consiglio comunque vivamente.

+1

Grazie mille per il vostro aiuto. Anche se il problema ha finito per essere (ehm) un errore di battitura, ho apprezzato la conoscenza di gDEBugger e glsldevil! Volevo fare le cose nel modo più duro, e ora capisco perché ogni libro, post di blog, tutorial, ecc. Dice di no. –

+1

Il mio piacere. Ho lottato con questa roba innumerevoli volte, e so quanto sia utile un paio di occhi in più. – luke

+0

Solo un rapido aggiornamento: c'è un nuovo strumento di renderdoc, https://github.com/baldurk/renderdoc che è un debugger di grafica estremamente utile. – luke

Problemi correlati