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

317 lines
14 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#include "HeterogeneousVolumesVoxelGridUtils.ush"
#include "HeterogeneousVolumesFrustumVoxelGridUtils.ush"
float3 EvalExtinctionOutOfFrustum(float3 WorldPos, inout int LinearBottomLevelVoxelPos)
{
float3 Extinction = 0;
float3 WorldBoundsMin = OrthoGridUniformBuffer.TopLevelGridWorldBoundsMin;
float3 WorldBoundsMax = OrthoGridUniformBuffer.TopLevelGridWorldBoundsMax;
float3 WorldBoundsExtent = WorldBoundsMax - WorldBoundsMin;
float3 GridUV = (WorldPos - WorldBoundsMin) / WorldBoundsExtent;
if (all(GridUV >= 0.0) && all(GridUV <= 1.0))
{
float3 TopLevelVoxelPos = GridUV * OrthoGridUniformBuffer.TopLevelGridResolution;
uint LinearTopLevelVoxelPos = GetLinearIndex(TopLevelVoxelPos, OrthoGridUniformBuffer.TopLevelGridResolution);
if (OrthoGridUniformBuffer.bEnableIndirectionGrid)
{
FTopLevelGridData TopLevelGridData = OrthoGridUniformBuffer.TopLevelGridBuffer[LinearTopLevelVoxelPos];
if (IsBottomLevelAllocated(TopLevelGridData))
{
uint IndirectionGridIndex = GetBottomLevelIndex(TopLevelGridData);
uint3 IndirectionGridVoxelResolution = GetBottomLevelVoxelResolution(TopLevelGridData);
// Convert to Indirection voxel-space
float3 IndirectionGridVoxelPos = frac(TopLevelVoxelPos) * IndirectionGridVoxelResolution;
int3 IndirectionGridVoxelPosAsInt = clamp(IndirectionGridVoxelPos, 0, IndirectionGridVoxelResolution - 1);
FTopLevelGridData IndirectionData = OrthoGridUniformBuffer.IndirectionGridBuffer[IndirectionGridIndex + MortonEncode3(IndirectionGridVoxelPosAsInt)];
if (IsBottomLevelAllocated(IndirectionData))
{
uint BottomLevelIndex = GetBottomLevelIndex(IndirectionData);
uint3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(IndirectionData);
// Constant interpolation
float3 BottomLevelVoxelPos = frac(IndirectionGridVoxelPos) * BottomLevelVoxelResolution;
int3 BottomLevelVoxelPosAsInt = clamp(BottomLevelVoxelPos, 0, BottomLevelVoxelResolution - 1);
LinearBottomLevelVoxelPos = BottomLevelIndex + MortonEncode3(BottomLevelVoxelPosAsInt);
Extinction = GetExtinction(OrthoGridUniformBuffer.ExtinctionGridBuffer[LinearBottomLevelVoxelPos]);
//Albedo = GetAlbedo(OrthoGridUniformBuffer.ScatteringGridBuffer[LinearBottomLevelVoxelPos]);
}
}
}
else
{
FTopLevelGridData TopLevelData = OrthoGridUniformBuffer.TopLevelGridBuffer[LinearTopLevelVoxelPos];
if (IsBottomLevelAllocated(TopLevelData))
{
uint BottomLevelIndex = GetBottomLevelIndex(OrthoGridUniformBuffer.TopLevelGridBuffer[LinearTopLevelVoxelPos]);
uint3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(OrthoGridUniformBuffer.TopLevelGridBuffer[LinearTopLevelVoxelPos]);
// Constant Interpolation
float3 BottomLevelVoxelPos = frac(TopLevelVoxelPos) * BottomLevelVoxelResolution;
int3 BottomLevelVoxelPosAsInt = clamp(BottomLevelVoxelPos, 0, BottomLevelVoxelResolution - 1);
LinearBottomLevelVoxelPos = BottomLevelIndex + MortonEncode3(BottomLevelVoxelPosAsInt);
Extinction = GetExtinction(OrthoGridUniformBuffer.ExtinctionGridBuffer[LinearBottomLevelVoxelPos]);
//Albedo = GetAlbedo(OrthoGridUniformBuffer.ScatteringGridBuffer[LinearBottomLevelVoxelPos]);
}
}
}
return Extinction;
}
float3 EvalExtinctionInFrustum(float3 WorldPos, inout bool bInFrustum)
{
float3 Extinction = 0;
// Convert WorldPos to voxel space
float3 ViewPos = mul(float4(WorldPos, 1), FrustumGridUniformBuffer.WorldToView).xyz;
int3 VoxelDimensions = FrustumGridUniformBuffer.VoxelDimensions;
float NearPlaneDepth = FrustumGridUniformBuffer.NearPlaneDepth;
float FarPlaneDepth = FrustumGridUniformBuffer.FarPlaneDepth;
float TanHalfFOV = FrustumGridUniformBuffer.TanHalfFOV;
float3 VoxelPos = ViewToVoxel(ViewPos, VoxelDimensions, NearPlaneDepth, FarPlaneDepth, TanHalfFOV);
bInFrustum = all(VoxelPos > 0) && all(VoxelPos < FrustumGridUniformBuffer.TopLevelFroxelGridResolution);
if (bInFrustum)
{
uint LinearTopLevelVoxelPos = GetLinearIndex(VoxelPos, FrustumGridUniformBuffer.TopLevelFroxelGridResolution);
FTopLevelGridData TopLevelGridData = FrustumGridUniformBuffer.TopLevelFroxelGridBuffer[LinearTopLevelVoxelPos];
if (IsBottomLevelAllocated(TopLevelGridData))
{
uint BottomLevelIndex = GetBottomLevelIndex(TopLevelGridData);
uint3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(TopLevelGridData);
float3 BottomLevelVoxelPos = frac(VoxelPos) * BottomLevelVoxelResolution;
uint LinearBottomLevelVoxelPos = BottomLevelIndex + MortonEncode3(uint3(BottomLevelVoxelPos));
Extinction = GetExtinction(FrustumGridUniformBuffer.ExtinctionFroxelGridBuffer[LinearBottomLevelVoxelPos]);
}
}
return Extinction;
}
float3 EvalExtinction(float3 WorldPos)
{
bool bInFrustum = false;
float3 Extinction = EvalExtinctionInFrustum(WorldPos, bInFrustum);
if (!bInFrustum)
{
int LinearVoxelPos;
Extinction = EvalExtinctionOutOfFrustum(WorldPos, LinearVoxelPos);
}
return Extinction;
}
float3 EvalAlbedoOutOfFrustum(float3 WorldPos, inout int LinearBottomLevelVoxelPos)
{
float3 Albedo = 0;
float3 WorldBoundsMin = OrthoGridUniformBuffer.TopLevelGridWorldBoundsMin;
float3 WorldBoundsMax = OrthoGridUniformBuffer.TopLevelGridWorldBoundsMax;
float3 WorldBoundsExtent = WorldBoundsMax - WorldBoundsMin;
float3 GridUV = (WorldPos - WorldBoundsMin) / WorldBoundsExtent;
if (all(GridUV >= 0.0) && all(GridUV <= 1.0))
{
float3 TopLevelVoxelPos = GridUV * OrthoGridUniformBuffer.TopLevelGridResolution;
uint LinearTopLevelVoxelPos = GetLinearIndex(TopLevelVoxelPos, OrthoGridUniformBuffer.TopLevelGridResolution);
if (OrthoGridUniformBuffer.bEnableIndirectionGrid)
{
FTopLevelGridData TopLevelGridData = OrthoGridUniformBuffer.TopLevelGridBuffer[LinearTopLevelVoxelPos];
if (IsBottomLevelAllocated(TopLevelGridData))
{
uint IndirectionGridIndex = GetBottomLevelIndex(TopLevelGridData);
uint3 IndirectionGridVoxelResolution = GetBottomLevelVoxelResolution(TopLevelGridData);
// Convert to Indirection voxel-space
float3 IndirectionGridVoxelPos = frac(TopLevelVoxelPos) * IndirectionGridVoxelResolution;
int3 IndirectionGridVoxelPosAsInt = clamp(IndirectionGridVoxelPos, 0, IndirectionGridVoxelResolution - 1);
FTopLevelGridData IndirectionData = OrthoGridUniformBuffer.IndirectionGridBuffer[IndirectionGridIndex + MortonEncode3(IndirectionGridVoxelPosAsInt)];
if (IsBottomLevelAllocated(IndirectionData))
{
uint BottomLevelIndex = GetBottomLevelIndex(IndirectionData);
uint3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(IndirectionData);
// Constant interpolation
float3 BottomLevelVoxelPos = frac(IndirectionGridVoxelPos) * BottomLevelVoxelResolution;
int3 BottomLevelVoxelPosAsInt = clamp(BottomLevelVoxelPos, 0, BottomLevelVoxelResolution - 1);
LinearBottomLevelVoxelPos = BottomLevelIndex + MortonEncode3(BottomLevelVoxelPosAsInt);
Albedo = GetAlbedo(OrthoGridUniformBuffer.ScatteringGridBuffer[LinearBottomLevelVoxelPos]);
//Albedo = GetAlbedo(OrthoGridUniformBuffer.ScatteringGridBuffer[LinearBottomLevelVoxelPos]);
}
}
}
else
{
FTopLevelGridData TopLevelData = OrthoGridUniformBuffer.TopLevelGridBuffer[LinearTopLevelVoxelPos];
if (IsBottomLevelAllocated(TopLevelData))
{
uint BottomLevelIndex = GetBottomLevelIndex(OrthoGridUniformBuffer.TopLevelGridBuffer[LinearTopLevelVoxelPos]);
uint3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(OrthoGridUniformBuffer.TopLevelGridBuffer[LinearTopLevelVoxelPos]);
// Constant Interpolation
float3 BottomLevelVoxelPos = frac(TopLevelVoxelPos) * BottomLevelVoxelResolution;
int3 BottomLevelVoxelPosAsInt = clamp(BottomLevelVoxelPos, 0, BottomLevelVoxelResolution - 1);
LinearBottomLevelVoxelPos = BottomLevelIndex + MortonEncode3(BottomLevelVoxelPosAsInt);
Albedo = GetAlbedo(OrthoGridUniformBuffer.ScatteringGridBuffer[LinearBottomLevelVoxelPos]);
//Albedo = GetAlbedo(OrthoGridUniformBuffer.ScatteringGridBuffer[LinearBottomLevelVoxelPos]);
}
}
}
return Albedo;
}
float3 EvalAlbedoInFrustum(float3 WorldPos, inout bool bInFrustum)
{
float3 Albedo = 0;
// Convert WorldPos to voxel space
float3 ViewPos = mul(float4(WorldPos, 1), FrustumGridUniformBuffer.WorldToView).xyz;
int3 VoxelDimensions = FrustumGridUniformBuffer.VoxelDimensions;
float NearPlaneDepth = FrustumGridUniformBuffer.NearPlaneDepth;
float FarPlaneDepth = FrustumGridUniformBuffer.FarPlaneDepth;
float TanHalfFOV = FrustumGridUniformBuffer.TanHalfFOV;
float3 VoxelPos = ViewToVoxel(ViewPos, VoxelDimensions, NearPlaneDepth, FarPlaneDepth, TanHalfFOV);
bInFrustum = all(VoxelPos > 0) && all(VoxelPos < FrustumGridUniformBuffer.TopLevelFroxelGridResolution);
if (bInFrustum)
{
uint LinearTopLevelVoxelPos = GetLinearIndex(VoxelPos, FrustumGridUniformBuffer.TopLevelFroxelGridResolution);
FTopLevelGridData TopLevelGridData = FrustumGridUniformBuffer.TopLevelFroxelGridBuffer[LinearTopLevelVoxelPos];
if (IsBottomLevelAllocated(TopLevelGridData))
{
uint BottomLevelIndex = GetBottomLevelIndex(TopLevelGridData);
uint3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(TopLevelGridData);
float3 BottomLevelVoxelPos = frac(VoxelPos) * BottomLevelVoxelResolution;
uint LinearBottomLevelVoxelPos = BottomLevelIndex + MortonEncode3(uint3(BottomLevelVoxelPos));
Albedo = GetAlbedo(FrustumGridUniformBuffer.ScatteringFroxelGridBuffer[LinearBottomLevelVoxelPos]);
}
}
return Albedo;
}
float3 EvalAlbedo(float3 WorldPos)
{
bool bInFrustum = false;
float3 Albedo = EvalAlbedoInFrustum(WorldPos, bInFrustum);
if (!bInFrustum)
{
int LinearVoxelPos;
Albedo = EvalAlbedoOutOfFrustum(WorldPos, LinearVoxelPos);
}
return Albedo;
}
float3 EvalEmissionOutOfFrustum(float3 WorldPos, inout int LinearBottomLevelVoxelPos)
{
float3 Emission = 0;
float3 WorldBoundsMin = OrthoGridUniformBuffer.TopLevelGridWorldBoundsMin;
float3 WorldBoundsMax = OrthoGridUniformBuffer.TopLevelGridWorldBoundsMax;
float3 WorldBoundsExtent = WorldBoundsMax - WorldBoundsMin;
float3 GridUV = (WorldPos - WorldBoundsMin) / WorldBoundsExtent;
if (all(GridUV >= 0.0) && all(GridUV <= 1.0))
{
float3 TopLevelVoxelPos = GridUV * OrthoGridUniformBuffer.TopLevelGridResolution;
uint LinearTopLevelVoxelPos = GetLinearIndex(TopLevelVoxelPos, OrthoGridUniformBuffer.TopLevelGridResolution);
if (OrthoGridUniformBuffer.bEnableIndirectionGrid)
{
FTopLevelGridData TopLevelGridData = OrthoGridUniformBuffer.TopLevelGridBuffer[LinearTopLevelVoxelPos];
if (IsBottomLevelAllocated(TopLevelGridData))
{
uint IndirectionGridIndex = GetBottomLevelIndex(TopLevelGridData);
uint3 IndirectionGridVoxelResolution = GetBottomLevelVoxelResolution(TopLevelGridData);
// Convert to Indirection voxel-space
float3 IndirectionGridVoxelPos = frac(TopLevelVoxelPos) * IndirectionGridVoxelResolution;
int3 IndirectionGridVoxelPosAsInt = clamp(IndirectionGridVoxelPos, 0, IndirectionGridVoxelResolution - 1);
FTopLevelGridData IndirectionData = OrthoGridUniformBuffer.IndirectionGridBuffer[IndirectionGridIndex + MortonEncode3(IndirectionGridVoxelPosAsInt)];
if (IsBottomLevelAllocated(IndirectionData))
{
uint BottomLevelIndex = GetBottomLevelIndex(IndirectionData);
uint3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(IndirectionData);
// Constant interpolation
float3 BottomLevelVoxelPos = frac(IndirectionGridVoxelPos) * BottomLevelVoxelResolution;
int3 BottomLevelVoxelPosAsInt = clamp(BottomLevelVoxelPos, 0, BottomLevelVoxelResolution - 1);
LinearBottomLevelVoxelPos = BottomLevelIndex + MortonEncode3(BottomLevelVoxelPosAsInt);
Emission = GetEmission(OrthoGridUniformBuffer.EmissionGridBuffer[LinearBottomLevelVoxelPos]);
}
}
}
else
{
FTopLevelGridData TopLevelData = OrthoGridUniformBuffer.TopLevelGridBuffer[LinearTopLevelVoxelPos];
if (IsBottomLevelAllocated(TopLevelData))
{
uint BottomLevelIndex = GetBottomLevelIndex(OrthoGridUniformBuffer.TopLevelGridBuffer[LinearTopLevelVoxelPos]);
uint3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(OrthoGridUniformBuffer.TopLevelGridBuffer[LinearTopLevelVoxelPos]);
// Constant Interpolation
float3 BottomLevelVoxelPos = frac(TopLevelVoxelPos) * BottomLevelVoxelResolution;
int3 BottomLevelVoxelPosAsInt = clamp(BottomLevelVoxelPos, 0, BottomLevelVoxelResolution - 1);
LinearBottomLevelVoxelPos = BottomLevelIndex + MortonEncode3(BottomLevelVoxelPosAsInt);
Emission = GetEmission(OrthoGridUniformBuffer.EmissionGridBuffer[LinearBottomLevelVoxelPos]);
}
}
}
return Emission;
}
float3 EvalEmissionInFrustum(float3 WorldPos, inout bool bInFrustum)
{
float3 Emission = 0;
// Convert WorldPos to voxel space
float3 ViewPos = mul(float4(WorldPos, 1), FrustumGridUniformBuffer.WorldToView).xyz;
int3 VoxelDimensions = FrustumGridUniformBuffer.VoxelDimensions;
float NearPlaneDepth = FrustumGridUniformBuffer.NearPlaneDepth;
float FarPlaneDepth = FrustumGridUniformBuffer.FarPlaneDepth;
float TanHalfFOV = FrustumGridUniformBuffer.TanHalfFOV;
float3 VoxelPos = ViewToVoxel(ViewPos, VoxelDimensions, NearPlaneDepth, FarPlaneDepth, TanHalfFOV);
bInFrustum = all(VoxelPos > 0) && all(VoxelPos < FrustumGridUniformBuffer.TopLevelFroxelGridResolution);
if (bInFrustum)
{
uint LinearTopLevelVoxelPos = GetLinearIndex(VoxelPos, FrustumGridUniformBuffer.TopLevelFroxelGridResolution);
FTopLevelGridData TopLevelGridData = FrustumGridUniformBuffer.TopLevelFroxelGridBuffer[LinearTopLevelVoxelPos];
if (IsBottomLevelAllocated(TopLevelGridData))
{
uint BottomLevelIndex = GetBottomLevelIndex(TopLevelGridData);
uint3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(TopLevelGridData);
float3 BottomLevelVoxelPos = frac(VoxelPos) * BottomLevelVoxelResolution;
uint LinearBottomLevelVoxelPos = BottomLevelIndex + MortonEncode3(uint3(BottomLevelVoxelPos));
Emission = GetEmission(FrustumGridUniformBuffer.EmissionFroxelGridBuffer[LinearBottomLevelVoxelPos]);
}
}
return Emission;
}
float3 EvalEmission(float3 WorldPos)
{
bool bInFrustum = false;
float3 Emission = EvalEmissionInFrustum(WorldPos, bInFrustum);
if (!bInFrustum)
{
int LinearVoxelPos;
Emission = EvalEmissionOutOfFrustum(WorldPos, LinearVoxelPos);
}
return Emission;
}