--- title: Lighting阶段的ShadowMap逻辑 date: 2023-04-10 14:45:45 excerpt: tags: rating: ⭐ --- ## PS Parameter `FDeferredLightPS::FParameters GetDeferredLightPSParameters()` - LightAttenuationTexture = ShadowMaskTexture ? ShadowMaskTexture : WhiteDummy; - One pass projection - VirtualShadowMap = VirtualShadowMapUniformBuffer; - VirtualShadowMapId = VirtualShadowMapId; - ShadowMaskBits = ShadowMaskBits ? ShadowMaskBits : GSystemTextures.GetZeroUIntDummy(GraphBuilder); 最后输出 - SceneColorTexture - SceneDepthTexture ## Lighting阶段中VSM 渲染函数 RenderDeferredShadowProjections(),输出`ScreenShadowMaskTexture`。 ## 问题所在 LightAttenuation - x:整个场景的方向光阴影。 - y:整个场景的方向光SSS阴影。 - z:Light function + per-object shadows - w:per-object SSS shadowing in w zw用于非方向光或者移动端渲染路径。 ```c++ if (LightData.bRadialLight || SHADING_PATH_MOBILE) { // Remapping the light attenuation buffer (see ShadowRendering.cpp) Shadow.SurfaceShadow = LightAttenuation.z * StaticShadowing; // SSS uses a separate shadowing term that allows light to penetrate the surface //@todo - how to do static shadowing of SSS correctly? Shadow.TransmissionShadow = LightAttenuation.w * StaticShadowing; Shadow.TransmissionThickness = LightAttenuation.w; } else { // Remapping the light attenuation buffer (see ShadowRendering.cpp) // Also fix up the fade between dynamic and static shadows // to work with plane splits rather than spheres. float DynamicShadowFraction = DistanceFromCameraFade(SceneDepth, LightData); // For a directional light, fade between static shadowing and the whole scene dynamic shadowing based on distance + per object shadows Shadow.SurfaceShadow = lerp(LightAttenuation.x, StaticShadowing, DynamicShadowFraction); // Fade between SSS dynamic shadowing and static shadowing based on distance Shadow.TransmissionShadow = min(lerp(LightAttenuation.y, StaticShadowing, DynamicShadowFraction), LightAttenuation.w); Shadow.SurfaceShadow *= LightAttenuation.z; Shadow.TransmissionShadow *= LightAttenuation.z; // Need this min or backscattering will leak when in shadow which cast by non perobject shadow(Only for directional light) Shadow.TransmissionThickness = min(LightAttenuation.y, LightAttenuation.w); } ``` **DeferredLightingCommon.ush**与**DeferredLightPixelShaders.usf**中的**LightAttenuation**即为ShadowMap数据。具体可以参考**GetLightAttenuationFromShadow()**,可以看得出EPIC之后打算通过抖动来消除VSM的阴影锯齿。 主要的阴影效果由**LightAttenuation**与ShadingModels.ush中的NoL提供。我们只需要调整自阴影也就是z通道,其他的整个场景的阴影。