2

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.

genpfault
  • 51,148
  • 11
  • 85
  • 139
BlastDV
  • 112
  • 7

1 Answers1

1

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...

jozxyqk
  • 16,424
  • 12
  • 91
  • 180
  • You're right, that was the problem. I set the near value to 0.1 and it's working now! Thanks! :) – BlastDV Mar 10 '14 at 15:49
  • I'm also checking the links you posted, the second one reminds me of something that I've already heard of. – BlastDV Mar 10 '14 at 15:50
  • 1
    You can use a `zNear` value of **0.0** in a projection matrix. The problem is actually the use of a ***perspective*** projection matrix; **0.0** is perfectly valid in ***orthographic***. – Andon M. Coleman Mar 11 '14 at 02:03