OpenGL立方体无法正确渲染

3
我在OpenGL中渲染立方体时遇到了问题。我正在绘制两个立方体,一个是线框立方体,围绕原点居中,而另一个则偏离原点且为实心。我映射了一些键以使物体相对于原点旋转一定角度,因此整个场景可以围绕原点旋转。
问题是,在渲染场景时,当线框立方体应该在其它实心立方体的前面时,它不能正确地显示自己。

enter image description here

在上面的图像中,彩色立方体应该在线框立方体后面。即绿色线框立方体应该在上面。
此外,该立方体的行为不正确。

enter image description here

在我围绕x轴(当前水平线)稍微旋转一下之后,这个立方体出现了缺失的面并且无法正确渲染。我做错了什么?

我已经编写了以下代码。 请注意,rotateX、rotateY和rotateZ被映射到键,并且是我的全局旋转变量。

//The Initialize function, called once:    
void Init(){
    glEnable(GL_TEXTURE_2D); 
    glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);               // Black Background
    glClearDepth(1.0f);                                 // Depth Buffer Setup
    glEnable(GL_DEPTH_TEST);                            // Depth Buffer Setup                       // Enables Depth Testing
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Really Nice Perspective Calculations
    glEnable(GL_LIGHTING);
}

void draw(){
    //The main draw function
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective(45, 640/480.0, .5, 100);

    glMatrixMode(GL_MODELVIEW); //select the modelview matrix.
    glLoadIdentity ();
    gluLookAt(0,0,5,
              0,0,0,
              0,1,0);    

    glRotatef(rotateX,1,0,0);
    glRotatef(rotateY,0,1,0);
    glRotatef(rotateZ,0,0,1);
    drawScene();  // this just draws the main axis lines,

    glutWireCube(1);  

    glPopMatrix();
    glPushMatrix();
    glTranslatef(-2,1,0);
    drawNiceCube();
    glPopMatrix();

    glutSwapBuffers();
}

drawNiceCube()的代码只是使用了GL_QUADS,而drawWireCube则是在GLUT中内置的。

编辑: 我已经在http://pastebin.com/p1kwPjEM上发布了完整的代码,如果没有很好的文档说明,我很抱歉。

3个回答

4

您是否也请求了具有深度缓冲区的窗口?

glutInitDisplayMode( ... | GLUT_DEPTH | ...);

更新:

你是否在某处启用了面剔除?

glEnable(GL_CULL_FACE);

是的,在主函数中我使用了: glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); - Jonathan Simbahan
嗨,我没有使用glEnable(GL_CULL_FACE);所以我真的不知道它是否被剔除了。谢谢! - Jonathan Simbahan
@JonathanSimbahan:嗯,有些东西搞乱了你的深度排序。你能否将你程序的完整源代码发布到pastebin.com上,这样我/我们就可以测试和修复它了吗? - datenwolf
更新有所帮助,答案的第一部分似乎与我正在处理的问题无关。 - ThorSummoner
@ThorSummoner:任何一种情况都可能导致深度外观不当,因此我提到了两种情况。 - datenwolf
显示剩余2条评论

1

这可能是顺时针的原因

10.090 面剔除是如何工作的?为什么不使用表面法线?
OpenGL 面剔除计算窗口坐标空间中填充图元的有符号面积。当窗口坐标按逆时针顺序排列时,有符号面积为正;当按顺时针顺序排列时,有符号面积为负。应用程序可以使用 glFrontFace() 指定顺序(逆时针或顺时针)以解释前向或后向图元。应用程序可以通过调用 glCullFace() 指定剔除前面或后面的面。最后,必须通过调用 glEnable(GL_CULL_FACE) 启用面剔除。
OpenGL 使用图元的窗口空间投影来确定面剔除的两个原因。为了创建有趣的照明效果,通常希望指定法线不垂直于被近似的表面。如果这些法线用于面剔除,可能会导致一些图元被错误地剔除。此外,点积剔除方案可能需要矩阵求逆,这并不总是可能的(即在矩阵奇异的情况下),而 DC 空间中的有符号面积始终被定义。
然而,一些 OpenGL 实现支持 GL_EXT_cull_vertex 扩展。如果存在此扩展,应用程序可以在对象空间中指定一个齐次眼位置。基于当前法线与从顶点到眼睛的向量的点积,将顶点标记为剔除。如果一个图元的所有顶点都被剔除,则不会渲染该图元。在许多情况下,使用此扩展是有益的。

请点击此处以获取更多信息。

同时,您也可以在此处阅读相关内容。


0

datenwolf解决了我的问题。我引用他的话:

"@JonathanSimbahan:你的代码有些多余,但是缺少一些东西:在创建GLUT窗口后,你忘记调用Init();,因此深度测试和所有其他状态都没有启用。我建议你根本不要使用Init,而是将它的代码移动到绘图代码中,那里才是它真正属于的地方。"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接