Files
UnrealEngine/Engine/Shaders/Private/Lumen/Radiosity/LumenRadiosityHardwareRayTracing.usf
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

155 lines
5.5 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
LumenRadiosityProbeGatherHardwareRayTracing.usf
=============================================================================*/
// TODO: Remove hair dependency
#include "../../HairStrands/HairStrandsVoxelPageCommonStruct.ush"
#include "/Engine/Shared/RayTracingTypes.h"
#include "../../Common.ush"
#include "../../MonteCarlo.ush"
#include "../../MortonCode.ush"
#include "../../SceneTextureParameters.ush"
#include "../../RayTracing/RayGenUtils.ush"
#include "../LumenCardCommon.ush"
#include "../LumenTracingCommon.ush"
#include "../LumenHardwareRayTracingCommon.ush"
#include "../LumenSceneLighting.ush"
#include "../LumenCardTile.ush"
#include "LumenRadiosity.ush"
RWTexture2D<float3> RWTraceRadianceAtlas;
RWTexture2D<float> RWTraceHitDistanceAtlas;
RaytracingAccelerationStructure TLAS;
RaytracingAccelerationStructure FarFieldTLAS;
#if LUMEN_HARDWARE_INLINE_RAYTRACING
StructuredBuffer<FHitGroupRootConstants> HitGroupData;
StructuredBuffer<FRayTracingSceneMetadataRecord> RayTracingSceneMetadata;
RWStructuredBuffer<uint> RWInstanceHitCountBuffer;
#endif // LUMEN_HARDWARE_INLINE_RAYTRACING
float MinTraceDistance;
float MaxTraceDistance;
float SurfaceBias;
float HeightfieldSurfaceBias;
float AvoidSelfIntersectionTraceDistance;
float MaxRayIntensity;
uint NumThreadsToDispatch;
float TanRadiosityRayConeHalfAngle;
uint MaxTraversalIterations;
float MinTraceDistanceToSampleSurfaceCache;
uint MeshSectionVisibilityTest;
float CachedLightingPreExposure;
LUMEN_HARDWARE_RAY_TRACING_ENTRY(LumenRadiosityHardwareRayTracing)
{
uint GlobalThreadIndex = GetUnWrappedRayTracingDispatchThreadId(DispatchGroupId, THREADGROUP_SIZE);
// When running with indirect inline RT, ThreadIndex is actually GroupIndex, so we need to account for that.
#if LUMEN_HARDWARE_INLINE_RAYTRACING
GlobalThreadIndex = GlobalThreadIndex * INLINE_RAY_TRACING_THREAD_GROUP_SIZE_X + DispatchGroupIndex;
#endif
uint NumTracesPerRadiosityTile = RadiosityTileSizeInProbes * RadiosityTileSizeInProbes * NumTracesPerProbe;
if (GlobalThreadIndex < GetRadiosityTileCount(ViewIndex) * NumTracesPerRadiosityTile)
{
uint RadiosityTileIndex;
uint2 CoordInRadiosityTile;
uint2 TraceTexelCoord;
UnswizzleTexelTraceCoords(GlobalThreadIndex, RadiosityTileIndex, CoordInRadiosityTile, TraceTexelCoord);
FRadiosityTexel RadiosityTexel = GetRadiosityTexelFromRadiosityTile(RadiosityTileIndex, CoordInRadiosityTile);
if (RadiosityTexel.bInsideAtlas)
{
float3 Radiance = 0.0f;
float TraceHitDistance = MaxTraceDistance;
if (RadiosityTexel.bValid)
{
float3 TranslatedWorldPosition = RadiosityTexel.WorldPosition + DFHackToFloat(PrimaryView.PreViewTranslation); // LUMEN_LWC_TODO
float3 WorldNormal = RadiosityTexel.WorldNormal;
float3 WorldRayDirection;
float ConeHalfAngle;
float PDF;
GetRadiosityRay(RadiosityTexel, RadiosityTexel.CardCoord / ProbeSpacingInCardTexels, TraceTexelCoord, WorldRayDirection, ConeHalfAngle, PDF);
float ReceiverBias = 0.0f;
if (RadiosityTexel.bHeightfield)
{
float3 TranslatedWorldCameraOrigin = PrimaryView.TranslatedWorldCameraOrigin;
ReceiverBias = CalculateDistanceBasedHeightfieldBias(HeightfieldSurfaceBias, TranslatedWorldPosition, TranslatedWorldCameraOrigin);
}
FRayDesc Ray;
Ray.Origin = TranslatedWorldPosition + WorldNormal * (SurfaceBias + ReceiverBias);
Ray.Direction = WorldRayDirection;
Ray.TMin = MinTraceDistance;
FRayCone RayCone = (FRayCone)0;
RayCone = PropagateRayCone(RayCone, ConeHalfAngle, 0.0);
const uint RadiosityTileSize = RadiosityTileSizeInProbes * ProbeSpacingInCardTexels;
const uint LinearCoord = CoordInRadiosityTile.y * RadiosityTileSize + CoordInRadiosityTile.x;
FRayTracedLightingContext Context = CreateRayTracedLightingContext(
RayCone,
CoordInRadiosityTile,
LinearCoord,
/*CullingMode*/ RAY_FLAG_CULL_BACK_FACING_TRIANGLES,
MaxTraversalIterations,
MeshSectionVisibilityTest != 0);
Context.MinTraceDistanceToSampleSurfaceCache = MinTraceDistanceToSampleSurfaceCache;
#if LUMEN_HARDWARE_INLINE_RAYTRACING
Context.HitGroupData = HitGroupData;
Context.RayTracingSceneMetadata = RayTracingSceneMetadata;
Context.RWInstanceHitCountBuffer = RWInstanceHitCountBuffer;
#endif
Ray.TMax = MaxTraceDistance;
FRayTracedLightingResult RayResult = TraceSurfaceCacheRay(TLAS, Ray, Context);
if (RayResult.bIsHit)
{
Radiance = RayResult.Radiance;
// Recalculate TraceHitDistance to incorporate biases
float3 HitPosition = Ray.Origin + Ray.Direction * RayResult.TraceHitDistance;
TraceHitDistance = length(TranslatedWorldPosition - HitPosition);
}
else
{
Radiance = EvaluateSkyRadiance(WorldRayDirection);
}
float MaxLighting = max3(Radiance.x, Radiance.y, Radiance.z);
if (MaxLighting > MaxRayIntensity * View.OneOverPreExposure)
{
Radiance *= MaxRayIntensity * View.OneOverPreExposure / MaxLighting;
}
}
FRadiosityTileData RadiosityTile = GetRadiosityTile(RadiosityTileIndex);
FLumenCardPageData CardPage = GetLumenCardPageData(RadiosityTile.CardPageIndex);
uint2 RadiosityProbeTracingAtlasCoord = GetRadiosityProbeAtlasCoord(CardPage, RadiosityTile, CoordInRadiosityTile) * HemisphereProbeResolution + TraceTexelCoord;
RWTraceRadianceAtlas[RadiosityProbeTracingAtlasCoord] = Radiance * CachedLightingPreExposure;
#if PROBE_OCCLUSION
{
RWTraceHitDistanceAtlas[RadiosityProbeTracingAtlasCoord] = TraceHitDistance;
}
#endif
}
}
}