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

Opengl 阴影贴图-将视图空间位置转换为阴影贴图空间,opengl,math,matrix,3d,glsl,Opengl,Math,Matrix,3d,Glsl,我使用延迟渲染,并在摄影机视图空间中存储片段位置。执行阴影计算时,我需要将摄影机视图空间转换为阴影贴图空间。我以这种方式构建阴影矩阵: shadowMatrix = shadowBiasMatrix * lightProjectionMatrix * lightViewMatrix * inverseCameraViewMatrix; shadowBiasMatrix将值从[-1,1]范围移动到[0,1]范围。 lightProjectionMatrix是平行光的正交投影矩阵。lightVi

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

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;

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

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

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

// 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;
我还发现本教程使用了类似的方法,这可能会很有帮助:

float readShadowMap(vec3-eyeDir)
{
mat4 cameraViewToWorldMatrix=逆矩阵(worldToCameraViewMatrix);
mat4 CameraviewWToProjectedLightSpace=lightViewToProjectionMatrix*worldToLightViewMatrix*CameraviewWToWorldMatrix;
vec4 projectedEyeDir=cameraViewToProjectedLightSpace*vec4(eyeDir,1);
projectedeydir=projectedeydir/projectedeydir.w;
vec2纹理坐标=投影的edeyedir.xy*vec2(0.5,0.5)+vec2(0.5,0.5);
常数浮动偏差=0.0001;
浮动深度值=纹理2D(tShadowMap,纹理坐标)-偏差;
返回projectedeydir.z*0.5+0.5<深度值;
}
输入中的eyeDir位于视图空间中。在中查找像素 阴影贴图我们需要抓住那个点,把它隐藏到 灯光的剪辑空间,这意味着从摄影机视图空间进入 世界空间,然后进入光视图空间,而不是进入光投影 空间/剪辑空间。所有这些转换都是使用矩阵完成的; 如果您不熟悉空间更改,您可能需要阅读我的 关于空间和变换的文章

一旦我们在正确的空间,我们计算纹理坐标 我们终于准备好从阴影图中读取。偏见是一个小问题 我们应用于贴图中的值以避免由于 舍入错误一个点最终会使自身着色!所以我们转移了所有的时间 稍微向后映射,使映射中的所有值都稍微小一些 比他们应该做的还要多


lightProjectionMatrix
是透视变换吗?然后需要除以w.lightProjectionMatrix,这是平行光的正交投影矩阵
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;
}