2012-03-12 2 views
15

균일 한 4x4 행렬을 바인딩하려는 불운이 있습니다. 이 프로그램으로 OpenGL 3.3을 대상으로하고 있지만 OpenGL 4.2 환경입니다. 내 정점 쉐이더에서 단위 행렬을 유니폼에 단순히 바인딩하는 함수가 있지만 glUniformMatrix4fv에 대한 호출이 GL_INVALID_OPERATION으로 실패합니다.glUniformMatrix4fv가 GL_INVALID_OPERATION의 오류 코드와 함께 실패합니다.

여기 내 버텍스 쉐이더입니다 :

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

내가 매트릭스 전위 왼쪽/오른쪽 곱셈의 함정 알고 있어요,하지만 난 그게 내가 실제로 균일 한 매트릭스를 통과 할 때의 전투의 그림.

여기는 문제가있는 기능에서 참조되는 간단한 함수입니다. 나는 오류가 발생한 곳을 찾아 내려고 고정하기 위해서만 이것을 사용하고있다.

: glUniformMatrix4fv의 평가는 모든 서버 측에 있기 때문에, 나는 등

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

SDK docs는 glMatrixUniform4fv가 GL_INVALID_OPERATION을 설정할 수있는 몇 가지 이유가 있다고 중단 점을 사용하는 방법을 가지고 있지 않습니다

  1. 현재 프로그램 개체가 없으면 GL_INVALID_OPERATION이 생성됩니다.
  2. GL_INVALID_OPERATION은 셰이더에서 선언 된 균일 변수의 크기가 glUniform 명령에서 지정한 크기와 일치하지 않으면 생성됩니다.
  3. GL_INVALID_OPERATION은이 함수의 정수 변형 중 하나가 float, vec2, vec3, vec4 또는 이들의 배열의 균일 변수를로드하는 데 사용되거나이 함수의 부동 소수점 변형 중 하나 ivec2, ivec3 또는 ivec4 유형의 균일 변수 또는 이들의 배열을로드하는 데 사용됩니다.
  4. GL_INVALID_OPERATION은 location이 현재 프로그램 객체의 유효하지 않은 균일 한 위치이고 location이 -1과 같지 않은 경우에 생성됩니다.
  5. count가 1보다 크고 표시된 균일 변수가 배열 변수가 아니면 GL_INVALID_OPERATION이 생성됩니다.
  6. GLUINiform1i 및 glUniform1iv 이외의 명령을 사용하여 샘플러를로드하면 GL_INVALID_OPERATION이 생성됩니다.
  7. GL_INVALID_OPERATION은 glBegin 실행과 glEnd 실행 사이에 glUniform이 실행되면 생성됩니다.

이 함수가 호출되는 객체에는 현재 활성화 된 GLSL 프로그램의 번호를 저장하는 active_program이라는 매개 변수가 있습니다. identity_matrix과 같이 선언 :

float identity_matrix[16]; 

다음과 같이 정의 : 속히없이

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

, 여기 나에게 문제를주고 무엇을 모든 그 후

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

을, 여기에 출력입니다 :

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

Type 8b5c는 물론 GL_FLOAT_MAT4이고 크기는 1입니다. 그래서 어떤 잘못된 작동 조건이 나를 물어 뜯는 지 알 수 없습니다!

편집 :

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)이와 업데이트 전달 INT의 유효성을 검사 단지 래퍼입니다 :

여기 UseProgram이 함수가 호출되는 주에있는 루프의 객체의 active_program 매개 변수

편집 2 :뿐만 아니라 GL 오류를 감지 gDEBugger를, 나를 가리키는위한 luke 감사를드립니다. gDEBugger의 호출 정보에서 필자는 세 가지 인수 만 나열되었음을 지적했습니다. 이것은 4 번째가 배열에 대한 포인터 였기 때문에 (클라이언트 측에 존재합니까, 아니면 glUniform가 호출 될 때마다 서버 측에 전달됩니까?), 다른 생각이 들었습니다. 원인.

선언 :

PFNGLUNIFORMMATRIX4FV glUniformMatrix4fv; 

할당은 :

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

이것은 경우

는 glUniformMatrix4fv은 물론과 같이 자신의 어드레스를 취득 실제로 함수 포인터, 시험하는이야 나는 학구적 이유로 GLEW를 피했다. 그러나 glext.h을보고있을 때 PFNGLUNIFORMMATRIX4FVARBPROC인데,이 기능이 코어에 적용되기 전에 작성된 코드베이스에 대한 것입니다. 그렇지 않은 경우 알려 주시기 바랍니다.

+0

나는이 질문이 4000+ 리뷰에 국한되어 있지 않다고 생각합니다. –

답변

8

glXGetProcAddress 전화에서보세요 : 당신은 glUniform4fv 대신 glUniformMatrix4fv을 요청하는

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

!

학술적 이유로 확장 래퍼 라이브러리를 사용하지 않는다고 알고 있는데, 여전히 권장합니다.

+1

도움을 주셔서 대단히 감사합니다. 문제가 오타 (ahem)가되는 경우에도 gDEBugger와 glsldevil에 대해 아는 데 감사드립니다! 나는 어려운 일을하고 싶었고, 이제 모든 책, 블로그 포스트, 튜토리얼 등이 왜 그렇게 말하지 않는지 알 수 있습니다. –

+1

내 기쁨. 나는이 물건들과 무수히 많은 시간을 보냈고, 나는 여분의 한 쌍의 눈이 얼마나 도움이되는지 안다. – luke

+0

빠른 업데이트 : 매우 유용한 그래픽 디버거 인 새로운 도구 인 renderdoc (https://github.com/baldurk/renderdoc)이 있습니다. – luke

관련 문제