Files
UnrealEngine/Engine/Shaders/Private/ShadowFactorsUpsampleCommon.ush
2025-05-18 13:04:45 +08:00

107 lines
4.4 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
ShadowFactorsUpsampleCommon.ush
=============================================================================*/
#ifndef SHADOW_FACTORS_UPSAMPLE_REQUIRED
#error "Must define SHADOW_FACTORS_UPSAMPLE_REQUIRED"
#endif
#include "Common.ush"
#include "ComputeShaderUtils.ush"
void UpsampleShadowFactors(
float4 SVPos,
int4 ScissorRectMinAndSize,
float OneOverDownsampleFactor,
float ShadowFactorsMinDepth,
float ShadowFactorsMaxDepth,
Texture2D ShadowFactorsTexture,
SamplerState ShadowFactorsSampler,
float2 ShadowFactorsUVBilinearMax,
out float ShadowFactor,
out float SceneDepth,
uint EyeIndex)
{
float2 BufferUV = SvPositionToBufferUV(SVPos);
// ShadowFactors is computed at 0,0 regardless of viewrect min
float2 ShadowFactorsUV = BufferUV - ScissorRectMinAndSize.xy * View.BufferSizeAndInvSize.zw;
#if MOBILE_MULTI_VIEW
SceneDepth = CalcSceneDepth(BufferUV, EyeIndex);
#else
SceneDepth = CalcSceneDepth(BufferUV);
#endif
#define BILATERAL_UPSAMPLE 1
#if BILATERAL_UPSAMPLE && SHADOW_FACTORS_UPSAMPLE_REQUIRED
float2 LowResBufferSize = floor(View.BufferSizeAndInvSize.xy * OneOverDownsampleFactor);
float2 LowResTexelSize = 1.0f / LowResBufferSize;
// since DF shadow rays are traced from the position of the full-res texel at the top left of low-res tile
// we need to use different UVs for calculating bilinear weights and sampling the 4 texels
float2 Corner00UVBase = floor(ShadowFactorsUV * LowResBufferSize) / LowResBufferSize;
// Calculate bilinear weights using the same UVs that rays were traced from
float2 Corner00UV = Corner00UVBase + 0.5f * View.BufferSizeAndInvSize.zw;
float2 BilinearWeights = saturate((ShadowFactorsUV - Corner00UV) * LowResBufferSize);
// Sample low res texture using UVs at center of low-res texels since we are interpolating manually
float2 Corner00SampleUV = Corner00UVBase + 0.5f * LowResTexelSize;
float2 TextureValues00 = Texture2DSampleLevel(ShadowFactorsTexture, ShadowFactorsSampler, min(Corner00SampleUV, ShadowFactorsUVBilinearMax), 0).xy;
float2 TextureValues10 = Texture2DSampleLevel(ShadowFactorsTexture, ShadowFactorsSampler, min(Corner00SampleUV + float2(LowResTexelSize.x, 0), ShadowFactorsUVBilinearMax), 0).xy;
float2 TextureValues01 = Texture2DSampleLevel(ShadowFactorsTexture, ShadowFactorsSampler, min(Corner00SampleUV + float2(0, LowResTexelSize.y), ShadowFactorsUVBilinearMax), 0).xy;
float2 TextureValues11 = Texture2DSampleLevel(ShadowFactorsTexture, ShadowFactorsSampler, min(Corner00SampleUV + LowResTexelSize, ShadowFactorsUVBilinearMax), 0).xy;
float4 CornerWeights = float4(
(1 - BilinearWeights.y) * (1 - BilinearWeights.x),
(1 - BilinearWeights.y) * BilinearWeights.x,
BilinearWeights.y * (1 - BilinearWeights.x),
BilinearWeights.y * BilinearWeights.x);
float Epsilon = .0001f;
float4 ShadowFactors = float4(TextureValues00.x, TextureValues10.x, TextureValues01.x, TextureValues11.x);
float4 CornerDepths = abs(float4(TextureValues00.y, TextureValues10.y, TextureValues01.y, TextureValues11.y));
// Ignore pixels marked as non-shadowed if they lie outside the DF shadows range.
// Shadowed pixels outside the range are marked as valid, these could be from heightfield traces.
float4 CornerDepthsValid =
or(
and(ShadowFactorsMinDepth.xxxx < CornerDepths, CornerDepths < ShadowFactorsMaxDepth.xxxx),
ShadowFactors < 1.0
);
float4 DepthWeights = 1.0f / (abs(CornerDepths - SceneDepth.xxxx) + Epsilon);
float4 FinalWeights = CornerWeights * CornerDepthsValid * DepthWeights;
float TotalWeight = dot(FinalWeights, 1);
float InterpolatedResult = 1;
if (TotalWeight != 0)
{
InterpolatedResult = dot(ShadowFactors, FinalWeights) / TotalWeight;
}
ShadowFactor = InterpolatedResult;
#else
ShadowFactor = Texture2DSampleLevel(ShadowFactorsTexture, ShadowFactorsSampler, ShadowFactorsUV, 0).x;
#endif
}
void UpsampleShadowFactors(
float4 SVPos,
int4 ScissorRectMinAndSize,
float OneOverDownsampleFactor,
float ShadowFactorsMinDepth,
float ShadowFactorsMaxDepth,
Texture2D ShadowFactorsTexture,
SamplerState ShadowFactorsSampler,
float2 ShadowFactorsUVBilinearMax,
out float ShadowFactor,
out float SceneDepth)
{
UpsampleShadowFactors(SVPos, ScissorRectMinAndSize, OneOverDownsampleFactor, ShadowFactorsMinDepth, ShadowFactorsMaxDepth, ShadowFactorsTexture, ShadowFactorsSampler, ShadowFactorsUVBilinearMax, ShadowFactor, SceneDepth, 0);
}