2012-03-12 4 views
15

Tôi đang gặp một số may mắn khi cố gắng ràng buộc ma trận 4x4 thống nhất. Tôi đang nhắm mục tiêu OpenGL 3.3 với chương trình này, nhưng môi trường của tôi là OpenGL 4.2. Tôi có một chức năng chỉ đơn giản là ràng buộc một ma trận nhận dạng để thống nhất trong shader đỉnh của tôi, nhưng các cuộc gọi đến glUniformMatrix4fv không thành công với GL_INVALID_OPERATION.glUniformMatrix4fv không thành công với mã lỗi GL_INVALID_OPERATION

Đây là vertex shader của tôi:

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

Tôi nhận thức được những cạm bẫy của ma trận chuyển vị và trái/phải nhân lên, nhưng tôi hình dung đó là một trận chiến cho khi tôi thực sự có thể vượt qua một ma trận thống nhất.

Đây là một hàm đơn giản được tham chiếu trong hàm mà tôi gặp sự cố. Tôi chỉ sử dụng tính năng này ngay bây giờ để thử và ghim xuống vị trí xảy ra lỗi. Kể từ khi đánh giá glUniformMatrix4fv là tất cả ở phía máy chủ, tôi không có một cách để sử dụng breakpoint vv

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

Các SDK docs nói rằng có một vài lý do tại sao glMatrixUniform4fv có thể thiết lập GL_INVALID_OPERATION:

  1. GL_INVALID_OPERATION được tạo nếu không có đối tượng chương trình hiện tại.
  2. GL_INVALID_OPERATION được tạo nếu kích thước của biến thống nhất được khai báo trong trình đổ bóng không khớp với kích thước được chỉ ra bởi lệnh glUniform. Nếu bạn sử dụng một trong các biến số nguyên của hàm này để tải một biến thống nhất kiểu float, vec2, vec3, vec4 hoặc một mảng trong số này hoặc nếu một trong các biến thể dấu phẩy động của hàm này được sử dụng để tải một biến thống nhất của kiểu int, ivec2, ivec3 hoặc ivec4 hoặc một mảng trong số này.
  3. GL_INVALID_OPERATION được tạo nếu vị trí là vị trí thống nhất không hợp lệ cho đối tượng chương trình hiện tại và vị trí không bằng -1.
  4. GL_INVALID_OPERATION được tạo nếu số lớn hơn 1 và biến đồng nhất được chỉ định không phải là biến mảng.
  5. GL_INVALID_OPERATION được tạo nếu một mẫu được nạp bằng lệnh khác với glUniform1i và glUniform1iv.
  6. GL_INVALID_OPERATION được tạo nếu glUniform được thực hiện giữa việc thực thi glBegin và thực thi tương ứng của glEnd.

Đối với ngữ cảnh, đối tượng mà hàm này được gọi có tham số được gọi là active_program lưu số của chương trình GLSL hiện được kích hoạt. identity_matrix được khai báo là:

float identity_matrix[16]; 

và định nghĩa là:

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

Nếu không có thêm ado, đây là những gì đem lại cho tôi rắc rối:

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

Sau tất cả những gì, đây là kết quả:

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

Loại 8b5c là GL_FLOAT_MAT4, tất nhiên, và kích thước là 1, tất nhiên, vì vậy tôi không thể thấy điều kiện hoạt động không hợp lệ nào đang cắn tôi!

Edit:

Đây là vòng lặp trong chính nơi UseProgram và chức năng này được gọi là:

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) chỉ là một wrapper để kiểm tra tính hợp lệ của int thông qua vào và cập nhật tham số active_program của đối tượng.

Sửa 2: Tôi xin cám ơn luke đã chỉ cho tôi tại gDEBugger, mà phát hiện các lỗi GL là tốt. Trong thông tin cuộc gọi trong gDEBugger, tôi lưu ý rằng chỉ có ba đối số được liệt kê. Trong khi tôi giả định điều này có thể là vì thứ tư là một con trỏ tới một mảng (nó nằm ở phía máy khách, hay nó được chuyển đến phía máy chủ mỗi khi glUniform được gọi?), Nó khiến tôi nghĩ về những gì khác có thể là nguyên nhân.

Trong trường hợp đó là để chứng minh, glUniformMatrix4fv là, tất nhiên, thực sự là một con trỏ hàm có được địa chỉ của nó như sau:

Tuyên bố:

PFNGLUNIFORMMATRIX4FV glUniformMatrix4fv; 

Bài tập:

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

Đây là tôi tránh GLEW vì lý do học tập. Tuy nhiên, khi tôi nhìn qua glext.h, tôi lưu ý rằng có cũng là một PFNGLUNIFORMMATRIX4FVARBPROC, mà tôi cho là chỉ có các mã được viết trước khi hàm này được áp dụng vào lõi. Nếu đó không phải là trường hợp, xin vui lòng cho tôi biết.

+0

Tôi nghĩ câu hỏi này không phải là soooo được bản địa hóa với hơn 4000 đánh giá. –

Trả lời

8

Hãy xem glXGetProcAddress cuộc gọi của bạn:

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

Bạn đang yêu cầu glUniform4fv thay vì glUniformMatrix4fv!

Tôi biết bạn đã nói bạn không sử dụng thư viện trình bao bọc tiện ích mở rộng vì lý do học tập, nhưng tôi vẫn khuyên bạn nên sử dụng chúng.

+1

Cảm ơn bạn rất nhiều vì sự giúp đỡ của bạn. Ngay cả khi vấn đề đã kết thúc (ahem) một lỗi đánh máy, tôi đánh giá cao việc biết về gDEBugger và glsldevil! Tôi muốn làm mọi thứ một cách khó khăn, và bây giờ tôi thấy tại sao mọi cuốn sách, bài đăng trên blog, hướng dẫn, v.v. đều không nói. –

+1

Niềm vui của tôi. Tôi đã vật lộn với công cụ này vô số lần, và tôi biết một cặp mắt bổ sung hữu ích như thế nào. – luke

+0

Chỉ cần cập nhật nhanh: có một công cụ mới renderdoc, https://github.com/baldurk/renderdoc là trình gỡ rối đồ họa cực kỳ hữu ích. – luke