107 lines
4.4 KiB
HLSL
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);
|
|
}
|