diff --git a/Content/Editor/DebugMaterials/DDGIDebugProbes.flax b/Content/Editor/DebugMaterials/DDGIDebugProbes.flax index 60c62fba3..dd9c206d9 100644 --- a/Content/Editor/DebugMaterials/DDGIDebugProbes.flax +++ b/Content/Editor/DebugMaterials/DDGIDebugProbes.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a57f6ae32a6b5b67540914583757752fee027ce187b2ff5655e1de774cdac3fb -size 41699 +oid sha256:ac0e118b9cb0fe9fdcaed25a141ff036441959dcb75435d4d436d51dc5ec9dd9 +size 41695 diff --git a/Content/Shaders/GI/DDGI.flax b/Content/Shaders/GI/DDGI.flax index 5fea80f23..1622d78d9 100644 --- a/Content/Shaders/GI/DDGI.flax +++ b/Content/Shaders/GI/DDGI.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:220cdb9a73d181fb2dccf59de1169e57d42537b8aaf9deba495dc753fd19c8b6 -size 22031 +oid sha256:ba8bc039e5a098638c5a2cc2d2c1d412fda6b10b5747c0075e8755897f65688f +size 21756 diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp index f143c1d0b..e5e14acd7 100644 --- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp +++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp @@ -461,7 +461,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext, ddgiData.Result.Constants.ProbesOriginAndSpacing[cascadeIndex] = Float4(cascade.ProbesOrigin, cascade.ProbesSpacing); 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.RaysCount = probeRaysCount; ddgiData.Result.Constants.ProbeHistoryWeight = probeHistoryWeight; diff --git a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp index eca4c8b34..d5c3b7efa 100644 --- a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp +++ b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp @@ -1232,19 +1232,20 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con _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) - Matrix localToWorldBounds; - object->Bounds.Transformation.GetWorld(localToWorldBounds); - Matrix worldToLocalBounds; - Matrix::Invert(localToWorldBounds, worldToLocalBounds); uint32 objectAddress = surfaceAtlasData.ObjectsBuffer.Data.Count() / sizeof(Float4); auto* objectData = surfaceAtlasData.ObjectsBuffer.WriteReserve(GLOBAL_SURFACE_ATLAS_OBJECT_DATA_STRIDE); objectData[0] = *(Float4*)&actorObjectBounds; objectData[1] = Float4::Zero; - objectData[2] = Float4(worldToLocalBounds.M11, worldToLocalBounds.M12, worldToLocalBounds.M13, worldToLocalBounds.M41); - objectData[3] = Float4(worldToLocalBounds.M21, worldToLocalBounds.M22, worldToLocalBounds.M23, worldToLocalBounds.M42); - objectData[4] = Float4(worldToLocalBounds.M31, worldToLocalBounds.M32, worldToLocalBounds.M33, worldToLocalBounds.M43); - objectData[5] = Float4(object->Bounds.Extents, useVisibility ? 1.0f : 0.0f); + objectData[2] = Float4(worldToLocalRotation.M11, worldToLocalRotation.M12, worldToLocalRotation.M13, worldPosition.X); + objectData[3] = Float4(worldToLocalRotation.M21, worldToLocalRotation.M22, worldToLocalRotation.M23, worldPosition.Y); + objectData[4] = Float4(worldToLocalRotation.M31, worldToLocalRotation.M32, worldToLocalRotation.M33, worldPosition.Z); + objectData[5] = Float4(worldExtents, useVisibility ? 1.0f : 0.0f); auto tileOffsets = reinterpret_cast(&objectData[1]); // xyz used for tile offsets packed into uint16 auto objectDataSize = reinterpret_cast(&objectData[1].W); // w used for object size (count of Float4s for object+tiles) *objectDataSize = GLOBAL_SURFACE_ATLAS_OBJECT_DATA_STRIDE; diff --git a/Source/Shaders/GI/DDGI.shader b/Source/Shaders/GI/DDGI.shader index 75a2f68a8..2090ddfb7 100644 --- a/Source/Shaders/GI/DDGI.shader +++ b/Source/Shaders/GI/DDGI.shader @@ -414,10 +414,6 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_ // Reduce flickering during rapid brightness changes //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); #else result = float4(lerp(result.rg, previous.rg, historyWeight), 0.0f, 1.0f); diff --git a/Source/Shaders/GI/GlobalSurfaceAtlas.hlsl b/Source/Shaders/GI/GlobalSurfaceAtlas.hlsl index 30c963d85..0fa43d451 100644 --- a/Source/Shaders/GI/GlobalSurfaceAtlas.hlsl +++ b/Source/Shaders/GI/GlobalSurfaceAtlas.hlsl @@ -23,8 +23,9 @@ struct GlobalSurfaceObject { float3 BoundsPosition; float BoundsRadius; - float4x4 WorldToLocal; - float3 Extent; + float3x3 WorldToLocalRotation; + float3 WorldPosition; + float3 WorldExtents; bool UseVisibility; uint TileOffsets[6]; uint DataSize; // count of float4s for object+tiles @@ -54,11 +55,11 @@ GlobalSurfaceObject LoadGlobalSurfaceAtlasObject(Buffer objects, uint ob GlobalSurfaceObject object = (GlobalSurfaceObject)0; object.BoundsPosition = vector0.xyz; object.BoundsRadius = vector0.w; - object.WorldToLocal[0] = float4(vector2.xyz, 0.0f); - object.WorldToLocal[1] = float4(vector3.xyz, 0.0f); - object.WorldToLocal[2] = float4(vector4.xyz, 0.0f); - object.WorldToLocal[3] = float4(vector2.w, vector3.w, vector4.w, 1.0f); - object.Extent = vector5.xyz; + object.WorldToLocalRotation[0] = vector2.xyz; + object.WorldToLocalRotation[1] = vector3.xyz; + object.WorldToLocalRotation[2] = vector4.xyz; + object.WorldPosition = float3(vector2.w, vector3.w, vector4.w); + object.WorldExtents = vector5.xyz; object.UseVisibility = vector5.w > 0.5f; uint vector1x = asuint(vector1.x); uint vector1y = asuint(vector1.y); @@ -198,47 +199,36 @@ float4 SampleGlobalSurfaceAtlas(const GlobalSurfaceAtlasData data, ByteAddressBu float4 objectBounds = LoadGlobalSurfaceAtlasObjectBounds(objects, objectAddress); if (distance(objectBounds.xyz, worldPosition) > objectBounds.w) 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 - float3x3 worldToLocal = (float3x3)object.WorldToLocal; - float scaleX = length(worldToLocal[0]); - float scaleY = length(worldToLocal[1]); - float scaleZ = length(worldToLocal[2]); - float3 invScale = float3( - 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; + // Cull point vs box + GlobalSurfaceObject object = LoadGlobalSurfaceAtlasObject(objects, objectAddress); + float3 localPosition = mul(worldPosition - object.WorldPosition, object.WorldToLocalRotation); + float3 localExtents = object.WorldExtents + surfaceThreshold; + if (any(abs(localPosition) > localExtents)) + continue; // Sample tiles based on the directionality #if GLOBAL_SURFACE_ATLAS_TILE_NORMAL_THRESHOLD_ENABLED - float3 localNormal = normalize(mul(worldNormal, worldToLocal)); - float3 localNormalSq = localNormal * localNormal; - 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) - { - GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(objects, objectAddress + tileOffset); - result += SampleGlobalSurfaceAtlasTile(data, object, tile, depth, atlas, worldPosition, worldNormal, surfaceThreshold); - } - 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) - { - GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(objects, objectAddress + tileOffset); - result += SampleGlobalSurfaceAtlasTile(data, object, tile, depth, atlas, worldPosition, worldNormal, surfaceThreshold); - } - 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) - { - GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(objects, objectAddress + tileOffset); - result += SampleGlobalSurfaceAtlasTile(data, object, tile, depth, atlas, worldPosition, worldNormal, surfaceThreshold); - } + float3 localNormal = mul(worldNormal, object.WorldToLocalRotation); + float3 localNormalSq = localNormal * localNormal; + 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) + { + GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(objects, objectAddress + tileOffset); + result += SampleGlobalSurfaceAtlasTile(data, object, tile, depth, atlas, worldPosition, worldNormal, surfaceThreshold); + } + 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) + { + GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(objects, objectAddress + tileOffset); + result += SampleGlobalSurfaceAtlasTile(data, object, tile, depth, atlas, worldPosition, worldNormal, surfaceThreshold); + } + 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) + { + GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(objects, objectAddress + tileOffset); + result += SampleGlobalSurfaceAtlasTile(data, object, tile, depth, atlas, worldPosition, worldNormal, surfaceThreshold); + } #else uint tileOffset = object.TileOffsets[0]; if (tileOffset != 0)