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

89 lines
3.4 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#include "../Common.ush"
#include "/Engine/Shared/RayTracingDefinitions.h"
#include "/Engine/Shared/RayTracingTypes.h"
#include "/Engine/Shared/PathTracingDefinitions.h"
StructuredBuffer<FRayTracingDecal> SceneDecals;
uint SceneDecalCount;
float3 SceneDecalsTranslatedBoundMin;
float3 SceneDecalsTranslatedBoundMax;
uint DecalGridResolution;
uint DecalGridMaxCount;
uint DecalGridAxis;
RWTexture2DArray<uint> RWDecalGrid;
RWBuffer<uint> RWDecalGridData;
[numthreads(THREADGROUPSIZE_X, THREADGROUPSIZE_Y, 1)]
void BuildDecalGridCS(uint3 DispatchThreadId : SV_DispatchThreadID)
{
if (any(DispatchThreadId >= DecalGridResolution) || DispatchThreadId.z >= 3)
{
return;
}
// figure out dimension of the 3d grid and the current ID to be filled
uint3 VoxelId = 0, VoxelRes = 1;
int Axis = DispatchThreadId.z;
if (DecalGridAxis != Axis && DecalGridAxis < 3)
{
RWDecalGrid[DispatchThreadId] = 0;
return;
}
switch (Axis)
{
case 0: VoxelId.yz = DispatchThreadId.xy; VoxelRes.yz = DecalGridResolution; break;
case 1: VoxelId.xz = DispatchThreadId.xy; VoxelRes.xz = DecalGridResolution; break;
case 2: VoxelId.xy = DispatchThreadId.xy; VoxelRes.xy = DecalGridResolution; break;
}
// get bounding box of current voxel
float3 Lo = lerp(SceneDecalsTranslatedBoundMin, SceneDecalsTranslatedBoundMax, float3(VoxelId + 0) / float3(VoxelRes));
float3 Hi = lerp(SceneDecalsTranslatedBoundMin, SceneDecalsTranslatedBoundMax, float3(VoxelId + 1) / float3(VoxelRes));
uint NumVisible = 0;
uint MaxVisible = min(DecalGridMaxCount, RAY_TRACING_DECAL_COUNT_MAXIMUM);
uint Offset = DecalGridMaxCount * (Axis + 3 * (DispatchThreadId.x + DecalGridResolution * DispatchThreadId.y));
for (uint DecalIndex = 0; DecalIndex < SceneDecalCount; DecalIndex++)
{
FRayTracingDecal Decal = SceneDecals[DecalIndex];
if (any(Hi < Decal.TranslatedBoundMin) || any(Lo > Decal.TranslatedBoundMax))
{
continue;
}
#if 1
// Transform the corners of the voxel into decal space so we can cull the "other way" as well and account for rotated decals
float3 DecalPos000 = mul(float4(Lo.x, Lo.y, Lo.z, 1), Decal.TranslatedWorldToDecal).xyz;
float3 DecalPos001 = mul(float4(Lo.x, Lo.y, Hi.z, 1), Decal.TranslatedWorldToDecal).xyz;
float3 DecalPos010 = mul(float4(Lo.x, Hi.y, Lo.z, 1), Decal.TranslatedWorldToDecal).xyz;
float3 DecalPos011 = mul(float4(Lo.x, Hi.y, Hi.z, 1), Decal.TranslatedWorldToDecal).xyz;
float3 DecalPos100 = mul(float4(Hi.x, Lo.y, Lo.z, 1), Decal.TranslatedWorldToDecal).xyz;
float3 DecalPos101 = mul(float4(Hi.x, Lo.y, Hi.z, 1), Decal.TranslatedWorldToDecal).xyz;
float3 DecalPos110 = mul(float4(Hi.x, Hi.y, Lo.z, 1), Decal.TranslatedWorldToDecal).xyz;
float3 DecalPos111 = mul(float4(Hi.x, Hi.y, Hi.z, 1), Decal.TranslatedWorldToDecal).xyz;
float3 DecalLo = min(min(min(DecalPos000, DecalPos001), min(DecalPos010, DecalPos011)), min(min(DecalPos100, DecalPos101), min(DecalPos110, DecalPos111)));
float3 DecalHi = max(max(max(DecalPos000, DecalPos001), max(DecalPos010, DecalPos011)), max(max(DecalPos100, DecalPos101), max(DecalPos110, DecalPos111)));
if (any(DecalHi < -1) || any(DecalLo > 1))
{
continue;
}
#endif
RWDecalGridData[Offset + NumVisible] = Decal.CallableSlotIndex;
NumVisible++;
// TODO: handle overflow better?
if (NumVisible >= MaxVisible)
{
break;
}
}
RWDecalGrid[DispatchThreadId] = NumVisible;
}