From 9e1df33440fc306621abe71dbb3096ea2b28ea35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 29 Oct 2021 16:50:38 +0200 Subject: [PATCH] Graphics: Add RenderMask (WIP) --- examples/PhysicsDemo/main.cpp | 44 ++++++++++--------- include/Nazara/Graphics/AbstractViewer.hpp | 1 + include/Nazara/Graphics/Camera.hpp | 3 ++ include/Nazara/Graphics/Camera.inl | 10 +++++ .../Graphics/Components/GraphicsComponent.hpp | 18 +++++--- .../Graphics/Components/GraphicsComponent.inl | 12 ++--- .../Nazara/Graphics/ForwardFramePipeline.hpp | 4 +- include/Nazara/Graphics/FramePipeline.hpp | 2 +- src/Nazara/Graphics/Camera.cpp | 5 +++ src/Nazara/Graphics/ForwardFramePipeline.cpp | 16 +++++-- src/Nazara/Graphics/Systems/RenderSystem.cpp | 16 +++---- 11 files changed, 87 insertions(+), 44 deletions(-) diff --git a/examples/PhysicsDemo/main.cpp b/examples/PhysicsDemo/main.cpp index fb22fe9d6..d87b9fae0 100644 --- a/examples/PhysicsDemo/main.cpp +++ b/examples/PhysicsDemo/main.cpp @@ -140,29 +140,35 @@ int main() Nz::SparsePtr vertices = vertexMapper.GetComponentPtr(Nz::VertexComponent::Position); entt::registry registry; - entt::registry registry2D; Nz::Physics3DSystem physSytem(registry); Nz::RenderSystem renderSystem(registry); - Nz::RenderSystem renderSystem2D(registry2D); Nz::Canvas canvas(registry, window.GetEventHandler(), window.GetCursorController().CreateHandle()); Nz::LabelWidget* labelWidget = canvas.Add(); //labelWidget->EnableBackground(true); labelWidget->UpdateText(Nz::SimpleTextDrawer::Draw("Bonjour Paris !", 72), 0.1f); - entt::entity viewer2D = registry2D.create(); - registry2D.emplace(viewer2D); - registry2D.emplace(viewer2D, window.GetRenderTarget(), Nz::ProjectionType::Orthographic); + /*entt::entity viewer2D = registry.create(); + { + registry.emplace(viewer2D); + auto& cameraComponent = registry.emplace(viewer2D, window.GetRenderTarget(), Nz::ProjectionType::Orthographic); + cameraComponent.UpdateRenderMask(2); + }*/ - entt::entity text2D = registry2D.create(); - - registry2D.emplace(text2D).AttachRenderable(sprite); - registry2D.emplace(text2D).SetPosition(Nz::Vector3f(0.f, 200.f, 0.f)); + entt::entity text2D = registry.create(); + { + registry.emplace(text2D).SetPosition(Nz::Vector3f(0.f, 200.f, 0.f)); + auto& gfxComponent = registry.emplace(text2D); + gfxComponent.AttachRenderable(sprite, 2); + } entt::entity viewer = registry.create(); - registry.emplace(viewer); - registry.emplace(viewer, window.GetRenderTarget()); + { + registry.emplace(viewer); + auto& cameraComponent = registry.emplace(viewer, window.GetRenderTarget()); + cameraComponent.UpdateRenderMask(1); + } auto shipCollider = std::make_shared(vertices, vertexMapper.GetVertexCount(), 0.01f); @@ -187,7 +193,6 @@ int main() colliderModel->SetMaterial(i, colliderMat); } - entt::entity textEntity = registry.create(); { auto& entityGfx = registry.emplace(textEntity); @@ -201,7 +206,7 @@ int main() entt::entity headingEntity = registry.create(); { auto& entityGfx = registry.emplace(playerEntity); - entityGfx.AttachRenderable(model); + entityGfx.AttachRenderable(model, 1); auto& entityNode = registry.emplace(playerEntity); entityNode.SetPosition(Nz::Vector3f(12.5f, 0.f, 25.f)); @@ -218,15 +223,15 @@ int main() registry.get(viewer).SetParent(registry, headingEntity); registry.get(viewer).SetPosition(Nz::Vector3f::Backward() * 2.5f + Nz::Vector3f::Up() * 1.f); - for (std::size_t x = 0; x < 2; ++x) + for (std::size_t x = 0; x < 3; ++x) { - for (std::size_t y = 0; y < 2; ++y) + for (std::size_t y = 0; y < 3; ++y) { - for (std::size_t z = 0; z < 2; ++z) + for (std::size_t z = 0; z < 3; ++z) { entt::entity entity = registry.create(); auto& entityGfx = registry.emplace(entity); - entityGfx.AttachRenderable(model); + entityGfx.AttachRenderable(model, 1); //entityGfx.AttachRenderable(sprite); auto& entityNode = registry.emplace(entity); @@ -249,7 +254,7 @@ int main() Nz::Clock secondClock; unsigned int fps = 0; - Nz::Mouse::SetRelativeMouseMode(true); + //Nz::Mouse::SetRelativeMouseMode(true); float elapsedTime = 0.f; Nz::UInt64 time = Nz::GetElapsedMicroseconds(); @@ -337,8 +342,6 @@ int main() { float updateTime = updateClock.Restart() / 1'000'000.f; - float cameraSpeed = 20.f * updateTime; - physSytem.Update(registry, 1000.f / 60.f); auto spaceshipView = registry.view(); @@ -392,7 +395,6 @@ int main() continue; renderSystem.Render(registry, frame); - //renderSystem2D.Render(registry2D, frame); frame.Present(); diff --git a/include/Nazara/Graphics/AbstractViewer.hpp b/include/Nazara/Graphics/AbstractViewer.hpp index 477b42f3a..a0e0c4352 100644 --- a/include/Nazara/Graphics/AbstractViewer.hpp +++ b/include/Nazara/Graphics/AbstractViewer.hpp @@ -22,6 +22,7 @@ namespace Nz AbstractViewer() = default; ~AbstractViewer() = default; + virtual UInt32 GetRenderMask() const = 0; virtual const RenderTarget& GetRenderTarget() = 0; virtual ViewerInstance& GetViewerInstance() = 0; virtual const ViewerInstance& GetViewerInstance() const = 0; diff --git a/include/Nazara/Graphics/Camera.hpp b/include/Nazara/Graphics/Camera.hpp index 9d260d5af..fd9c75a9a 100644 --- a/include/Nazara/Graphics/Camera.hpp +++ b/include/Nazara/Graphics/Camera.hpp @@ -29,6 +29,7 @@ namespace Nz inline float GetAspectRatio() const; inline DegreeAnglef GetFOV() const; + UInt32 GetRenderMask() const override; const RenderTarget& GetRenderTarget() override; inline const Vector2f& GetSize() const; inline const Rectf& GetTargetRegion() const; @@ -40,6 +41,7 @@ namespace Nz inline void UpdateFOV(DegreeAnglef fov); inline void UpdateProjectionType(ProjectionType projectionType); + inline void UpdateRenderMask(UInt32 renderMask); inline void UpdateSize(const Vector2f& size); void UpdateTarget(const RenderTarget* framebuffer); inline void UpdateTargetRegion(const Rectf& targetRegion); @@ -65,6 +67,7 @@ namespace Nz Recti m_viewport; Vector2f m_size; ViewerInstance m_viewerInstance; + UInt32 m_renderMask; float m_aspectRatio; float m_zFar; float m_zNear; diff --git a/include/Nazara/Graphics/Camera.inl b/include/Nazara/Graphics/Camera.inl index 0aebd05d4..16399ef5a 100644 --- a/include/Nazara/Graphics/Camera.inl +++ b/include/Nazara/Graphics/Camera.inl @@ -14,6 +14,7 @@ namespace Nz m_projectionType(projectionType), m_targetRegion(0.f, 0.f, 1.f, 1.f), m_viewport(0, 0, 0, 0), + m_renderMask(0xFFFFFFFF), m_size(-1.f, -1.f), m_zFar(1000.f), m_zNear(1.f) @@ -27,6 +28,7 @@ namespace Nz m_projectionType(camera.m_projectionType), m_targetRegion(camera.m_targetRegion), m_viewport(camera.m_viewport), + m_renderMask(camera.m_renderMask), m_size(camera.m_size), m_aspectRatio(camera.m_aspectRatio), m_zFar(camera.m_zFar), @@ -41,6 +43,7 @@ namespace Nz m_projectionType(camera.m_projectionType), m_targetRegion(camera.m_targetRegion), m_viewport(camera.m_viewport), + m_renderMask(camera.m_renderMask), m_size(camera.m_size), m_aspectRatio(camera.m_aspectRatio), m_zFar(camera.m_zFar), @@ -137,6 +140,13 @@ namespace Nz UpdateProjectionMatrix(); } + inline void Camera::UpdateRenderMask(UInt32 renderMask) + { + m_renderMask = renderMask; + + // TODO: Signal RenderTechnique to regenerate commandbuffers + } + inline void Camera::UpdateTargetRegion(const Rectf& targetRegion) { m_targetRegion = targetRegion; diff --git a/include/Nazara/Graphics/Components/GraphicsComponent.hpp b/include/Nazara/Graphics/Components/GraphicsComponent.hpp index 612dae985..777a616cb 100644 --- a/include/Nazara/Graphics/Components/GraphicsComponent.hpp +++ b/include/Nazara/Graphics/Components/GraphicsComponent.hpp @@ -19,25 +19,33 @@ namespace Nz class NAZARA_GRAPHICS_API GraphicsComponent { public: + struct Renderable; + GraphicsComponent(); GraphicsComponent(const GraphicsComponent&) = default; GraphicsComponent(GraphicsComponent&&) = default; ~GraphicsComponent() = default; - inline void AttachRenderable(std::shared_ptr renderable); + inline void AttachRenderable(std::shared_ptr renderable, UInt32 renderMask = 0xFFFFFFFF); inline void DetachRenderable(const std::shared_ptr& renderable); - inline const std::vector>& GetRenderables() const; + inline const std::vector& GetRenderables() const; inline const WorldInstancePtr& GetWorldInstance() const; GraphicsComponent& operator=(const GraphicsComponent&) = default; GraphicsComponent& operator=(GraphicsComponent&&) = default; - NazaraSignal(OnRenderableAttached, GraphicsComponent* /*graphicsComponent*/, const std::shared_ptr& /*renderable*/); - NazaraSignal(OnRenderableDetach, GraphicsComponent* /*graphicsComponent*/, const std::shared_ptr& /*renderable*/); + NazaraSignal(OnRenderableAttached, GraphicsComponent* /*graphicsComponent*/, const Renderable& /*renderable*/); + NazaraSignal(OnRenderableDetach, GraphicsComponent* /*graphicsComponent*/, const Renderable& /*renderable*/); + + struct Renderable + { + std::shared_ptr renderable; + UInt32 renderMask; + }; private: - std::vector> m_renderables; + std::vector m_renderables; WorldInstancePtr m_worldInstance; }; } diff --git a/include/Nazara/Graphics/Components/GraphicsComponent.inl b/include/Nazara/Graphics/Components/GraphicsComponent.inl index c1dcffffc..7ef308a0d 100644 --- a/include/Nazara/Graphics/Components/GraphicsComponent.inl +++ b/include/Nazara/Graphics/Components/GraphicsComponent.inl @@ -12,25 +12,27 @@ namespace Nz m_worldInstance = std::make_shared(); //< FIXME: Use pools } - inline void GraphicsComponent::AttachRenderable(std::shared_ptr renderable) + inline void GraphicsComponent::AttachRenderable(std::shared_ptr renderable, UInt32 renderMask) { - m_renderables.push_back(std::move(renderable)); + auto& entry = m_renderables.emplace_back(); + entry.renderable = std::move(renderable); + entry.renderMask = renderMask; OnRenderableAttached(this, m_renderables.back()); } inline void GraphicsComponent::DetachRenderable(const std::shared_ptr& renderable) { - auto it = std::find(m_renderables.begin(), m_renderables.end(), renderable); + auto it = std::find_if(m_renderables.begin(), m_renderables.end(), [&](const auto& renderableEntry) { return renderableEntry.renderable == renderable; }); if (it != m_renderables.end()) { - OnRenderableDetach(this, renderable); + OnRenderableDetach(this, *it); m_renderables.erase(it); } } - inline const std::vector>& GraphicsComponent::GetRenderables() const + inline auto GraphicsComponent::GetRenderables() const -> const std::vector& { return m_renderables; } diff --git a/include/Nazara/Graphics/ForwardFramePipeline.hpp b/include/Nazara/Graphics/ForwardFramePipeline.hpp index f93233090..0458debf9 100644 --- a/include/Nazara/Graphics/ForwardFramePipeline.hpp +++ b/include/Nazara/Graphics/ForwardFramePipeline.hpp @@ -38,7 +38,7 @@ namespace Nz void InvalidateViewer(AbstractViewer* viewerInstance) override; void InvalidateWorldInstance(WorldInstance* worldInstance) override; - void RegisterInstancedDrawable(WorldInstancePtr worldInstance, const InstancedRenderable* instancedRenderable) override; + void RegisterInstancedDrawable(WorldInstancePtr worldInstance, const InstancedRenderable* instancedRenderable, UInt32 renderMask) override; void RegisterViewer(AbstractViewer* viewerInstance) override; void Render(RenderFrame& renderFrame) override; @@ -65,6 +65,8 @@ namespace Nz struct RenderableData { + UInt32 renderMask = 0; + NazaraSlot(InstancedRenderable, OnMaterialInvalidated, onMaterialInvalidated); }; diff --git a/include/Nazara/Graphics/FramePipeline.hpp b/include/Nazara/Graphics/FramePipeline.hpp index 2967fd85c..4cb230390 100644 --- a/include/Nazara/Graphics/FramePipeline.hpp +++ b/include/Nazara/Graphics/FramePipeline.hpp @@ -28,7 +28,7 @@ namespace Nz virtual void InvalidateViewer(AbstractViewer* viewerInstance) = 0; virtual void InvalidateWorldInstance(WorldInstance* worldInstance) = 0; - virtual void RegisterInstancedDrawable(WorldInstancePtr worldInstance, const InstancedRenderable* instancedRenderable) = 0; + virtual void RegisterInstancedDrawable(WorldInstancePtr worldInstance, const InstancedRenderable* instancedRenderable, UInt32 renderMask) = 0; virtual void RegisterViewer(AbstractViewer* viewerInstance) = 0; virtual void Render(RenderFrame& renderFrame) = 0; diff --git a/src/Nazara/Graphics/Camera.cpp b/src/Nazara/Graphics/Camera.cpp index e1c6a3ce2..caa4d7f87 100644 --- a/src/Nazara/Graphics/Camera.cpp +++ b/src/Nazara/Graphics/Camera.cpp @@ -8,6 +8,11 @@ namespace Nz { + UInt32 Camera::GetRenderMask() const + { + return m_renderMask; + } + const RenderTarget& Camera::GetRenderTarget() { if (!m_renderTarget) diff --git a/src/Nazara/Graphics/ForwardFramePipeline.cpp b/src/Nazara/Graphics/ForwardFramePipeline.cpp index 71dacd628..52be3a011 100644 --- a/src/Nazara/Graphics/ForwardFramePipeline.cpp +++ b/src/Nazara/Graphics/ForwardFramePipeline.cpp @@ -46,7 +46,7 @@ namespace Nz m_invalidatedWorldInstances.insert(worldInstance); } - void ForwardFramePipeline::RegisterInstancedDrawable(WorldInstancePtr worldInstance, const InstancedRenderable* instancedRenderable) + void ForwardFramePipeline::RegisterInstancedDrawable(WorldInstancePtr worldInstance, const InstancedRenderable* instancedRenderable, UInt32 renderMask) { m_removedWorldInstances.erase(worldInstance); @@ -57,6 +57,8 @@ namespace Nz if (auto it = renderableMap.find(instancedRenderable); it == renderableMap.end()) { auto& renderableData = renderableMap.emplace(instancedRenderable, RenderableData{}).first->second; + renderableData.renderMask = renderMask; + renderableData.onMaterialInvalidated.Connect(instancedRenderable->OnMaterialInvalidated, [this](InstancedRenderable* instancedRenderable, std::size_t materialIndex, const std::shared_ptr& newMaterial) { if (newMaterial) @@ -100,8 +102,11 @@ namespace Nz for (auto&& [viewer, viewerData] : m_viewers) { - viewerData.rebuildDepthPrepass = true; - viewerData.rebuildForwardPass = true; + if (viewer->GetRenderMask() & renderMask) + { + viewerData.rebuildDepthPrepass = true; + viewerData.rebuildForwardPass = true; + } } } } @@ -178,6 +183,8 @@ namespace Nz { auto& viewerData = data; + UInt32 renderMask = viewer->GetRenderMask(); + // Frustum culling const Matrix4f& viewProjMatrix = viewer->GetViewerInstance().GetViewProjMatrix(); @@ -192,6 +199,9 @@ namespace Nz for (const auto& [renderable, renderableData] : renderables) { + if (renderMask & renderableData.renderMask == 0) + continue; + // Get global AABB BoundingVolumef boundingVolume(renderable->GetAABB()); boundingVolume.Update(worldInstance->GetWorldMatrix()); diff --git a/src/Nazara/Graphics/Systems/RenderSystem.cpp b/src/Nazara/Graphics/Systems/RenderSystem.cpp index 9dff25bca..ce99e52a5 100644 --- a/src/Nazara/Graphics/Systems/RenderSystem.cpp +++ b/src/Nazara/Graphics/Systems/RenderSystem.cpp @@ -61,8 +61,8 @@ namespace Nz NodeComponent& entityNode = registry.get(entity); const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance(); - for (const auto& renderable : entityGfx.GetRenderables()) - m_pipeline->RegisterInstancedDrawable(worldInstance, renderable.get()); + for (const auto& renderableEntry : entityGfx.GetRenderables()) + m_pipeline->RegisterInstancedDrawable(worldInstance, renderableEntry.renderable.get(), renderableEntry.renderMask); m_invalidatedWorldNode.insert(entity); @@ -73,16 +73,16 @@ namespace Nz m_invalidatedWorldNode.insert(entity); }); - graphicsEntity.onRenderableAttached.Connect(entityGfx.OnRenderableAttached, [this](GraphicsComponent* gfx, const std::shared_ptr& renderable) + graphicsEntity.onRenderableAttached.Connect(entityGfx.OnRenderableAttached, [this](GraphicsComponent* gfx, const GraphicsComponent::Renderable& renderableEntry) { const WorldInstancePtr& worldInstance = gfx->GetWorldInstance(); - m_pipeline->RegisterInstancedDrawable(worldInstance, renderable.get()); + m_pipeline->RegisterInstancedDrawable(worldInstance, renderableEntry.renderable.get(), renderableEntry.renderMask); }); - graphicsEntity.onRenderableDetach.Connect(entityGfx.OnRenderableDetach, [this](GraphicsComponent* gfx, const std::shared_ptr& renderable) + graphicsEntity.onRenderableDetach.Connect(entityGfx.OnRenderableDetach, [this](GraphicsComponent* gfx, const GraphicsComponent::Renderable& renderableEntry) { const WorldInstancePtr& worldInstance = gfx->GetWorldInstance(); - m_pipeline->UnregisterInstancedDrawable(worldInstance, renderable.get()); + m_pipeline->UnregisterInstancedDrawable(worldInstance, renderableEntry.renderable.get()); }); }); @@ -107,8 +107,8 @@ namespace Nz GraphicsComponent& entityGfx = registry.get(entity); const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance(); - for (const auto& renderable : entityGfx.GetRenderables()) - m_pipeline->UnregisterInstancedDrawable(worldInstance, renderable.get()); + for (const auto& renderableEntry : entityGfx.GetRenderables()) + m_pipeline->UnregisterInstancedDrawable(worldInstance, renderableEntry.renderable.get()); } void RenderSystem::OnNodeDestroy(entt::registry& registry, entt::entity entity)