Files
UnrealEngine/Engine/Plugins/Compositing/Composite/Shaders/Private/CompositeSingleLightShadow.usf
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

94 lines
3.3 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#include "/Engine/Private/Common.ush"
#include "/Engine/Private/ShadowFilteringCommon.ush"
Texture2D SceneDepthTex;
SamplerState SceneDepthSampler;
Texture2D ShadowDepthTexture;
SamplerState ShadowDepthTextureSampler;
float4 SceneDepthPositionScaleBias;
float4x4 SceneDepthScreenToWorld;
float4x4 ShadowMatrix;
float4 ShadowBufferSize;
float4 ShadowInvDeviceZToWorldZ;
float4 ShadowStrengthBias;
float3 LightWorldDirection;
uint bIsPerspectiveProjection;
// Returns the screen position for projection matrix calculations depending on the type of projection the view is using
float2 GetScreenPositionForProj(in float2 ScreenPosition, in float SceneDepth)
{
return select(bIsPerspectiveProjection == 0, ScreenPosition, ScreenPosition * SceneDepth);
}
// Calculate world position from scene depth
float4 CalcWorldFromSceneDepth(in float2 UV, in float Depth)
{
float2 ScreenPosition = (UV - SceneDepthPositionScaleBias.wz) / SceneDepthPositionScaleBias.xy;
float4 HomogeneousWorldPosition = mul(float4(GetScreenPositionForProj(ScreenPosition, Depth), Depth, 1), SceneDepthScreenToWorld);
float3 WorldPosition = HomogeneousWorldPosition.xyz / HomogeneousWorldPosition.w;
return float4(WorldPosition, 1.0);
}
// Convert device-z depth to scene depth
float ShadowDeviceZToSceneDepth(float DeviceZ)
{
return DeviceZ * ShadowInvDeviceZToWorldZ[0] + ShadowInvDeviceZToWorldZ[1] + 1.0f / (DeviceZ * ShadowInvDeviceZToWorldZ[2] - ShadowInvDeviceZToWorldZ[3]);
}
// Percentage-close filtering shadow mapping
float ManualPCF(in float4 ShadowPosition, in float NoL)
{
float SceneDepth = ShadowDeviceZToSceneDepth(ShadowPosition.z) - saturate(1 - NoL) * ShadowStrengthBias.y;
FPCFSamplerSettings Settings;
Settings.ShadowDepthTexture = ShadowDepthTexture;
Settings.ShadowDepthTextureSampler = ShadowDepthTextureSampler;
Settings.ShadowBufferSize = ShadowBufferSize;
Settings.TransitionScale = 1.0; // TODO: Parametrize like FProjectedShadowInfo::ComputeTransitionSize
Settings.SceneDepth = SceneDepth;
Settings.bSubsurface = false;
Settings.bTreatMaxDepthUnshadowed = false;
Settings.DensityMulConstant = 0;
Settings.ProjectionDepthBiasParameters = 0;
float Shadow = Manual5x5PCF(ShadowPosition.xy, Settings);
return Shadow;
}
void MainPS(
noperspective float4 InUVAndScreenPos : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 UV = InUVAndScreenPos.xy;
float SceneDepth = SceneDepthTex.SampleLevel(SceneDepthSampler, UV, 0).r;
float4 WorldPosition = CalcWorldFromSceneDepth(UV, SceneDepth);
float4 ShadowPosition = mul(WorldPosition, ShadowMatrix);
float2 ShadowUV = ShadowPosition.xy;
if(any(ShadowUV < 0.0) || any(ShadowUV > 1.0))
{
OutColor.rgb = 1.0;
}
else
{
float3 Ddx = ddx(WorldPosition);
float3 Ddy = ddy(WorldPosition);
float3 WorldNormal = normalize(cross(Ddx, Ddy));
const float NoL = saturate(abs(dot(WorldNormal, LightWorldDirection)));
float ShadowVisibility = ManualPCF(ShadowPosition, NoL);
OutColor.rgb = lerp(1.0, ShadowVisibility, ShadowStrengthBias.x);
}
OutColor.a = 1.0;
}