You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
* Decreased Global Distance Field border from full voxel to half voxel and decreased page size from 16 to 8. This removes ~30% of pages, saving memory and improving update speed * Half texel border requires to compute gradients using 8 page table fetches, but it didn�t influence Lumen tracing performance on console * Smaller pages put some pressure on culling and other passes. Culling grid was switch from per page to per 4x4x4 pages. Overall full GDF update speed in FortGPUTestBed decreased from 5.89ms to 4.57ms * Switched page table format to UInt32 in order to support larger Global Distance Field resolutions * Moved all GlobalDistanceField shaders into /DistanceField/* folder, in future we should move other distance field shaders there * Moved GlobalDistanceField page stats from r.Lumen.Visualize.Stats in Lumen code to r.GlobalDistanceField.Debug in GlobalDistanceField code * Fixed Lumen normal visualization when only Global Distance Field tracing is enabled #preflight 62630427006fa20b683b405a [FYI] Tiago.Costa, Daniel.Wright #ROBOMERGE-AUTHOR: krzysztof.narkowicz #ROBOMERGE-SOURCE: CL 19873116 via CL 19873429 via CL 19874251 #ROBOMERGE-BOT: UE5 (Release-Engine-Staging -> Main) (v940-19807014) [CL 19878047 by krzysztof narkowicz in ue5-main branch]
109 lines
3.7 KiB
Plaintext
109 lines
3.7 KiB
Plaintext
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "../Common.ush"
|
|
#include "../DeferredShadingCommon.ush"
|
|
#include "GlobalDistanceFieldShared.ush"
|
|
|
|
RWTexture3D<float> RWMipTexture;
|
|
uint ClipmapMipResolution;
|
|
float OneOverClipmapMipResolution;
|
|
float MipInfluenceRadius;
|
|
Texture3D<uint> PageTableTexture;
|
|
Texture3D PageAtlasTexture;
|
|
Texture3D PrevMipTexture;
|
|
|
|
// https://en.wikipedia.org/wiki/Eikonal_equation
|
|
float Eikonal1(float X, float Step)
|
|
{
|
|
return X + Step;
|
|
}
|
|
|
|
float Eikonal2(float X, float Y, float Step)
|
|
{
|
|
float SumU = X + Y;
|
|
float SumUSq = X * X + Y * Y;
|
|
float DistanceSq = SumU * SumU - 2.0f * (SumUSq - Step * Step);
|
|
return (1.0f / 2.0f) * (SumU + sqrt(DistanceSq));
|
|
}
|
|
|
|
float Eikonal3(float X, float Y, float Z, float Step)
|
|
{
|
|
float SumU = X + Y + Z;
|
|
float SumUSq = X * X + Y * Y + Z * Z;
|
|
float DistanceSq = SumU * SumU - 3.0f * (SumUSq - Step * Step);
|
|
return (1.0f / 3.0f) * (SumU + sqrt(DistanceSq));
|
|
}
|
|
|
|
uint ClipmapIndex;
|
|
uint PrevClipmapOffsetZ;
|
|
uint ClipmapOffsetZ;
|
|
float3 ClipmapUVScrollOffset;
|
|
float CoarseDistanceFieldValueScale;
|
|
float CoarseDistanceFieldValueBias;
|
|
|
|
float LoadPrevDistanceFieldValue(int3 MipCoord, int3 Offset)
|
|
{
|
|
MipCoord = clamp(MipCoord + Offset, 0, (int)ClipmapMipResolution - 1);
|
|
|
|
#if READ_PAGES
|
|
// Reverse clipmap scroll offset as coarse clipmap is always centered around camera
|
|
float3 ScrolledClipmapUV = (MipCoord + 0.5f) * OneOverClipmapMipResolution;
|
|
ScrolledClipmapUV = frac(ScrolledClipmapUV + ClipmapUVScrollOffset); // wraparound addressing
|
|
ScrolledClipmapUV = frac(ScrolledClipmapUV); // apply frac twice to prevent UV == 1.0f because frac(-0.00...001f) = 1.0f
|
|
|
|
int3 PageTableTextureCoord = saturate(ScrolledClipmapUV) * GlobalDistanceFieldClipmapSizeInPages + int3(0, 0, ClipmapIndex * GlobalDistanceFieldClipmapSizeInPages);
|
|
uint PageIndex = PageTableTexture.Load(int4(PageTableTextureCoord, 0));
|
|
|
|
float DistanceFieldValue = 1.0f;
|
|
if (PageIndex < GLOBAL_DISTANCE_FIELD_INVALID_PAGE_ID)
|
|
{
|
|
float3 PageUV = ComputeGlobalDistanceFieldPageUV(ScrolledClipmapUV, PageIndex);
|
|
DistanceFieldValue = Texture3DSampleLevel(PageAtlasTexture, GlobalTrilinearWrappedSampler, PageUV, 0).x;
|
|
if (DistanceFieldValue < 1.0f)
|
|
{
|
|
DistanceFieldValue = DistanceFieldValue * CoarseDistanceFieldValueScale + CoarseDistanceFieldValueBias;
|
|
}
|
|
}
|
|
|
|
return DistanceFieldValue;
|
|
#else
|
|
|
|
MipCoord.z += PrevClipmapOffsetZ;
|
|
return PrevMipTexture[MipCoord].x;
|
|
|
|
#endif
|
|
}
|
|
|
|
[numthreads(THREADGROUP_SIZE_X, THREADGROUP_SIZE_Y, THREADGROUP_SIZE_Z)]
|
|
void PropagateMipDistanceCS(
|
|
uint3 GroupId : SV_GroupID,
|
|
uint3 DispatchThreadId : SV_DispatchThreadID,
|
|
uint3 GroupThreadId : SV_GroupThreadID)
|
|
{
|
|
uint3 MipCoord = DispatchThreadId.xyz;
|
|
|
|
if (all(MipCoord < ClipmapMipResolution))
|
|
{
|
|
float Center = LoadPrevDistanceFieldValue(MipCoord, int3(0, 0, 0));
|
|
|
|
float3 V;
|
|
V.x = min(LoadPrevDistanceFieldValue(MipCoord, int3(-1, 0, 0)), LoadPrevDistanceFieldValue(MipCoord, int3(+1, 0, 0)));
|
|
V.y = min(LoadPrevDistanceFieldValue(MipCoord, int3(0, -1, 0)), LoadPrevDistanceFieldValue(MipCoord, int3(0, +1, 0)));
|
|
V.z = min(LoadPrevDistanceFieldValue(MipCoord, int3(0, 0, -1)), LoadPrevDistanceFieldValue(MipCoord, int3(0, 0, +1)));
|
|
|
|
float MinV = min3(V.x, V.y, V.z);
|
|
float MaxV = max3(V.x, V.y, V.z);
|
|
|
|
float3 SortedV;
|
|
SortedV.x = MinV;
|
|
SortedV.y = (V.x != MinV && V.x != MaxV) ? V.x : ((V.y != MinV && V.y != MaxV) ? V.y : V.z);
|
|
SortedV.z = MaxV;
|
|
|
|
const float Step = 1.0f / (2.0f * GLOBAL_DISTANCE_FIELD_INFLUENCE_RANGE_IN_VOXELS);
|
|
Center = min(Center, Eikonal1(SortedV.x, Step));
|
|
Center = min(Center, Eikonal2(SortedV.x, SortedV.y, Step));
|
|
Center = min(Center, Eikonal3(SortedV.x, SortedV.y, SortedV.z, Step));
|
|
|
|
RWMipTexture[MipCoord + int3(0, 0, ClipmapOffsetZ)] = Center;
|
|
}
|
|
} |