2011-06-12 59 views
1

在我的OpenGL代码中存在一个奇怪的行为。我想在地上画一块地毯。同一平面内的另一个多边形内的多边形

在下面的代码中,如果GROUND_SIZE大于2071且CARPET_HEIGHT小于0.0003,则不会绘制较小的多边形。绘图顺序不会更改生成的图像。

#include <GL/glut.h> 

const int GROUND_SIZE = 3000; 
const bool GROUND_FIRST = true; 
const float CARPET_HEIGHT = 0.0003; 

void carpet(){ 
    glColor3f(1.0,0.0,0.0); 
    glBegin(GL_QUADS); 
     glNormal3f(0,1,0); 
     glVertex3f(-1.0, -1.0, CARPET_HEIGHT); 
     glVertex3f(1.0, -1.0, CARPET_HEIGHT); 
     glVertex3f(1.0, 1.0, CARPET_HEIGHT); 
     glVertex3f(-1.0, 1.0, CARPET_HEIGHT); 
    glEnd(); 
} 
void ground(){ 
    glColor3f(0.0,0.7,0.0); 
    glBegin(GL_QUADS); 
     glNormal3f(0,1,0); 
     glVertex3f(-GROUND_SIZE, -GROUND_SIZE, 0); 
     glVertex3f(GROUND_SIZE, -GROUND_SIZE, 0); 
     glVertex3f(GROUND_SIZE, GROUND_SIZE, 0); 
     glVertex3f(-GROUND_SIZE, GROUND_SIZE, 0); 
    glEnd(); 
} 

void draw(){ 
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    if (GROUND_FIRST) { 
     ground(); 
     carpet(); 
    } 
    else { 
     carpet(); 
     ground(); 
    } 

    glutSwapBuffers(); 
} 

int main(){ 

    int argc = 1; char* argv[] = { (char*)"" }; 
    glutInit(&argc, argv); 

    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); 
    glutInitWindowPosition(100, 50); 
    glutInitWindowSize(640, 640); 
    glutCreateWindow("Window"); 

    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    glEnable(GL_DEPTH_TEST); 

    glClearColor(0.0f, 1.0f, 1.0f, 1.0f); 

    glutDisplayFunc(draw); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(45, 1, 0.1, 1000.0); 
    gluLookAt(0.0, -5.0, 1.0, 0.0f, 0.0f, 1.0f, 0,0,1); 

    glutMainLoop(); 
    return 0; 
} 

我想了解OpenGL用来决定是否会在同一平面内的另一个多边形内绘制多边形的规则。

谢谢

回答

4

首先,几个代码错误。

切勿将gluLookAt矩阵放在GL_PROJECTION矩阵中。这可以用你的照明来玩havok。 gluLookAt的矩阵应该是您在GL_MODELVIEW中放置的第一个矩阵。

将GL_MODELVIEW矩阵作为默认矩阵也是一个好主意。也就是说,任何切换到GL_PROJECTION(或其中一个纹理矩阵)的代码都会在完成其他矩阵后立即切换回GL_MODELVIEW。

最后,调用glClearDepth和glDepthFunc总是很好的形式。默认值(1.0和GL_LESS)正是你想要的,但对这些事情明确表示总是很好的。这样,您不必通过搜索规范来确保默认值是您的想法。

现在,就主要问题。

这个规则只是深度缓冲区的规则。这是简单和复杂的同时。

首先,有两个飞机的斜率。虽然它们在世界空间中确实具有相同的斜率,但它们在投影后空间中不一定具有相同的斜率。这是由于从世界空间转换到后投影空间的各种计算中的浮点错误。其次,如果它们之间的Z-差异太小,那么可能发生的是它们会得到相同的Z值。或者由于浮点错误,地毯甚至可能具有较小的Z值。

我想如果你为视角设置动画,你会看到地毯飞机进出视野。

你可以做的一件简单的事情是总是在地平面后面画地毯,并使用GL_LEQUAL作为glDepthFunc。这可能无法100%的时间,再次由于浮点错误。

下一步是使用多边形偏移。这样做会使某个基元的Z值偏离某个固定值。它是如何工作的细节是讨论过的技术(检查OpenGL规范,如果你很好奇),但其基本思想是,你carpet函数应该是这个样子:

glEnable(GL_POLYGON_OFFSET_FILL); //Activates polygon offsets for filled triangles. 
glPolygonOffset(0, 2); //The 2 is just for safety's sake; 1 ought to be enough. 
//Draw the carpet 
glDisable(GL_POLYGON_OFFSET_FILL); //Turn off polygon offsetting. 
+0

我通常建议设置在任何矩阵操作之前的适当矩阵模式,而不是依赖于事物被正确地切换回来。 – datenwolf 2011-06-14 09:43:37

相关问题