OpenGL 深度测试不起作用

OpenGL depth test is not working

我正在尝试使用 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.


编辑:鉴于newly-posted 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()ing(glutCreateWindow() 创建上下文并使其成为当前上下文)。

glutCreateWindow().

之前不要调用任何 gl*() 函数
   public void onSurfaceChanged(int w, int h)
    {
        Matrix.frustumM(projectionMatrix,0,-(9f/18.5f),(9f/18.5f),-1f,1f,1.0f,1000f);
    }

我不得不将近裁剪形式 0.01f 更改为 1.0f。