2017-07-15 4 views
0

J'essaye de rendre ma carte de profondeur, pour l'instant je l'ai rendue sur les objets de la scène pour obtenir un aperçu du résultat que je reçois. D'après ce que j'ai appris, les valeurs noires sont des objets proches de la lumière et le blanc est plus éloigné. Corrigez-moi si je me trompe. Voici le résultat que j'obtiens: Shadow map rendered onto a cubeOpenGL - Shadow map/Depth Map donnant un résultat bizarre

Avec ce résultat, je suppose que j'ai créé le framebuffer dans le mauvais sens. voilà comment je générer:

void createFrameBuffer() 
{ 
    glGenFramebuffers(1, &frameBuffer); 


    glGenTextures(1, &DepthMap); 
    glBindTexture(GL_TEXTURE_2D, DepthMap); 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 
     SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 

    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,         
     GL_TEXTURE_2D, DepthMap, 0); 

    glDrawBuffer(GL_NONE); 
    glReadBuffer(GL_NONE); 

    glBindFramebuffer(GL_FRAMEBUFFER, 0); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
} 

Nous avons suivi le tutoriel Learn OpenGL - Shadow Mapping et nos shaders est presque identique à la sienne. Donc, il ne devrait pas y avoir de problème là-bas. Je pense que j'ai mal compris quelque chose dans la partie CPU du shadow mapping, et non dans le GPU. C'est comme ça que je dessine tout, que je mets des matrices et que j'utilise des programmes.

float orthoValue = 20.0f; 

glm::mat4 lightProjection = glm::ortho(-orthoValue, 
    orthoValue, -orthoValue, orthoValue, NEARPLANE, FARPLANE); 
glm::mat4 lightView = glm::lookAt(lightPos, glm::vec3(0.0f), 
    glm::vec3(0.0, 1.0f, 0.0)); 
glm::mat4 lightSpaceMatrix = lightProjection * lightView; 
//lightSpaceMatrix[3] = glm::vec4(lightPos, 1.0f); 

if (shadows == true) { 

    glUseProgram(sShaderProgram); 
    glBindVertexArray(mesh.VAO); 
    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
    glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); 
    glClear(GL_DEPTH_BUFFER_BIT); 
    glActiveTexture(GL_TEXTURE0); 


    glUniformMatrix4fv(glGetUniformLocation(sShaderProgram, "lightSpaceMatrix"), 
     1, GL_FALSE, glm::value_ptr(lightSpaceMatrix)); 
    glUniformMatrix4fv(glGetUniformLocation(sShaderProgram, "modelMatrix"), 
     1, GL_FALSE, glm::value_ptr(mesh.modelMatrix)); 

    glDrawArrays(GL_TRIANGLES, 0, mesh.vertices.size()); 
    glBindFramebuffer(GL_FRAMEBUFFER, 0); 
    glBindVertexArray(0); 

    setViewPort(); 
} 

Je suis vraiment reconnaissant pour tous les conseils et l'aide à l'avance. Si j'ai omis des informations cruciales, je vais ajouter ce qui manque.

Plus code de l'édition de rendu partiel, a également édité la façon dont nous tirons:

Ceci est la boucle principale

   glClearColor(0.0, 0.0, 0.5, 1); 
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
       glDisable(GL_CULL_FACE); 
       glEnable(GL_LIGHTING); 

       //Keyboard input 
       keyPressed(); 
       //Mouse movement 
       MousePointer(); 

       lightProjection = glm::ortho(-orthoValue, 
        orthoValue, -orthoValue, orthoValue, NEARPLANE, FARPLANE); 
       glm::lookAt(lightPos, glm::vec3(0.0f), 
        glm::vec3(0.0, 1.0, 0.0)); 
       lightSpaceMatrix = lightProjection * lightView; 

       glUseProgram(sShaderProgram); 
       glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); 
       glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
       glClear(GL_DEPTH_BUFFER_BIT); 

       glActiveTexture(GL_TEXTURE0); 
       glBindTexture(GL_TEXTURE_2D, DepthMap); 

       GLint samplerLoc = glGetUniformLocation(sShaderProgram, "DepthMap"); 
       glUniform1i(samplerLoc, 0); 

       glUniformMatrix4fv(glGetUniformLocation(sShaderProgram, "lightSpaceMatrix"), 
        1, GL_FALSE, glm::value_ptr(lightSpaceMatrix)); 

       for (int i = 0; i < objmesh.size(); i++) { 
        RenderShadows(*objmesh[i]); 
       } 
       glBindFramebuffer(GL_FRAMEBUFFER, 0); 
       setViewPort(); 
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
       //glDisable(GL_DEPTH_TEST); 

       for (int i = 0; i < objmesh.size(); i++){ 
        RenderVertices(gShaderProgram, *objmesh[i], true); 
       } 

      } 

Ici, nous avons la fonction RenderShadows qui utilise l'ombre GLSL programme:

void RenderShadows(OBJMeshes mesh){ 
glUniformMatrix4fv(glGetUniformLocation(sShaderProgram, "modelMatrix"), 
    1, GL_FALSE, glm::value_ptr(mesh.modelMatrix)); 

glBindVertexArray(mesh.VAO); 
glDrawArrays(GL_TRIANGLES, 0, mesh.vertices.size()); 
glBindVertexArray(0); 

} 

Et enfin la fonction normale rendu qui rend la géométrie:

void RenderVertices(GLuint shaderProgram, OBJMeshes mesh, bool shadows) { 

GLuint CPUValuesID = glGetUniformLocation(gUbo, "MVP"); 

glBindBuffer(GL_UNIFORM_BUFFER, gUbo); 
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(CPUMatricies), &globalCPU); 

glBindBuffer(GL_UNIFORM_BUFFER, mtlBuff); 
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(mtlValues), &mtl); 

glUniformMatrix4fv(CPUValuesID, 1, GL_FALSE, &globalCPU.MVP[0][0]); 

glUseProgram(shaderProgram); 
glBindVertexArray(mesh.VAO); 

glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, mesh.texture); 

glActiveTexture(GL_TEXTURE1); 
glBindTexture(GL_TEXTURE_2D, DepthMap); 

GLint samplerLoc = glGetUniformLocation(shaderProgram, "DepthMap"); 
glUniform1i(samplerLoc, 1); 

glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "modelMatrix"), 
    1, GL_FALSE, glm::value_ptr(mesh.modelMatrix)); 
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "lightSpaceMatrix"), 
    1, GL_FALSE, glm::value_ptr(lightSpaceMatrix)); 

glUniform3f(glGetUniformLocation(shaderProgram, "lightPos"), lightPos.x, lightPos.y, lightPos.z); 

glDrawArrays(GL_TRIANGLES, 0, mesh.vertices.size()); 

glBindVertexArray(0); 

} 

Répondre

2

Si vous voulez rendre votre tampon de profondeur à une texture, vous devez lier une texture au format GL_DEPTH_COMPONENT au tampon rendu de votre tampon de mémoire tampon de trame. Qu'est-ce que vous avez fait était de lier une texture à la couleur du plan 0 de votre tampon de trame, parce que vous avez utilisé GL_COLOR_ATTACHMENT0 pour lier la texture dans votre code.

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ColorMap0, 0); 

Ce que vous avez à faire est de créer un tampon de rendu et le lier à votre tampon de trame.

GLuint frameBuffer; 
glGenFramebuffers(1, &frameBuffer); 
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 

GLuint renderbuffer; 
glGenRenderbuffers(1, &renderbuffer); 
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 

Ensuite, vous devez lier votre texture de profondeur dans la mémoire tampon de cadre à l'aide GL_DEPTH_ATTACHMENT:

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, DepthMap, 0); 

Notez que vous pouvez lier des textures séparées pour le tampon profond et tous les plans de couleurs à la mémoire tampon de trame. Une fois que vous avez fait cela correctement, vous devez dessiner votre scène et remplir vos tampons et/ou textures.

// enable the depth test 
glEnable(GL_DEPTH_TEST); 

// bind frame buffer and clear the frame buffer and the depth buffer 
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)` 

// draw the scene 
// ... 

// unbind frame buffer 
glBindFramebuffer(GL_FRAMEBUFFER, 0); 

// clear the drawing buffer and the depth buffer 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

Après votre tampon de trame a été unbind, vous pouvez utiliser ses textures comme entrée pour votre carte d'ombre. Pour lier la texture au nuanceur, vous devez lier la texture à une unité de texture et affecter l'indice de l'unité de texture à l'échantillonneur uniforme du nuanceur.

Bind la texture à une unité de texture:

GLuint DepthMap; 
int textureUnit = 1; 
glActiveTexture(GL_TEXTURE0 + textureUnit); 
glBindTexture(GL_TEXTURE_2D, DepthMap); 

Utilisez le programme et assigne l'indice de l'unité de texture à l'échantillonneur uniforme:

GLuint depthProg = ...; 
glUseProgram(depthProg); 

GLint depthSamplerLocation = glGetUniformLocation(u_depthAttachment); 
glUniform1i(depthSamplerLocation, textureUnit); 

Extension de la réponse

Il y a encore quelques problèmes dans votre code:

dans la boucle principale vous effacer le tampon de trame glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); avant d'appeler RenderShadows, mais à l'intérieur de la fonction vous liez un tampon de trame glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);, de sorte que la suppression est inutile.

Dans RenderShadows vous essayez de lier la texture DepthMap à un sampler de texture, mais la texture DepthMap est la texture cible de la mémoire tampon de trame actuellement lié. Une texture ne peut pas être source et destination en même temps, cela entraînerait un comportement indéfini.

Dans RenderVertices vous devez attribuer l'indice de l'unité de texture à l'échantillonneur de texture pas l'objet de texture:

glActiveTexture(GL_TEXTURE1); 
glBindTexture(GL_TEXTURE_2D, DepthMap); 

GLint samplerLoc = glGetUniformLocation(shaderProgram, "DepthMap"); 
// glUniform1i(samplerLoc, DepthMap); <- this is wrong 
glUniform1i(samplerLoc, 1); // 1 because the texture is bound to GL_TEXTURE1 
+0

Bonjour, merci pour la réponse longue! J'ai essayé de faire comme tu l'as dit, mais il semble que ça ne marche pas. J'ai ajouté un avion, et je mets la DepthMap en tant que texture dessus mais elle n'a rien dessus. Si j'utilise GL_COLOR_ATTACHMENT0 il devient noir, si j'utilise le GL_DEPTH_ATTACHMENT, tout est gris. Se pourrait-il que le DepthMap ne reçoive rien de l'ombre shake/fragment shader? – Haplue

+0

Avez-vous activé le test de profondeur? (J'ai ajouté ceci à ma réponse.) – Rabbid76

+0

Le test de profondeur est activé (avant la création du framebuffer), et j'ai changé autour dans le rendu pour le rendre plus facile à voir. J'ai ajouté le code de mon rendu si vous avez le temps de le vérifier, il commence après le texte en gras. Merci pour votre aide, cela signifie beaucoup! – Haplue