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

163 lines
3.8 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#include "../Common.ush"
#include "/Engine/Shared/FroxelDefinitions.h"
// Froxel grid constants
float4 FroxelToViewScaleBias;
float4 FroxelToClipScaleBias;
float2 FroxelClipToViewScale;
float FroxelRecLog2DepthScale1; // 1 / log2(1.0 + DepthScale)
float FroxelRecNearScale;
float FroxelDepthScale1;
float FroxelNear;
float FroxelViewToClipTransformScale;
float FroxelClipToViewTransformScale;
float FroxelClipToViewTransformBias;
float FroxelRadius;
float FroxelInvRadius;
uint bFroxelIsOrtho;
uint FroxelArgsStride;
uint FroxelArgsOffset;
int CalcFroxelSliceFromDeviceZ(float DeviceZ)
{
float DeviceZScaleBias = DeviceZ * FroxelClipToViewTransformScale + FroxelClipToViewTransformBias;
if (bFroxelIsOrtho)
{
int K = int(floor((DeviceZScaleBias - FroxelNear) * FroxelInvRadius));
return K;
}
// Special case for infinity
if (DeviceZ == 0.0f)
{
return FROXEL_INVALID_SLICE;
}
int K = int(floor(log2(rcp(DeviceZScaleBias) * FroxelRecNearScale) * FroxelRecLog2DepthScale1));
return K;
}
float GetViewDepthFromFroxelSlice(float SliceZ)
{
if (bFroxelIsOrtho)
{
return SliceZ * FroxelRadius + FroxelNear;
}
return FroxelNear * pow(FroxelDepthScale1, SliceZ);
}
float GetViewDepthFromFroxelSlice(int SliceZ)
{
return GetViewDepthFromFroxelSlice(float(SliceZ));
}
float GetClipDepthFromFroxelSlice(float SliceZ)
{
float ViewDepth = GetViewDepthFromFroxelSlice(SliceZ);
float TmpViewDepth = ViewDepth - FroxelClipToViewTransformBias;
if (!bFroxelIsOrtho)
{
TmpViewDepth = rcp(TmpViewDepth);
}
return TmpViewDepth * FroxelViewToClipTransformScale;
}
FPackedFroxel PackFroxel(int3 Froxel)
{
FPackedFroxel Result;
Result.XY = uint(Froxel.x) | (uint(Froxel.y) << 16u);
Result.Z = Froxel.z;
return Result;
}
int3 UnpackFroxel(FPackedFroxel PackedFroxel)
{
int3 Result;
Result.x = int(BitFieldExtractU32(PackedFroxel.XY, 16, 0));
Result.y = int(BitFieldExtractU32(PackedFroxel.XY, 16, 16));
Result.z = PackedFroxel.Z;
return Result;
}
float3 GetFroxelViewSpaceCenter(int3 Froxel)
{
float ViewSpaceCenterZ = GetViewDepthFromFroxelSlice(float(Froxel.z) + 0.5f);
float2 TmpXY = (float2(Froxel.xy) + 0.5f) * FroxelToViewScaleBias.xy + FroxelToViewScaleBias.zw;
if (bFroxelIsOrtho)
{
return float3(TmpXY, ViewSpaceCenterZ);
}
return float3(TmpXY * ViewSpaceCenterZ, ViewSpaceCenterZ);
}
struct FFroxelViewBounds
{
float3 Min;
float3 Max;
};
FFroxelViewBounds GetFroxelViewSpaceAABB(int3 Froxel)
{
float2 MinXY = ((float2(Froxel.xy)) * FroxelToViewScaleBias.xy + FroxelToViewScaleBias.zw);
float2 MaxXY = MinXY + FroxelToViewScaleBias.xy;
float MinViewZ = GetViewDepthFromFroxelSlice(Froxel.z);
FFroxelViewBounds Result;
if (bFroxelIsOrtho)
{
Result.Min.xy = MinXY;
Result.Min.z = MinViewZ;
Result.Max.xy = MaxXY;
Result.Max.z = MinViewZ + FroxelRadius;
return Result;
}
if (abs(MinXY.x) > abs(MaxXY.x))
{
Swap(MinXY.x, MaxXY.x);
}
if (abs(MinXY.y) > abs(MaxXY.y))
{
Swap(MinXY.y, MaxXY.y);
}
float MaxViewZ = MinViewZ * FroxelDepthScale1;
// Extrema corners in X plane near and far
float2 ExtNear = MinXY * MinViewZ;
float2 ExtFar = MaxXY * MaxViewZ; // ==
Result.Min.xy = min(ExtNear, ExtFar);
Result.Min.z = MinViewZ;
Result.Max.xy = max(ExtNear, ExtFar);
Result.Max.z = MaxViewZ;
return Result;
}
struct FFroxelClipBounds
{
float3 ClipMin;
float3 ClipMax;
};
FFroxelClipBounds GetFroxelClipBounds(int3 Froxel)
{
float MinDeviceZ = GetClipDepthFromFroxelSlice(Froxel.z);
float MaxDeviceZ = GetClipDepthFromFroxelSlice(Froxel.z + 1.0f);
float2 MinClipSpaceXY = ((float2(Froxel.xy)) * FroxelToClipScaleBias.xy + FroxelToClipScaleBias.zw);
float2 MaxClipSpaceXY = MinClipSpaceXY + FroxelToClipScaleBias.xy;
FFroxelClipBounds Result;
Result.ClipMin = float3(MinClipSpaceXY, MinDeviceZ);
Result.ClipMax = float3(MaxClipSpaceXY, MaxDeviceZ);
return Result;
}