diff --git a/Source/Engine/Level/Actors/DirectionalLight.cpp b/Source/Engine/Level/Actors/DirectionalLight.cpp
index 3d198e042..cef1eba97 100644
--- a/Source/Engine/Level/Actors/DirectionalLight.cpp
+++ b/Source/Engine/Level/Actors/DirectionalLight.cpp
@@ -39,6 +39,7 @@ void DirectionalLight::Draw(RenderContext& renderContext)
data.IndirectLightingIntensity = IndirectLightingIntensity;
data.CastVolumetricShadow = CastVolumetricShadow;
data.ShadowsUpdateRate = ShadowsUpdateRate;
+ data.ShadowFrame = _invalidateShadowFrame;
data.ShadowsUpdateRateAtDistance = ShadowsUpdateRateAtDistance;
data.ShadowsMode = ShadowsMode;
data.CascadeCount = CascadeCount;
diff --git a/Source/Engine/Level/Actors/Light.cpp b/Source/Engine/Level/Actors/Light.cpp
index 6a0dfa726..81aeb2e4a 100644
--- a/Source/Engine/Level/Actors/Light.cpp
+++ b/Source/Engine/Level/Actors/Light.cpp
@@ -84,6 +84,11 @@ LightWithShadow::LightWithShadow(const SpawnParams& params)
{
}
+void LightWithShadow::InvalidateShadow()
+{
+ _invalidateShadowFrame++;
+}
+
void LightWithShadow::Serialize(SerializeStream& stream, const void* otherObj)
{
// Base
diff --git a/Source/Engine/Level/Actors/Light.h b/Source/Engine/Level/Actors/Light.h
index afe644c27..8fd40c530 100644
--- a/Source/Engine/Level/Actors/Light.h
+++ b/Source/Engine/Level/Actors/Light.h
@@ -79,6 +79,9 @@ public:
API_CLASS(Abstract) class FLAXENGINE_API LightWithShadow : public Light
{
DECLARE_SCENE_OBJECT_ABSTRACT(LightWithShadow);
+protected:
+ uint32 _invalidateShadowFrame = 0;
+
public:
///
/// The minimum roughness value used to clamp material surface roughness during shading pixel.
@@ -145,6 +148,11 @@ public:
///
API_FIELD(Attributes="EditorOrder(60), EditorDisplay(\"Shadow\", \"Mode\")")
ShadowsCastingMode ShadowsMode = ShadowsCastingMode::All;
+
+ ///
+ /// Marks the light shadow to be refreshes during next drawing. Invalidates any cached shadow map and redraws static shadows of the object (if any in use).
+ ///
+ API_FUNCTION() void InvalidateShadow();
public:
// [Light]
diff --git a/Source/Engine/Level/Actors/PointLight.cpp b/Source/Engine/Level/Actors/PointLight.cpp
index 626008a54..5f2be645b 100644
--- a/Source/Engine/Level/Actors/PointLight.cpp
+++ b/Source/Engine/Level/Actors/PointLight.cpp
@@ -105,6 +105,7 @@ void PointLight::Draw(RenderContext& renderContext)
data.CastVolumetricShadow = CastVolumetricShadow;
data.ShadowsUpdateRate = ShadowsUpdateRate;
data.ShadowsUpdateRateAtDistance = ShadowsUpdateRateAtDistance;
+ data.ShadowFrame = _invalidateShadowFrame;
data.ShadowsMode = ShadowsMode;
data.Radius = radius;
data.FallOffExponent = FallOffExponent;
diff --git a/Source/Engine/Level/Actors/SpotLight.cpp b/Source/Engine/Level/Actors/SpotLight.cpp
index f2b6046ee..892bdf02e 100644
--- a/Source/Engine/Level/Actors/SpotLight.cpp
+++ b/Source/Engine/Level/Actors/SpotLight.cpp
@@ -155,6 +155,7 @@ void SpotLight::Draw(RenderContext& renderContext)
data.CastVolumetricShadow = CastVolumetricShadow;
data.ShadowsUpdateRate = ShadowsUpdateRate;
data.ShadowsUpdateRateAtDistance = ShadowsUpdateRateAtDistance;
+ data.ShadowFrame = _invalidateShadowFrame;
data.ShadowsMode = ShadowsMode;
data.Radius = radius;
data.FallOffExponent = FallOffExponent;
diff --git a/Source/Engine/Renderer/RenderList.h b/Source/Engine/Renderer/RenderList.h
index a58eeb0c4..0fe3bc960 100644
--- a/Source/Engine/Renderer/RenderList.h
+++ b/Source/Engine/Renderer/RenderList.h
@@ -58,6 +58,7 @@ struct RenderLightData
float ShadowsUpdateRate;
float ShadowsUpdateRateAtDistance;
+ uint32 ShadowFrame;
bool CanRenderShadow(const RenderView& view) const;
};
diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp
index 32ec246aa..d6a40238a 100644
--- a/Source/Engine/Renderer/ShadowsPass.cpp
+++ b/Source/Engine/Renderer/ShadowsPass.cpp
@@ -121,6 +121,7 @@ struct ShadowAtlasLightCache
bool DynamicValid;
float ShadowsUpdateRate;
float ShadowsUpdateRateAtDistance;
+ uint32 ShadowFrame;
float OuterConeAngle;
Float3 Position;
float Radius;
@@ -136,6 +137,7 @@ struct ShadowAtlasLightCache
ShadowsUpdateRate = light.ShadowsUpdateRate;
ShadowsUpdateRateAtDistance = light.ShadowsUpdateRateAtDistance;
Direction = light.Direction;
+ ShadowFrame = light.ShadowFrame;
if (light.IsDirectionalLight)
{
// Sun
@@ -229,6 +231,7 @@ struct ShadowAtlasLight
if (!Math::NearEqual(Cache.Distance, light.ShadowsDistance) ||
!Math::NearEqual(Cache.ShadowsUpdateRate, light.ShadowsUpdateRate) ||
!Math::NearEqual(Cache.ShadowsUpdateRateAtDistance, light.ShadowsUpdateRateAtDistance) ||
+ Cache.ShadowFrame != light.ShadowFrame ||
Float3::Dot(Cache.Direction, light.Direction) < 0.999999f)
{
// Invalidate