c++ - OpenGL 深度测试不起作用

标签 c++ opengl glut

我正在尝试使用 OpenGL 创建模型,并尝试启用深度测试。

我在我的 main 中使用这些命令:

glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glEnable(GL_DEPTH_TEST);

在我的显示中:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

我什至尝试添加:

glDepthFunc(GL_LEQUAL);

而且它不起作用。我仍然可以看到我认为是深度问题的东西。 这是显示问题的视频:https://www.youtube.com/watch?v=OafrRH4Mzjc

  • 注意:在该视频中,电路板是从右到左、从上到下构建的,因此第一个角度可以,但任何其他角度都不好。

我错过了什么?


编辑:复制的最小示例文件:

#define _CRT_SECURE_NO_WARNINGS

#define SIZE_MOVES 17

#include <stdio.h>

/* Include the GLUT library. This file (glut.h) contains gl.h and glu.h */
#include <GL\glew.h>
#include <GL\freeglut.h>

static int  left_click = GLUT_UP;
static int  right_click = GLUT_UP;
static int  xold;
static int  yold;
static float rotate_x = 146;
static float rotate_y = -26;

int width, height;

GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 0, 5, -10, 0 };

GLfloat mat_specular[] = { 0.3, 0.3, 0.3, 1.0 };
GLfloat mat_shininess[] = { 1 };


// colors
const GLfloat colors[2][4] = {
    { 1.0, 1.0, 1.0, 1.0 }, //white
    { 0.0, 0.0, 0.0, 1.0 } //black
};

// rgb
const GLfloat rgb[3][4] = {
    { 1.0, 0.0, 0.0, 1.0 },
    { 0.0, 1.0, 0.0, 1.0 },
    { 0.0, 0.0, 1.0, 1.0 }
};

void resetMaterial() {
    GLfloat c[] = { 1, 1, 1, 1 };
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
}

void drawSquare(int color) {
    glPushMatrix(); {
        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, colors[color]);

        glScalef(1, 0.5, 1);
        glutSolidCube(1);
    } glPopMatrix();
}

void drawBoard() {
    for (int i = 0; i < 8; i++)
        for (int j = 0; j < 8; j++) {
            glPushMatrix(); {
                glTranslatef(i + 0.5, 0, j + 0.5);
                drawSquare((i + j) % 2);
            } glPopMatrix();
        }
}

void drawAxes() {
    glBegin(GL_LINES); {
        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, rgb[0]);
        glVertex3f(-2, 0, 0); glVertex3f(5, 0, 0);
        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, rgb[1]);
        glVertex3f(0, -2, 0); glVertex3f(0, 5, 0);
        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, rgb[2]);
        glVertex3f(0, 0, -2); glVertex3f(0, 0, 5);
    } glEnd();
}

void letThereBeLight() {
    /*Add ambient light*/
    GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);

    /*Add positioned light*/
    GLfloat lightColor1[] = { 0.2f, 0.2f, 0.1f, 1.0f };
    GLfloat lightPosition1[] = { -8, 8, 5, 0.0f };

    glLightfv(GL_LIGHT0, GL_SPECULAR, lightColor1);
    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition1);

    /*Add directed light*/
    GLfloat lightColor2[] = { 0.3, 0.3, 0.3, 1.0f };
    GLfloat lightPosition2[] = { 8, 8, -5, 1.0f };
    glLightfv(GL_LIGHT1, GL_AMBIENT, lightColor2);
    glLightfv(GL_LIGHT1, GL_POSITION, lightPosition2);
}

void display(void) {
    // Clear frame buffer and depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Set up viewing transformation, looking down -Z axis
    glLoadIdentity();
    gluLookAt(0, 5, -15, 0, 0, 3, 0, 1, 0);

    letThereBeLight();

    resetMaterial();

    // Rotate view:
    glPushMatrix(); {
        glRotatef(rotate_y, 1, 0, 0);
        glRotatef(rotate_x, 0, 1, 0);

        glLightfv(GL_LIGHT0, GL_POSITION, light_position);

        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, colors[0]);

        glPushMatrix(); {
            glTranslatef(-4, 0, -4); // Move to center
            drawBoard();
        } glPopMatrix();

        drawAxes(); // For debuging
    } glPopMatrix();

    /* End */
    glFlush();
    glutSwapBuffers();
}

void mouseFunc(int button, int state, int x, int y) {
    if (GLUT_LEFT_BUTTON == button)
        left_click = state;

    xold = x;
    yold = y;
}

void motionFunc(int x, int y) {
    if (GLUT_DOWN == left_click) {
        rotate_y = rotate_y + (y - yold) / 5.f;
        rotate_x = rotate_x + (x - xold) / 5.f;
        glutPostRedisplay();
    }

    xold = x;
    yold = y;
}


void reshapeFunc(int new_width, int new_height) {
    width = new_width;
    height = new_height;

    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(50, width / height, 1, 20);

    glMatrixMode(GL_MODELVIEW);

    glutPostRedisplay();
}

int main(int argc, char **argv) {
    /* Creation of the window */
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(900, 600);
    glEnable(GL_DEPTH_TEST);

    glutCreateWindow("Chess");

    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);

    glEnable(GL_POLYGON_SMOOTH);
    glEnable(GL_LINE_SMOOTH);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHT1);
    glShadeModel(GL_SMOOTH);
    glDisable(GL_COLOR_MATERIAL);

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

    /* Declaration of the callbacks */
    glutDisplayFunc(&display);
    glutReshapeFunc(&reshapeFunc);
    glutMouseFunc(&mouseFunc);
    glutMotionFunc(&motionFunc);

    /* Loop */
    glutMainLoop();

    /* Never reached */
    return 0;
}

最佳答案

gluPerspective(50, width / height, 0, 20);
                                   ^ wat

zNear 需要为 greater than zero (强调我的):

Depth buffer precision is affected by the values specified for zNear and zFar. The greater the ratio of zFar to zNear is, the less effective the depth buffer will be at distinguishing between surfaces that are near each other.

If r = zFar / zNear roughtly log2(r) bits of depth buffer precision are lost. Because r approaches infinity as zNear approaches 0, zNear must never be set to 0.


编辑:鉴于新发布的 MCVE:

int main(int argc, char **argv) {
    /* Creation of the window */
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(900, 600);
    glEnable(GL_DEPTH_TEST);  // too soon

    glutCreateWindow("Chess");
    ...
}

就像datenwolf said :在拥有当前 GL 上下文之前,您正在使用 glEnable()(glutCreateWindow() 创建上下文并使其成为当前上下文)。

glutCreateWindow() 之前不要调用任何 gl*() 函数。

关于c++ - OpenGL 深度测试不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41935764/

相关文章:

c++ - 未调用带有 nullptr 的重载函数

c++ - 悬挂指针 - 请验证

c++ - 有关C++中char数据类型的问题

c++ - GLUT 定时器/空闲功能不更新

c++ - 用cuda计算一张图片,直接用OpenGL显示

c++ - 已编译的可执行文件被视为特洛伊木马威胁

c++ - 奇怪的 OpenGL 阴影映射行为

c++ - 当不是最后加载的纹理时,纹理会显得模糊

opengl - 解除绑定(bind) OpenGL 缓冲区有什么影响?

c++ - XCode 项目无法识别某些 GLUT 命令