diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs
index b4fb8f8f1..3281d130a 100644
--- a/Source/Editor/Viewport/EditorViewport.cs
+++ b/Source/Editor/Viewport/EditorViewport.cs
@@ -1538,6 +1538,7 @@ namespace FlaxEditor.Viewport
new ViewFlagOptions(ViewFlags.MotionBlur, "Motion Blur"),
new ViewFlagOptions(ViewFlags.ContactShadows, "Contact Shadows"),
new ViewFlagOptions(ViewFlags.PhysicsDebug, "Physics Debug"),
+ new ViewFlagOptions(ViewFlags.LightsDebug, "Lights Debug"),
new ViewFlagOptions(ViewFlags.DebugDraw, "Debug Draw"),
};
diff --git a/Source/Engine/Graphics/Enums.h b/Source/Engine/Graphics/Enums.h
index 3ef462925..4d1422f96 100644
--- a/Source/Engine/Graphics/Enums.h
+++ b/Source/Engine/Graphics/Enums.h
@@ -1031,6 +1031,11 @@ API_ENUM(Attributes="Flags") enum class ViewFlags : uint64
///
Sky = 1 << 26,
+ ///
+ /// Shows/hides light debug shapes.
+ ///
+ LightsDebug = 1 << 27,
+
///
/// Default flags for Game.
///
diff --git a/Source/Engine/Level/Actors/Light.cpp b/Source/Engine/Level/Actors/Light.cpp
index 594ebdc2b..5e86f6e7e 100644
--- a/Source/Engine/Level/Actors/Light.cpp
+++ b/Source/Engine/Level/Actors/Light.cpp
@@ -26,6 +26,7 @@ void Light::OnEnable()
GetSceneRendering()->AddActor(this, _sceneRenderingKey);
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
+ GetSceneRendering()->AddLightsDebug(this);
#endif
// Base
@@ -36,6 +37,7 @@ void Light::OnDisable()
{
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
+ GetSceneRendering()->RemoveLightsDebug(this);
#endif
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
@@ -43,6 +45,12 @@ void Light::OnDisable()
Actor::OnDisable();
}
+#if USE_EDITOR
+void Light::DrawLightsDebug(RenderView& view)
+{
+}
+#endif
+
void Light::Serialize(SerializeStream& stream, const void* otherObj)
{
// Base
diff --git a/Source/Engine/Level/Actors/Light.h b/Source/Engine/Level/Actors/Light.h
index dab613c71..86ca59ef5 100644
--- a/Source/Engine/Level/Actors/Light.h
+++ b/Source/Engine/Level/Actors/Light.h
@@ -66,6 +66,8 @@ public:
const Vector3 size(50);
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
}
+
+ virtual void DrawLightsDebug(RenderView& view);
#endif
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
diff --git a/Source/Engine/Level/Actors/PointLight.cpp b/Source/Engine/Level/Actors/PointLight.cpp
index 49c0f4c88..0e7ea79ec 100644
--- a/Source/Engine/Level/Actors/PointLight.cpp
+++ b/Source/Engine/Level/Actors/PointLight.cpp
@@ -143,6 +143,16 @@ void PointLight::OnDebugDrawSelected()
LightWithShadow::OnDebugDrawSelected();
}
+void PointLight::DrawLightsDebug(RenderView& view)
+{
+ const BoundingSphere sphere(_sphere.Center - view.Origin, _sphere.Radius);
+ if (!view.CullingFrustum.Intersects(sphere))
+ return;
+
+ // Draw influence range
+ DEBUG_DRAW_WIRE_SPHERE(_sphere, Color::Yellow, 0, true);
+}
+
#endif
void PointLight::OnLayerChanged()
diff --git a/Source/Engine/Level/Actors/PointLight.h b/Source/Engine/Level/Actors/PointLight.h
index d3e170a03..50df19232 100644
--- a/Source/Engine/Level/Actors/PointLight.h
+++ b/Source/Engine/Level/Actors/PointLight.h
@@ -95,6 +95,7 @@ public:
#if USE_EDITOR
void OnDebugDraw() override;
void OnDebugDrawSelected() override;
+ void DrawLightsDebug(RenderView& view) override;
#endif
void OnLayerChanged() override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
diff --git a/Source/Engine/Level/Actors/SpotLight.cpp b/Source/Engine/Level/Actors/SpotLight.cpp
index 26f1700d5..557d69cd9 100644
--- a/Source/Engine/Level/Actors/SpotLight.cpp
+++ b/Source/Engine/Level/Actors/SpotLight.cpp
@@ -203,6 +203,11 @@ void SpotLight::OnDebugDrawSelected()
DEBUG_DRAW_LINE(position, position + forward * radius + right * discRadius, color, 0, true);
DEBUG_DRAW_LINE(position, position + forward * radius - right * discRadius, color, 0, true);
+ DEBUG_DRAW_LINE(position, position + forward * radius + up * falloffDiscRadius, color * 0.6f, 0, true);
+ DEBUG_DRAW_LINE(position, position + forward * radius - up * falloffDiscRadius, color * 0.6f, 0, true);
+ DEBUG_DRAW_LINE(position, position + forward * radius + right * falloffDiscRadius, color * 0.6f, 0, true);
+ DEBUG_DRAW_LINE(position, position + forward * radius - right * falloffDiscRadius, color * 0.6f, 0, true);
+
DEBUG_DRAW_CIRCLE(position + forward * radius, forward, discRadius, color, 0, true);
DEBUG_DRAW_CIRCLE(position + forward * radius, forward, falloffDiscRadius, color * 0.6f, 0, true);
@@ -210,6 +215,34 @@ void SpotLight::OnDebugDrawSelected()
LightWithShadow::OnDebugDrawSelected();
}
+void SpotLight::DrawLightsDebug(RenderView& view)
+{
+ const BoundingSphere sphere(_sphere.Center - view.Origin, _sphere.Radius);
+ if (!view.CullingFrustum.Intersects(sphere))
+ return;
+
+ const auto color = Color::Yellow;
+ Vector3 right = _transform.GetRight();
+ Vector3 up = _transform.GetUp();
+ Vector3 forward = GetDirection();
+ float radius = GetScaledRadius();
+ float discRadius = radius * Math::Tan(_outerConeAngle * DegreesToRadians);
+ float falloffDiscRadius = radius * Math::Tan(_innerConeAngle * DegreesToRadians);
+ Vector3 position = GetPosition();
+
+ DEBUG_DRAW_LINE(position, position + forward * radius + up * discRadius, color, 0, true);
+ DEBUG_DRAW_LINE(position, position + forward * radius - up * discRadius, color, 0, true);
+ DEBUG_DRAW_LINE(position, position + forward * radius + right * discRadius, color, 0, true);
+ DEBUG_DRAW_LINE(position, position + forward * radius - right * discRadius, color, 0, true);
+
+ DEBUG_DRAW_LINE(position, position + forward * radius + up * falloffDiscRadius, color * 0.6f, 0, true);
+ DEBUG_DRAW_LINE(position, position + forward * radius - up * falloffDiscRadius, color * 0.6f, 0, true);
+ DEBUG_DRAW_LINE(position, position + forward * radius + right * falloffDiscRadius, color * 0.6f, 0, true);
+ DEBUG_DRAW_LINE(position, position + forward * radius - right * falloffDiscRadius, color * 0.6f, 0, true);
+
+ DEBUG_DRAW_CIRCLE(position + forward * radius, forward, discRadius, color, 0, true);
+ DEBUG_DRAW_CIRCLE(position + forward * radius, forward, falloffDiscRadius, color * 0.6f, 0, true);
+}
#endif
void SpotLight::Serialize(SerializeStream& stream, const void* otherObj)
diff --git a/Source/Engine/Level/Actors/SpotLight.h b/Source/Engine/Level/Actors/SpotLight.h
index 6bb0daf8d..e6179a522 100644
--- a/Source/Engine/Level/Actors/SpotLight.h
+++ b/Source/Engine/Level/Actors/SpotLight.h
@@ -127,6 +127,7 @@ public:
#if USE_EDITOR
void OnDebugDraw() override;
void OnDebugDrawSelected() override;
+ void DrawLightsDebug(RenderView& view) override;
#endif
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
diff --git a/Source/Engine/Level/Scene/SceneRendering.cpp b/Source/Engine/Level/Scene/SceneRendering.cpp
index 48420ed49..65773b6c0 100644
--- a/Source/Engine/Level/Scene/SceneRendering.cpp
+++ b/Source/Engine/Level/Scene/SceneRendering.cpp
@@ -96,6 +96,16 @@ void SceneRendering::Draw(RenderContextBatch& renderContextBatch, DrawCategory c
physicsDebugData[i](view);
}
}
+
+ // Draw light shapes
+ if (EnumHasAnyFlags(view.Flags, ViewFlags::LightsDebug))
+ {
+ const LightsDebugCallback* lightsDebugData = LightsDebug.Get();
+ for (int32 i = 0; i < LightsDebug.Count(); i++)
+ {
+ lightsDebugData[i](view);
+ }
+ }
}
#endif
}
diff --git a/Source/Engine/Level/Scene/SceneRendering.h b/Source/Engine/Level/Scene/SceneRendering.h
index ef9fc6c3c..0afe4ea3c 100644
--- a/Source/Engine/Level/Scene/SceneRendering.h
+++ b/Source/Engine/Level/Scene/SceneRendering.h
@@ -65,6 +65,7 @@ class FLAXENGINE_API SceneRendering
{
#if USE_EDITOR
typedef Function PhysicsDebugCallback;
+ typedef Function LightsDebugCallback;
friend class ViewportIconsRendererService;
#endif
public:
@@ -95,6 +96,7 @@ public:
private:
#if USE_EDITOR
Array PhysicsDebug;
+ Array LightsDebug;
Array ViewportIcons;
#endif
@@ -153,6 +155,22 @@ public:
PhysicsDebug.Remove(f);
}
+ template
+ FORCE_INLINE void AddLightsDebug(T* obj)
+ {
+ LightsDebugCallback f;
+ f.Bind(obj);
+ LightsDebug.Add(f);
+ }
+
+ template
+ void RemoveLightsDebug(T* obj)
+ {
+ LightsDebugCallback f;
+ f.Bind(obj);
+ LightsDebug.Remove(f);
+ }
+
FORCE_INLINE void AddViewportIcon(Actor* obj)
{
ViewportIcons.Add(obj);