1

我正在尝试获得一些 OpenGL 的实践经验,所以我一直在编写一些基本程序。下面的简短程序是我第一次尝试渲染一个实体对象——一个旋转的立方体——但由于某种原因,一些后多边形似乎被绘制在前多边形上。我的问题是什么可能导致这种情况?它与深度缓冲区有关吗?我发现在这种情况下启用面部剔除会隐藏效果,但为什么需要这样做呢?不应该隐藏被更近的脸遮挡的脸吗?

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

typedef struct{
    int width;
    int height;
    char * title;
} window;
window win;

float theta = 0;
const float rotRate = 0.05;//complete rotations per second
int lastTime;

const float verts[][3] = {
    {0.0,0.0,0.0},
    {1.0,0.0,0.0},
    {0.0,1.0,0.0},
    {0.0,0.0,1.0},
    {0.0,1.0,1.0},
    {1.0,0.0,1.0},
    {1.0,1.0,0.0},
    {1.0,1.0,1.0}};

const int faceIndices[][4] = {
    {3,5,7,4},//front
    {1,0,2,6},//back
    {4,7,6,2},//top
    {0,1,5,3},//bottom
    {5,1,6,7},//right
    {0,3,4,2}};//left

void display(){
    //timing and rotation 
    int currentTime = glutGet(GLUT_ELAPSED_TIME);
    int dt = lastTime - currentTime;
    lastTime = currentTime;
    theta += (float)dt/1000.0*rotRate*360.0;
    if (theta > 360.0) theta += -360.0;

    //draw
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -5.0);
    glRotatef(theta, 0.0, 1.0, 0.0);
    glTranslatef(-1.0,-1.0,-1.0);
    glScalef(2.0, 2.0, 2.0);
    int f;
    for(f=0; f<6;f++){
        glBegin(GL_POLYGON);
        int v;
        for(v=0; v<4; v++){
            glColor3fv(verts[faceIndices[f][v]]);
            glVertex3fv(verts[faceIndices[f][v]]);
        }
        glEnd();
    }

    glutSwapBuffers();
}

void initializeGLUT(int * argc, char ** argv){
    glutInit(argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    glutInitWindowSize(win.width, win.height);
    glutCreateWindow("OpenGL Cube");
    glutDisplayFunc(display);
    glutIdleFunc(display);
}

void initializeGL(){
    //Setup Viewport matrix
    glViewport(0,0,win.width, win.height);

    //Setup Projection matrix
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45,(float) win.width/win.height, 0.1, 100.0);

    //Initialize Modelview matrix
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    //Other
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClearDepth(1.0);
}

int main(int argc, char** argv){
    win.width = 640;
    win.height = 480;

    initializeGLUT(&argc, argv);
    initializeGL();

    glutMainLoop();

    return 0;
}
4

1 回答 1

2

它与深度缓冲区有关吗?

是的,这是一个深度缓冲区问题,您在代码中启用了深度缓冲区,但显然您丢失了一些步骤来使用深度缓冲区

  1. 通过调用启用深度测试glEnable(GL_DEPTH_TEST)
  2. 通过 glDepthFunc 设置深度测试功能,大多数情况下推荐选择 GL_LEQUAL,glDepthFunc(GL_LEQUAL);默认值为 GL_LESS。
  3. 调用glClearDepth设置清零值,初始值为1.0,如果要默认值,此步骤不强制。
  4. 不要忘记在绘制之前清除深度位,glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

我发现在这种情况下启用面部剔除会隐藏效果,但为什么需要这样做呢?

默认情况下,OpenGL 不剔除任何人脸,推荐选项是

  1. 以顺时针顺序定义顶点作为背面(这也是 OpenGL 的选择)
  2. 必要时剔除背面。

在您的情况下,您以 CCW 顺序定义了所有多边形顶点,因此默认情况下它们都是正面,您只需要剔除背面以防止它们绘制,因此以下代码也解决了您的问题。

glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glCullFace(GL_BACK);

不应该隐藏被更近的脸遮挡的脸吗?

是的,这是有道理的,因为我们是人类,但对于计算机,你有责任告诉它如何做到这一点。

参考:

深度缓冲区

面剔除

于 2014-05-19T07:41:01.577 回答