Question

I'm having a problem when I enable GL_DEPTH_TEST when rendering my objects, here's what happens:

enter image description here

GL_CULL_FACE is disable on that one.

It only happens with perspective view! Does anyone have and idea of what's happening?

I'm using Qt 4.8 for this.

Of course, if I disable the depth test, it looks fine, but then the objects overlays in a wrong way, as expected.

Update

I create my projection matrix with this:

ProjectionMatrix.setToIdentity();
ProjectionMatrix.perspective(45, float(width) / float(height), 0, 20.0);

Where width and height are related to the viewport size.

Here's the code where I draw my scene:

void GLWidget::paintGL()
{
    glClearColor(0.4765625, 0.54296875, 0.6171875, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    editor->setUniformValue("projectMatrix", controller->getProjectionMatrix());
    editor->setUniformValue("viewMatrix", controller->getViewMatrix());

    /** Dibujemos los grids **/
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);
    for (int i=0; i<3; i++)
    {
        if ((front && i==1) || (side && i==2) || (i==0))
        {
            editor->setUniformValue("modelMatrix", Objects.at(i).modelMatrix);
            editor->setUniformValue("normalMatrix", Objects[i].getNormalMatrix());
            editor->setUniformValue("texture", textureon);

            glEnableClientState(GL_VERTEX_ARRAY);
            editor->enableAttributeArray("vertices");
            Objects[i].vertexbuffer->bind();
            editor->setAttributeBuffer("vertices", GL_FLOAT, 0, 3);
            glDisableClientState(GL_VERTEX_ARRAY);

            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            editor->enableAttributeArray("texuv");
            Objects[i].uvbuffer->bind();
            editor->setAttributeBuffer ("texuv", GL_FLOAT, 0, 2);
            glDisableClientState(GL_TEXTURE_COORD_ARRAY);

            glEnableClientState(GL_NORMAL_ARRAY);
            editor->enableAttributeArray("normals");
            Objects[i].normalbuffer->bind();
            editor->setAttributeBuffer ("normals", GL_FLOAT, 0, 3);
            glDisableClientState(GL_NORMAL_ARRAY);

            Objects[i].elementbuffer->bind();
            glBindTexture(GL_TEXTURE_2D, Objects[i].texture);
            glDrawElements(GL_TRIANGLES, Objects[i].indices.size(), GL_UNSIGNED_SHORT, (void*)0);
        }
    }

    /** Ahora para las operaciones especificas de cada objeto **/
    glEnable(GL_DEPTH_TEST);
    //glEnable(GL_CULL_FACE);
    for (int i=3; i<Objects.size(); i++)
    {
        //Objects[i].modelMatrix.scale(1.0, 1.0, 1.0);
        //Objects[i].modelMatrix.rotate(1.0, 0.0, 1.0, 0.0);

        editor->setUniformValue("modelMatrix", Objects.at(i).modelMatrix);
        editor->setUniformValue("normalMatrix", Objects[i].getNormalMatrix());
        editor->setUniformValue("texture", textureoff);
        editor->setUniformValue("diffuseColor", Objects.at(i).diffuseColor);
        editor->setUniformValue("shininess", Objects.at(i).shininess);
        editor->setUniformValue("hardness", Objects.at(i).hardness);
        editor->setUniformValue("LPos1", Objects.at(i).L1Pos);
        editor->setUniformValue("LPos2", Objects.at(i).L2Pos);
        editor->setUniformValue("LPos3", Objects.at(i).L3Pos);
        editor->setUniformValue("LPos4", Objects.at(i).L4Pos);

        glEnableClientState(GL_VERTEX_ARRAY);
        editor->enableAttributeArray("vertices");
        Objects[i].vertexbuffer->bind();
        editor->setAttributeBuffer("vertices", GL_FLOAT, 0, 3);
        glDisableClientState(GL_VERTEX_ARRAY);

        glEnableClientState(GL_NORMAL_ARRAY);
        editor->enableAttributeArray("normals");
        Objects[i].normalbuffer->bind();
        editor->setAttributeBuffer ("normals", GL_FLOAT, 0, 3);
        glDisableClientState(GL_NORMAL_ARRAY);

        Objects[i].elementbuffer->bind();
        glDrawElements(GL_TRIANGLES, Objects[i].indices.size(), GL_UNSIGNED_SHORT, (void*)0);
    }
}

In short lines, I first draw the grids according to where the camera is facing, in order to give a functionallity like Blender's. Then, I draw all the objects. I'm using indexed VBOs to achieve this.

I also draw them in CCW, I'm 99% sure that the triangles are being passed to the OpenGL in that way.

Was it helpful?

Solution

The near value of the [EDIT perspective] projection matrix is zero. This results in all depth values equal to one after the perspective divide (.xyz/.w). @Raxvan clearly had the right idea. Try this...

ProjectionMatrix.perspective(45, float(width) / float(height), 0.01, 20.0);

Of course for large scenes you want a large depth range, but if you make it too big you wind up with z-fighting where fragments at different distances still have the same depth values and which ever gets rasterized first wins (which seems to be the problem you're having). I try to keep my depth range no bigger than a factor of 10,000 apart.

If you have very large scenes, you might need to look at alternative methods. For a start, use a higher precision depth buffer. If that's not enough, maybe use two projection matrices and split the scene into near and far objects. Sometimes that causes issues if objects intersect the boundary. Here's some related links...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top