gluPerspective会混淆3D物体

时间:2014-04-23 19:11:48

标签: opengl camera glut

void drawTire(void)
{
    GLint num_of_tri = 32;
    GLfloat vertex[3]; 
    const GLfloat delta_angle = 2.0*PI/float(num_of_tri);

    //Draw Front tire
    glBegin(GL_TRIANGLE_FAN);
        glColor3f(0.5, 0.5, 0.5);

        vertex[0] = vertex[1] = vertex[2] = 0.0;
        glVertex3fv(vertex);

        for(int i = 0; i < num_of_tri ; i++)
        {
            vertex[0] = cos(delta_angle*i) * wheelRadius; //wheel Radius is 1.0
            vertex[1] = sin(delta_angle*i) * wheelRadius;
            vertex[2] = 0.0;
            glVertex3fv(vertex);
        }
        vertex[0] = 1.0 * wheelRadius;
        vertex[1] = 0.0 * wheelRadius;
        vertex[2] = 0.0;
        glVertex3fv(vertex);
    glEnd();

    //Draw Back Tire
    const GLfloat depth = -wheelRadius/1.5; 
    glBegin(GL_TRIANGLE_FAN);
        glColor3f(1.0, 0.0, 0.0);
        vertex[0] = vertex[1] = 0.0;
        vertex[2] = depth;
        glVertex3fv(vertex);

        for(int i = 0; i < num_of_tri ; i++)
        {
            vertex[0] = cos(delta_angle*i) * wheelRadius;
            vertex[1] = sin(delta_angle*i) * wheelRadius;
            vertex[2] = depth;
            glVertex3fv(vertex);
        }
        vertex[0] = 1.0 * wheelRadius;
        vertex[1] = 0.0 * wheelRadius;
        vertex[2] = depth;
        glVertex3fv(vertex);
    glEnd();

    //Connect Front&Back
    glBegin(GL_QUADS);
        glColor3f(0.0, 0.0, 0.0);
        for(int i = 0; i < num_of_tri; i++)
        {
            vertex[0] = cos(delta_angle*i) * wheelRadius;
            vertex[1] = sin(delta_angle*i) * wheelRadius;
            vertex[2] = 0;
            glVertex3fv(vertex);

            vertex[0] = cos(delta_angle*i) * wheelRadius;
            vertex[1] = sin(delta_angle*i) * wheelRadius;
            vertex[2] = depth;
            glVertex3fv(vertex);

            vertex[0] = cos(delta_angle*((i + 1)%num_of_tri)) * wheelRadius;
            vertex[1] = sin(delta_angle*((i + 1)%num_of_tri)) * wheelRadius;
            vertex[2] = depth;
            glVertex3fv(vertex);

            vertex[0] = cos(delta_angle*((i + 1)%num_of_tri)) * wheelRadius;
            vertex[1] = sin(delta_angle*((i + 1)%num_of_tri)) * wheelRadius;
            vertex[2] = 0;
            glVertex3fv(vertex);
        }
    glEnd();

    glFlush();
}

我使用上面的代码绘制一种(某种)3D车轮。此代码似乎有效。
这是我的初始函数:

void init(void)
{    
    glClearColor (1.0, 1.0, 1.0, 0.0);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective(45.0f, (GLfloat)1366/(GLfloat)768, 0.1f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, 5.0, 0, 0, 0, 0, 1, 0);
}

这是我的显示功能:

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
drawTire();
glFlush();
}

结果搞砸了车轮,如下所示:http://postimg.org/image/fuf9o75ub/

轮胎的前部(相机应该看的一侧)是灰色的。相机以某种方式看着轮胎的后部,这是红色的。
另外,轮胎侧(接触地面的那个。我不知道如何命名)也显示出来,这很奇怪(黑色)。

为什么gluPerspective会混淆3D对象,如何解决这个问题呢? (我试过改变fov ......结果差不多了)

1 个答案:

答案 0 :(得分:1)

目前,您还没有使用深度测试。这意味着渲染的最后一个原语是“在顶部”,因为没有深度测试,OpenGL在渲染后无法知道像素的“深度”。

为了解决这个问题,OpenGL使用深度缓冲区,这是一个隐藏的屏幕大小的缓冲区,用于存储每个像素距摄像机的距离。启用深度测试后,当OpenGL呈现片段时,它首先检查片段的深度并将其与深度缓冲区中的值进行比较。如果片段的深度值小于存储值(注释1),则OpenGL断定片段位于已渲染对象的前面并写入片段。否则,它在一个对象后面并忽略该片段。

要使用深度测试,首先需要确保在创建上下文时已分配深度缓冲区。这取决于您使用的窗口库,但通常默认情况下会为您提供深度缓冲区。

然后,您需要致电glEnable(GL_DEPTH_TEST)开始使用深度测试。

此外,重新渲染场景时,需要清除深度缓冲区中的深度值。将glClear(GL_COLOR_BUFFER_BIT)更改为glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

这就是您使用深度测试所需的一切。


(注1):更具体地说,它使用了设置的任何函数glDepthFunc,但99%的时间是GL_LESSGL_LEQUAL