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

86 lines
3.3 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#define DISTANCE_FIELD_OBJECT_GRID_INVALID_ID 0xFFFFFFFF
#define DISTANCE_FIELD_OBJECT_GRID_CELL_SIZE 4 // Up to 4 objects per cell
#define DISTANCE_FIELD_OBJECT_GRID_PAGE_RESOLUTION 4
#define DISTANCE_FIELD_OBJECT_GRID_CARD_INTERPOLATION_RANGE_IN_VOXELS 3.0f
#define DISTANCE_FIELD_OBJECT_GRID_PAGE_STRIDE (DISTANCE_FIELD_OBJECT_GRID_PAGE_RESOLUTION * DISTANCE_FIELD_OBJECT_GRID_PAGE_RESOLUTION * DISTANCE_FIELD_OBJECT_GRID_PAGE_RESOLUTION)
StructuredBuffer<uint4> GlobalDistanceFieldPageObjectGridBuffer;
struct FObjectGridCell
{
uint4 PackedIndex4;
};
FObjectGridCell InitObjectGridCell()
{
FObjectGridCell GridCell;
GridCell.PackedIndex4 = uint4(DISTANCE_FIELD_OBJECT_GRID_INVALID_ID, DISTANCE_FIELD_OBJECT_GRID_INVALID_ID, DISTANCE_FIELD_OBJECT_GRID_INVALID_ID, DISTANCE_FIELD_OBJECT_GRID_INVALID_ID);
return GridCell;
}
struct FObjectGridCellIndex
{
uint GPUSceneInstanceIndex;
bool bValid;
};
uint PackObjectGridCellIndex(uint GPUSceneInstanceIndex, float Distance, float ObjectGridCellWorldExtent, float MaxQueryDistance)
{
float NormalizedPackedDistance = saturate((Distance + 0.25f * ObjectGridCellWorldExtent) / (MaxQueryDistance + 0.25f * ObjectGridCellWorldExtent));
uint PackedDistanceUInt = uint(clamp(NormalizedPackedDistance * (0xFF + 1.0f), 0, 0xFF));
uint GridCellElement = (GPUSceneInstanceIndex & 0xFFFFFF) | (PackedDistanceUInt << 24);
return GridCellElement;
}
// Unpack GPUSceneInstanceIndex
FObjectGridCellIndex UnpackObjectGridCellIndex(uint PackedIndex)
{
FObjectGridCellIndex ObjectGridCellIndex;
ObjectGridCellIndex.bValid = PackedIndex < DISTANCE_FIELD_OBJECT_GRID_INVALID_ID;
ObjectGridCellIndex.GPUSceneInstanceIndex = PackedIndex & 0xFFFFFF;
return ObjectGridCellIndex;
}
// Unordered add to a grid cell
void AddToObjectGridCell(inout FObjectGridCell ObjectGridCell, uint GPUSceneInstanceIndex, float Distance, float ObjectGridCellWorldExtent, float MaxQueryDistance)
{
if (abs(Distance) < MaxQueryDistance)
{
uint PackedIndexToInsert = PackObjectGridCellIndex(GPUSceneInstanceIndex, Distance, ObjectGridCellWorldExtent, MaxQueryDistance);
uint MaxPackedIndex = 0;
for (uint IndexInList = 0; IndexInList < DISTANCE_FIELD_OBJECT_GRID_CELL_SIZE; ++IndexInList)
{
MaxPackedIndex = max(MaxPackedIndex, ObjectGridCell.PackedIndex4[IndexInList]);
}
if (PackedIndexToInsert < MaxPackedIndex)
{
for (uint IndexInList = 0; IndexInList < DISTANCE_FIELD_OBJECT_GRID_CELL_SIZE; ++IndexInList)
{
if (ObjectGridCell.PackedIndex4[IndexInList] == MaxPackedIndex)
{
ObjectGridCell.PackedIndex4[IndexInList] = PackedIndexToInsert;
break;
}
}
}
}
}
// Sort grid cell elements by distance
void SortObjectGridCell(inout FObjectGridCell ObjectGridCell)
{
for (uint PassIndex = 0; PassIndex < DISTANCE_FIELD_OBJECT_GRID_CELL_SIZE - 1; ++PassIndex)
{
for (uint ElementIndex = 0; ElementIndex < DISTANCE_FIELD_OBJECT_GRID_CELL_SIZE - PassIndex - 1; ++ElementIndex)
{
uint MinIndex = min(ObjectGridCell.PackedIndex4[ElementIndex], ObjectGridCell.PackedIndex4[ElementIndex + 1]);
uint MaxIndex = max(ObjectGridCell.PackedIndex4[ElementIndex], ObjectGridCell.PackedIndex4[ElementIndex + 1]);
ObjectGridCell.PackedIndex4[ElementIndex] = MinIndex;
ObjectGridCell.PackedIndex4[ElementIndex + 1] = MaxIndex;
}
}
}