定向光阴影贴图问题

问题描述

所以我一直在尝试使用定向光在我的引擎中重新实现阴影贴图,但到目前为止我必须为我的进度添加阴影(看看我在那里做了什么?)。

我在前一次提交中使用过它,但重构了我的引擎,我正在尝试重做一些阴影映射。不会说我在绘制阴影方面是最好的,所以我想我会尝试寻求一些帮助。

基本上我的问题似乎源于光空间矩阵的计算(似乎很多人都有同样的问题)。最初我有一个硬编码的投影矩阵和像这样的光的简单视图矩阵


    void ZLight::UpdateLightspaceMatrix()
    {
        // …
       if (type == ZLightType::Directional) {
           auto lightDir = glm::normalize(glm::eulerAngles(Orientation()));
           glm::mat4 lightV = glm::lookAt(lightDir,glm::vec3(0.f),WORLD_UP);
           glm::mat4 lightP = glm::ortho(-50.f,50.f,-50.f,-100.f,100.f);
           lightspaceMatrix_ = lightP * lightV;
       }
        // …
    }

然后将其作为着色器统一传递未经修改,我将顶点世界空间位置乘以它。几个月前,这是有效的,但最近我在引擎上进行了重构,它不再显示任何内容。阴影贴图的输出看起来像这样

enter image description here

而且我的场景没有显示任何阴影,至少在重要的地方没有

enter image description here

除此之外,经过数小时的搜索帖子和文章,了解如何在任何给定时间为包含场景内容的光实现动态视锥体,我还实现了一个基于将相机视锥体转换为光空间的简单解决方案,使用 NDC 立方体并使用逆相机 VP 矩阵对其进行变换,并根据结果计算边界框,将其传递给 glm::ortho 以制作光的投影矩阵


    void ZLight::UpdateLightspaceMatrix()
    {
        static std::vector <glm::vec4> ndcCube = {
            glm::vec4{ -1.0f,-1.0f,1.0f },glm::vec4{ 1.0f,glm::vec4{ -1.0f,1.0f,1.0f }
        };
        if (type == ZLightType::Directional) {
            auto activeCamera = Scene()->ActiveCamera();
    
            auto lightDir = normalize(glm::eulerAngles(Orientation()));
            glm::mat4 lightV = glm::lookAt(lightDir,WORLD_UP);
    
            lightspaceRegion_ = ZAABBox();
            for (const auto& corner : ndcCube) {
                auto invVPMatrix = glm::inverse(activeCamera->ProjectionMatrix() * activeCamera->ViewMatrix());
                auto transformedCorner = lightV * invVPMatrix * corner;
                transformedCorner /= transformedCorner.w;
                lightspaceRegion_.minimum.x = glm::min(lightspaceRegion_.minimum.x,transformedCorner.x);
                lightspaceRegion_.minimum.y = glm::min(lightspaceRegion_.minimum.y,transformedCorner.y);
                lightspaceRegion_.minimum.z = glm::min(lightspaceRegion_.minimum.z,transformedCorner.z);
                lightspaceRegion_.maximum.x = glm::max(lightspaceRegion_.maximum.x,transformedCorner.x);
                lightspaceRegion_.maximum.y = glm::max(lightspaceRegion_.maximum.y,transformedCorner.y);
                lightspaceRegion_.maximum.z = glm::max(lightspaceRegion_.maximum.z,transformedCorner.z);
            }
    
            glm::mat4 lightP = glm::ortho(lightspaceRegion_.minimum.x,lightspaceRegion_.maximum.x,lightspaceRegion_.minimum.y,lightspaceRegion_.maximum.y,-lightspaceRegion_.maximum.z,-lightspaceRegion_.minimum.z);
    
            lightspaceMatrix_ = lightP * lightV;
        }
    }

结果是我的场景(任何地方都没有阴影)和下面的阴影贴图的输出相同

enter image description here

我一遍又一遍地检查了光空间矩阵的计算,并尝试了数十次调整值,包括使用 glm::lookAt 函数的各种 lightV 矩阵,但我从未得到所需的输出

更多参考,这是我的阴影顶点着色器


    #version 450 core
    
    #include "Shaders/common.glsl" //! #include "../common.glsl"
    
    layout (location = 0) in vec3 position;
    layout (location = 5) in ivec4 boneIDs;
    layout (location = 6) in vec4 boneWeights;
    layout (location = 7) in mat4 instanceM;
    
    uniform mat4 P_lightSpace;
    uniform mat4 M;
    uniform mat4 Bones[MAX_BOnes];
    uniform bool rigged = false;
    uniform bool instanced = false;
    
    void main()
    {
    vec4 pos = vec4(position,1.0);
       if (rigged) {
        mat4 boneTransform = Bones[boneIDs[0]] * boneWeights[0];
     boneTransform += Bones[boneIDs[1]] * boneWeights[1];
     boneTransform += Bones[boneIDs[2]] * boneWeights[2];
     boneTransform += Bones[boneIDs[3]] * boneWeights[3];
    
           pos = boneTransform * pos;
       }
    
       gl_Position = P_lightSpace * (instanced ? instanceM : M) * pos;
    }

我的软阴影实现


    float PCFShadow(VertexOutput vout,sampler2D shadowMap) {
     vec3 projCoords = vout.FragPosLightSpace.xyz / vout.FragPosLightSpace.w;
     if (projCoords.z > 1.0)
       return 0.0;
    
     projCoords = projCoords * 0.5 + 0.5;
    
     // PCF
     float shadow = 0.0;
     float bias = max(0.05 * (1.0 - dot(vout.Fragnormal,vout.FragPosLightSpace.xyz - vout.FragPos.xzy)),0.005);  
     for (int i = 0; i < 4; ++i) {
       float z = texture(shadowMap,projCoords.xy + poissondisk[i]).r;
       shadow += z < (projCoords.z - bias) ? 1.0 : 0.0;
     }
     return shadow / 4;
    }
    ...
    ...
    float shadow = PCFShadow(vout,shadowSampler0);
    vec3 color = (ambient + (1.0 - shadow) * (diffuse + specular)) + materials[materialIndex].emission;
    FragColor = vec4(color,albd.a);

以及我的相机视图和投影矩阵获取


    glm::mat4 ZCamera::ProjectionMatrix()
    {
       glm::mat4 projectionMatrix(1.f);
    
       auto scene = Scene();
       if (!scene) return projectionMatrix;
    
       if (cameraType_ == ZCameraType::Orthographic)
       {
           float zoomInverse_ = 1.f / (2.f * zoom_);
           glm::vec2 resolution = scene->Domain()->Resolution();
           float left = -((float)resolution.x * zoomInverse_);
           float right = -left;
           float bottom = -((float)resolution.y * zoomInverse_);
           float top = -bottom;
           projectionMatrix = glm::ortho(left,right,bottom,top,-farClippingPlane_,farClippingPlane_);
       }
       else
       {
           projectionMatrix = glm::perspective(glm::radians(zoom_),(float)scene->Domain()->Aspect(),nearClippingPlane_,farClippingPlane_);
       }
       return projectionMatrix;
    }
    
    glm::mat4 ZCamera::ViewMatrix()
    {
       return glm::lookAt(Position(),Position() + Front(),Up());
    }

一直在尝试各种小的变化,但我仍然没有得到正确的阴影。不知道我在这里做错了什么。我得到的最接近的是在光空间矩阵计算中将 lightspaceRegion_ 边界缩放 10 倍(仅在 X 和 Y 中),但阴影仍然不正确。

相机的近剪裁平面和远剪裁平面设置为合理的值(分别为 0.01 和 100.0),相机缩放为 45.0 度,scene→Domain()→Aspect() 仅返回帧缓冲区分辨率的宽度/高度纵横比。我的阴影贴图分辨率设置为 2048x2048。

这里的任何帮助将不胜感激。如果我遗漏了任何重要的代码或信息,请告诉我。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)