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

125 lines
3.9 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================================
RayTracingLightCullingCommon.ush: Common functions for culling lights.
===============================================================================================*/
#pragma once
#include "../Visualization.ush"
// *************** LIGHT CULLING *********************************
// Use a 2D grid built along the longest axes of the bounding boxes of all finite light sources.
struct FCulledLightList
{
uint NumLights;
uint LightGridOffset;
static FCulledLightList Create(float3 TranslatedWorldPos)
{
FCulledLightList Result = (FCulledLightList) 0;
Result.NumLights = RaytracingLightGridData.SceneInfiniteLightCount;
Result.LightGridOffset = ~0u;
const float3 SceneMin = RaytracingLightGridData.SceneLightsTranslatedBoundMin;
const float3 SceneMax = RaytracingLightGridData.SceneLightsTranslatedBoundMax;
if (all(SceneMin <= TranslatedWorldPos) &&
all(TranslatedWorldPos <= SceneMax))
{
float3 P = TranslatedWorldPos - SceneMin;
float3 D = SceneMax - SceneMin;
int2 UVx = int2(floor(RaytracingLightGridData.LightGridResolution * P.yz / D.yz));
int2 UVy = int2(floor(RaytracingLightGridData.LightGridResolution * P.xz / D.xz));
int2 UVz = int2(floor(RaytracingLightGridData.LightGridResolution * P.xy / D.xy));
uint LightGridNx = RaytracingLightGridData.LightGrid.Load(int4(UVx, 0, 0));
uint LightGridNy = RaytracingLightGridData.LightGrid.Load(int4(UVy, 1, 0));
uint LightGridNz = RaytracingLightGridData.LightGrid.Load(int4(UVz, 2, 0));
uint LightGridN = LightGridNx;
uint LightGridOffset = RaytracingLightGridData.LightGridMaxCount * (0 + 3 * (UVx.x + UVx.y * RaytracingLightGridData.LightGridResolution));
if ((RaytracingLightGridData.LightGridAxis >= 3 && LightGridNy < LightGridN) || RaytracingLightGridData.LightGridAxis == 1)
{
LightGridN = LightGridNy;
LightGridOffset = RaytracingLightGridData.LightGridMaxCount * (1 + 3 * (UVy.x + UVy.y * RaytracingLightGridData.LightGridResolution));
}
if ((RaytracingLightGridData.LightGridAxis >= 3 && LightGridNz < LightGridN) || RaytracingLightGridData.LightGridAxis == 2)
{
LightGridN = LightGridNz;
LightGridOffset = RaytracingLightGridData.LightGridMaxCount * (2 + 3 * (UVz.x + UVz.y * RaytracingLightGridData.LightGridResolution));
}
Result.LightGridOffset = LightGridOffset;
Result.NumLights += LightGridN;
}
return Result;
}
uint GetNumLights()
{
return NumLights;
}
uint GetLightIndex(int LightNum, out uint Valid)
{
if (LightNum >= NumLights)
{
Valid = 0;
return 0;
}
Valid = 1;
if (LightNum >= RaytracingLightGridData.SceneInfiniteLightCount)
{
return RaytracingLightGridData.LightGridData[LightGridOffset + LightNum - RaytracingLightGridData.SceneInfiniteLightCount];
}
return LightNum;
}
float3 Visualize(int VisualizeMode)
{
const float3 OutsideColor = 0.18;
const float3 EmptyColor = 0.36;
if (LightGridOffset != ~0u)
{
switch (VisualizeMode)
{
case 2:
{
// color by unique light list
uint H = 0;
for (int Index = 0; Index < NumLights; Index++)
{
uint Valid = 0;
uint LightId = GetLightIndex(Index, Valid);
if (Valid)
{
H += LightId;
H ^= H >> 16;
H *= 0xa812d533;
H ^= H >> 15;
H *= 0xb278e4ad;
H ^= H >> 17;
}
}
return HUEtoRGB((H & 0xFFFFFF) * 5.96046447754e-08);
}
default:
{
// default mode - color by light count
uint N = NumLights - RaytracingLightGridData.SceneInfiniteLightCount;
if (N < 1)
{
return EmptyColor;
}
float Max = RaytracingLightGridData.LightGridMaxCount;
float t = saturate(float(N) / Max);
return BlueGreenRedColorMap(t);
}
}
}
// outside light grid bounds
return OutsideColor;
}
};