From 4c0a2e26cd4707ac13cc54f8a84ac059b4a921d6 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 13 Jul 2026 17:38:59 +0200 Subject: [PATCH] Optimize dirty shadow bounds update for particles and foliage --- Source/Engine/Foliage/Foliage.cpp | 2 +- Source/Engine/Particles/ParticleEffect.cpp | 2 +- Source/Engine/Renderer/ShadowsPass.cpp | 13 +++++++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Source/Engine/Foliage/Foliage.cpp b/Source/Engine/Foliage/Foliage.cpp index 7428a5a8b..fc6458272 100644 --- a/Source/Engine/Foliage/Foliage.cpp +++ b/Source/Engine/Foliage/Foliage.cpp @@ -909,7 +909,7 @@ void Foliage::RebuildClusters() _box = BoundingBox(_transform.Translation, _transform.Translation); _sphere = BoundingSphere(_transform.Translation, 0.0f); if (_sceneRenderingKey != -1) - GetSceneRendering()->UpdateActor(this, _sceneRenderingKey); + GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, ISceneRenderingListener::Bounds); return; } diff --git a/Source/Engine/Particles/ParticleEffect.cpp b/Source/Engine/Particles/ParticleEffect.cpp index 5e11cb2d9..e0fc7ceb9 100644 --- a/Source/Engine/Particles/ParticleEffect.cpp +++ b/Source/Engine/Particles/ParticleEffect.cpp @@ -372,7 +372,7 @@ void ParticleEffect::UpdateBounds() _box = bounds; BoundingSphere::FromBox(bounds, _sphere); if (_sceneRenderingKey != -1) - GetSceneRendering()->UpdateActor(this, _sceneRenderingKey); + GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, ISceneRenderingListener::Bounds); } void ParticleEffect::Sync() diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index da9f3909a..12848ed47 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -404,8 +404,17 @@ public: // Dirty static objects to redraw when changed (eg. material modification) if (a->HasStaticFlag(StaticFlags::Shadow)) { - DirtyStaticBounds(prevBounds); - DirtyStaticBounds(a->GetSphere()); + // TODO: skip actors that don't cast shadows (eg. particles) + BoundingSphere bounds = a->GetSphere(); + if (bounds != prevBounds) + { + // Avoid dirtying twice when bounds are close to each other + if (BoundingSphere::NearEqual(bounds, prevBounds, METERS_TO_UNITS_SCALE)) + BoundingSphere::Merge(bounds, prevBounds, bounds); + else + DirtyStaticBounds(prevBounds); + } + DirtyStaticBounds(bounds); } else if (flags & StaticFlags) {