317 lines
14 KiB
HLSL
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;
|
|
} |