2017-07-15 12 views
0

Ich versuche, meine Tiefenkarte zu rendern, jetzt habe ich sie auf die Objekte in der Szene gerendert, um einen Überblick zu bekommen, was das Ergebnis ist, das ich bekomme. Aus dem, was ich gelernt habe, sind die schwarzen Werte Objekte, die nah am Licht sind, und Weiß ist weiter weg. Bitte korrigieren Sie mich, wenn ich es falsch verstanden habe. Dies ist das Ergebnis, das ich bekomme: Shadow map rendered onto a cubeOpenGL - Schattenkarte/Tiefenkarte mit seltsamen Ergebnissen

Mit diesem Ergebnis spekuliere ich, dass ich den Framebuffer in der falschen Weise erstellt habe. das ist, wie ich es generieren:

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); 
} 

Wir haben die Learn OpenGL - Shadow Mapping Tutorial befolgt haben, und unsere Shadern sieht zu seiner fast identisch. Also sollte es dort kein Problem geben. Ich denke, ich habe etwas im CPU-Teil des Shadow-Mapping missverstanden und nicht die GPU. So zeichne ich alles, richte Matrizen ein und benutze Programme.

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(); 
} 

Ich bin wirklich dankbar für alle Tipps und Hilfe im Voraus. Wenn ich wichtige Informationen weggelassen habe, füge ich hinzu, was fehlt.

Weitere Code des Rendering Teil bearbeiten, bearbeitet auch die Art, wie wir ziehen:

Dies ist die Hauptschleife

   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); 
       } 

      } 

Hier haben wir die RenderShadows Funktion haben, das den Schatten GLSL-Programm verwendet:

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); 

} 

Und schließlich die normale Funktion machen, die die Geometrie macht:

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); 

} 

Antwort

2

Wenn Sie Ihre Tiefenpuffer auf eine Textur Sie mit GL_DEPTH_COMPONENT-Format an den machen Puffer Ihres Frame-Buffer-Puffer eine Textur binden zu machen. Sie haben eine Textur an den Farbplan 0 Ihres Bildspeichers gebunden, weil Sie GL_COLOR_ATTACHMENT0 verwendet haben, um die Textur in Ihrem Code zu binden.

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

Was Sie tun müssen, ist einen Render-Puffer zu erstellen und binden Sie es an Ihren Bildspeicher.

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

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

Dann haben Sie Ihre Tiefe Textur an den Rahmenpuffer zu binden, mit GL_DEPTH_ATTACHMENT:

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

Beachten Sie, dass Sie separate Texturen für den tiefen Puffer und alle Farbebenen an den Rahmenpuffer binden kann.

Nachdem Sie dies richtig gemacht haben, müssen Sie Ihre Szene zeichnen und Ihre Puffer und/oder Texturen füllen.

// 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); 

nach dem Rahmenpuffer unbind, hat man seine Texturen als Eingabe für Ihren Schatten Pass nutzen können.

Um die Textur an den Shader zu binden, müssen Sie die Textur an eine Textureinheit binden und den Index der Textureinheit dem einheitlichen Sampler des Shaders zuweisen.

Bind die Textur auf eine Textureinheit:

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

Verwenden Sie das Programm und assigne den Index der Textureinheit zur einheitlichen Sampler:

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

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

Erweiterung der Antwort

Es gibt einige weitere Probleme in Ihrem Code:

In der Hauptschleife Sie Löschen Sie den Framebuffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);, bevor Sie RenderShadows aufrufen, aber innerhalb der Funktion binden Sie einen Framepuffer glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);, so dass das Löschen nutzlos ist.

In RenderShadows versuchen Sie die DepthMap Textur auf einen Textur-Sampler zu binden, aber die DepthMap Textur ist die Zieltextur des aktuell gebunden Frame-Buffer. Eine Textur kann nicht Quelle und Ziel gleichzeitig sein, dies würde zu undefiniertem Verhalten führen.

In RenderVertices haben Sie den Index der Textureinheit zur Textur Sampler nicht das Textur-Objekt zuordnen:

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

Hallo, danke für die ausführliche Antwort! Ich habe versucht zu tun, wie du es gesagt hast, aber es scheint, dass es nicht funktioniert. Ich habe ein Flugzeug hinzugefügt, und ich stelle die DepthMap als Textur dar, aber sie enthält nichts. Wenn ich GL_COLOR_ATTACHMENT0 verwende, wird es schwarz, wenn ich GL_DEPTH_ATTACHMENT verwende, ist alles grau. Könnte es sein, dass die DepthMap nichts vom Schatten-Vertex-/Fragment-Shader erhält? – Haplue

+0

Haben Sie den Tiefentest aktiviert? (Ich habe das zu meiner Antwort hinzugefügt.) – Rabbid76

+0

Der Tiefen-Test ist aktiviert (vor der Erstellung des Framebuffers), und ich habe das Rendering geändert, um es einfacher zu sehen. Ich habe den Code meines Renderings hinzugefügt, wenn Sie das Gefühl haben, dass Sie Zeit haben, es auszuprobieren, es beginnt nach dem fett gedruckten Text. Vielen Dank für Ihre Hilfe, es bedeutet viel! – Haplue

Verwandte Themen