OpenGL立方体显示异常求助:远层面覆盖近层面
OpenGL立方体抛掷模拟显示异常问题
问题现象
实现了立方体抛掷模拟的OpenGL代码,但立方体显示逻辑错误,远层面出现在近层面上方。尝试调整Z缓冲相关函数与参数后,要么出现黑屏,要么显示问题依旧,立方体深度层级完全错乱。
相关代码
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <math.h> #include <GL/glut.h> float z = 7.0f, y = 0, x = 0; float v0 = 0.2; float alfa = 5; float fi = 5; float r = 1; float dt = 0.01; float g = 9.80665f; float t = 0; float omega = 0; float vY = 0, vX = 0, vZ = 0, Y = 0, X = 0, Z = 0; float ymax = 0, xmax = 0, zmax = 0, tD = 0, tm = 0; void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(xmax + 10, zmax, ymax+10, 0.0, 0.0, 0.0, 0.0, 2, 0.0); glPushMatrix(); glColor3f(0.0f, 0.0f, 1.0f); glBegin(GL_LINES); glVertex2f(0.0f, 0.0f); glVertex2f(333, 0.0f); glEnd(); glBegin(GL_LINES); glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(0.001f, 0.0f); glVertex2f(0.001f, 333); glEnd(); glBegin(GL_LINES); glColor3f(0.0f, 1.0f, 1.0f); glVertex3f(0.001f, 0.001f, 0.0f); glVertex3f(0.001f, 0.001f, 333); glEnd(); glPopMatrix(); glPushMatrix(); static float angle = 0.0f; angle += omega; // glTranslatef(X-xmax-r, Z-zmax, Y-(xmax+ymax+zmax)); glTranslatef(X, Z, Y); glRotatef(angle, 0.0f, 1.0f, 0.0f); glScalef(r, r, r); glBegin(GL_QUADS); glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(-0.5f, -0.5f, 0.5f); glVertex3f(0.5f, -0.5f, 0.5f); glVertex3f(0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f, 0.5f); glColor3f(0.5f, 1.0f, 0.5f); glVertex3f(-0.5f, -0.5f, -0.5f); glVertex3f(-0.5f, -0.5f, 0.5f); glVertex3f(-0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f, -0.5f); glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(0.5f, -0.5f, -0.5f); glVertex3f(-0.5f, -0.5f, -0.5f); glVertex3f(-0.5f, 0.5f, -0.5f); glVertex3f(0.5f, 0.5f, -0.5f); glColor3f(1.0f, 1.0f, 0.0f); glVertex3f(-0.5f, 0.5f, 0.5f); glVertex3f(0.5f, 0.5f, 0.5f); glVertex3f(0.5f, 0.5f, -0.5f); glVertex3f(-0.5f, 0.5f, -0.5f); glColor3f(1.0f, 0.0f, 1.0f); glVertex3f(-0.5f, -0.5f, -0.5f); glVertex3f(0.5f, -0.5f, -0.5f); glVertex3f(0.5f, -0.5f, 0.5f); glVertex3f(-0.5f, -0.5f, 0.5f); glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(0.5f, -0.5f, 0.5f); glVertex3f(0.5f, -0.5f, -0.5f); glVertex3f(0.5f, 0.5f, -0.5f); glVertex3f(0.5f, 0.5f, 0.5f); glEnd(); // glPopMatrix(); glutSwapBuffers(); } void timer(int value) { glutPostRedisplay(); glutTimerFunc(15, timer, 0); if (Z >= 0) { vX = v0 * cos(alfa * (3.14 / 180)) * cos(fi * (3.14 / 180)); vY = v0 * cos(alfa * (3.14 / 180)) * sin(fi * (3.14 / 180)); vZ = v0 * sin(alfa * (3.14 / 180))- g * t; Z = z + (v0 * sin(alfa * (3.14 / 180))) * t - 1 / 2.0 * g * t * t; X = t * vX; Y = t * vY; } t += dt; } void obsluhaReshape(int width, int height) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (width == 0) width++; const float aspect_ratio = (float)(width) / (height); gluPerspective(100, aspect_ratio, 0, zmax + 10); } int main(int argc, char** argv) { z = atof(argv[1]); v0 = atof(argv[2]); alfa = atof(argv[3]); fi = atof(argv[4]); r = atof(argv[5]); omega = atof(argv[6]); tD = (v0 * sin(alfa * (3.14 / 180)) + sqrt(pow(v0 * sin(alfa * (3.14 / 180)), 2) + 2 * g * z)) / g; vX = v0 * cos(alfa * (3.14 / 180)) * cos(fi * (3.14 / 180)); vY = v0 * cos(alfa * (3.14 / 180)) * sin(fi * (3.14 / 180)); zmax = z + (v0* v0* sin(alfa * (3.141592 / 180))* sin(alfa * (3.141592 / 180))) / (2 * g); xmax = tD*vX; ymax = tD * vY; printf("tD = %.2fs\nxmax = %.2fm\nymax = %.2fm\nzmax = %.2fm\n", tD, xmax, zmax, ymax); glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(640, 640); glutCreateWindow("DU6"); glClearDepth(100.0); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glutDisplayFunc(display); glutTimerFunc(0, timer, 0); glutReshapeFunc(obsluhaReshape); glutMainLoop(); return 0; }
问题分析与修复方案
1. 投影矩阵近裁剪面参数错误
gluPerspective的近裁剪面不能设为0,这会直接导致深度缓冲精度丢失,引发深度测试逻辑混乱。将近裁剪面改为极小正值:
gluPerspective(100, aspect_ratio, 0.1, zmax + 10);
2. 显示模式与缓冲交换不匹配
代码使用glutSwapBuffers()双缓冲交换,但初始化时设置的是GLUT_SINGLE单缓冲模式,这会导致缓冲逻辑冲突,引发黑屏。修改显示模式为双缓冲:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
3. 矩阵栈未正确弹出
display函数中调用glPushMatrix()后未执行glPopMatrix(),会导致矩阵栈溢出,后续绘制的变换矩阵完全错乱。取消注释对应的弹出代码:
glEnd(); glPopMatrix(); glutSwapBuffers();
4. 额外优化:开启面剔除
如果修复后仍有层级问题,可以开启背面剔除,避免背面与正面的深度冲突:
// 在main函数的初始化部分添加 glEnable(GL_CULL_FACE); glCullFace(GL_BACK);
内容的提问来源于stack exchange,提问作者srgerh
相关产品推荐
相关产品推荐

