// Copyright Epic Games, Inc. All Rights Reserved. /*============================================================================= ForwardShadowingCommon.ush =============================================================================*/ #include "ShadowFilteringCommon.ush" float ComputeDirectionalLightStaticShadowing(float3 TranslatedWorldPosition) { float ShadowFactor = 1; #if ALLOW_STATIC_LIGHTING BRANCH if (ForwardLightStruct.DirectionalLightUseStaticShadowing > 0) { // Transform the world position into shadowmap space float4 HomogeneousShadowPosition = mul(float4(TranslatedWorldPosition, 1), ForwardLightStruct.DirectionalLightTranslatedWorldToStaticShadow); float2 ShadowUVs = HomogeneousShadowPosition.xy / HomogeneousShadowPosition.w; // Treat as unshadowed if the voxel is outside of the shadow map if (all(and(ShadowUVs >= 0, ShadowUVs <= 1))) { #define FILTER_STATIC_SHADOWING 0 #if FILTER_STATIC_SHADOWING FPCFSamplerSettings Settings; Settings.ShadowDepthTexture = ForwardLightStruct.DirectionalLightStaticShadowmap; Settings.ShadowDepthTextureSampler = ForwardLightStruct.StaticShadowmapSampler; Settings.ShadowBufferSize = ForwardLightStruct.DirectionalLightStaticShadowBufferSize; Settings.SceneDepth = 1 - HomogeneousShadowPosition.z; Settings.TransitionScale = 40; Settings.bSubsurface = false; // We can sample outside of the static shadowmap, which is centered around the lightmass importance volume. These 'infinite' depth values should not cause occlusion. Settings.bTreatMaxDepthUnshadowed = true; Settings.DensityMulConstant = 0; Settings.ProjectionDepthBiasParameters = float2(0, 0); ShadowFactor = Manual1x1PCF(ShadowUVs, Settings); #else // Sample the shadowmap depth and determine if this voxel is shadowed float ShadowDepth = Texture2DSampleLevel(ForwardLightStruct.DirectionalLightStaticShadowmap, ForwardLightStruct.StaticShadowmapSampler, ShadowUVs, 0).x; ShadowFactor = HomogeneousShadowPosition.z < ShadowDepth || ShadowDepth > .99f; #endif } } #endif return ShadowFactor; } #ifndef FILTER_DIRECTIONAL_LIGHT_SHADOWING #define FILTER_DIRECTIONAL_LIGHT_SHADOWING 0 #endif uint GetForwardLightingCascadeIndex(float4 CascadeEndDepths, float SceneDepth) { float4 Count = float4(SceneDepth.xxxx >= CascadeEndDepths); return uint(Count.x + Count.y + Count.z + Count.w); } float ComputeDirectionalLightDynamicShadowing(float3 TranslatedWorldPosition, float SceneDepth, inout bool bShadowingFromValidUVArea) { float ShadowFactor = 1; bShadowingFromValidUVArea = false; const uint NumCascades = ForwardLightStruct.NumDirectionalLightCascades; if (NumCascades > 0) { uint CascadeIndex = GetForwardLightingCascadeIndex(ForwardLightStruct.CascadeEndDepths, SceneDepth); if (CascadeIndex < NumCascades) { // Transform the world position into shadowmap space float4 HomogeneousShadowPosition = mul(float4(TranslatedWorldPosition, 1), ForwardLightStruct.DirectionalLightTranslatedWorldToShadowMatrix[CascadeIndex]); float2 ShadowUVs = HomogeneousShadowPosition.xy / HomogeneousShadowPosition.w; float4 ShadowmapMinMax = ForwardLightStruct.DirectionalLightShadowmapMinMax[CascadeIndex]; // Treat as unshadowed if the voxel is outside of the shadow map if (all(and(ShadowUVs >= ShadowmapMinMax.xy, ShadowUVs <= ShadowmapMinMax.zw))) { #if FILTER_DIRECTIONAL_LIGHT_SHADOWING FPCFSamplerSettings Settings; Settings.ShadowDepthTexture = ForwardLightStruct.DirectionalLightShadowmapAtlas; Settings.ShadowDepthTextureSampler = ForwardLightStruct.ShadowmapSampler; Settings.ShadowBufferSize = ForwardLightStruct.DirectionalLightShadowmapAtlasBufferSize; Settings.SceneDepth = 1 - HomogeneousShadowPosition.z; Settings.TransitionScale = 4000; Settings.bSubsurface = false; Settings.bTreatMaxDepthUnshadowed = false; Settings.DensityMulConstant = 0; Settings.ProjectionDepthBiasParameters = float2(0, 0); ShadowFactor = Manual1x1PCF(ShadowUVs, Settings); #else // Sample the shadowmap depth and determine if this voxel is shadowed float ShadowDepth = Texture2DSampleLevel(ForwardLightStruct.DirectionalLightShadowmapAtlas, ForwardLightStruct.ShadowmapSampler, ShadowUVs, 0).x; ShadowFactor = 1 - HomogeneousShadowPosition.z < ShadowDepth - ForwardLightStruct.DirectionalLightDepthBias.x; #endif // Note this doesn't actually mean the shadow factor computed is valid, eg CSM culling removes meshes which would cast on off-screen areas of the shadowmap, which still have valid UVs bShadowingFromValidUVArea = true; } } } return ShadowFactor; }