Lumen - fixed artifacts when null elements of a sparse HeightfieldMeshCardsIndicesBuffer array were used as valid heightfields

#preflight 61f15d09fc74f46b563c6b81
#rb Patrick.Kelly

#ROBOMERGE-AUTHOR: krzysztof.narkowicz
#ROBOMERGE-SOURCE: CL 18735212 in //UE5/Release-5.0/... via CL 18735218 via CL 18735270
#ROBOMERGE-BOT: UE5 (Release-Engine-Test -> Main) (v903-18687472)

[CL 18735279 by krzysztof narkowicz in ue5-main branch]
This commit is contained in:
krzysztof narkowicz
2022-01-26 09:50:53 -05:00
parent d82995b358
commit 62803f383f
8 changed files with 79 additions and 64 deletions

View File

@@ -287,4 +287,16 @@ float3 DecodeSurfaceCacheNormal(FLumenCardData Card, float2 EncodedNormal)
float3 DecodeSurfaceCacheAlbedo(float3 EncodedAlbedo)
{
return EncodedAlbedo * EncodedAlbedo;
}
uint GetMeshCardsIndexFromSceneInstanceIndex(uint SceneInstanceIndex)
{
const uint MeshCardsIndex = LumenCardScene.SceneInstanceIndexToMeshCardsIndexBuffer.Load(4 * SceneInstanceIndex);
return MeshCardsIndex;
}
uint GetMeshCardsIndexFromHeightfieldObjectIndex(uint HeightfieldObjectIndex)
{
const uint MeshCardsIndex = LumenCardScene.HeightfieldMeshCardsIndicesBuffer.Load(4 * HeightfieldObjectIndex);
return MeshCardsIndex;
}

View File

@@ -368,7 +368,7 @@ float3 CalculateSurfaceCacheLighting(
// FarField proxies are less accurate
float SurfaceCacheDepthTestBias = (Context.InstanceMask == RAY_TRACING_MASK_FAR_FIELD) ? 1000.0f : 20.0f;
const uint MeshCardsIndex = GetMeshCardsIndex(SceneInstanceIndex);
const uint MeshCardsIndex = GetMeshCardsIndexFromSceneInstanceIndex(SceneInstanceIndex);
FSurfaceCacheSample SurfaceCacheSample = SampleLumenMeshCards(
Context.TraceCoord,

View File

@@ -58,22 +58,27 @@ void CullHeightfieldObjectsForViewCS(
GSNumCulledObjects = 0;
GroupMemoryBarrierWithGroupSync();
bool bShouldKeep = false;
uint ObjectIndex = DispatchThreadId.x;
bool bShouldKeep = ObjectIndex < MaxNumObjects;
if (bShouldKeep)
if (ObjectIndex < MaxNumObjects)
{
if (bShouldCull)
uint MeshCardsIndex = GetMeshCardsIndexFromHeightfieldObjectIndex(ObjectIndex);
if (MeshCardsIndex < LumenCardScene.NumMeshCards)
{
uint MeshCardsIndex = LumenCardScene.HeightfieldMeshCardsIndicesBuffer.Load(4 * ObjectIndex);
FLumenMeshCardsData MeshCardsData = GetLumenMeshCardsData(MeshCardsIndex);
bShouldKeep = true;
// Fetch card
int LocalCardIndex = LUMEN_HEIGHTFIELD_LOCAL_CARD_INDEX;
FLumenCardData LumenCardData = GetLumenCardData(MeshCardsData.CardOffset + LocalCardIndex);
if (bShouldCull)
{
FLumenMeshCardsData MeshCardsData = GetLumenMeshCardsData(MeshCardsIndex);
float MaxCullingDistance = length(LumenCardData.Origin - LWCHackToFloat(PrimaryView.WorldCameraOrigin)) + length(LumenCardData.LocalExtent);
bShouldKeep = MaxCullingDistance < CardTraceEndDistanceFromCamera;
// Fetch card
int LocalCardIndex = LUMEN_HEIGHTFIELD_LOCAL_CARD_INDEX;
FLumenCardData LumenCardData = GetLumenCardData(MeshCardsData.CardOffset + LocalCardIndex);
float MaxCullingDistance = length(LumenCardData.Origin - LWCHackToFloat(PrimaryView.WorldCameraOrigin)) + length(LumenCardData.LocalExtent);
bShouldKeep = MaxCullingDistance < CardTraceEndDistanceFromCamera;
}
}
}

View File

@@ -408,18 +408,6 @@ void SampleLumenCard(
}
}
uint GetMeshCardsIndex(uint SceneInstanceIndex)
{
const uint MeshCardsIndex = LumenCardScene.SceneInstanceIndexToMeshCardsIndexBuffer.Load(4 * SceneInstanceIndex);
return MeshCardsIndex;
}
uint GetMeshCardsIndexFromHeightfieldObjectIndex(uint HeightfieldObjectIndex)
{
const uint MeshCardsIndex = LumenCardScene.HeightfieldMeshCardsIndicesBuffer.Load(4 * HeightfieldObjectIndex);
return MeshCardsIndex;
}
FSurfaceCacheSample SampleLumenMeshCards(uint2 ScreenCoord, uint MeshCardsIndex, float3 SamplePosition, float3 SampleNormal, float SampleRadius, float SurfaceCacheDepthTestBias, float CardInterpolateDepthVisibilityRadius, bool bHiResSurface, uint AtlasId)
{
FSurfaceCacheSample SurfaceCacheSample;

View File

@@ -760,7 +760,7 @@ FTraceMeshSDFDerivedData CalculateMeshSDFDerivedData(
}
TraceSDFData.SceneInstanceIndex = DFObjectData.GPUSceneInstanceIndex;
TraceSDFData.MeshCardsIndex = GetMeshCardsIndex(TraceSDFData.SceneInstanceIndex);
TraceSDFData.MeshCardsIndex = GetMeshCardsIndexFromSceneInstanceIndex(TraceSDFData.SceneInstanceIndex);
return TraceSDFData;
}
@@ -800,7 +800,7 @@ FConeTraceHeightfieldSimpleResult ConeTraceHeightfieldSimple(
Result.bRayStartInsideGeometry = false;
Result.HitDistance = TraceInput.MaxTraceDistance;
uint MeshCardsIndex = LumenCardScene.HeightfieldMeshCardsIndicesBuffer.Load(4 * HeightfieldIndex);
uint MeshCardsIndex = GetMeshCardsIndexFromHeightfieldObjectIndex(HeightfieldIndex);
FLumenMeshCardsData MeshCardsData = GetLumenMeshCardsData(MeshCardsIndex);
// Fetch card
@@ -962,15 +962,18 @@ FGlobalSDFTraceResult ShadowTraceHeightfield(
TraceMeshHeightfieldResult.HitDistance = ConeTraceInput.MaxTraceDistance;
//@todo - use culling where appropriate
for (uint Index = 0; Index < LumenCardScene.NumHeightfields; Index++)
for (uint HeightfieldObjectIndex = 0; HeightfieldObjectIndex < LumenCardScene.NumHeightfields; HeightfieldObjectIndex++)
{
uint HeightfieldObjectIndex = LumenCardScene.HeightfieldMeshCardsIndicesBuffer.Load(4 * Index);
FConeTraceHeightfieldSimpleResult SimpleResult = ConeTraceHeightfieldSimple(ConeTraceInput, HeightfieldObjectIndex);
if (SimpleResult.bIsHit && (SimpleResult.HitDistance < TraceMeshHeightfieldResult.HitDistance))
uint MeshCardsIndex = GetMeshCardsIndexFromHeightfieldObjectIndex(HeightfieldObjectIndex);
if (MeshCardsIndex < LumenCardScene.NumMeshCards)
{
TraceMeshHeightfieldResult.HitDistance = SimpleResult.HitDistance;
TraceMeshHeightfieldResult.HeightfieldObjectIndex = HeightfieldObjectIndex;
FConeTraceHeightfieldSimpleResult SimpleResult = ConeTraceHeightfieldSimple(ConeTraceInput, HeightfieldObjectIndex);
if (SimpleResult.bIsHit && (SimpleResult.HitDistance < TraceMeshHeightfieldResult.HitDistance))
{
TraceMeshHeightfieldResult.HitDistance = SimpleResult.HitDistance;
TraceMeshHeightfieldResult.HeightfieldObjectIndex = HeightfieldObjectIndex;
}
}
}

View File

@@ -239,42 +239,48 @@ void CullToVoxelClipmapCS(
{
uint ObjectIndex = DispatchThreadId.x;
#if MESH_TYPE == SDF_MESH_TYPE
uint NumMeshObjects = NumSceneObjects;
#else // MESH_TYPE == HEIGHTFIELD_MESH_TYPE
uint NumMeshObjects = LumenCardScene.NumHeightfields;
#endif // MESH_TYPE
float3 WorldObjectCenter = float3(0, 0, 0);
float3 WorldObjectExtent = float3(0, 0, 0);
if (ObjectIndex < NumMeshObjects)
#if MESH_TYPE == SDF_MESH_TYPE
{
#if MESH_TYPE == SDF_MESH_TYPE
float3 WorldObjectCenter = SceneObjectBounds[ObjectIndex * OBJECT_BOUNDS_STRIDE + 0].xyz;
float3 WorldObjectExtent = SceneObjectBounds[ObjectIndex * OBJECT_BOUNDS_STRIDE + 1].xyz;
#else // MESH_TYPE == HEIGHTFIELD_MESH_TYPE
uint MeshCardsIndex = LumenCardScene.HeightfieldMeshCardsIndicesBuffer.Load(4 * ObjectIndex);
FLumenMeshCardsData MeshCardsData = GetLumenMeshCardsData(MeshCardsIndex);
// Fetch card
FLumenCardData LumenCardData = GetLumenCardData(MeshCardsData.CardOffset + LUMEN_HEIGHTFIELD_LOCAL_CARD_INDEX);
float3 WorldObjectCenter;
float3 WorldObjectExtent;
GetCardAABB(LumenCardData, WorldObjectCenter, WorldObjectExtent);
#endif // MESH_TYPE
float BoundsRadius = length(WorldObjectExtent);
BRANCH
if (BoundsRadius > MeshRadiusThreshold)
if (ObjectIndex < NumSceneObjects)
{
float DistanceSq = ComputeSquaredDistanceBetweenAABBs(VoxelClipmapWorldCenter, VoxelClipmapWorldExtent, WorldObjectCenter, WorldObjectExtent);
if (DistanceSq <= 0.0f)
WorldObjectCenter = SceneObjectBounds[ObjectIndex * OBJECT_BOUNDS_STRIDE + 0].xyz;
WorldObjectExtent = SceneObjectBounds[ObjectIndex * OBJECT_BOUNDS_STRIDE + 1].xyz;
}
}
#else // MESH_TYPE == HEIGHTFIELD_MESH_TYPE
{
if (ObjectIndex < LumenCardScene.NumHeightfields)
{
uint MeshCardsIndex = GetMeshCardsIndexFromHeightfieldObjectIndex(ObjectIndex);
if (MeshCardsIndex < LumenCardScene.NumMeshCards)
{
uint DestIndex;
InterlockedAdd(RWTraceSetupIndirectArgBuffer[0], 1, DestIndex);
RWObjectIndexBuffer[DestIndex] = ObjectIndex;
FLumenMeshCardsData MeshCardsData = GetLumenMeshCardsData(MeshCardsIndex);
// Fetch card
FLumenCardData LumenCardData = GetLumenCardData(MeshCardsData.CardOffset + LUMEN_HEIGHTFIELD_LOCAL_CARD_INDEX);
GetCardAABB(LumenCardData, WorldObjectCenter, WorldObjectExtent);
}
}
}
#endif
float BoundsRadius = length(WorldObjectExtent);
BRANCH
if (BoundsRadius > 0.0f && BoundsRadius > MeshRadiusThreshold)
{
float DistanceSq = ComputeSquaredDistanceBetweenAABBs(VoxelClipmapWorldCenter, VoxelClipmapWorldExtent, WorldObjectCenter, WorldObjectExtent);
if (DistanceSq <= 0.0f)
{
uint DestIndex;
InterlockedAdd(RWTraceSetupIndirectArgBuffer[0], 1, DestIndex);
RWObjectIndexBuffer[DestIndex] = ObjectIndex;
}
}
}
RWStructuredBuffer<uint> RWVoxelTraceAllocator;
@@ -315,7 +321,7 @@ void SetupVoxelTracesCS(
float3 ObjectExtent = DFObjectBounds.BoxExtent;
#else // MESH_TYPE == HEIGHTFIELD_MESH_TYPE
uint MeshCardsIndex = LumenCardScene.HeightfieldMeshCardsIndicesBuffer.Load(4 * ObjectIndex);
uint MeshCardsIndex = GetMeshCardsIndexFromHeightfieldObjectIndex(ObjectIndex);
FLumenMeshCardsData MeshCardsData = GetLumenMeshCardsData(MeshCardsIndex);
// Fetch card

View File

@@ -611,6 +611,7 @@ void FLumenSceneData::ResetAndConsolidate()
MeshCards.Consolidate();
Cards.Consolidate();
PageTable.Consolidate();
HeightfieldMeshCardsIndices.Consolidate();
}
void FLumenSceneData::UpdatePrimitiveInstanceOffset(int32 PrimitiveIndex)

View File

@@ -407,7 +407,7 @@ public:
TSparseSpanArray<FLumenMeshCards> MeshCards;
FRWBufferStructured MeshCardsBuffer;
// Array of indices into MeshCards, containing heightfields for Landscape rendering
// Sparse array of indices into MeshCards, containing heightfields for Landscape rendering
bool bHeightfieldMeshCardsIndicesBufferDirty = false;
TSparseSpanArray<uint32> HeightfieldMeshCardsIndices;
TRefCountPtr<FRDGPooledBuffer> HeightfieldMeshCardsIndicesBuffer;