2014-12-25 106 views
2

我无法在我的应用程序中获得阴影映射。我尝试渲染一辆四轮摩托车,并在它下面的地板上观察它的影子。 这是我的一些代码。 纹理制作:OpenGL中的阴影映射

// Create a depth texture 
    glGenTextures(1, &depth_texture); 
    glBindTexture(GL_TEXTURE_2D, depth_texture); 
    // Allocate storage for the texture data 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32 ,1600, 900, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); 
    // Set the default filtering modes 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    // Set up wrapping modes 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
    glBindTexture(GL_TEXTURE_2D, 0); 
    // Create FBO to render depth into 
    glGenFramebuffers(1, &depth_fbo); 
    glBindFramebuffer(GL_FRAMEBUFFER, depth_fbo); 
    // Attach the depth texture to it 
    glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
    depth_texture, 0); 
    // Disable color rendering as there are no color attachments 
    glDrawBuffer(GL_NONE); 
    //check fbo status 
    GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER); 
    if(result != GL_FRAMEBUFFER_COMPLETE) 
     throw std::runtime_error("shadow mapping framebuffer error"); 
    //bind default framebuffer 
    glBindFramebuffer(GL_FRAMEBUFFER, 0); 

渲染到深度纹理:

progShadow.Use(); 
glBindFramebuffer(GL_FRAMEBUFFER, depth_fbo); 

glClear(GL_DEPTH_BUFFER_BIT); 

glm::mat4 shadowProjection = glm::frustum(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 100.0f); 
glm::mat4 shadowView = glm::lookAt(light.position, glm::vec3(0,0,0), glm::vec3(0,1,0)); 
glm::mat4 shadowModel(1); 
if(g_rotate) 
    shadowModel = glm::rotate((float)clock()/(float)CLOCKS_PER_SEC, glm::vec3(0,1,0)); 
glm::mat4 shadowMVP = shadowProjection * shadowView * shadowModel; 
progShadow.SetUniform("MVPMatrix", shadowMVP); 
quadBike.Draw(); 

我也用的是我的呈现深度纹理“测试”着色器程序。这是它的样子。 image

所以我觉得我很好,直到现在。 现在我正常渲染场景。

glBindTexture(GL_TEXTURE_2D, depth_texture); 
prog.Use();//main program 
glBindFramebuffer(GL_FRAMEBUFFER, 0); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
glm::mat4 shadowBias = glm::mat4(0.5, 0.0, 0.0, 0.0, 
           0.0, 0.5, 0.0, 0.0, 
           0.0, 0.0, 0.5, 0.0, 
           0.5, 0.5, 0.5, 1.0); 
glm::mat4 ShadowBiasMVP = shadowBias * shadowMVP; 
prog.SetUniform("ShadowBiasMVP", ShadowBiasMVP); 

//draw quadBike and floor 
... 

我的顶点着色器的相关部分:

#version 430 

... 

out vec4 shadowCoord; 

void main() 
{ 
    gl_Position = ProjectionMatrix * CameraMatrix * ModelMatrix * vec4(vertex, 1.0); 
    shadowCoord = ShadowBiasMVP * vec4(vertex, 1.0); 
    ... 
} 

我的片段着色器的相关部分:

#version 430 

... 

uniform sampler2D shadowMap; 
in vec4 shadowCoord; 

void main() 
{ 
    ... 

    float visibility = 1.0; 
    if (texture(shadowMap, shadowCoord.xy).z < shadowCoord.z) 
     visibility = 0.0; 

    ... 
} 

现在的问题是,我得到一个场景是因为如果完全黑暗它全部被阴影覆盖。只有当灯光非常接近四轮摩托车时,才能正常呈现。 (深度纹理在右侧是可见的,因为它是用不同的程序渲染的,我用它来测试) scene

我在做什么错了?

+0

偏置矩阵的目的是将'xy'(纹理坐标)和z(深度)重新缩放(x ** 0.5 **)和偏移(+ ** 0.5 **)纹理坐标和深度范围[** 0.0 **,** 1.0 **]来自剪辑空间([** - w **,** w **])。为了完成偏倚矩阵应该做的变换,你需要用'w'来划分(现在你的数学只有在'shadowCoord.w'是** 1.0 **时才有效,如果你是使用透视投影)。 –

回答

1
  1. 您应该在第一个组件处读取灰度depthtexture。

    texture(shadowMap, shadowCoord.xy).r

    texture(shadowMap, shadowCoord.xy).x

  2. 暗影坐标应当dehomogenized(由瓦特除以)内插之后。

    - >在片段着色器:shadowPos = shadowPos/shadowPos.w;

  3. 如果像面偏移没有其他的技术被用于需要从。减去阴影深度值偏向于防止自阴影。

以下是计算片段着色器中阴影的示例函数。注意:它是延迟渲染器的一部分,这就是矩阵乘法在片段着色器中完成的原因。

float calculateShadow(vec3 position){ 
    vec4 shadowPos = depthBiasMV * vec4(position,1); 
    shadowPos = shadowPos/shadowPos.w; 


    float bias = 0.0012; 
    float visibility = 1.0f; 
    if ((shadowPos.x < 0 || shadowPos.x > 1 || shadowPos.y < 0 || shadowPos.y > 1 || shadowPos.z < 0 || shadowPos.z > 1)){ 
     visibility = 1.0f; 
    }else{ 
     float shadowDepth = texture(depthTex, shadowPos.xy).r; 
     if(shadowDepth<shadowPos.z-bias) 
      visibility = 0.0f; 
    } 
    return visibility; 

} 
+0

使用您发布的功能,我在地板上获得了非常大的影子。 [链接](http://s30.postimg.org/pbzx2fy41/scenee.png) – Pilpel

+0

仍然坚持在这:(:(谁能够发布一个良好的指南,广泛解释这个话题的链接?使用[this](http ://www.opengl-tutorial。org/intermediate-tutorials/tutorial-16-shadow-mapping /)教程没有解决我的问题。 – Pilpel

+0

事情是基本的阴影映射其实很简单,所以你可能有一个愚蠢的错误。但也许阅读其他教程将有所帮助。 http://ogldev.atspace.co.uk/www/tutorial23/tutorial23.html – dari