2017-07-15 131 views
0

我想渲染我的深度图,现在我已经把它渲染到场景中的对象上,以获得我得到的结果的概览。从我所了解到的情况来看,黑色值是靠近光线的物体,而白色距离较远。如果我弄错了,请纠正我。这是我得到的结果:Shadow map rendered onto a cubeOpenGL - 阴影地图/深度地图给出奇怪的结果

有了这个结果,我推测我以错误的方式创建了framebuffer。我这是怎么产生的呢:

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

我们都跟着Learn OpenGL - Shadow Mapping教程,和我们的着色器看起来几乎相同,他的。所以那里不应该有任何问题。我想我误解了阴影映射的CPU部分,而不是GPU。这是我绘制所有东西,设置矩阵和使用程序的方式。

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

我真的很感谢所有的提示和帮助提前。如果我遗漏了关键信息,我会添加缺失的内容。

更多的渲染部分编辑的代码,还编辑我们得出这样:

这是主循环

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

      } 

在这里,我们有一个使用阴影GLSL程序RenderShadows功能:

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

} 

最后渲染几何的普通渲染函数:

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

} 

回答

2

如果你想渲染你的深度缓冲你有一个纹理绑定GL_DEPTH_COMPONENT格式的 渲染你的帧缓冲缓冲缓冲纹理。你所做的是将纹理绑定到帧缓冲区的颜色计划0,因为你使用GL_COLOR_ATTACHMENT0来绑定代码中的纹理。

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

你需要做的是创建一个渲染缓冲区并将其绑定到帧缓冲区。

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

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

然后你有你的深度纹理结合使用GL_DEPTH_ATTACHMENT帧缓冲:

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

请注意,您可以绑定为深缓冲器分开的纹理和色彩的所有飞机的帧缓冲区。

正确完成此操作后,您必须绘制场景并填充缓冲区和/或纹理。

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

你的帧缓冲后一直解除绑定,你可以使用它的纹理,因为你的身影通输入。

要将纹理绑定到着色器,必须将纹理绑定到纹理单元,并将纹理单元的索引指定给着色器的统一采样器。

绑定的质地纹理单元:

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

使用程序和assigne纹理单元,以均匀采样指数:

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

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

答案的扩展

代码中还有一些问题:

在主循环中在你调用RenderShadows之前清除帧缓冲区glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);,但是在函数内部绑定一个帧缓冲区glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);,所以清除没用。

RenderShadows您尝试DepthMap纹理绑定到纹理采样, 但DepthMap质地当前绑定的帧缓冲区的目标质感。纹理不能同时作为源和目标,这会导致未定义的行为。

RenderVertices您必须将指数纹理单元的分配给 纹理采样不是纹理对象:

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

您好,感谢您的长期答案!我试图做你如何说,但它似乎不起作用。我添加了一架飞机,并将DepthMap作为纹理加入,但它没有任何内容。如果我使用GL_COLOR_ATTACHMENT0,它会变成黑色,如果我使用GL_DEPTH_ATTACHMENT,则全是灰色。难道DepthMap没有从阴影顶点/片段着色器中获取任何东西? – Haplue

+0

您是否启用了深度测试? (我将其添加到我的答案中。) – Rabbid76

+0

启用了深度测试(在创建帧缓冲区之前),并且我在渲染中进行了更改以使其更易于查看。如果您觉得有时间检查它,我会添加我的渲染代码,它会在粗体文本之后开始。谢谢你的帮助,这意味着很多! – Haplue