PDA

View Full Version : Issue with depth-test



Shurin
11-30-2015, 03:22 AM
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):
2194

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

2193

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),QVector3 D(-90,0,0),QVector3D(1,1,1),0);

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

createCube(2.0, matProj*matView*matWorld,QVector3D(5,1,0),QVector3 D(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*matVi ew*matWorld,QVector3D(1,0,0),QVector3D(0,90,0),QVe ctor3D(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\n"
"attribute highp vec4 posAttr;\n" //Positions des vertex
"attribute highp vec3 nmAttr;\n" //Positions des vertex normales
"attribute lowp vec2 uvAttr;\n" //Position de la texture
"attribute highp vec3 tangent;\n" //Vecteur tangent
"attribute highp vec3 bitangent;\n"//Vecteur bitangent

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


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

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

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

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

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

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

"uniform sampler2D tex;\n"
"uniform sampler2D nmTex;\n"

"uniform float near;\n"
"uniform float far;\n "

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

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.

mhagain
11-30-2015, 05:28 AM
Have you created your GL context with a depth buffer?

Shurin
11-30-2015, 05:46 AM
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 );

mhagain
11-30-2015, 06:35 AM
In the function initialize() I enable depth test this way:

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

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?

Shurin
11-30-2015, 06:51 AM
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?


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?

GClements
11-30-2015, 07:00 AM
So, I have to create the depth buffer in there?
Yes. You need e.g.


format.setDepthBufferSize(24);

Shurin
11-30-2015, 07:06 AM
Yes. You need e.g.


format.setDepthBufferSize(24);


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