OpenGL投影矩阵异常:透视/正交投影下模型显示怪异求助
投影与视图矩阵异常导致3D模型显示问题
我正在使用讲师提供的LookAt()函数构建视图矩阵,Ortho()和Perspective()函数构建投影矩阵,并将这些矩阵传入着色器,通过GLUT提供的glutWireTeapot()、glutWireCube()、glutWireSphere()等线框模型进行测试。尽管我认为参数设置合理,但程序显示的模型效果怪异:透视投影始终无法正常显示,正交投影仅偶尔显示正常。我尝试过修改LookAt()、Perspective()、Ortho()的参数,以及调整着色器中矩阵乘法的顺序(如改为gl_Vertex * Mv * Proj等组合),但问题仍未解决。以下是我的代码实现及异常显示效果:
键盘回调函数
用于切换投影模式和3D模型。
void keyboard(unsigned char key, int x, int y) { // ToDo if(key == 'p') { isPerspective = true; } else if (key == 'o') { isPerspective = false; } else if(key == 'm') { currentobject = (currentobject + 1) % numObjects; } glutPostRedisplay(); }
渲染回调函数
当前正交和透视投影均显示怪异效果。
void renderScene(void) { // ToDo glUseProgram(p); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); viewMatrix = LookAt(vec4(0, 0, 5, 1), vec4(0.0, 0.0, 0.0, 1), vec4(0.0, 1.0, 0.0, 0.0)); if (!isPerspective) { projMatrix = Ortho(-1.0, 1.0, -1.0, 1.0, -1, 10); } else { projMatrix = Perspective(45, 1.0, -2, 10); } glUniformMatrix4fv(glGetUniformLocation(p, "Proj"), 1, GL_FALSE, projMatrix); glUniformMatrix4fv(glGetUniformLocation(p, "Mv"), 1, GL_FALSE, viewMatrix); // x轴(红色) glColor3f(1.0, 0.0, 0.0); glBegin(GL_LINES); glVertex3f(0.0, 0.0, 0.0); glVertex3f(1.0, 0.0, 0.0); glEnd(); // y轴(绿色) glColor3f(0.0, 1.0, 0.0); glBegin(GL_LINES); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0, 1.0, 0.0); glEnd(); // z轴(蓝色) glColor3f(0.0, 0.0, 1.0); glBegin(GL_LINES); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0, 0.0, 1.0); glEnd(); glColor3f(1, 0, 0); switch (currentobject) { case 0: glutWireTeapot(0.5); break; case 1: glutWireCube(0.5); break; case 2: glutWireSphere(0.5, 20, 20); break; } glutSwapBuffers(); glUseProgram(0); }
透视投影效果

正交投影效果

初始化函数
void init() { // 创建着色器程序 p = createGLSLProgram("../vshader.vert", NULL, "../fshader.frag"); glEnable(GL_DEPTH_TEST); glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); }
创建GLSL程序函数
GLuint createGLSLProgram(char *vs, char *gs, char *fs) { GLuint v, g, f, p; if( !vs && !gs && !fs ) return 0; p = glCreateProgram(); if( vs ) { v = loadShader( GL_VERTEX_SHADER, vs ); glAttachShader(p,v); } if( gs ) { g = loadShader( GL_GEOMETRY_SHADER_EXT, gs ); glAttachShader(p,g); } if( fs ) { f = loadShader( GL_FRAGMENT_SHADER, fs ); glAttachShader(p,f); } glLinkProgram(p); // 验证程序 GLint status; glGetProgramiv(p, GL_LINK_STATUS, &status); if(status == GL_FALSE) { GLint sizeLog; glGetProgramiv(p, GL_INFO_LOG_LENGTH, &sizeLog); char *log = new char[sizeLog + 1]; glGetProgramInfoLog(p, sizeLog, NULL, log); std::cout << "程序链接错误: " << log << std::endl; delete [] log; assert( false ); } glValidateProgram(p); glGetProgramiv(p, GL_VALIDATE_STATUS, &status); if (status == GL_FALSE) { std::cerr << "验证程序错误: "<< p << std::endl; assert( false ); } // 验证通过,使用该程序 glUseProgram(p); return p; }
主函数
int main(int argc, char **argv) { // 初始化GLUT并创建窗口 glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100,100); glutInitWindowSize(600,600); glutCreateWindow("COSE436 - 作业1"); // 注册回调函数 glutDisplayFunc(renderScene); // glutIdleFunc(renderScene); glutReshapeFunc(changeSize); glutKeyboardFunc(keyboard); glutIdleFunc(idle); glewInit(); if (glewIsSupported("GL_VERSION_3_3")) printf("已支持OpenGL 3.3\n"); else { printf("不支持OpenGL 3.3\n"); exit(1); } init(); // 进入GLUT事件处理循环 glutMainLoop(); return 1; }
空闲函数
void idle() { glutPostRedisplay(); }
顶点着色器
#version 140 #extension GL_ARB_compatibility: enable out vec4 color; uniform mat4 Mv; // 模型视图矩阵 uniform mat4 Proj; // 投影矩阵 void main() { // 组合模型视图和投影矩阵 gl_Position = Proj * Mv * gl_Vertex; // 顶点 -> Mv -> Proj color = gl_Color; }
片段着色器
#version 140 #extension GL_ARB_compatibility: enable in vec4 color; out vec4 fColor; void main() { fColor = color; }
讲师提供的矩阵函数
inline mat4 LookAt( const vec4& eye, const vec4& at, const vec4& up ) { vec4 n = normalize(eye - at); vec4 u = vec4(normalize(cross(up,n)), 0.0); vec4 v = vec4(normalize(cross(n,u)), 0.0); vec4 t = vec4(0.0, 0.0, 0.0, 1.0); mat4 c = mat4(u, v, n, t); return c * Translate( -eye ); } inline mat4 Ortho( const GLfloat left, const GLfloat right, const GLfloat bottom, const GLfloat top, const GLfloat zNear, const GLfloat zFar ) { mat4 c; c[0][0] = 2.0/(right - left); c[1][1] = 2.0/(top - bottom); c[2][2] = 2.0/(zNear - zFar); c[3][3] = 1.0; c[0][3] = -(right + left)/(right - left); c[1][3] = -(top + bottom)/(top - bottom); c[2][3] = -(zFar + zNear)/(zFar - zNear); return c; } inline mat4 Perspective( const GLfloat fovy, const GLfloat aspect, const GLfloat zNear, const GLfloat zFar) { GLfloat top = tan(fovy*DegreesToRadians/2) * zNear; GLfloat right = top * aspect; mat4 c; c[0][0] = zNear/right; c[1][1] = zNear/top; c[2][2] = -(zFar + zNear)/(zFar - zNear); c[2][3] = -2.0*zFar*zNear/(zFar - zNear); c[3][2] = -1.0; c[3][3] = 0.0; return c; }
内容的提问来源于stack exchange,提问作者morjun
相关产品推荐
相关产品推荐

