阴影贴图 - 将视图空间位置转换为阴影贴图空间

时间:2015-11-28 19:35:50

标签: opengl math matrix 3d glsl

我使用延迟渲染,并在相机视图空间中存储片段位置。当我执行阴影计算时,我需要将摄像机视图空间转换为阴影贴图空间。我用这种方式构建了一个阴影矩阵:

shadowMatrix  = shadowBiasMatrix * lightProjectionMatrix * lightViewMatrix * inverseCameraViewMatrix;

shadowBiasMatrix将值从[-1,1]移位到[0,1]范围。 lightProjectionMatrix是定向光的正交投影矩阵。 lightViewMatrix查看视锥体中心并包含光线方向。 inverseCameraViewMatrix将片段位置从摄像机视图空间转换为世界空间。

我想知道将逆相机视图矩阵与其他矩阵相乘是否正确?也许我应该单独使用逆相机视图矩阵?

第一种情况:

vec4 shadowCoord = shadowMatrix * vec4(cameraViewSpacePosition, 1.0);

第二种情况,反向摄像机视图矩阵单独使用:

vec4 worldSpacePosition = inverseCameraViewSpaceMatrix * vec4(cameraViewSpacePosition, 1.0);
vec4 shadowCoord = shadowMatrix * worldSpacePosition;

1 个答案:

答案 0 :(得分:2)

以所描述的方式预先计算阴影矩阵是正确的方法,应该按预期工作。

由于矩阵乘法的相关性,三个场景的结果应该相同(忽略浮点精度),因此是可互换的。 但是因为这些计算是在片段着色器中完成的,所以最好将主程序中的矩阵预乘,以便对每个片段进行尽可能少的操作。

我目前也在编写一个延迟渲染器,并以同样的方式计算我的矩阵,没有任何问题。

// precomputed: lightspace_mat = light_projection * light_view * inverse_cam_view
// calculate position in clip-space of the lightsource
vec4 lightspace_pos = lightspace_mat * vec4(viewspace_pos, 1.0);

// perspective divide
lightspace_pos/=lightspace_pos.w;

// move range from [-1.0, 1.0] to [0.0, 1.0]
lightspace_pos = lightspace_pos * vec4(0.5) + vec4(0.5);

// sample shadowmap
float shadowmap_depth = texture(shadowmap, lightspace_pos.xy).r;
float fragment_depth  = lightspace_pos.z;

我还使用simillar方法找到了本教程,这可能会有所帮助:http://www.codinglabs.net/tutorial_opengl_deferred_rendering_shadow_mapping.aspx

float readShadowMap(vec3 eyeDir)
{
    mat4 cameraViewToWorldMatrix = inverse(worldToCameraViewMatrix);
    mat4 cameraViewToProjectedLightSpace = lightViewToProjectionMatrix * worldToLightViewMatrix * cameraViewToWorldMatrix;
    vec4 projectedEyeDir = cameraViewToProjectedLightSpace * vec4(eyeDir,1);
    projectedEyeDir = projectedEyeDir/projectedEyeDir.w;

    vec2 textureCoordinates = projectedEyeDir.xy * vec2(0.5,0.5) + vec2(0.5,0.5);

    const float bias = 0.0001;
    float depthValue = texture2D( tShadowMap, textureCoordinates ) - bias;
    return projectedEyeDir.z * 0.5 + 0.5 < depthValue;
}
     

输入的eyeDir位于View Space中。要找到像素   阴影贴图我们需要采取这一点并将其转换为   light的剪辑空间,意味着从Camera View Space进入   世界空间,然后进入光视空间,而不是光投影   空间/剪辑空间。所有这些转换都是使用矩阵完成的;   如果你不熟悉空间变化,你可能想读我的   关于空间和变换的文章。

     

一旦我们在正确的空间,我们计算纹理坐标   我们终于准备好从阴影贴图中读取。偏见很小   我们应用于地图中的值的偏移量,以避免因为   舍入错误一个点最终遮蔽自己!所以我们改变了所有   稍微映射一下,使地图中的所有值都略小一些   比他们应该的。