Issue with depth-test

Hello everybody.

I come to you with a little issue with depth-test.
I’m trying to display two cubes, one behind another, with texture and that’s all for now.
The problem is that the last drawn cube is always “in front”.
My goal is to get the front cube to hide the one behind.
The result (the left cube is in front but we can see the other through):
[ATTACH=CONFIG]1326[/ATTACH]

The result with fragment shader trying to display the depth (which seem good, black in front and white in back…):

[ATTACH=CONFIG]1325[/ATTACH]

My code, the two cubes are drawn with createCube() in render(), and use, each, 6 time the function createFace().
The arguments are for the position, the lenght in X and Y, the differents matrix (for translate, rotate and scale) and the texture to use.
All the tangent and bitangent things are use for the normal mapping used in the shaders.

#include "castlewindow.h"


CastleWindow::CastleWindow()
    : m_program(0)
    , m_frame(0)
{
}



//Charger les shaders
GLuint CastleWindow::loadShader(GLenum type, const char *source)
{
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &source, 0);
    glCompileShader(shader);
    return shader;
}


void CastleWindow::initialize()
{
    // Enable depth buffer    
    glEnable( GL_DEPTH_TEST );
    glDepthFunc( GL_LESS );
     //glDepthFunc( GL_GREATER );

    // Enable back face culling
    glEnable(GL_CULL_FACE);


    glClearColor(1.0f,1.0f,1.0f,1.0f);

    m_program = new QOpenGLShaderProgram(this);
    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
    m_program->link();
    m_posAttr = m_program->attributeLocation("posAttr");
    m_uvAttr = m_program->attributeLocation( "uvAttr" );
    m_matrixUniform = m_program->uniformLocation( "matrix" );
    m_camPos = m_program->uniformLocation( "camPos" );
    m_nmAttr = m_program->attributeLocation( "nmAttr" );
    m_tangent = m_program->attributeLocation( "tangent" );
    m_bitangent = m_program->attributeLocation( "bitangent" );

    //TEXTURES
    //-----------------------------------------------------------------
    //Sol
    texGround = new QOpenGLTexture(QImage( ":/pave.jpg" ));

    // Set nearest filtering mode for texture minification
    texGround->setMinificationFilter( QOpenGLTexture::NearestMipMapLinear );

    // Set bilinear filtering mode for texture magnification
    texGround->setMagnificationFilter( QOpenGLTexture::Linear );

    // Wrap texture coordinates by repeating
    // f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2)
    texGround->setWrapMode( QOpenGLTexture::MirroredRepeat );

    //-----------------------------------------------------------------
    //Mur
    texWall = new QOpenGLTexture( QImage( ":/brickwall.jpg" ) );

    // Set nearest filtering mode for texture minification
    texWall->setMinificationFilter( QOpenGLTexture::NearestMipMapLinear );

    // Set bilinear filtering mode for texture magnification
    texWall->setMagnificationFilter( QOpenGLTexture::Linear );

    // Wrap texture coordinates by repeating
    // f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2)
    texWall->setWrapMode( QOpenGLTexture::MirroredRepeat);

    //-----------------------------------------------------------------
    //Normal map pour le mur
    nmWall = new QOpenGLTexture( QImage( ":/brickwall_normal.jpg" ) );

    // Set nearest filtering mode for texture minification
    nmWall->setMinificationFilter( QOpenGLTexture::NearestMipMapLinear );

    // Set bilinear filtering mode for texture magnification
    nmWall->setMagnificationFilter( QOpenGLTexture::Linear );

    // Wrap texture coordinates by repeating
    // f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2)
    nmWall->setWrapMode( QOpenGLTexture::MirroredRepeat);

    //-----------------------------------------------------------------


    // initialisation de la camera
    cam = Camera();



}

//Transmettre les events et les tailles à la caméra
void CastleWindow::mouseMoveEvent ( QMouseEvent * event ){
    static const qreal retinaScale = devicePixelRatio();
    static float hei = height() * retinaScale;
    static float wid = width() * retinaScale;
    cam.mouseMoveEvent(event, retinaScale, hei, wid);
}

//Transmettre les events à la caméra
void CastleWindow::keyPressEvent(QKeyEvent *event){
    cam.keyPressEvent(event);
}


void CastleWindow::render()
{
    //Petits calculs de la fenêtre (taille...)
    const qreal retinaScale = devicePixelRatio();
    glViewport(0, 0, width() * retinaScale, height() * retinaScale);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);


    //-------------------------------

    //Binder les textures avec le programme
    m_program->bind();
    texGround->bind(0);
    texWall->bind(2);
    nmWall->bind(3);

    //-------------------------------


    //Gérer la vue
    // la matrice finale = matWORLD * matVIEW * matPROJ
    // on place donc la caméra; la matVIEW
    // OpenGL -> matrices inversees... donc cacul inverse; matPROJ * matVIEW * matWORLD

    QMatrix4x4 matWorld, matView, matProj;
    matWorld.setToIdentity();
    matView.setToIdentity();
    matProj.setToIdentity();

    matWorld.rotate(0,0,0);
    matWorld.translate(0, 0, 0);
    matWorld.scale(1,1,1);

    //Calcul du vecteur directeur de la camera
    float camRotX_rad = (cam.getCamRotX() / 360.0f) * 6.2831853f;
    float camRotY_rad = (cam.getCamRotY() / 360.0f) * 6.2831853f;
    QVector3D cameraDirection(cam.getCamPosX() + cosf(camRotY_rad), cam.getCamPosY() + sinf(camRotX_rad), cam.getCamPosZ() + sinf(camRotY_rad));

    //Où l'on regarde
    matView.lookAt(QVector3D(cam.getCamPosX(), cam.getCamPosY(), cam.getCamPosZ()), cameraDirection, QVector3D(0, 1, 0));

    //Projection, angle de vue...
    float near = 1.0f;
    float far = 100.0f;
    matProj.perspective(80.0f, 4.0f/3.0f, near, far);

    //-------------------------------


    //Fournir au programme l'ensemble des données utiles
    m_program->setUniformValue( m_matrixUniform, matProj * matView * matWorld );
    m_program->setUniformValue( m_camPos, QVector3D( cam.getCamPosX(), cam.getCamPosY(), cam.getCamPosZ() ) );
    m_program->setUniformValue( "tex", 0 );
    m_program->setUniformValue( "nmTex", 1 );
    m_program->setUniformValue( "lightPos", QVector3D(0.5f,1.0f,0.3f));
    m_program->setUniformValue( "model" ,matWorld);
    m_program->setUniformValue( "near" ,near);
    m_program->setUniformValue( "far" ,far);


    createFace(QVector3D(0.0, 0.0, 0.0), 50.0, 50.0, matProj*matView*matWorld,QVector3D(0,0,0),QVector3D(-90,0,0),QVector3D(1,1,1),0);

    createCube(1.0, matProj*matView*matWorld,QVector3D(0,0,0),QVector3D(0,0,0),QVector3D(1,1,1),1);

    createCube(2.0, matProj*matView*matWorld,QVector3D(5,1,0),QVector3D(0,45,0),QVector3D(1,1,1),1);

    //createTour(2.0, 2.0, matProj*matView*matWorld, QVector3D(-5,1,0),QVector3D(0,0,0),QVector3D(1,1,1),1);


    //createMur(1.0,QVector3D(1.0,2.0,2.0),matProj*matView*matWorld,QVector3D(1,0,0),QVector3D(0,90,0),QVector3D(1,1,1),1);
    m_program->release();

    ++m_frame;

}

void CastleWindow::initTextures(int nbTexture){
    m_program->setUniformValue( "tex", nbTexture*2 );
    m_program->setUniformValue( "nmTex", (nbTexture*2)+1 );
}

QMatrix4x4 CastleWindow::createMatrixWorld(QVector3D translate, QVector3D rotate, QVector3D scale){
    QMatrix4x4 matWorld;
    matWorld.setToIdentity();
    matWorld.scale(scale);
    matWorld.translate(translate);
    matWorld.rotate(rotate.x(),QVector3D(1.0,0.0,0.0));
    matWorld.rotate(rotate.y(),QVector3D(0.0,1.0,0.0));
    matWorld.rotate(rotate.z(),QVector3D(0.0,0.0,1.0));

    return matWorld;
}

void CastleWindow::createFace(QVector3D pos, GLfloat lenghtX, GLfloat lenghtY, QMatrix4x4  matGlobale,QVector3D translate, QVector3D rotate, QVector3D scale,int texture){

    QMatrix4x4 matWorld = createMatrixWorld(translate,rotate,scale);
    initTextures(texture);

    m_program->setUniformValue( m_matrixUniform, matGlobale * matWorld );


    //Vertex
    QVector3D pos1(pos.x()-lenghtX/2, pos.y()+lenghtY/2, pos.z());
    QVector3D pos2(pos.x()-lenghtX/2, pos.y()-lenghtY/2, pos.z());
    QVector3D pos3(pos.x()+lenghtX/2, pos.y()-lenghtY/2, pos.z());
    QVector3D pos4(pos.x()+lenghtX/2, pos.y()+lenghtY/2, pos.z());
    //Tex
    QVector2D uv1(0.0, 1.0);
    QVector2D uv22(0.0, 0.0);
    QVector2D uv3(1.0, 0.0);
    QVector2D uv4(1.0, 1.0);
    //Vecteur Normal
    QVector3D nm;//(0.0, 0.0, 1.0);
    nm.crossProduct(pos1,pos2);

    // calculate tangent/bitangent vectors of both triangles
    QVector3D tangent1, bitangent1;
    QVector3D tangent2, bitangent2;
    // - triangle 1
    QVector3D edge1 = pos2 - pos1;
    QVector3D edge2 = pos3 - pos1;
    QVector2D deltaUV1 = uv22 - uv1;
    QVector2D deltaUV2 = uv3 - uv1;

    GLfloat f = 1.0f / (deltaUV1.x() * deltaUV2.y() - deltaUV2.x() * deltaUV1.y());

    tangent1.setX(f * (deltaUV2.y() * edge1.x() - deltaUV1.y() * edge2.x()));
    tangent1.setY(f * (deltaUV2.y() * edge1.y() - deltaUV1.y() * edge2.y()));
    tangent1.setZ(f * (deltaUV2.y() * edge1.z() - deltaUV1.y() * edge2.z()));
    tangent1.normalize();

    bitangent1.setX(f * (-deltaUV2.x() * edge1.x() + deltaUV1.x() * edge2.x()));
    bitangent1.setY(f * (-deltaUV2.x() * edge1.y() + deltaUV1.x() * edge2.y()));
    bitangent1.setZ(f * (-deltaUV2.x() * edge1.z() + deltaUV1.x() * edge2.z()));
    bitangent1.normalize();

    // - triangle 2
    edge1 = pos3 - pos1;
    edge2 = pos4 - pos1;
    deltaUV1 = uv3 - uv1;
    deltaUV2 = uv4 - uv1;

    f = 1.0f / (deltaUV1.x() * deltaUV2.y() - deltaUV2.x() * deltaUV1.y());

    tangent2.setX(f * (deltaUV2.y() * edge1.x() - deltaUV1.y() * edge2.x()));
    tangent2.setY(f * (deltaUV2.y() * edge1.y() - deltaUV1.y() * edge2.y()));
    tangent2.setZ(f * (deltaUV2.y() * edge1.z() - deltaUV1.y() * edge2.z()));
    tangent2.normalize();


    bitangent2.setX(f * (-deltaUV2.x() * edge1.x() + deltaUV1.x() * edge2.x()));
    bitangent2.setY(f * (-deltaUV2.x() * edge1.y() + deltaUV1.x() * edge2.y()));
    bitangent2.setZ(f * (-deltaUV2.x() * edge1.z() + deltaUV1.x() * edge2.z()));
    bitangent2.normalize();



     GLfloat vertices2[] = {
         pos1.x(), pos1.y(), pos1.z(),
         pos2.x(), pos2.y(), pos2.z(),
         pos3.x(), pos3.y(), pos3.z(),

         pos1.x(), pos1.y(), pos1.z(),
         pos3.x(), pos3.y(), pos3.z(),
         pos4.x(), pos4.y(), pos4.z(),
    };

    GLfloat uv2[] = {
        uv1.x(),uv1.y(),
        uv22.x(),uv22.y(),
        uv3.x(),uv3.y(),

        uv1.x(),uv1.y(),
        uv3.x(),uv3.y(),
        uv4.x(),uv4.y(),
    };

    GLfloat tangent[] = {
        tangent1.x(), tangent1.y(), tangent1.z(),

        tangent2.x(), tangent2.y(), tangent2.z(),
    };

    GLfloat bitangent[] = {
        bitangent1.x(), bitangent1.y(), bitangent1.z(),

        bitangent2.x(), bitangent2.y(), bitangent2.z(),
    };

    glEnableVertexAttribArray( 0 );
    glEnableVertexAttribArray( 1 );
    glEnableVertexAttribArray( 2 );
    glEnableVertexAttribArray( 3 );

    glVertexAttribPointer( m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, vertices2 );
    glVertexAttribPointer( m_uvAttr, 2, GL_FLOAT, GL_FALSE, 0, uv2 );
    glVertexAttribPointer( m_tangent, 3, GL_FLOAT, GL_FALSE, 0, tangent );
    glVertexAttribPointer( m_bitangent, 3, GL_FLOAT, GL_FALSE, 0, bitangent );

    glDrawArrays( GL_TRIANGLES, 0, 6 );

    glDisableVertexAttribArray( 3 );
    glDisableVertexAttribArray( 2 );
    glDisableVertexAttribArray( 1 );
    glDisableVertexAttribArray( 0 );
}

void CastleWindow::createCube(GLfloat lenght, QMatrix4x4  matGlobale,QVector3D translate, QVector3D rotate, QVector3D scale,int texture){

    QMatrix4x4 matWorld = createMatrixWorld(translate,rotate,scale);

    //Face Bas
    createFace(QVector3D(0.0, 0.0, 0.0), lenght, lenght, matGlobale * matWorld,QVector3D(0,-lenght/2.0,0),
               QVector3D(90,0,0),QVector3D(1,1,1),texture);

    //Face Haut
    createFace(QVector3D(0.0, 0.0, 0.0), lenght, lenght, matGlobale * matWorld,QVector3D(0,lenght/2.0,0),
               QVector3D(-90,0,0),QVector3D(1,1,1),texture);

   //Face Avant
   createFace(QVector3D(0.0, 0.0, 0.0), lenght, lenght, matGlobale * matWorld,QVector3D(0,0,lenght/2.0),
               QVector3D(0,0,0),QVector3D(1,1,1),texture);

    //Face Arrière
    createFace(QVector3D(0.0, 0.0, 0.0), lenght, lenght, matGlobale * matWorld,QVector3D(0,0,- lenght/2.0),
               QVector3D(0,180,0),QVector3D(1,1,1),texture);

    //Face Droite
    createFace(QVector3D(0.0, 0.0, 0.0), lenght, lenght, matGlobale * matWorld,QVector3D(lenght/2.0,0,0),
               QVector3D(0,90,0),QVector3D(1,1,1),texture);

    //Face Gauche
    createFace(QVector3D(0.0, 0.0, 0.0), lenght, lenght, matGlobale * matWorld,QVector3D(- lenght/2.0,0,0),
               QVector3D(0,0-90,0),QVector3D(1,1,1),texture);
}

Vertex shader :

static const char *vertexShaderSource =
    "#version 120
"
    "attribute highp vec4 posAttr;
" //Positions des vertex
    "attribute highp vec3 nmAttr;
"  //Positions des vertex normales
    "attribute lowp vec2 uvAttr;
"   //Position de la texture
    "attribute highp vec3 tangent;
" //Vecteur tangent
    "attribute highp vec3 bitangent;
"//Vecteur bitangent

                                     //A transmettre au fragment shader
    "varying lowp vec2 uv;
"        //Positions de la texture
    "varying lowp vec4 p;
"         //Positions du vertex
    "varying lowp vec3 fragPos;
"   //Positions du fragment
    "varying lowp vec3 nm;
"        //Positions des vertex normales
    "varying lowp vec3 tangentLightPos;
" //Les tangents pour la lumière
    "varying lowp vec3 tangentViewPos;
"  //vue
    "varying lowp vec3 tangentFragPos;
"  // fragment


    "uniform highp mat4 matrix;
"    //WorldMatrix * ViewMatrix * ProjectionMatrix
    "uniform lowp vec3 camPos;
"    //Vecteur de position de la camera
    "uniform lowp vec3 lightPos;
"  //Position de la lumière
    "uniform highp mat4 model;
"     //WorldMatrix
    "void main() {
"
    "   uv = uvAttr;
"
    "	p = posAttr;
"
    "	nm = nmAttr;
"
    "   fragPos = vec3(model * posAttr);
"

    "   mat3 normalMatrix = transpose(inverse(mat3(model)));
"
    "   vec3 T = normalize(normalMatrix * tangent);
"
    "   vec3 B = normalize(normalMatrix * bitangent);
"
    "   vec3 N = normalize(normalMatrix * nmAttr);
"

    "   mat3 TBN = transpose(mat3(T, B, N));
"
    "   tangentLightPos = TBN * lightPos;
"
    "   tangentViewPos  = TBN * camPos;
"
    "   tangentFragPos  = TBN * fragPos;
"

    "	vec4 wvp_pos = matrix * posAttr;
"
    "   gl_Position = wvp_pos;
"
    "}
";

Fragment shader (the first main is for the display of the z-test) :

static const char *fragmentShaderSource =
    "#version 120
"
    "varying lowp vec2 uv;
"
    "varying lowp vec3 nm;
"
    "varying lowp vec4 p;
"
    "varying lowp vec3 fragpos;
"
    "varying lowp vec3 tangentLightPos;
"
    "varying lowp vec3 tangentViewPos;
"
    "varying lowp vec3 tangentFragPos;
"

    "uniform sampler2D tex;
"
    "uniform sampler2D nmTex;
"

    "uniform float near;
"
    "uniform float far;
 "

        "void main()
"
        "{
"
            "float depth = ( 2.0 * near * far) / (far + near - (gl_FragCoord.z * 2.0 - 1.0) * (far -near) )/ far;
" // divide by far for demonstration
            "gl_FragColor = vec4(vec3(depth), 1.0f);
"
        "}
";
/*
    "void main() {
"
    "   gl_FragDepth = ( 2.0 * near * far) / (far + near - (gl_FragCoord.z * 2.0 - 1.0) * (far -near) )/ far;
"
        // Obtain normal from normal map in range [0,1]
    "       vec3 normal = texture2D(nmTex, uv).rgb;
"
        // Transform normal vector to range [-1,1]
    "       normal = normalize(normal * 2.0 - 1.0);
"// this normal is in tangent space
        // Get diffuse color
    "       vec3 color = texture2D(tex, uv).rgb;
"
        // Ambient
    "       vec3 ambient = 0.8 * color;
"
        // Diffuse
    "       vec3 lightDir = normalize(tangentLightPos - tangentFragPos);"
    "       float diff = max(dot(lightDir, normal), 0.0);
"
    "       vec3 diffuse = diff * color;
"
        // Specular
    "       vec3 viewDir = normalize(tangentViewPos - tangentFragPos);
"
    "       vec3 reflectDir = reflect(-lightDir, normal);
"
    "       vec3 halfwayDir = normalize(lightDir + viewDir);
"
    "       float spec = pow(max(dot(normal, halfwayDir), 0.0), 32.0);
"
    "       vec3 specular = vec3(0.2) * spec;
"
    "       gl_FragColor = vec4(ambient + diffuse + specular, 1.0f);
"
    "}
"*/;

I use glEnable( GL_DEPTH_TEST ); and glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); but that not really helping…
So, if you can help me and find a solution, it would be wonderful…

And sorry for my bad english, i’m a french student.

Have you created your GL context with a depth buffer?

In the function initialize() I enable depth test this way:

// Enable depth buffer    
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LESS );

[QUOTE=Shurin;1280465]In the function initialize() I enable depth test this way:

// Enable depth buffer    
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LESS );[/QUOTE]

That’s not enough. If OpenGL doesn’t have a depth buffer you can still call these and nothing will happen.

How do you create your window?

[QUOTE=mhagain;1280467]That’s not enough. If OpenGL doesn’t have a depth buffer you can still call these and nothing will happen.

How do you create your window?[/QUOTE]

I create my window (castleWindow) in main like this.


int main(int argc, char **argv)
{
    QGuiApplication app(argc, argv);

    QSurfaceFormat format;
    format.setSamples(16);

    CastleWindow window;
    window.setFormat(format);
    window.resize(640, 480);
    window.show();

    window.setAnimating(true);

    return app.exec();
}

So, I have to create the depth buffer in there?

Yes. You need e.g.


format.setDepthBufferSize(24);

[QUOTE=GClements;1280470]Yes. You need e.g.


format.setDepthBufferSize(24);

[/QUOTE]

Thanks to you i fell stupid but it’s working now :o
Thanks a lot!