diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp index 52091a1c1..d9d8d9691 100644 --- a/examples/GraphicsTest/main.cpp +++ b/examples/GraphicsTest/main.cpp @@ -103,11 +103,11 @@ int main() framePipeline.RegisterRenderable(worldInstanceIndex1, Nz::FramePipeline::NoSkeletonInstance, &model, 0xFFFFFFFF, scissorBox); framePipeline.RegisterRenderable(worldInstanceIndex2, Nz::FramePipeline::NoSkeletonInstance, &model, 0xFFFFFFFF, scissorBox); - std::shared_ptr light = std::make_shared(); + std::unique_ptr light = std::make_unique(); light->UpdateInnerAngle(Nz::DegreeAnglef(15.f)); light->UpdateOuterAngle(Nz::DegreeAnglef(20.f)); - framePipeline.RegisterLight(light, 0xFFFFFFFF); + framePipeline.RegisterLight(light.get(), 0xFFFFFFFF); Nz::Vector3f viewerPos = Nz::Vector3f::Zero(); diff --git a/examples/PhysicallyBasedRendering/main.cpp b/examples/PhysicallyBasedRendering/main.cpp index d2ce93912..8afcdb2f1 100644 --- a/examples/PhysicallyBasedRendering/main.cpp +++ b/examples/PhysicallyBasedRendering/main.cpp @@ -92,10 +92,10 @@ int main() std::size_t worldInstanceIndex1 = framePipeline.RegisterWorldInstance(modelInstance); framePipeline.RegisterRenderable(worldInstanceIndex1, Nz::FramePipeline::NoSkeletonInstance, &model, 0xFFFFFFFF, scissorBox); - std::shared_ptr light = std::make_shared(); + std::unique_ptr light = std::make_unique(); light->UpdateRotation(Nz::EulerAnglesf(-45.f, 0.f, 0.f)); - framePipeline.RegisterLight(light, 0xFFFFFFFF); + framePipeline.RegisterLight(light.get(), 0xFFFFFFFF); Nz::Vector3f viewerPos = Nz::Vector3f::Zero(); diff --git a/examples/PhysicsDemo/main.cpp b/examples/PhysicsDemo/main.cpp index 61e646efe..3b7cfdaf4 100644 --- a/examples/PhysicsDemo/main.cpp +++ b/examples/PhysicsDemo/main.cpp @@ -148,12 +148,10 @@ int main() entt::entity headingEntity = registry.create(); { - auto spotLight = std::make_shared(); - spotLight->EnableShadowCasting(true); - spotLight->UpdateShadowMapSize(1024); - auto& entityLight = registry.emplace(playerEntity); - entityLight.AttachLight(std::move(spotLight), 1); + auto& spotLight = entityLight.AddLight(1); + spotLight.EnableShadowCasting(true); + spotLight.UpdateShadowMapSize(1024); auto& entityGfx = registry.emplace(playerEntity); entityGfx.AttachRenderable(model, 1); diff --git a/examples/Showcase/main.cpp b/examples/Showcase/main.cpp index bedf06b08..13f1f0874 100644 --- a/examples/Showcase/main.cpp +++ b/examples/Showcase/main.cpp @@ -169,14 +169,13 @@ int main() lightNode.SetPosition(Nz::Vector3f::Up() * 3.f + Nz::Vector3f::Backward() * 1.f); lightNode.SetRotation(Nz::EulerAnglesf(-70.f, 0.f, 0.f)); - auto spotLight = std::make_shared(); - spotLight->UpdateColor(Nz::Color::Red); - spotLight->UpdateInnerAngle(Nz::DegreeAnglef(15.f)); - spotLight->UpdateOuterAngle(Nz::DegreeAnglef(20.f)); - spotLight->EnableShadowCasting(true); - auto& cameraLight = registry.emplace(lightEntity1); - cameraLight.AttachLight(spotLight, 0xFFFFFFFF); + + auto& spotLight = cameraLight.AddLight(0xFFFFFFFF); + spotLight.UpdateColor(Nz::Color::Red); + spotLight.UpdateInnerAngle(Nz::DegreeAnglef(15.f)); + spotLight.UpdateOuterAngle(Nz::DegreeAnglef(20.f)); + spotLight.EnableShadowCasting(true); } entt::entity lightEntity2 = registry.create(); @@ -185,13 +184,12 @@ int main() lightNode.SetPosition(Nz::Vector3f::Up() * 3.5f + Nz::Vector3f::Right() * 1.5f); lightNode.SetRotation(Nz::EulerAnglesf(-70.f, 90.f, 0.f)); - auto spotLight = std::make_shared(); - spotLight->UpdateColor(Nz::Color::Green); - spotLight->EnableShadowCasting(true); - spotLight->UpdateShadowMapSize(1024); - auto& cameraLight = registry.emplace(lightEntity2); - cameraLight.AttachLight(spotLight, 0xFFFFFFFF); + + auto& spotLight = cameraLight.AddLight(0xFFFFFFFF); + spotLight.UpdateColor(Nz::Color::Green); + spotLight.EnableShadowCasting(true); + spotLight.UpdateShadowMapSize(1024); } entt::entity lightEntity3 = registry.create(); @@ -255,14 +253,13 @@ int main() lightNode.SetRotation(Nz::EulerAnglesf(-45.f, 180.f, 0.f)); lightNode.SetParentJoint(bobEntity, "Spine2"); - auto spotLight = std::make_shared(); - spotLight->UpdateColor(Nz::Color::Blue); - spotLight->UpdateInnerAngle(Nz::DegreeAnglef(15.f)); - spotLight->UpdateOuterAngle(Nz::DegreeAnglef(20.f)); - spotLight->EnableShadowCasting(true); - auto& cameraLight = registry.emplace(lightEntity3); - cameraLight.AttachLight(spotLight, 0xFFFFFFFF); + + auto& spotLight = cameraLight.AddLight(0xFFFFFFFF); + spotLight.UpdateColor(Nz::Color::Blue); + spotLight.UpdateInnerAngle(Nz::DegreeAnglef(15.f)); + spotLight.UpdateOuterAngle(Nz::DegreeAnglef(20.f)); + spotLight.EnableShadowCasting(true); } } @@ -522,7 +519,7 @@ int main() Nz::DebugDrawer& debugDrawer = renderSystem.GetFramePipeline().GetDebugDrawer(); auto& lightNode = registry.get(lightEntity3); - debugDrawer.DrawLine(lightNode.GetPosition(Nz::CoordSys::Global), lightNode.GetForward() * 10.f, Nz::Color::Blue); + //debugDrawer.DrawLine(lightNode.GetPosition(Nz::CoordSys::Global), lightNode.GetForward() * 10.f, Nz::Color::Blue); /*Nz::Boxf test = spotLight->GetBoundingVolume().aabb; debugDrawer.DrawBox(test, Nz::Color::Blue); debugDrawer.DrawBox(floorBox, Nz::Color::Red); diff --git a/include/Nazara/Graphics/Components/LightComponent.hpp b/include/Nazara/Graphics/Components/LightComponent.hpp index e9832f215..8e014186c 100644 --- a/include/Nazara/Graphics/Components/LightComponent.hpp +++ b/include/Nazara/Graphics/Components/LightComponent.hpp @@ -28,12 +28,10 @@ namespace Nz LightComponent(LightComponent&&) = default; ~LightComponent() = default; - inline void AttachLight(std::shared_ptr renderable, UInt32 renderMask); + template T& AddLight(UInt32 renderMask, Args&&... args); inline void Clear(); - inline void DetachLight(const std::shared_ptr& renderable); - inline const LightEntry& GetLightEntry(std::size_t lightIndex) const; inline const std::array& GetLights() const; @@ -41,6 +39,9 @@ namespace Nz inline bool IsVisible() const; + inline void RemoveLight(std::size_t lightIndex); + inline void RemoveLight(const Light& renderable); + inline void Show(bool show = true); LightComponent& operator=(const LightComponent&) = default; @@ -52,7 +53,7 @@ namespace Nz struct LightEntry { - std::shared_ptr light; + std::unique_ptr light; UInt32 renderMask; }; diff --git a/include/Nazara/Graphics/Components/LightComponent.inl b/include/Nazara/Graphics/Components/LightComponent.inl index 0ed1a42c1..b31f61b44 100644 --- a/include/Nazara/Graphics/Components/LightComponent.inl +++ b/include/Nazara/Graphics/Components/LightComponent.inl @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz @@ -12,20 +13,25 @@ namespace Nz { } - inline void LightComponent::AttachLight(std::shared_ptr light, UInt32 renderMask) + template + T& LightComponent::AddLight(UInt32 renderMask, Args&&... args) { + static_assert(std::is_base_of_v, "Type must inherit Light"); + for (std::size_t i = 0; i < m_lightEntries.size(); ++i) { auto& entry = m_lightEntries[i]; if (entry.light) continue; - entry.light = std::move(light); + entry.light = std::make_unique(std::forward(args)...); entry.renderMask = renderMask; OnLightAttached(this, i); - break; + return static_cast(*entry.light); } + + throw std::runtime_error("too many lights attached to the same entity"); } inline void LightComponent::Clear() @@ -33,7 +39,7 @@ namespace Nz for (std::size_t i = 0; i < m_lightEntries.size(); ++i) { auto& entry = m_lightEntries[i]; - if (entry.light) + if (!entry.light) continue; OnLightDetach(this, i); @@ -41,17 +47,6 @@ namespace Nz } } - inline void LightComponent::DetachLight(const std::shared_ptr& light) - { - auto it = std::find_if(m_lightEntries.begin(), m_lightEntries.end(), [&](const auto& lightEntry) { return lightEntry.light == light; }); - if (it != m_lightEntries.end()) - { - OnLightDetach(this, std::distance(m_lightEntries.begin(), it)); - - it->light.reset(); - } - } - inline auto LightComponent::GetLightEntry(std::size_t lightIndex) const -> const LightEntry& { assert(lightIndex < m_lightEntries.size()); @@ -73,6 +68,24 @@ namespace Nz return m_isVisible; } + inline void LightComponent::RemoveLight(std::size_t lightIndex) + { + assert(lightIndex < m_lightEntries.size()); + auto& entry = m_lightEntries[lightIndex]; + if (!entry.light) + return; + + OnLightDetach(this, lightIndex); + entry.light.reset(); + } + + inline void LightComponent::RemoveLight(const Light& light) + { + auto it = std::find_if(m_lightEntries.begin(), m_lightEntries.end(), [&](const auto& lightEntry) { return lightEntry.light.get() == &light; }); + if (it != m_lightEntries.end()) + RemoveLight(std::distance(m_lightEntries.begin(), it)); + } + inline void LightComponent::Show(bool show) { if (m_isVisible != show)