我试图绑定一个统一的4x4矩阵运气不好.我用这个程序瞄准OpenGL 3.3,但我的环境是OpenGL 4.2.我有一个函数,它简单地将一个单位矩阵绑定到我的顶点着色器中的一个统一体,但是对glUniformMatrix4fv的调用因GL_INVALID_OPERATION而失败.
这是我的顶点着色器:
#version 330
in vec4 in_vertex;
uniform mat4 mvMatrix;
void main(void) {
gl_Position = mvMatrix * in_vertex;
}
Run Code Online (Sandbox Code Playgroud)
我知道矩阵换位和左/右乘法的缺陷,但我认为这是一场战斗,因为我可以实际传递均匀矩阵.
这是一个简单的函数,在我遇到问题的函数中引用.我现在只使用它来尝试确定发生错误的地方.由于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);
}
}
Run Code Online (Sandbox Code Playgroud)
该SDK文档说,有几个原因glMatrixUniform4fv可以设置GL_INVALID_OPERATION:
对于上下文,调用此函数的对象具有一个名为active_program的参数,用于存储当前激活的GLSL程序的编号.identity_matrix声明为:
float identity_matrix[16];
Run Code Online (Sandbox Code Playgroud)
并定义为:
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
};
Run Code Online (Sandbox Code Playgroud)
不用多说,这就是给我带来麻烦的:
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, ¤t_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");
}
Run Code Online (Sandbox Code Playgroud)
毕竟,这是输出:
There are 1 uniform(s) active in program 3.
Uniform mvMatrix: Type:8b5c Size:1
GL Error 502 encountered in UniformMatrix4f.
Run Code Online (Sandbox Code Playgroud)
类型8b5c当然是GL_FLOAT_MAT4,当然大小是1,所以我看不出哪个无效的操作条件正在咬我!
编辑:
这是main中的循环,其中调用了UseProgram和this函数:
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);
}
Run Code Online (Sandbox Code Playgroud)
gl->use_program(program) 只是一个包装器,它检查传入的int的有效性并更新对象的active_program参数.
编辑2:感谢 luke指向我的gDEBugger,它也检测到GL错误.在gDEBugger的调用信息中,我注意到只列出了三个参数.虽然我认为这可能是因为第四个是指向数组的指针(它是驻留在客户端,还是每次调用glUniform时都传递给服务器端?),它让我想到了其他可能是什么原因.
如果它是证明,glUniformMatrix4fv当然实际上是一个函数指针,它获取它的地址,如下所示:
宣言:
PFNGLUNIFORMMATRIX4FV glUniformMatrix4fv;
Run Code Online (Sandbox Code Playgroud)
分配:
glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)glXGetProcAddress((const GLubyte*)"glUniform4fv");
Run Code Online (Sandbox Code Playgroud)
这是我出于学术原因避免使用GLEW的原因.然而,当我翻阅glext.h,我注意到,有也是一个PFNGLUNIFORMMATRIX4FVARBPROC,这我相信只是有书面的代码库之前,此功能是通过与核心.如果不是这样,请告诉我.
看看你的glXGetProcAddress电话:
glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)glXGetProcAddress((const GLubyte*)"glUniform4fv");
Run Code Online (Sandbox Code Playgroud)
你请求glUniform4fv而不是glUniformMatrix4fv!
我知道你说你出于学术原因没有使用扩展包装库,但我仍然强烈推荐它们.