163 lines
3.8 KiB
HLSL
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;
|
|
} |