2017-03-08 95 views
-1

我试图在延迟渲染管道中实现阴影贴图,但是我遇到了几个实际产生阴影贴图的问题,然后对像素进行了阴影处理 - 我认为这些像素应该只是阴影不是。阴影贴图产生不正确的结果

我有一个单向灯,这是我的引擎中的'太阳'。我已经推迟渲染设置照明,到目前为止正常工作。我再次渲染场景成深度仅FBO为阴影图,使用以下代码来生成视图矩阵:

glm::vec3 position = r->getCamera()->getCameraPosition(); // position of level camera 
glm::vec3 lightDir = this->sun->getDirection(); // sun direction vector 
glm::mat4 depthProjectionMatrix = glm::ortho<float>(-10,10,-10,10,-10,20); // ortho projection 
glm::mat4 depthViewMatrix = glm::lookAt(position + (lightDir * 20.f/2.f), -lightDir, glm::vec3(0,1,0)); 

glm::mat4 lightSpaceMatrix = depthProjectionMatrix * depthViewMatrix; 

然后,在我的照明着色器,我使用下面的代码来确定是否一个像素在阴影中:

// lightSpaceMatrix is the same as above, FragWorldPos is world position of the texekl 
vec4 FragPosLightSpace = lightSpaceMatrix * vec4(FragWorldPos, 1.0f); 

// multiply non-ambient light values by ShadowCalculation(FragPosLightSpace) 
// ... do more stuff ... 

float ShadowCalculation(vec4 fragPosLightSpace) { 
    // perform perspective divide 
    vec3 projCoords = fragPosLightSpace.xyz/fragPosLightSpace.w; 
    // vec3 projCoords = fragPosLightSpace.xyz; 

    // Transform to [0,1] range 
    projCoords = projCoords * 0.5 + 0.5; 

    // Get closest depth value from light's perspective (using [0,1] range fragPosLight as coords) 
    float closestDepth = texture(gSunShadowMap, projCoords.xy).r; 

    // Get depth of current fragment from light's perspective 
    float currentDepth = projCoords.z; 

    // Check whether current frag pos is in shadow 
    float bias = 0.005; 
    float shadow = (currentDepth - bias) > closestDepth ? 1.0 : 0.0; 

    // Ensure that Z value is no larger than 1 
    if(projCoords.z > 1.0) { 
     shadow = 0.0; 
    } 

    return shadow; 
} 

但是,这并不真正让我知道我在做什么。这里的遮蔽后的输出的屏幕截图,以及阴影映射半assedly在Photoshop转换为图像:

Render Output 渲染输出

Shadow Map 阴影图

由于定向光在我的着色器中唯一的光,看起来阴影贴图被正确渲染得非常接近,因为透视图/方向大致匹配。然而,我不明白的是为什么没有一个茶壶真的最终会对其他人产生影子。

我很感谢任何关于我可能会做错什么的指针。我认为我的问题在于计算光线空间矩阵(我不知道如何正确地计算出这个问题,给出一个移动的摄像头,这样就可以更新视图中的东西),或者按照我确定的方式延迟渲染器的纹理是否在阴影中。 (FWIW,我从深度缓冲区确定世界位置,但我已经证明这个计算工作正常。)

感谢您的任何帮助。

回答

1

调试阴影问题可能会非常棘手。如果你看一下你的渲染观察,你会真正看到在左上角盆的一个影子

  1. :让我们开始的几个点。

  2. 尝试旋转你的太阳,这通常有助于查看光转换矩阵是否存在任何问题。从你的输出中看来,太阳是非常水平的,可能不会在这个设置上投下阴影。 (另一个角度可能会显示更多的阴影)

  3. 看起来好像您正在计算矩阵,但尝试缩小glm :: ortho(-10,10,-10,10,-10,20)中的最大深度)紧紧地适合你的场景。如果深度过大,则会失去精度,阴影会产生伪影。

  4. 为了形象问题的根源所在,从进一步的到来,尝试从这里outputing从阴影贴图的查找结果:

closestDepth = texture(gSunShadowMap, projCoords.xy).r 

如果阴影贴图被正确投影,那么你知道你在深度比较中存在问题。希望这可以帮助!

+0

谢谢 - 事实证明,当我分配我的深度纹理用于阴影贴图时,我将错误的值传递给OpenGL,导致着色器在读取时错误地解释贴图。奇怪,但现在起作用。 –