Improve Global Surface Atlas objects surfaces sampling
This commit is contained in:
BIN
Content/Editor/DebugMaterials/DDGIDebugProbes.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/DDGIDebugProbes.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/GI/DDGI.flax
(Stored with Git LFS)
BIN
Content/Shaders/GI/DDGI.flax
(Stored with Git LFS)
Binary file not shown.
@@ -461,7 +461,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
|
|||||||
ddgiData.Result.Constants.ProbesOriginAndSpacing[cascadeIndex] = Float4(cascade.ProbesOrigin, cascade.ProbesSpacing);
|
ddgiData.Result.Constants.ProbesOriginAndSpacing[cascadeIndex] = Float4(cascade.ProbesOrigin, cascade.ProbesSpacing);
|
||||||
ddgiData.Result.Constants.ProbesScrollOffsets[cascadeIndex] = Int4(cascade.ProbeScrollOffsets, 0);
|
ddgiData.Result.Constants.ProbesScrollOffsets[cascadeIndex] = Int4(cascade.ProbeScrollOffsets, 0);
|
||||||
}
|
}
|
||||||
ddgiData.Result.Constants.RayMaxDistance = 10000.0f; // TODO: adjust to match perf/quality ratio (make it based on Global SDF and Global Surface Atlas distance)
|
ddgiData.Result.Constants.RayMaxDistance = distance;
|
||||||
ddgiData.Result.Constants.ViewPos = renderContext.View.Position;
|
ddgiData.Result.Constants.ViewPos = renderContext.View.Position;
|
||||||
ddgiData.Result.Constants.RaysCount = probeRaysCount;
|
ddgiData.Result.Constants.RaysCount = probeRaysCount;
|
||||||
ddgiData.Result.Constants.ProbeHistoryWeight = probeHistoryWeight;
|
ddgiData.Result.Constants.ProbeHistoryWeight = probeHistoryWeight;
|
||||||
|
|||||||
@@ -1232,19 +1232,20 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
|
|||||||
_dirtyObjectsBuffer.Add(actorObject);
|
_dirtyObjectsBuffer.Add(actorObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Matrix3x3 worldToLocalRotation;
|
||||||
|
Matrix3x3::RotationQuaternion(object->Bounds.Transformation.Orientation.Conjugated(), worldToLocalRotation);
|
||||||
|
Float3 worldPosition = object->Bounds.Transformation.Translation;
|
||||||
|
Float3 worldExtents = object->Bounds.Extents * object->Bounds.Transformation.Scale;
|
||||||
|
|
||||||
// Write to objects buffer (this must match unpacking logic in HLSL)
|
// Write to objects buffer (this must match unpacking logic in HLSL)
|
||||||
Matrix localToWorldBounds;
|
|
||||||
object->Bounds.Transformation.GetWorld(localToWorldBounds);
|
|
||||||
Matrix worldToLocalBounds;
|
|
||||||
Matrix::Invert(localToWorldBounds, worldToLocalBounds);
|
|
||||||
uint32 objectAddress = surfaceAtlasData.ObjectsBuffer.Data.Count() / sizeof(Float4);
|
uint32 objectAddress = surfaceAtlasData.ObjectsBuffer.Data.Count() / sizeof(Float4);
|
||||||
auto* objectData = surfaceAtlasData.ObjectsBuffer.WriteReserve<Float4>(GLOBAL_SURFACE_ATLAS_OBJECT_DATA_STRIDE);
|
auto* objectData = surfaceAtlasData.ObjectsBuffer.WriteReserve<Float4>(GLOBAL_SURFACE_ATLAS_OBJECT_DATA_STRIDE);
|
||||||
objectData[0] = *(Float4*)&actorObjectBounds;
|
objectData[0] = *(Float4*)&actorObjectBounds;
|
||||||
objectData[1] = Float4::Zero;
|
objectData[1] = Float4::Zero;
|
||||||
objectData[2] = Float4(worldToLocalBounds.M11, worldToLocalBounds.M12, worldToLocalBounds.M13, worldToLocalBounds.M41);
|
objectData[2] = Float4(worldToLocalRotation.M11, worldToLocalRotation.M12, worldToLocalRotation.M13, worldPosition.X);
|
||||||
objectData[3] = Float4(worldToLocalBounds.M21, worldToLocalBounds.M22, worldToLocalBounds.M23, worldToLocalBounds.M42);
|
objectData[3] = Float4(worldToLocalRotation.M21, worldToLocalRotation.M22, worldToLocalRotation.M23, worldPosition.Y);
|
||||||
objectData[4] = Float4(worldToLocalBounds.M31, worldToLocalBounds.M32, worldToLocalBounds.M33, worldToLocalBounds.M43);
|
objectData[4] = Float4(worldToLocalRotation.M31, worldToLocalRotation.M32, worldToLocalRotation.M33, worldPosition.Z);
|
||||||
objectData[5] = Float4(object->Bounds.Extents, useVisibility ? 1.0f : 0.0f);
|
objectData[5] = Float4(worldExtents, useVisibility ? 1.0f : 0.0f);
|
||||||
auto tileOffsets = reinterpret_cast<uint16*>(&objectData[1]); // xyz used for tile offsets packed into uint16
|
auto tileOffsets = reinterpret_cast<uint16*>(&objectData[1]); // xyz used for tile offsets packed into uint16
|
||||||
auto objectDataSize = reinterpret_cast<uint32*>(&objectData[1].W); // w used for object size (count of Float4s for object+tiles)
|
auto objectDataSize = reinterpret_cast<uint32*>(&objectData[1].W); // w used for object size (count of Float4s for object+tiles)
|
||||||
*objectDataSize = GLOBAL_SURFACE_ATLAS_OBJECT_DATA_STRIDE;
|
*objectDataSize = GLOBAL_SURFACE_ATLAS_OBJECT_DATA_STRIDE;
|
||||||
|
|||||||
@@ -414,10 +414,6 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
|
|||||||
// Reduce flickering during rapid brightness changes
|
// Reduce flickering during rapid brightness changes
|
||||||
//result.rgb = previous + (irradianceDelta * 0.25f);
|
//result.rgb = previous + (irradianceDelta * 0.25f);
|
||||||
}
|
}
|
||||||
float3 resultDelta = (1.0f - historyWeight) * irradianceDelta;
|
|
||||||
if (Max3(result.rgb) < Max3(previous))
|
|
||||||
resultDelta = min(max(abs(resultDelta), 1.0f / 1024.0f), abs(irradianceDelta)) * sign(resultDelta);
|
|
||||||
//result = float4(previous + resultDelta, 1.0f);
|
|
||||||
result = float4(lerp(result.rgb, previous.rgb, historyWeight), 1.0f);
|
result = float4(lerp(result.rgb, previous.rgb, historyWeight), 1.0f);
|
||||||
#else
|
#else
|
||||||
result = float4(lerp(result.rg, previous.rg, historyWeight), 0.0f, 1.0f);
|
result = float4(lerp(result.rg, previous.rg, historyWeight), 0.0f, 1.0f);
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ struct GlobalSurfaceObject
|
|||||||
{
|
{
|
||||||
float3 BoundsPosition;
|
float3 BoundsPosition;
|
||||||
float BoundsRadius;
|
float BoundsRadius;
|
||||||
float4x4 WorldToLocal;
|
float3x3 WorldToLocalRotation;
|
||||||
float3 Extent;
|
float3 WorldPosition;
|
||||||
|
float3 WorldExtents;
|
||||||
bool UseVisibility;
|
bool UseVisibility;
|
||||||
uint TileOffsets[6];
|
uint TileOffsets[6];
|
||||||
uint DataSize; // count of float4s for object+tiles
|
uint DataSize; // count of float4s for object+tiles
|
||||||
@@ -54,11 +55,11 @@ GlobalSurfaceObject LoadGlobalSurfaceAtlasObject(Buffer<float4> objects, uint ob
|
|||||||
GlobalSurfaceObject object = (GlobalSurfaceObject)0;
|
GlobalSurfaceObject object = (GlobalSurfaceObject)0;
|
||||||
object.BoundsPosition = vector0.xyz;
|
object.BoundsPosition = vector0.xyz;
|
||||||
object.BoundsRadius = vector0.w;
|
object.BoundsRadius = vector0.w;
|
||||||
object.WorldToLocal[0] = float4(vector2.xyz, 0.0f);
|
object.WorldToLocalRotation[0] = vector2.xyz;
|
||||||
object.WorldToLocal[1] = float4(vector3.xyz, 0.0f);
|
object.WorldToLocalRotation[1] = vector3.xyz;
|
||||||
object.WorldToLocal[2] = float4(vector4.xyz, 0.0f);
|
object.WorldToLocalRotation[2] = vector4.xyz;
|
||||||
object.WorldToLocal[3] = float4(vector2.w, vector3.w, vector4.w, 1.0f);
|
object.WorldPosition = float3(vector2.w, vector3.w, vector4.w);
|
||||||
object.Extent = vector5.xyz;
|
object.WorldExtents = vector5.xyz;
|
||||||
object.UseVisibility = vector5.w > 0.5f;
|
object.UseVisibility = vector5.w > 0.5f;
|
||||||
uint vector1x = asuint(vector1.x);
|
uint vector1x = asuint(vector1.x);
|
||||||
uint vector1y = asuint(vector1.y);
|
uint vector1y = asuint(vector1.y);
|
||||||
@@ -198,47 +199,36 @@ float4 SampleGlobalSurfaceAtlas(const GlobalSurfaceAtlasData data, ByteAddressBu
|
|||||||
float4 objectBounds = LoadGlobalSurfaceAtlasObjectBounds(objects, objectAddress);
|
float4 objectBounds = LoadGlobalSurfaceAtlasObjectBounds(objects, objectAddress);
|
||||||
if (distance(objectBounds.xyz, worldPosition) > objectBounds.w)
|
if (distance(objectBounds.xyz, worldPosition) > objectBounds.w)
|
||||||
continue;
|
continue;
|
||||||
GlobalSurfaceObject object = LoadGlobalSurfaceAtlasObject(objects, objectAddress);
|
|
||||||
float3 localPosition = mul(float4(worldPosition, 1), object.WorldToLocal).xyz;
|
|
||||||
float3 localExtent = object.Extent + surfaceThreshold;
|
|
||||||
if (any(localPosition > localExtent) || any(localPosition < -localExtent))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Remove the scale vector from the transformation matrix
|
// Cull point vs box
|
||||||
float3x3 worldToLocal = (float3x3)object.WorldToLocal;
|
GlobalSurfaceObject object = LoadGlobalSurfaceAtlasObject(objects, objectAddress);
|
||||||
float scaleX = length(worldToLocal[0]);
|
float3 localPosition = mul(worldPosition - object.WorldPosition, object.WorldToLocalRotation);
|
||||||
float scaleY = length(worldToLocal[1]);
|
float3 localExtents = object.WorldExtents + surfaceThreshold;
|
||||||
float scaleZ = length(worldToLocal[2]);
|
if (any(abs(localPosition) > localExtents))
|
||||||
float3 invScale = float3(
|
continue;
|
||||||
scaleX > 0.00001f ? 1.0f / scaleX : 0.0f,
|
|
||||||
scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
|
|
||||||
scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
|
|
||||||
worldToLocal[0] *= invScale.x;
|
|
||||||
worldToLocal[1] *= invScale.y;
|
|
||||||
worldToLocal[2] *= invScale.z;
|
|
||||||
|
|
||||||
// Sample tiles based on the directionality
|
// Sample tiles based on the directionality
|
||||||
#if GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD_ENABLED
|
#if GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD_ENABLED
|
||||||
float3 localNormal = normalize(mul(worldNormal, worldToLocal));
|
float3 localNormal = mul(worldNormal, object.WorldToLocalRotation);
|
||||||
float3 localNormalSq = localNormal * localNormal;
|
float3 localNormalSq = localNormal * localNormal;
|
||||||
uint tileOffset = object.TileOffsets[localNormal.x > 0.0f ? 0 : 1];
|
uint tileOffset = object.TileOffsets[localNormal.x > 0.0f ? 0 : 1];
|
||||||
if (localNormalSq.x > GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD * GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD && tileOffset != 0)
|
if (localNormalSq.x > GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD * GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD && tileOffset != 0)
|
||||||
{
|
{
|
||||||
GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(objects, objectAddress + tileOffset);
|
GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(objects, objectAddress + tileOffset);
|
||||||
result += SampleGlobalSurfaceAtlasTile(data, object, tile, depth, atlas, worldPosition, worldNormal, surfaceThreshold);
|
result += SampleGlobalSurfaceAtlasTile(data, object, tile, depth, atlas, worldPosition, worldNormal, surfaceThreshold);
|
||||||
}
|
}
|
||||||
tileOffset = object.TileOffsets[localNormal.y > 0.0f ? 2 : 3];
|
tileOffset = object.TileOffsets[localNormal.y > 0.0f ? 2 : 3];
|
||||||
if (localNormalSq.y > GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD * GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD && tileOffset != 0)
|
if (localNormalSq.y > GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD * GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD && tileOffset != 0)
|
||||||
{
|
{
|
||||||
GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(objects, objectAddress + tileOffset);
|
GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(objects, objectAddress + tileOffset);
|
||||||
result += SampleGlobalSurfaceAtlasTile(data, object, tile, depth, atlas, worldPosition, worldNormal, surfaceThreshold);
|
result += SampleGlobalSurfaceAtlasTile(data, object, tile, depth, atlas, worldPosition, worldNormal, surfaceThreshold);
|
||||||
}
|
}
|
||||||
tileOffset = object.TileOffsets[localNormal.z > 0.0f ? 4 : 5];
|
tileOffset = object.TileOffsets[localNormal.z > 0.0f ? 4 : 5];
|
||||||
if (localNormalSq.z > GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD * GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD && tileOffset != 0)
|
if (localNormalSq.z > GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD * GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD && tileOffset != 0)
|
||||||
{
|
{
|
||||||
GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(objects, objectAddress + tileOffset);
|
GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(objects, objectAddress + tileOffset);
|
||||||
result += SampleGlobalSurfaceAtlasTile(data, object, tile, depth, atlas, worldPosition, worldNormal, surfaceThreshold);
|
result += SampleGlobalSurfaceAtlasTile(data, object, tile, depth, atlas, worldPosition, worldNormal, surfaceThreshold);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
uint tileOffset = object.TileOffsets[0];
|
uint tileOffset = object.TileOffsets[0];
|
||||||
if (tileOffset != 0)
|
if (tileOffset != 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user