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

531 lines
18 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "HeterogeneousVolumesVoxelGridUtils.ush"
#include "HeterogeneousVolumesFrustumVoxelGridUtils.ush"
void MarchBottomLevelVoxelGrid(
float3 VoxelRayOrigin,
float3 VoxelRayDirection,
float VoxelRayTMin,
float VoxelRayTMax,
float WorldRayHitSpan,
float3 TopLevelVoxelStartPos,
float3 TopLevelVoxelEndPos,
FTopLevelGridData TopLevelGridData,
StructuredBuffer<FScalarGridData> ExtinctionGridBuffer,
inout float3 Transmittance
)
{
uint BottomLevelVoxelIndex = GetBottomLevelIndex(TopLevelGridData);
int3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(TopLevelGridData);
float TopLevelVoxelRayLength = length(TopLevelVoxelEndPos - TopLevelVoxelStartPos);
// Transform to local-space
float3 MinTopLevelVoxelPos = floor((TopLevelVoxelStartPos + TopLevelVoxelEndPos) * 0.5);
float3 LocalRayOrigin = (TopLevelVoxelStartPos - MinTopLevelVoxelPos) * BottomLevelVoxelResolution;
float3 LocalRayEnd = (TopLevelVoxelEndPos - MinTopLevelVoxelPos) * BottomLevelVoxelResolution;
float3 LocalRayDirection = LocalRayEnd - LocalRayOrigin;
float LocalRayLength = length(LocalRayDirection);
LocalRayDirection /= LocalRayLength;
float3 LocalRayDirectionInv = 1.0 / LocalRayDirection;
float LocalRayMarchT = 0.0;
float3 LocalRayMarchPos = LocalRayOrigin;
float3 LocalBoundsPos;
LocalBoundsPos.x = sign(LocalRayDirection.x) > 0 ? floor(LocalRayMarchPos.x) + 1 : ceil(LocalRayMarchPos.x) - 1;
LocalBoundsPos.y = sign(LocalRayDirection.y) > 0 ? floor(LocalRayMarchPos.y) + 1 : ceil(LocalRayMarchPos.y) - 1;
LocalBoundsPos.z = sign(LocalRayDirection.z) > 0 ? floor(LocalRayMarchPos.z) + 1 : ceil(LocalRayMarchPos.z) - 1;
float3 LocalBoundsHitT = (LocalBoundsPos - LocalRayMarchPos) * LocalRayDirectionInv;
// Remove floating-point rounding error
float Epsilon = 1.0e-4;
if (LocalBoundsHitT.x <= Epsilon) LocalBoundsHitT.x += abs(LocalRayDirectionInv.x);
if (LocalBoundsHitT.y <= Epsilon) LocalBoundsHitT.y += abs(LocalRayDirectionInv.y);
if (LocalBoundsHitT.z <= Epsilon) LocalBoundsHitT.z += abs(LocalRayDirectionInv.z);
float3 OpacityThreshold = 1.0e-4;
while ((LocalRayMarchT < LocalRayLength) && all(Transmittance > OpacityThreshold))
{
float LocalRayMarchDeltaT = 0.0;
if (LocalBoundsHitT.x < LocalBoundsHitT.y)
{
if (LocalBoundsHitT.x < LocalBoundsHitT.z)
{
LocalRayMarchDeltaT = LocalBoundsHitT.x - LocalRayMarchT;
LocalBoundsHitT.x += abs(LocalRayDirectionInv.x);
}
else
{
LocalRayMarchDeltaT = LocalBoundsHitT.z - LocalRayMarchT;
LocalBoundsHitT.z += abs(LocalRayDirectionInv.z);
}
}
else
{
if (LocalBoundsHitT.y < LocalBoundsHitT.z)
{
LocalRayMarchDeltaT = LocalBoundsHitT.y - LocalRayMarchT;
LocalBoundsHitT.y += abs(LocalRayDirectionInv.y);
}
else
{
LocalRayMarchDeltaT = LocalBoundsHitT.z - LocalRayMarchT;
LocalBoundsHitT.z += abs(LocalRayDirectionInv.z);
}
}
// Clip voxel delta-t by overall voxel ray-length.
if (LocalRayMarchT + LocalRayMarchDeltaT > LocalRayLength)
{
LocalRayMarchDeltaT = LocalRayLength - LocalRayMarchT;
}
float3 LocalEndPos = LocalRayMarchPos + LocalRayDirection * LocalRayMarchDeltaT;
float3 LocalSamplePos = clamp((LocalRayMarchPos + LocalEndPos) * 0.5, 0.0, BottomLevelVoxelResolution - 1.0);
uint LocalSampleLinearPos = BottomLevelVoxelIndex + MortonEncode3(LocalSamplePos);
float3 Extinction = GetExtinction(ExtinctionGridBuffer[LocalSampleLinearPos]);
float WorldRayMarchDeltaT = max((LocalRayMarchDeltaT / LocalRayLength) * TopLevelVoxelRayLength * WorldRayHitSpan / VoxelRayTMax, 0.0);
Transmittance *= saturate(exp(-Extinction * WorldRayMarchDeltaT));
LocalRayMarchT += LocalRayMarchDeltaT;
LocalRayMarchPos = LocalEndPos;
}
}
void MarchIndirectionOrthoVoxelGrid(
float3 VoxelRayOrigin,
float3 VoxelRayDirection,
float VoxelRayTMin,
float VoxelRayTMax,
float WorldRayHitSpan,
float3 TopLevelVoxelStartPos,
float3 TopLevelVoxelEndPos,
FTopLevelGridData TopLevelGridData,
StructuredBuffer<FTopLevelGridData> IndirectionGridBuffer,
StructuredBuffer<FScalarGridData> ExtinctionGridBuffer,
inout float3 Transmittance
)
{
uint BottomLevelVoxelIndex = GetBottomLevelIndex(TopLevelGridData);
int3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(TopLevelGridData);
float TopLevelVoxelRayLength = length(TopLevelVoxelEndPos - TopLevelVoxelStartPos);
// Transform to local-space
float3 MinTopLevelVoxelPos = floor((TopLevelVoxelStartPos + TopLevelVoxelEndPos) * 0.5);
float3 LocalRayOrigin = (TopLevelVoxelStartPos - MinTopLevelVoxelPos) * BottomLevelVoxelResolution;
float3 LocalRayEnd = (TopLevelVoxelEndPos - MinTopLevelVoxelPos) * BottomLevelVoxelResolution;
float3 LocalRayDirection = LocalRayEnd - LocalRayOrigin;
float LocalRayLength = length(LocalRayDirection);
LocalRayDirection /= LocalRayLength;
float3 LocalRayDirectionInv = 1.0 / LocalRayDirection;
float LocalRayMarchT = 0.0;
float3 LocalRayMarchPos = LocalRayOrigin;
float3 LocalBoundsPos;
LocalBoundsPos.x = sign(LocalRayDirection.x) > 0 ? floor(LocalRayMarchPos.x) + 1 : ceil(LocalRayMarchPos.x) - 1;
LocalBoundsPos.y = sign(LocalRayDirection.y) > 0 ? floor(LocalRayMarchPos.y) + 1 : ceil(LocalRayMarchPos.y) - 1;
LocalBoundsPos.z = sign(LocalRayDirection.z) > 0 ? floor(LocalRayMarchPos.z) + 1 : ceil(LocalRayMarchPos.z) - 1;
float3 LocalBoundsHitT = (LocalBoundsPos - LocalRayMarchPos) * LocalRayDirectionInv;
// Remove floating-point rounding error
float Epsilon = 1.0e-4;
if (LocalBoundsHitT.x <= Epsilon) LocalBoundsHitT.x += abs(LocalRayDirectionInv.x);
if (LocalBoundsHitT.y <= Epsilon) LocalBoundsHitT.y += abs(LocalRayDirectionInv.y);
if (LocalBoundsHitT.z <= Epsilon) LocalBoundsHitT.z += abs(LocalRayDirectionInv.z);
float3 OpacityThreshold = 1.0e-4;
while ((LocalRayMarchT < LocalRayLength) && all(Transmittance > OpacityThreshold))
{
float LocalRayMarchDeltaT = 0.0;
if (LocalBoundsHitT.x < LocalBoundsHitT.y)
{
if (LocalBoundsHitT.x < LocalBoundsHitT.z)
{
LocalRayMarchDeltaT = LocalBoundsHitT.x - LocalRayMarchT;
LocalBoundsHitT.x += abs(LocalRayDirectionInv.x);
}
else
{
LocalRayMarchDeltaT = LocalBoundsHitT.z - LocalRayMarchT;
LocalBoundsHitT.z += abs(LocalRayDirectionInv.z);
}
}
else
{
if (LocalBoundsHitT.y < LocalBoundsHitT.z)
{
LocalRayMarchDeltaT = LocalBoundsHitT.y - LocalRayMarchT;
LocalBoundsHitT.y += abs(LocalRayDirectionInv.y);
}
else
{
LocalRayMarchDeltaT = LocalBoundsHitT.z - LocalRayMarchT;
LocalBoundsHitT.z += abs(LocalRayDirectionInv.z);
}
}
// Clip voxel delta-t by overall voxel ray-length.
if (LocalRayMarchT + LocalRayMarchDeltaT > LocalRayLength)
{
LocalRayMarchDeltaT = LocalRayLength - LocalRayMarchT;
}
float3 LocalEndPos = LocalRayMarchPos + LocalRayDirection * LocalRayMarchDeltaT;
float3 LocalSamplePos = clamp((LocalRayMarchPos + LocalEndPos) * 0.5, 0.0, BottomLevelVoxelResolution - 1.0);
uint LocalSampleLinearPos = BottomLevelVoxelIndex + MortonEncode3(LocalSamplePos);
float LocalScaleFactor = TopLevelVoxelRayLength / LocalRayLength;
FTopLevelGridData IndirectionData = IndirectionGridBuffer[LocalSampleLinearPos];
if (IsBottomLevelAllocated(IndirectionData))
{
MarchBottomLevelVoxelGrid(
LocalRayOrigin,
LocalRayDirection,
VoxelRayTMin,
VoxelRayTMax,
WorldRayHitSpan * LocalScaleFactor,
LocalRayMarchPos,
LocalEndPos,
IndirectionData,
ExtinctionGridBuffer,
Transmittance
);
}
LocalRayMarchT += LocalRayMarchDeltaT;
LocalRayMarchPos = LocalEndPos;
}
}
void MarchTopLevelOrthoVoxelGrid(
float3 VoxelRayOrigin,
float3 VoxelRayDirection,
float VoxelRayTMin,
float VoxelRayTMax,
float WorldRayHitSpan,
bool bEnableIndirectionGrid,
int3 TopLevelGridResolution,
StructuredBuffer<FTopLevelGridData> TopLevelGridBuffer,
StructuredBuffer<FTopLevelGridData> IndirectionGridBuffer,
StructuredBuffer<FScalarGridData> ExtinctionGridBuffer,
inout float3 Transmittance
)
{
float3 VoxelRayDirectionInv = 1.0 / VoxelRayDirection;
// Grid intersection
float VoxelRayMarchT = VoxelRayTMin;
float3 VoxelRayMarchPos = VoxelRayOrigin;
float3 VoxelBoundsPos;
VoxelBoundsPos.x = sign(VoxelRayDirection.x) > 0 ? floor(VoxelRayMarchPos.x) + 1 : ceil(VoxelRayMarchPos.x) - 1;
VoxelBoundsPos.y = sign(VoxelRayDirection.y) > 0 ? floor(VoxelRayMarchPos.y) + 1 : ceil(VoxelRayMarchPos.y) - 1;
VoxelBoundsPos.z = sign(VoxelRayDirection.z) > 0 ? floor(VoxelRayMarchPos.z) + 1 : ceil(VoxelRayMarchPos.z) - 1;
float3 VoxelBoundsHitT = (VoxelBoundsPos - VoxelRayMarchPos) * VoxelRayDirectionInv;
// Remove floating-point rounding error
float Epsilon = 1.0e-4;
if (VoxelBoundsHitT.x <= Epsilon) VoxelBoundsHitT.x += abs(VoxelRayDirectionInv.x);
if (VoxelBoundsHitT.y <= Epsilon) VoxelBoundsHitT.y += abs(VoxelRayDirectionInv.y);
if (VoxelBoundsHitT.z <= Epsilon) VoxelBoundsHitT.z += abs(VoxelRayDirectionInv.z);
float3 OpacityThreshold = 1.0e-4;
while ((VoxelRayMarchT < VoxelRayTMax) && all(Transmittance > OpacityThreshold))
{
float VoxelRayMarchDeltaT = 0.0;
if (VoxelBoundsHitT.x < VoxelBoundsHitT.y)
{
if (VoxelBoundsHitT.x < VoxelBoundsHitT.z)
{
VoxelRayMarchDeltaT = VoxelBoundsHitT.x - VoxelRayMarchT;
VoxelBoundsHitT.x += abs(VoxelRayDirectionInv.x);
}
else
{
VoxelRayMarchDeltaT = VoxelBoundsHitT.z - VoxelRayMarchT;
VoxelBoundsHitT.z += abs(VoxelRayDirectionInv.z);
}
}
else
{
if (VoxelBoundsHitT.y < VoxelBoundsHitT.z)
{
VoxelRayMarchDeltaT = VoxelBoundsHitT.y - VoxelRayMarchT;
VoxelBoundsHitT.y += abs(VoxelRayDirectionInv.y);
}
else
{
VoxelRayMarchDeltaT = VoxelBoundsHitT.z - VoxelRayMarchT;
VoxelBoundsHitT.z += abs(VoxelRayDirectionInv.z);
}
}
// Clip voxel delta-t by overall voxel ray-length.
if (VoxelRayMarchT + VoxelRayMarchDeltaT > VoxelRayTMax)
{
VoxelRayMarchDeltaT = VoxelRayTMax - VoxelRayMarchT;
}
// Sample at the midpoint of the voxel ray
float3 VoxelEndPos = VoxelRayMarchPos + VoxelRayDirection * VoxelRayMarchDeltaT;
float3 VoxelSamplePos = (VoxelRayMarchPos + VoxelEndPos) * 0.5;
uint VoxelSampleLinearPos = GetLinearIndex(VoxelSamplePos, TopLevelGridResolution);
int3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(TopLevelGridBuffer[VoxelSampleLinearPos]);
if (IsBottomLevelAllocated(TopLevelGridBuffer[VoxelSampleLinearPos]))
{
if (bEnableIndirectionGrid)
{
MarchIndirectionOrthoVoxelGrid(
VoxelRayOrigin,
VoxelRayDirection,
VoxelRayTMin,
VoxelRayTMax,
WorldRayHitSpan,
VoxelRayMarchPos,
VoxelEndPos,
TopLevelGridBuffer[VoxelSampleLinearPos],
IndirectionGridBuffer,
ExtinctionGridBuffer,
Transmittance
);
}
else if (all(BottomLevelVoxelResolution > 1))
{
MarchBottomLevelVoxelGrid(
VoxelRayOrigin,
VoxelRayDirection,
VoxelRayTMin,
VoxelRayTMax,
WorldRayHitSpan,
VoxelRayMarchPos,
VoxelEndPos,
TopLevelGridBuffer[VoxelSampleLinearPos],
ExtinctionGridBuffer,
Transmittance
);
}
else
{
float3 Extinction = GetExtinction(TopLevelGridBuffer[VoxelSampleLinearPos], ExtinctionGridBuffer);
float WorldRayMarchDeltaT = max(VoxelRayMarchDeltaT * WorldRayHitSpan / VoxelRayTMax, 0.0);
Transmittance *= saturate(exp(-Extinction * WorldRayMarchDeltaT));
}
}
VoxelRayMarchT += VoxelRayMarchDeltaT;
VoxelRayMarchPos = VoxelEndPos;
}
}
float3 TraceOrthoVoxelGrid(float3 Origin, float3 Direction, float TMin, float TMax)
{
float3 Transmittance = 1.0;
// Intersect world-space AABB to clip ray
float3 WorldBoundsMin = OrthoGridUniformBuffer.TopLevelGridWorldBoundsMin;
float3 WorldBoundsMax = OrthoGridUniformBuffer.TopLevelGridWorldBoundsMax;
float3 WorldRayOrigin = DFHackToFloat(DFFastSubtract(Origin, PrimaryView.PreViewTranslation));
float2 ClipHitT = IntersectAABB(WorldRayOrigin, Direction, TMin, TMax, WorldBoundsMin, WorldBoundsMax);
if (ClipHitT.x > ClipHitT.y)
{
return Transmittance;
}
float3 WorldRayBegin = WorldRayOrigin + Direction * ClipHitT.x;
float3 WorldRayEnd = WorldRayOrigin + Direction * ClipHitT.y;
float WorldRayLength = ClipHitT.y - ClipHitT.x;
// Transform to voxel-space
float3 WorldBoundsExtent = WorldBoundsMax - WorldBoundsMin;
float3 VoxelRayBegin = (WorldRayBegin - WorldBoundsMin) / WorldBoundsExtent * OrthoGridUniformBuffer.TopLevelGridResolution;
float3 VoxelRayEnd = (WorldRayEnd - WorldBoundsMin) / WorldBoundsExtent * OrthoGridUniformBuffer.TopLevelGridResolution;
float3 VoxelRayDirection = VoxelRayEnd - VoxelRayBegin;
float VoxelRayTMin = 0.0;
float VoxelRayTMax = length(VoxelRayDirection);
VoxelRayDirection /= VoxelRayTMax;
MarchTopLevelOrthoVoxelGrid(
VoxelRayBegin,
VoxelRayDirection,
VoxelRayTMin,
VoxelRayTMax,
WorldRayLength,
OrthoGridUniformBuffer.bEnableIndirectionGrid,
OrthoGridUniformBuffer.TopLevelGridResolution,
OrthoGridUniformBuffer.TopLevelGridBuffer,
OrthoGridUniformBuffer.IndirectionGridBuffer,
OrthoGridUniformBuffer.ExtinctionGridBuffer,
Transmittance
);
return Transmittance;
}
void MarchTopLevelFrustumVoxelGrid(
float3 VoxelRayOrigin,
float3 VoxelRayDirection,
float VoxelRayTMin,
float VoxelRayTMax,
float WorldRayHitSpan,
int3 TopLevelGridResolution,
StructuredBuffer<FTopLevelGridData> TopLevelGridBuffer,
StructuredBuffer<FScalarGridData> ExtinctionGridBuffer,
inout float3 Transmittance
)
{
float3 VoxelRayDirectionInv = 1.0 / VoxelRayDirection;
// Grid intersection
float VoxelRayMarchT = VoxelRayTMin;
float3 VoxelRayMarchPos = VoxelRayOrigin;
float3 VoxelBoundsPos;
VoxelBoundsPos.x = sign(VoxelRayDirection.x) > 0 ? floor(VoxelRayMarchPos.x) + 1 : ceil(VoxelRayMarchPos.x) - 1;
VoxelBoundsPos.y = sign(VoxelRayDirection.y) > 0 ? floor(VoxelRayMarchPos.y) + 1 : ceil(VoxelRayMarchPos.y) - 1;
VoxelBoundsPos.z = sign(VoxelRayDirection.z) > 0 ? floor(VoxelRayMarchPos.z) + 1 : ceil(VoxelRayMarchPos.z) - 1;
float3 VoxelBoundsHitT = (VoxelBoundsPos - VoxelRayMarchPos) * VoxelRayDirectionInv;
// Remove floating-point rounding error
float Epsilon = 1.0e-4;
if (VoxelBoundsHitT.x <= Epsilon) VoxelBoundsHitT.x += abs(VoxelRayDirectionInv.x);
if (VoxelBoundsHitT.y <= Epsilon) VoxelBoundsHitT.y += abs(VoxelRayDirectionInv.y);
if (VoxelBoundsHitT.z <= Epsilon) VoxelBoundsHitT.z += abs(VoxelRayDirectionInv.z);
float3 OpacityThreshold = 1.0e-4;
while ((VoxelRayMarchT < VoxelRayTMax) && all(Transmittance > OpacityThreshold))
{
float VoxelRayMarchDeltaT = 0.0;
if (VoxelBoundsHitT.x < VoxelBoundsHitT.y)
{
if (VoxelBoundsHitT.x < VoxelBoundsHitT.z)
{
VoxelRayMarchDeltaT = VoxelBoundsHitT.x - VoxelRayMarchT;
VoxelBoundsHitT.x += abs(VoxelRayDirectionInv.x);
}
else
{
VoxelRayMarchDeltaT = VoxelBoundsHitT.z - VoxelRayMarchT;
VoxelBoundsHitT.z += abs(VoxelRayDirectionInv.z);
}
}
else
{
if (VoxelBoundsHitT.y < VoxelBoundsHitT.z)
{
VoxelRayMarchDeltaT = VoxelBoundsHitT.y - VoxelRayMarchT;
VoxelBoundsHitT.y += abs(VoxelRayDirectionInv.y);
}
else
{
VoxelRayMarchDeltaT = VoxelBoundsHitT.z - VoxelRayMarchT;
VoxelBoundsHitT.z += abs(VoxelRayDirectionInv.z);
}
}
// Clip voxel delta-t by overall voxel ray-length.
if (VoxelRayMarchT + VoxelRayMarchDeltaT > VoxelRayTMax)
{
VoxelRayMarchDeltaT = VoxelRayTMax - VoxelRayMarchT;
}
// Sample at the midpoint of the voxel ray
float3 VoxelEndPos = VoxelRayMarchPos + VoxelRayDirection * VoxelRayMarchDeltaT;
float3 VoxelSamplePos = (VoxelRayMarchPos + VoxelEndPos) * 0.5;
uint VoxelSampleLinearPos = GetLinearIndex(VoxelSamplePos, TopLevelGridResolution);
int3 BottomLevelVoxelResolution = GetBottomLevelVoxelResolution(TopLevelGridBuffer[VoxelSampleLinearPos]);
if (IsBottomLevelAllocated(TopLevelGridBuffer[VoxelSampleLinearPos]))
{
if (all(BottomLevelVoxelResolution > 1))
{
MarchBottomLevelVoxelGrid(
VoxelRayOrigin,
VoxelRayDirection,
VoxelRayTMin,
VoxelRayTMax,
WorldRayHitSpan,
VoxelRayMarchPos,
VoxelEndPos,
TopLevelGridBuffer[VoxelSampleLinearPos],
ExtinctionGridBuffer,
Transmittance
);
}
else
{
float3 Extinction = GetExtinction(TopLevelGridBuffer[VoxelSampleLinearPos], ExtinctionGridBuffer);
float WorldRayMarchDeltaT = max(VoxelRayMarchDeltaT * WorldRayHitSpan / VoxelRayTMax, 0.0);
Transmittance *= saturate(exp(-Extinction * WorldRayMarchDeltaT));
}
}
VoxelRayMarchT += VoxelRayMarchDeltaT;
VoxelRayMarchPos = VoxelEndPos;
}
}
float3 TraceFrustumVoxelGrid(float3 Origin, float3 Direction, inout float TMin, inout float TMax)
{
float3 Transmittance = 1.0;
float3 WorldRayOrigin = DFHackToFloat(DFFastSubtract(Origin, PrimaryView.PreViewTranslation));
float3 ViewRayOrigin = mul(float4(WorldRayOrigin, 1), FrustumGridUniformBuffer.WorldToView).xyz;
float3 ViewRayDirection = mul(float4(WorldRayOrigin + Direction, 1), FrustumGridUniformBuffer.WorldToView).xyz;
ViewRayDirection -= ViewRayOrigin;
int3 VoxelDimensions = FrustumGridUniformBuffer.VoxelDimensions;
float NearPlaneDepth = FrustumGridUniformBuffer.NearPlaneDepth;
float FarPlaneDepth = FrustumGridUniformBuffer.FarPlaneDepth;
float TanHalfFOV = FrustumGridUniformBuffer.TanHalfFOV;
float3 VoxelRayOrigin = ViewToVoxel(ViewRayOrigin, VoxelDimensions, NearPlaneDepth, FarPlaneDepth, TanHalfFOV);
float3 VoxelRayDirection = ViewToVoxel(ViewRayOrigin + ViewRayDirection, VoxelDimensions, NearPlaneDepth, FarPlaneDepth, TanHalfFOV);
VoxelRayDirection -= VoxelRayOrigin;
float UnitWorldToVoxelScale = length(VoxelRayDirection);
VoxelRayDirection /= UnitWorldToVoxelScale;
// Intersect voxel-space AABB to clip ray
float VoxelRayTMin = TMin * UnitWorldToVoxelScale;
float VoxelRayTMax = (TMax == POSITIVE_INFINITY) ? POSITIVE_INFINITY : TMax * UnitWorldToVoxelScale;
float2 ClipHitT = IntersectAABB(VoxelRayOrigin, VoxelRayDirection, VoxelRayTMin, VoxelRayTMax, 0, VoxelDimensions);
if (ClipHitT.x > ClipHitT.y)
{
TMin = TMax = 0;
return Transmittance;
}
VoxelRayOrigin += VoxelRayDirection * ClipHitT.x;
VoxelRayTMin = 0.0;
VoxelRayTMax = ClipHitT.y - ClipHitT.x;
float UnitVoxelToWorldScale = 1.0 / UnitWorldToVoxelScale;
float WorldRayLength = VoxelRayTMax * UnitVoxelToWorldScale;
MarchTopLevelFrustumVoxelGrid(
VoxelRayOrigin,
VoxelRayDirection,
VoxelRayTMin,
VoxelRayTMax,
WorldRayLength,
FrustumGridUniformBuffer.TopLevelFroxelGridResolution,
FrustumGridUniformBuffer.TopLevelFroxelGridBuffer,
FrustumGridUniformBuffer.ExtinctionFroxelGridBuffer,
Transmittance
);
TMin = ClipHitT.x * UnitVoxelToWorldScale;
TMax = ClipHitT.y * UnitVoxelToWorldScale;
return Transmittance;
}