You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Contains all work on Lumen since shipping Reverb in March: * New Opaque Final Gather with higher quality in clean architecture and better performance * Improved global tracing which reduces leaking * New basic Reflections pipeline which respects material Roughness * New HZB traces that are more accurate at tracing against the depth buffer * Hardware Ray Tracing paths for Lumen shadowing and Final Gather #rb none [CL 14274844 by Daniel Wright in ue5-main branch]
307 lines
11 KiB
Plaintext
307 lines
11 KiB
Plaintext
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
GlobalDistanceFieldHeighfields.usf
|
|
=============================================================================*/
|
|
|
|
#include "Common.ush"
|
|
#include "GlobalDistanceFieldShared.ush"
|
|
#include "HeightfieldLightingShared.ush"
|
|
|
|
#define GLOBAL_DISTANCE_FIELD_PAGE_HEIGHFIELD_GROUP_X (GLOBAL_DISTANCE_FIELD_PAGE_RESOLUTION_IN_ATLAS / 8)
|
|
#define GLOBAL_DISTANCE_FIELD_PAGE_HEIGHFIELD_GROUP_NUM (GLOBAL_DISTANCE_FIELD_PAGE_HEIGHFIELD_GROUP_X * GLOBAL_DISTANCE_FIELD_PAGE_HEIGHFIELD_GROUP_X)
|
|
|
|
RWStructuredBuffer<uint> RWMarkedHeightfieldPageBuffer;
|
|
RWTexture3D<float> RWPageAtlasTexture;
|
|
|
|
StructuredBuffer<uint> MarkedHeightfieldPageBuffer;
|
|
StructuredBuffer<uint> PageUpdateTileBuffer;
|
|
StructuredBuffer<uint> ComposeTileBuffer;
|
|
Texture3D<uint> PageTableLayerTexture;
|
|
|
|
float3 PageCoordToPageWorldCenterScale;
|
|
float3 PageCoordToPageWorldCenterBias;
|
|
float3 PageCoordToVoxelCenterScale;
|
|
float3 PageCoordToVoxelCenterBias;
|
|
float3 PageWorldExtent;
|
|
float4 ClipmapVolumeWorldToUVAddAndMul;
|
|
float3 InvPageGridResolution;
|
|
uint3 PageGridResolution;
|
|
uint PageTableClipmapOffsetZ;
|
|
float ClipmapVoxelExtent;
|
|
float InfluenceRadius;
|
|
float HeightfieldThickness;
|
|
|
|
uint3 PageGridCoordToPageTableTextureCoord(uint3 PageGridCoord)
|
|
{
|
|
float3 PageWorldCenter = PageGridCoord * PageCoordToPageWorldCenterScale + PageCoordToPageWorldCenterBias;
|
|
|
|
float4 WorldToUVAddAndMul = ClipmapVolumeWorldToUVAddAndMul;
|
|
float3 ClipmapUV = frac(PageWorldCenter * WorldToUVAddAndMul.www + WorldToUVAddAndMul.xyz);
|
|
|
|
int3 PageTableTextureCoord = clamp(saturate(ClipmapUV) * PageGridResolution, 0, PageGridResolution - 1) + int3(0, 0, PageTableClipmapOffsetZ);
|
|
return PageTableTextureCoord;
|
|
}
|
|
|
|
groupshared uint GroupMarkedPage[256];
|
|
|
|
[numthreads(THREADGROUP_SIZE_X, THREADGROUP_SIZE_Y, 1)]
|
|
void MarkHeightfieldPagesCS(
|
|
uint3 GroupId : SV_GroupID,
|
|
uint3 DispatchThreadId : SV_DispatchThreadID,
|
|
uint3 GroupThreadId : SV_GroupThreadID)
|
|
{
|
|
uint3 VoxelCoord = uint3(GroupThreadId.xy, 0);
|
|
uint ThreadIndex = GroupThreadId.x + GroupThreadId.y * 16;
|
|
uint IndexInPageBuffer = GroupId.x;
|
|
uint PackedPageGridCoord = PageUpdateTileBuffer[IndexInPageBuffer];
|
|
|
|
uint3 PageGridCoord;
|
|
PageGridCoord.x = PackedPageGridCoord & 0xFF;
|
|
PageGridCoord.y = (PackedPageGridCoord >> 8) & 0xFF;
|
|
PageGridCoord.z = (PackedPageGridCoord >> 16) & 0xFF;
|
|
|
|
float3 PageWorldCenter = PageGridCoord * PageCoordToPageWorldCenterScale + PageCoordToPageWorldCenterBias;
|
|
float3 VoxelWorldCenter = PageWorldCenter - PageWorldExtent + VoxelCoord * 2.0f * PageWorldExtent;
|
|
|
|
GroupMarkedPage[ThreadIndex] = 0;
|
|
|
|
uint ValidHeightfieldIndex = 0;
|
|
|
|
LOOP
|
|
for (uint HeightfieldIndex = 0; HeightfieldIndex < NumHeightfields; HeightfieldIndex++)
|
|
{
|
|
float3 LocalPosition = mul(float4(VoxelWorldCenter, 1), GetWorldToLocal(HeightfieldIndex)).xyz;
|
|
float4 MinMaxHeightfieldUV;
|
|
float2 HeightfieldUV = GetHeightfieldUV(HeightfieldIndex, LocalPosition.xy, MinMaxHeightfieldUV);
|
|
|
|
if (all(HeightfieldUV > MinMaxHeightfieldUV.xy) && all(HeightfieldUV < MinMaxHeightfieldUV.zw))
|
|
{
|
|
ValidHeightfieldIndex = HeightfieldIndex;
|
|
break;
|
|
}
|
|
}
|
|
|
|
float3 LocalPosition = mul(float4(VoxelWorldCenter, 1), GetWorldToLocal(ValidHeightfieldIndex)).xyz;
|
|
float4 MinMaxHeightfieldUV;
|
|
float2 HeightfieldUV = GetHeightfieldUV(ValidHeightfieldIndex, LocalPosition.xy, MinMaxHeightfieldUV);
|
|
|
|
if (all(HeightfieldUV > MinMaxHeightfieldUV.xy) && all(HeightfieldUV < MinMaxHeightfieldUV.zw))
|
|
{
|
|
float3 WorldHeightfieldNormal;
|
|
float HeightfieldVisibility;
|
|
float3 WorldHeightfieldShadingPosition = GetHeightfieldWorldPositionAndNormal(ValidHeightfieldIndex, LocalPosition.xy, HeightfieldUV, WorldHeightfieldNormal, HeightfieldVisibility);
|
|
|
|
if (HeightfieldVisibility > 0.5f) // Skip holes in the heightfield
|
|
{
|
|
float3 WorldPositionNearestZ = VoxelWorldCenter;
|
|
WorldPositionNearestZ.z = clamp(WorldHeightfieldShadingPosition.z, VoxelWorldCenter.z, VoxelWorldCenter.z + GLOBAL_DISTANCE_FIELD_PAGE_RESOLUTION_IN_ATLAS * 2.0f * ClipmapVoxelExtent);
|
|
|
|
// Project the vertical height vector onto the normal of the heightfield directly below the point we are computing the distance field for, use the perpendicular distance
|
|
float DistanceToHeightfieldPlane = dot(WorldHeightfieldNormal, WorldPositionNearestZ - WorldHeightfieldShadingPosition);
|
|
|
|
// Limit negative region of a heightfield to a user defined thickness
|
|
const float MinInteriorDistance = -HeightfieldThickness;
|
|
if (DistanceToHeightfieldPlane < MinInteriorDistance)
|
|
{
|
|
DistanceToHeightfieldPlane = MinInteriorDistance - DistanceToHeightfieldPlane;
|
|
}
|
|
|
|
if (DistanceToHeightfieldPlane > -InfluenceRadius && DistanceToHeightfieldPlane < InfluenceRadius)
|
|
{
|
|
GroupMarkedPage[ThreadIndex] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
GroupMemoryBarrierWithGroupSync();
|
|
|
|
if (ThreadIndex < 128)
|
|
{
|
|
GroupMarkedPage[ThreadIndex] = GroupMarkedPage[ThreadIndex] + GroupMarkedPage[ThreadIndex + 64];
|
|
}
|
|
|
|
GroupMemoryBarrierWithGroupSync();
|
|
|
|
if (ThreadIndex < 64)
|
|
{
|
|
GroupMarkedPage[ThreadIndex] = GroupMarkedPage[ThreadIndex] + GroupMarkedPage[ThreadIndex + 64];
|
|
}
|
|
|
|
GroupMemoryBarrierWithGroupSync();
|
|
|
|
if (ThreadIndex < 32)
|
|
{
|
|
GroupMarkedPage[ThreadIndex] = GroupMarkedPage[ThreadIndex] + GroupMarkedPage[ThreadIndex + 32];
|
|
}
|
|
|
|
GroupMemoryBarrierWithGroupSync();
|
|
|
|
if (ThreadIndex < 16)
|
|
{
|
|
GroupMarkedPage[ThreadIndex] = GroupMarkedPage[ThreadIndex] + GroupMarkedPage[ThreadIndex + 16];
|
|
}
|
|
|
|
GroupMemoryBarrierWithGroupSync();
|
|
|
|
if (ThreadIndex < 8)
|
|
{
|
|
GroupMarkedPage[ThreadIndex] = GroupMarkedPage[ThreadIndex] + GroupMarkedPage[ThreadIndex + 8];
|
|
}
|
|
|
|
GroupMemoryBarrierWithGroupSync();
|
|
|
|
if (ThreadIndex < 4)
|
|
{
|
|
GroupMarkedPage[ThreadIndex] = GroupMarkedPage[ThreadIndex] + GroupMarkedPage[ThreadIndex + 4];
|
|
}
|
|
|
|
GroupMemoryBarrierWithGroupSync();
|
|
|
|
if (ThreadIndex < 2)
|
|
{
|
|
GroupMarkedPage[ThreadIndex] = GroupMarkedPage[ThreadIndex] + GroupMarkedPage[ThreadIndex + 2];
|
|
}
|
|
|
|
GroupMemoryBarrierWithGroupSync();
|
|
|
|
if (ThreadIndex == 0)
|
|
{
|
|
if (GroupMarkedPage[ThreadIndex] + GroupMarkedPage[ThreadIndex + 1] > 0)
|
|
{
|
|
RWMarkedHeightfieldPageBuffer[IndexInPageBuffer] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
RWBuffer<uint> RWBuildHeightfieldComposeTilesIndirectArgBuffer;
|
|
RWBuffer<uint> RWPageComposeHeightfieldIndirectArgBuffer;
|
|
Buffer<uint> PageUpdateIndirectArgBuffer;
|
|
|
|
[numthreads(1, 1, 1)]
|
|
void BuildHeightfieldComposeTilesIndirectArgBufferCS(
|
|
uint3 GroupId : SV_GroupID,
|
|
uint3 DispatchThreadId : SV_DispatchThreadID,
|
|
uint3 GroupThreadId : SV_GroupThreadID)
|
|
{
|
|
if (DispatchThreadId.x == 0)
|
|
{
|
|
const uint TileNum = PageUpdateIndirectArgBuffer[0];
|
|
|
|
RWBuildHeightfieldComposeTilesIndirectArgBuffer[0] = (TileNum + 63) / 64;
|
|
RWBuildHeightfieldComposeTilesIndirectArgBuffer[1] = 1;
|
|
RWBuildHeightfieldComposeTilesIndirectArgBuffer[2] = 1;
|
|
|
|
RWPageComposeHeightfieldIndirectArgBuffer[0] = 0;
|
|
RWPageComposeHeightfieldIndirectArgBuffer[1] = 1;
|
|
RWPageComposeHeightfieldIndirectArgBuffer[2] = 1;
|
|
}
|
|
}
|
|
|
|
RWStructuredBuffer<uint> RWPageComposeHeightfieldTileBuffer;
|
|
|
|
[numthreads(THREADGROUP_SIZE_X, 1, 1)]
|
|
void BuildHeightfieldComposeTilesCS(
|
|
uint3 GroupId : SV_GroupID,
|
|
uint3 DispatchThreadId : SV_DispatchThreadID,
|
|
uint3 GroupThreadId : SV_GroupThreadID)
|
|
{
|
|
const uint TileIndex = DispatchThreadId.x;
|
|
const uint TileNum = PageUpdateIndirectArgBuffer[0];
|
|
|
|
if (TileIndex < TileNum)
|
|
{
|
|
uint PackedPageGridCoord = PageUpdateTileBuffer[TileIndex];
|
|
bool bMarkedHeightfieldPage = MarkedHeightfieldPageBuffer[TileIndex] > 0;
|
|
|
|
if (bMarkedHeightfieldPage)
|
|
{
|
|
uint DestIndex;
|
|
InterlockedAdd(RWPageComposeHeightfieldIndirectArgBuffer[0], GLOBAL_DISTANCE_FIELD_PAGE_HEIGHFIELD_GROUP_NUM, DestIndex);
|
|
RWPageComposeHeightfieldTileBuffer[DestIndex / GLOBAL_DISTANCE_FIELD_PAGE_HEIGHFIELD_GROUP_NUM] = PackedPageGridCoord;
|
|
}
|
|
}
|
|
}
|
|
|
|
[numthreads(THREADGROUP_SIZE_X, THREADGROUP_SIZE_Y, 1)]
|
|
void ComposeHeightfieldsIntoPagesCS(
|
|
uint3 GroupId : SV_GroupID,
|
|
uint3 DispatchThreadId : SV_DispatchThreadID,
|
|
uint3 GroupThreadId : SV_GroupThreadID)
|
|
{
|
|
uint PackedPageTile = ComposeTileBuffer[GroupId.x / GLOBAL_DISTANCE_FIELD_PAGE_HEIGHFIELD_GROUP_NUM];
|
|
uint LinearPageGroupOffset = GroupId.x % GLOBAL_DISTANCE_FIELD_PAGE_HEIGHFIELD_GROUP_NUM;
|
|
|
|
uint3 PageGroupOffset;
|
|
PageGroupOffset.x = LinearPageGroupOffset % GLOBAL_DISTANCE_FIELD_PAGE_HEIGHFIELD_GROUP_X;
|
|
PageGroupOffset.y = LinearPageGroupOffset / GLOBAL_DISTANCE_FIELD_PAGE_HEIGHFIELD_GROUP_X;
|
|
PageGroupOffset.z = 0;
|
|
|
|
uint3 PageGridCoord;
|
|
PageGridCoord.x = PackedPageTile & 0xFF;
|
|
PageGridCoord.y = (PackedPageTile >> 8) & 0xFF;
|
|
PageGridCoord.z = (PackedPageTile >> 16) & 0xFF;
|
|
|
|
uint3 TexelCoordInPage = uint3(PageGroupOffset.xy * 8 + GroupThreadId.xy, 0);
|
|
|
|
uint3 PageCoord = PageGridCoord * GLOBAL_DISTANCE_FIELD_PAGE_RESOLUTION + TexelCoordInPage - 1;
|
|
float3 VoxelWorldCenter = PageCoord * PageCoordToVoxelCenterScale + PageCoordToVoxelCenterBias;
|
|
|
|
uint3 PageTableTextureCoord = PageGridCoordToPageTableTextureCoord(PageGridCoord);
|
|
uint PageId = PageTableLayerTexture.Load(int4(PageTableTextureCoord, 0));
|
|
uint3 PageAtlasCoord = GlobalDistanceFieldPageLinearIndexToPageAtlasCoord(PageId);
|
|
PageAtlasCoord += TexelCoordInPage;
|
|
|
|
uint ValidHeightfieldIndex = 0;
|
|
|
|
LOOP
|
|
for (uint HeightfieldIndex = 0; HeightfieldIndex < NumHeightfields; HeightfieldIndex++)
|
|
{
|
|
float3 LocalPosition = mul(float4(VoxelWorldCenter, 1), GetWorldToLocal(HeightfieldIndex)).xyz;
|
|
float4 MinMaxHeightfieldUV;
|
|
float2 HeightfieldUV = GetHeightfieldUV(HeightfieldIndex, LocalPosition.xy, MinMaxHeightfieldUV);
|
|
|
|
if (all(HeightfieldUV > MinMaxHeightfieldUV.xy) && all(HeightfieldUV < MinMaxHeightfieldUV.zw))
|
|
{
|
|
ValidHeightfieldIndex = HeightfieldIndex;
|
|
break;
|
|
}
|
|
}
|
|
|
|
float3 LocalPosition = mul(float4(VoxelWorldCenter, 1), GetWorldToLocal(ValidHeightfieldIndex)).xyz;
|
|
float4 MinMaxHeightfieldUV;
|
|
float2 HeightfieldUV = GetHeightfieldUV(ValidHeightfieldIndex, LocalPosition.xy, MinMaxHeightfieldUV);
|
|
|
|
if (all(HeightfieldUV > MinMaxHeightfieldUV.xy) && all(HeightfieldUV < MinMaxHeightfieldUV.zw))
|
|
{
|
|
float3 WorldHeightfieldNormal;
|
|
float HeightfieldVisibility;
|
|
float3 WorldHeightfieldShadingPosition = GetHeightfieldWorldPositionAndNormal(ValidHeightfieldIndex, LocalPosition.xy, HeightfieldUV, WorldHeightfieldNormal, HeightfieldVisibility);
|
|
|
|
if (HeightfieldVisibility > 0.5f) // Skip holes in the heightfield
|
|
{
|
|
// Compute distance for all Z values of the update region
|
|
LOOP
|
|
for (uint ZIndex = 0; ZIndex < GLOBAL_DISTANCE_FIELD_PAGE_RESOLUTION_IN_ATLAS; ++ZIndex)
|
|
{
|
|
float3 WorldPosition = VoxelWorldCenter.xyz + float3(0.0f, 0.0f, ZIndex * 2.0f * ClipmapVoxelExtent);
|
|
|
|
// Project the vertical height vector onto the normal of the heightfield directly below the point we are computing the distance field for, use the perpendicular distance
|
|
float DistanceToHeightfieldPlane = dot(WorldHeightfieldNormal, WorldPosition - WorldHeightfieldShadingPosition);
|
|
|
|
// Limit negative region of a heightfield to a user defined thickness
|
|
const float MinInteriorDistance = -HeightfieldThickness;
|
|
if (DistanceToHeightfieldPlane < MinInteriorDistance)
|
|
{
|
|
DistanceToHeightfieldPlane = MinInteriorDistance - DistanceToHeightfieldPlane;
|
|
}
|
|
|
|
const float MinDistance = clamp(DistanceToHeightfieldPlane, -InfluenceRadius, InfluenceRadius);
|
|
|
|
uint3 PageAtlasCoordZ = PageAtlasCoord + uint3(0, 0, ZIndex);
|
|
float PrevMinDistance = DecodeGlobalDistanceFieldPageDistance(RWPageAtlasTexture[PageAtlasCoordZ], InfluenceRadius);
|
|
RWPageAtlasTexture[PageAtlasCoordZ] = EncodeGlobalDistanceFieldPageDistance(min(MinDistance, PrevMinDistance), InfluenceRadius);
|
|
}
|
|
}
|
|
}
|
|
} |