You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Add a world dither. Not necessarily useful but can be somewhat analygous to PCF radius. Add permutation to SMRT samples = 0 (and possibly more in the future). #preflight 628eab6fc826bd5a7f1135ec #rb ola.olsson #ROBOMERGE-AUTHOR: andrew.lauritzen #ROBOMERGE-SOURCE: CL 20372897 via CL 20372913 via CL 20372922 #ROBOMERGE-BOT: UE5 (Release-Engine-Staging -> Main) (v949-20362246) [CL 20373677 by andrew lauritzen in ue5-main branch]
130 lines
4.6 KiB
Plaintext
130 lines
4.6 KiB
Plaintext
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
VirtualShadowMapSMRTTemplate.ush:
|
|
|
|
Required parameters before including this file:
|
|
1) Include "SMRTCommon.ush"
|
|
2) Define a "ray state" structure (FRayState here, but must be unique)
|
|
3) Implement FSMRTSample SMRTFindSample(inout FRayState RayState, float SampleTime)
|
|
4) Implement SMRTComputeOccluderDistance(FRayState RayState, float SampleDepth)
|
|
5) Include this file:
|
|
#define SMRT_TEMPLATE_RAY_STRUCT FRayState
|
|
#include "VirtualShadowMapSMRTTemplate.ush"
|
|
#undef SMRT_TEMPLATE_RAY_STRUCT
|
|
=============================================================================*/
|
|
|
|
// NOTE: No pragma(once) or inclusion guards because this file is meant to be
|
|
// included multiple times as our hacky way to generate template-like instantiations
|
|
// before HLSL supports templates natively.
|
|
|
|
// If defined, unrolls the loop and ignores the NumSteps parameter in favor of the define
|
|
#ifndef SMRT_TEMPLATE_STATIC_SAMPLES_PER_RAY
|
|
#define SMRT_TEMPLATE_STATIC_SAMPLES_PER_RAY -1
|
|
#endif
|
|
|
|
FSMRTResult SMRTRayCast(
|
|
inout SMRT_TEMPLATE_RAY_STRUCT RayState,
|
|
int NumSteps,
|
|
float StepOffset)
|
|
{
|
|
float DepthHistory = -1;
|
|
float DepthHistoryTime = -1;
|
|
float DepthSlope = 0;
|
|
|
|
int SampleMissCount = 0;
|
|
float OccluderDistance = 100000;
|
|
|
|
const float TimeScale = -1.0f / NumSteps;
|
|
const float TimeBias = 1.0f + ( 1.0 - StepOffset ) * TimeScale;
|
|
|
|
// Backward delta. Time[i] - Time[i-1]
|
|
const float DeltaTimeScale = 2.0 * Pow2( TimeScale );
|
|
const float DeltaTimeBias = 2.0 * TimeScale * ( TimeBias - 0.5 * TimeScale );
|
|
|
|
bool bValidHit = false;
|
|
#if SMRT_TEMPLATE_STATIC_SAMPLES_PER_RAY >= 0
|
|
NumSteps = SMRT_TEMPLATE_STATIC_SAMPLES_PER_RAY;
|
|
[unroll]
|
|
#endif
|
|
for (int i = 0; i <= NumSteps; i++)
|
|
{
|
|
const float SampleTime = i == NumSteps ? 0 : Pow2( TimeScale * i + TimeBias );
|
|
const float DeltaTime = i == NumSteps ? Pow2( TimeScale * StepOffset ) : DeltaTimeScale * i + DeltaTimeBias;
|
|
|
|
FSMRTSample Sample = SMRTFindSample(RayState, SampleTime);
|
|
if (Sample.bValid)
|
|
{
|
|
const float SampleDepth = Sample.SampleDepth;
|
|
const float ReferenceDepth = Sample.ReferenceDepth;
|
|
if (DepthHistory < 0)
|
|
{
|
|
// First valid sample we've seen. Do a regular depth compare.
|
|
DepthHistory = SampleDepth;
|
|
DepthHistoryTime = SampleTime;
|
|
if (SampleDepth > ReferenceDepth)
|
|
{
|
|
OccluderDistance = SMRTComputeOccluderDistance(RayState, SampleDepth);
|
|
bValidHit = true;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Add a small relative error to the comparison to avoid missing surfaces due to numeric precision issues
|
|
// Without this there are occasionally flickering fireflies in fully shadowed regions with SMRT
|
|
const float EpsScale = 1.5f;
|
|
const float CompareTolerance = abs(Sample.CompareToleranceScale * DeltaTime) * EpsScale;
|
|
const bool bBehind = (SampleDepth - ReferenceDepth) > CompareTolerance;
|
|
|
|
float DeltaHistoryTime = SampleTime - DepthHistoryTime;
|
|
float DepthForComparison = SampleDepth;
|
|
|
|
if (bBehind)
|
|
{
|
|
#if SMRT_EXTRAPOLATE_WITH_SLOPE
|
|
DepthForComparison = DepthSlope * DeltaHistoryTime + DepthHistory;
|
|
#else
|
|
DepthForComparison = DepthHistory;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// This must be the second valid sample we've seen, as the first will take the DepthHistory < 0 path
|
|
// Only update the slope if we sampled a new texel; otherwise it will just zero out the slope
|
|
// This can happen at high sample counts with rays that are nearly parallel to the light direction
|
|
if (SampleDepth != DepthHistory) // Exact test is fine here; point sampled texel with be identical
|
|
{
|
|
// NOTE: DCE will remove all this if SMRT_EXTRAPOLATE_WITH_SLOPE is false
|
|
const float SlopeClamp = 1e-5f;
|
|
DepthSlope = (SampleDepth - DepthHistory) / DeltaHistoryTime;
|
|
DepthSlope = clamp(DepthSlope, -SlopeClamp, SlopeClamp);
|
|
}
|
|
DepthHistory = SampleDepth;
|
|
DepthHistoryTime = SampleTime;
|
|
}
|
|
|
|
float DepthDiff = ReferenceDepth - DepthForComparison;
|
|
float HalfCompareTolerance = 0.5 * CompareTolerance;
|
|
bool bHit = abs(DepthDiff + HalfCompareTolerance) < HalfCompareTolerance;
|
|
if (bHit)
|
|
{
|
|
OccluderDistance = SMRTComputeOccluderDistance(RayState, SampleDepth);
|
|
bValidHit = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
++SampleMissCount;
|
|
}
|
|
}
|
|
|
|
FSMRTResult Result;
|
|
Result.bValidHit = bValidHit;
|
|
Result.OccluderDistance = OccluderDistance;
|
|
Result.SampleMissCount = SampleMissCount;
|
|
return Result;
|
|
}
|