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

199 lines
6.6 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "../Common.ush"
#include "../HZBTracing.ush"
#include "LumenMaterial.ush"
#include "../FastMath.ush"
#include "../SceneTextureParameters.ush"
#include "LumenPosition.ush"
#include "../HZB.ush"
void TraceScreen(
float3 RayTranslatedWorldOrigin,
float3 RayWorldDirection,
float MaxWorldTraceDistance,
float4 InHZBUvFactorAndInvFactor,
float MaxIterations,
float RelativeDepthThickness,
float NumThicknessStepsToDetermineCertainty,
uint MinimumTracingThreadOccupancy,
inout bool bHit,
inout bool bUncertain,
inout float3 OutScreenUV,
inout float3 OutLastVisibleScreenUV,
inout float OutHitTileZ)
{
TraceHZB(
SceneDepthTexture,
ClosestHZBTexture,
HZBBaseTexelSize,
HZBUVToScreenUVScaleBias,
RayTranslatedWorldOrigin,
RayWorldDirection,
MaxWorldTraceDistance,
InHZBUvFactorAndInvFactor,
MaxIterations,
RelativeDepthThickness,
NumThicknessStepsToDetermineCertainty,
MinimumTracingThreadOccupancy,
bHit,
bUncertain,
OutScreenUV,
OutLastVisibleScreenUV,
OutHitTileZ);
}
#include "../SSRT/SSRTRayCast.ush"
Texture2D PrevSceneColorTexture;
Texture2D HistorySceneDepth;
float2 PrevSceneColorBilinearUVMin;
float2 PrevSceneColorBilinearUVMax;
float4 PrevScreenPositionScaleBias;
float4 PrevScreenPositionScaleBiasForDepth;
float PrevSceneColorPreExposureCorrection;
float SampleSceneColorNormalTreshold;
/**
* Try to sample scene color at hit and return whether it was successfull
*/
bool SampleSceneColorAtHit(float3 HitTranslatedWorldPosition, float3 HitGeometryWorldNormal, uint2 SvPosition, float RelativeDepthThickness, inout float3 Lighting)
{
float4 HitClipPosition = mul(float4(HitTranslatedWorldPosition, 1.0f), View.TranslatedWorldToClip);
if (HitClipPosition.w > 0)
{
float2 HitScreenPosition = HitClipPosition.xy / HitClipPosition.w;
if (all(abs(HitScreenPosition) < float2(1, 1)))
{
float2 HitScreenUV = HitScreenPosition * View.ScreenPositionScaleBias.xy + View.ScreenPositionScaleBias.wz;
float HitDeviceZ = SceneDepthTexture.SampleLevel(GlobalPointClampedSampler, HitScreenUV, 0).r;
float HitSceneDepth = ConvertFromDeviceZ(HitDeviceZ);
float RayHitSceneDepth = HitClipPosition.w;
float3 PixelToCameraDirection = -GetCameraVectorFromTranslatedWorldPosition(HitTranslatedWorldPosition);
// Discard screen points which are either too far or face the other direction
// Also discard screen points at steep angle or facing backwards
if (abs(RayHitSceneDepth - HitSceneDepth) < RelativeDepthThickness * max(HitSceneDepth, .00001f)
&& dot(PixelToCameraDirection, HitGeometryWorldNormal) >= SampleSceneColorNormalTreshold)
{
float3 HitHistoryScreenPosition = GetHistoryScreenPosition(HitScreenPosition, HitScreenUV, HitDeviceZ);
float Vignette = min(ComputeHitVignetteFromScreenPos(HitScreenPosition), ComputeHitVignetteFromScreenPos(HitHistoryScreenPosition.xy));
float Noise = InterleavedGradientNoise(SvPosition + 0.5f, View.StateFrameIndexMod8);
bool bSampleSceneColor = true;
// Skip reporting a hit if near the edge of the screen
if (Vignette < Noise)
{
bSampleSceneColor = false;
}
if (bSampleSceneColor)
{
// Calculate the expected depth of the pixel last frame
float PrevDeviceZ = HitHistoryScreenPosition.z;
// Lookup the actual depth at the same screen position last frame
float2 HitHistoryScreenUVForDepth = HitHistoryScreenPosition.xy * PrevScreenPositionScaleBiasForDepth.xy + PrevScreenPositionScaleBiasForDepth.zw;
float HistoryDeviceZ = Texture2DSampleLevel(HistorySceneDepth, GlobalPointClampedSampler, HitHistoryScreenUVForDepth, 0).x;
bSampleSceneColor = abs(HistoryDeviceZ - PrevDeviceZ) < RelativeDepthThickness * lerp(.5f, 2.0f, Noise);
}
if (bSampleSceneColor)
{
float2 HitHistoryScreenUV = HitHistoryScreenPosition.xy * PrevScreenPositionScaleBias.xy + PrevScreenPositionScaleBias.zw;
HitHistoryScreenUV = clamp(HitHistoryScreenUV, PrevSceneColorBilinearUVMin, PrevSceneColorBilinearUVMax);
Lighting = SampleScreenColor(PrevSceneColorTexture, GlobalPointClampedSampler, HitHistoryScreenUV).xyz * PrevSceneColorPreExposureCorrection * View.OneOverPreExposure;
return true;
}
}
}
}
return false;
}
float DistantScreenTraceSlopeCompareTolerance;
float DistantScreenTraceMaxTraceDistance;
float DistantScreenTraceStepOffsetBias;
Texture2D DistantScreenTraceFurthestHZBTexture;
void DistantScreenTrace(
float2 NoiseCoord,
float4 InHZBUvFactorAndInvFactor,
float3 TranslatedRayOrigin,
float3 RayDirection,
float TraceDistance,
float SceneDepth,
inout bool bHit,
inout float3 TraceRadiance)
{
uint NumSteps = 16;
float StartMipLevel = 0.0f;
float RayRoughness = 0.0f;
float Noise = InterleavedGradientNoise(NoiseCoord, View.StateFrameIndexMod8);
float StepOffset = Noise + DistantScreenTraceStepOffsetBias;
FSSRTCastingSettings CastSettings = CreateDefaultCastSettings();
float Level;
float3 HitUVz;
bool bRayWasClipped;
FSSRTRay Ray = InitScreenSpaceRayFromWorldSpace(
TranslatedRayOrigin, RayDirection,
/* WorldTMax = */ TraceDistance,
/* SceneDepth = */ SceneDepth,
/* SlopeCompareToleranceScale */ DistantScreenTraceSlopeCompareTolerance,
/* bExtendRayToScreenBorder = */ false,
/* out */ bRayWasClipped,
/* WorldTMaxClamp */ 10000000.f);
bool bUncertain;
float3 DebugOutput;
CastScreenSpaceRay(
DistantScreenTraceFurthestHZBTexture, GlobalPointClampedSampler,
StartMipLevel,
CastSettings,
Ray, RayRoughness, NumSteps, StepOffset,
InHZBUvFactorAndInvFactor, false,
/* out */ DebugOutput,
/* out */ HitUVz,
/* out */ Level,
/* out */ bHit,
/* out */ bUncertain);
if (bHit)
{
float2 HitScreenUV = HitUVz.xy;
float2 HitScreenPosition = (HitUVz.xy - View.ScreenPositionScaleBias.wz) / View.ScreenPositionScaleBias.xy;
float HitDeviceZ = HitUVz.z;
float3 HitHistoryScreenPosition = GetHistoryScreenPosition(HitScreenPosition, HitScreenUV, HitDeviceZ);
float Vignette = min(ComputeHitVignetteFromScreenPos(HitScreenPosition), ComputeHitVignetteFromScreenPos(HitHistoryScreenPosition.xy));
// Skip reporting a hit if near the edge of the screen
if (Vignette < Noise)
{
bHit = false;
}
if (bHit)
{
float2 HitHistoryScreenUV = HitHistoryScreenPosition.xy * PrevScreenPositionScaleBias.xy + PrevScreenPositionScaleBias.zw;
HitHistoryScreenUV = clamp(HitHistoryScreenUV, PrevSceneColorBilinearUVMin, PrevSceneColorBilinearUVMax);
TraceRadiance = SampleScreenColor(PrevSceneColorTexture, GlobalPointClampedSampler, HitHistoryScreenUV).xyz * (PrevSceneColorPreExposureCorrection * View.OneOverPreExposure);
}
}
}