Graphics: Add RenderMask (WIP)

This commit is contained in:
Jérôme Leclercq 2021-10-29 16:50:38 +02:00
parent 078060cfc9
commit 9e1df33440
11 changed files with 87 additions and 44 deletions

View File

@ -140,29 +140,35 @@ int main()
Nz::SparsePtr<Nz::Vector3f> vertices = vertexMapper.GetComponentPtr<Nz::Vector3f>(Nz::VertexComponent::Position); Nz::SparsePtr<Nz::Vector3f> vertices = vertexMapper.GetComponentPtr<Nz::Vector3f>(Nz::VertexComponent::Position);
entt::registry registry; entt::registry registry;
entt::registry registry2D;
Nz::Physics3DSystem physSytem(registry); Nz::Physics3DSystem physSytem(registry);
Nz::RenderSystem renderSystem(registry); Nz::RenderSystem renderSystem(registry);
Nz::RenderSystem renderSystem2D(registry2D);
Nz::Canvas canvas(registry, window.GetEventHandler(), window.GetCursorController().CreateHandle()); Nz::Canvas canvas(registry, window.GetEventHandler(), window.GetCursorController().CreateHandle());
Nz::LabelWidget* labelWidget = canvas.Add<Nz::LabelWidget>(); Nz::LabelWidget* labelWidget = canvas.Add<Nz::LabelWidget>();
//labelWidget->EnableBackground(true); //labelWidget->EnableBackground(true);
labelWidget->UpdateText(Nz::SimpleTextDrawer::Draw("Bonjour Paris !", 72), 0.1f); labelWidget->UpdateText(Nz::SimpleTextDrawer::Draw("Bonjour Paris !", 72), 0.1f);
entt::entity viewer2D = registry2D.create(); /*entt::entity viewer2D = registry.create();
registry2D.emplace<Nz::NodeComponent>(viewer2D); {
registry2D.emplace<Nz::CameraComponent>(viewer2D, window.GetRenderTarget(), Nz::ProjectionType::Orthographic); registry.emplace<Nz::NodeComponent>(viewer2D);
auto& cameraComponent = registry.emplace<Nz::CameraComponent>(viewer2D, window.GetRenderTarget(), Nz::ProjectionType::Orthographic);
cameraComponent.UpdateRenderMask(2);
}*/
entt::entity text2D = registry2D.create(); entt::entity text2D = registry.create();
{
registry2D.emplace<Nz::GraphicsComponent>(text2D).AttachRenderable(sprite); registry.emplace<Nz::NodeComponent>(text2D).SetPosition(Nz::Vector3f(0.f, 200.f, 0.f));
registry2D.emplace<Nz::NodeComponent>(text2D).SetPosition(Nz::Vector3f(0.f, 200.f, 0.f)); auto& gfxComponent = registry.emplace<Nz::GraphicsComponent>(text2D);
gfxComponent.AttachRenderable(sprite, 2);
}
entt::entity viewer = registry.create(); entt::entity viewer = registry.create();
registry.emplace<Nz::NodeComponent>(viewer); {
registry.emplace<Nz::CameraComponent>(viewer, window.GetRenderTarget()); registry.emplace<Nz::NodeComponent>(viewer);
auto& cameraComponent = registry.emplace<Nz::CameraComponent>(viewer, window.GetRenderTarget());
cameraComponent.UpdateRenderMask(1);
}
auto shipCollider = std::make_shared<Nz::ConvexCollider3D>(vertices, vertexMapper.GetVertexCount(), 0.01f); auto shipCollider = std::make_shared<Nz::ConvexCollider3D>(vertices, vertexMapper.GetVertexCount(), 0.01f);
@ -187,7 +193,6 @@ int main()
colliderModel->SetMaterial(i, colliderMat); colliderModel->SetMaterial(i, colliderMat);
} }
entt::entity textEntity = registry.create(); entt::entity textEntity = registry.create();
{ {
auto& entityGfx = registry.emplace<Nz::GraphicsComponent>(textEntity); auto& entityGfx = registry.emplace<Nz::GraphicsComponent>(textEntity);
@ -201,7 +206,7 @@ int main()
entt::entity headingEntity = registry.create(); entt::entity headingEntity = registry.create();
{ {
auto& entityGfx = registry.emplace<Nz::GraphicsComponent>(playerEntity); auto& entityGfx = registry.emplace<Nz::GraphicsComponent>(playerEntity);
entityGfx.AttachRenderable(model); entityGfx.AttachRenderable(model, 1);
auto& entityNode = registry.emplace<Nz::NodeComponent>(playerEntity); auto& entityNode = registry.emplace<Nz::NodeComponent>(playerEntity);
entityNode.SetPosition(Nz::Vector3f(12.5f, 0.f, 25.f)); entityNode.SetPosition(Nz::Vector3f(12.5f, 0.f, 25.f));
@ -218,15 +223,15 @@ int main()
registry.get<Nz::NodeComponent>(viewer).SetParent(registry, headingEntity); registry.get<Nz::NodeComponent>(viewer).SetParent(registry, headingEntity);
registry.get<Nz::NodeComponent>(viewer).SetPosition(Nz::Vector3f::Backward() * 2.5f + Nz::Vector3f::Up() * 1.f); registry.get<Nz::NodeComponent>(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(); entt::entity entity = registry.create();
auto& entityGfx = registry.emplace<Nz::GraphicsComponent>(entity); auto& entityGfx = registry.emplace<Nz::GraphicsComponent>(entity);
entityGfx.AttachRenderable(model); entityGfx.AttachRenderable(model, 1);
//entityGfx.AttachRenderable(sprite); //entityGfx.AttachRenderable(sprite);
auto& entityNode = registry.emplace<Nz::NodeComponent>(entity); auto& entityNode = registry.emplace<Nz::NodeComponent>(entity);
@ -249,7 +254,7 @@ int main()
Nz::Clock secondClock; Nz::Clock secondClock;
unsigned int fps = 0; unsigned int fps = 0;
Nz::Mouse::SetRelativeMouseMode(true); //Nz::Mouse::SetRelativeMouseMode(true);
float elapsedTime = 0.f; float elapsedTime = 0.f;
Nz::UInt64 time = Nz::GetElapsedMicroseconds(); Nz::UInt64 time = Nz::GetElapsedMicroseconds();
@ -337,8 +342,6 @@ int main()
{ {
float updateTime = updateClock.Restart() / 1'000'000.f; float updateTime = updateClock.Restart() / 1'000'000.f;
float cameraSpeed = 20.f * updateTime;
physSytem.Update(registry, 1000.f / 60.f); physSytem.Update(registry, 1000.f / 60.f);
auto spaceshipView = registry.view<Nz::NodeComponent, Nz::RigidBody3DComponent>(); auto spaceshipView = registry.view<Nz::NodeComponent, Nz::RigidBody3DComponent>();
@ -392,7 +395,6 @@ int main()
continue; continue;
renderSystem.Render(registry, frame); renderSystem.Render(registry, frame);
//renderSystem2D.Render(registry2D, frame);
frame.Present(); frame.Present();

View File

@ -22,6 +22,7 @@ namespace Nz
AbstractViewer() = default; AbstractViewer() = default;
~AbstractViewer() = default; ~AbstractViewer() = default;
virtual UInt32 GetRenderMask() const = 0;
virtual const RenderTarget& GetRenderTarget() = 0; virtual const RenderTarget& GetRenderTarget() = 0;
virtual ViewerInstance& GetViewerInstance() = 0; virtual ViewerInstance& GetViewerInstance() = 0;
virtual const ViewerInstance& GetViewerInstance() const = 0; virtual const ViewerInstance& GetViewerInstance() const = 0;

View File

@ -29,6 +29,7 @@ namespace Nz
inline float GetAspectRatio() const; inline float GetAspectRatio() const;
inline DegreeAnglef GetFOV() const; inline DegreeAnglef GetFOV() const;
UInt32 GetRenderMask() const override;
const RenderTarget& GetRenderTarget() override; const RenderTarget& GetRenderTarget() override;
inline const Vector2f& GetSize() const; inline const Vector2f& GetSize() const;
inline const Rectf& GetTargetRegion() const; inline const Rectf& GetTargetRegion() const;
@ -40,6 +41,7 @@ namespace Nz
inline void UpdateFOV(DegreeAnglef fov); inline void UpdateFOV(DegreeAnglef fov);
inline void UpdateProjectionType(ProjectionType projectionType); inline void UpdateProjectionType(ProjectionType projectionType);
inline void UpdateRenderMask(UInt32 renderMask);
inline void UpdateSize(const Vector2f& size); inline void UpdateSize(const Vector2f& size);
void UpdateTarget(const RenderTarget* framebuffer); void UpdateTarget(const RenderTarget* framebuffer);
inline void UpdateTargetRegion(const Rectf& targetRegion); inline void UpdateTargetRegion(const Rectf& targetRegion);
@ -65,6 +67,7 @@ namespace Nz
Recti m_viewport; Recti m_viewport;
Vector2f m_size; Vector2f m_size;
ViewerInstance m_viewerInstance; ViewerInstance m_viewerInstance;
UInt32 m_renderMask;
float m_aspectRatio; float m_aspectRatio;
float m_zFar; float m_zFar;
float m_zNear; float m_zNear;

View File

@ -14,6 +14,7 @@ namespace Nz
m_projectionType(projectionType), m_projectionType(projectionType),
m_targetRegion(0.f, 0.f, 1.f, 1.f), m_targetRegion(0.f, 0.f, 1.f, 1.f),
m_viewport(0, 0, 0, 0), m_viewport(0, 0, 0, 0),
m_renderMask(0xFFFFFFFF),
m_size(-1.f, -1.f), m_size(-1.f, -1.f),
m_zFar(1000.f), m_zFar(1000.f),
m_zNear(1.f) m_zNear(1.f)
@ -27,6 +28,7 @@ namespace Nz
m_projectionType(camera.m_projectionType), m_projectionType(camera.m_projectionType),
m_targetRegion(camera.m_targetRegion), m_targetRegion(camera.m_targetRegion),
m_viewport(camera.m_viewport), m_viewport(camera.m_viewport),
m_renderMask(camera.m_renderMask),
m_size(camera.m_size), m_size(camera.m_size),
m_aspectRatio(camera.m_aspectRatio), m_aspectRatio(camera.m_aspectRatio),
m_zFar(camera.m_zFar), m_zFar(camera.m_zFar),
@ -41,6 +43,7 @@ namespace Nz
m_projectionType(camera.m_projectionType), m_projectionType(camera.m_projectionType),
m_targetRegion(camera.m_targetRegion), m_targetRegion(camera.m_targetRegion),
m_viewport(camera.m_viewport), m_viewport(camera.m_viewport),
m_renderMask(camera.m_renderMask),
m_size(camera.m_size), m_size(camera.m_size),
m_aspectRatio(camera.m_aspectRatio), m_aspectRatio(camera.m_aspectRatio),
m_zFar(camera.m_zFar), m_zFar(camera.m_zFar),
@ -137,6 +140,13 @@ namespace Nz
UpdateProjectionMatrix(); UpdateProjectionMatrix();
} }
inline void Camera::UpdateRenderMask(UInt32 renderMask)
{
m_renderMask = renderMask;
// TODO: Signal RenderTechnique to regenerate commandbuffers
}
inline void Camera::UpdateTargetRegion(const Rectf& targetRegion) inline void Camera::UpdateTargetRegion(const Rectf& targetRegion)
{ {
m_targetRegion = targetRegion; m_targetRegion = targetRegion;

View File

@ -19,25 +19,33 @@ namespace Nz
class NAZARA_GRAPHICS_API GraphicsComponent class NAZARA_GRAPHICS_API GraphicsComponent
{ {
public: public:
struct Renderable;
GraphicsComponent(); GraphicsComponent();
GraphicsComponent(const GraphicsComponent&) = default; GraphicsComponent(const GraphicsComponent&) = default;
GraphicsComponent(GraphicsComponent&&) = default; GraphicsComponent(GraphicsComponent&&) = default;
~GraphicsComponent() = default; ~GraphicsComponent() = default;
inline void AttachRenderable(std::shared_ptr<InstancedRenderable> renderable); inline void AttachRenderable(std::shared_ptr<InstancedRenderable> renderable, UInt32 renderMask = 0xFFFFFFFF);
inline void DetachRenderable(const std::shared_ptr<InstancedRenderable>& renderable); inline void DetachRenderable(const std::shared_ptr<InstancedRenderable>& renderable);
inline const std::vector<std::shared_ptr<InstancedRenderable>>& GetRenderables() const; inline const std::vector<Renderable>& GetRenderables() const;
inline const WorldInstancePtr& GetWorldInstance() const; inline const WorldInstancePtr& GetWorldInstance() const;
GraphicsComponent& operator=(const GraphicsComponent&) = default; GraphicsComponent& operator=(const GraphicsComponent&) = default;
GraphicsComponent& operator=(GraphicsComponent&&) = default; GraphicsComponent& operator=(GraphicsComponent&&) = default;
NazaraSignal(OnRenderableAttached, GraphicsComponent* /*graphicsComponent*/, const std::shared_ptr<InstancedRenderable>& /*renderable*/); NazaraSignal(OnRenderableAttached, GraphicsComponent* /*graphicsComponent*/, const Renderable& /*renderable*/);
NazaraSignal(OnRenderableDetach, GraphicsComponent* /*graphicsComponent*/, const std::shared_ptr<InstancedRenderable>& /*renderable*/); NazaraSignal(OnRenderableDetach, GraphicsComponent* /*graphicsComponent*/, const Renderable& /*renderable*/);
struct Renderable
{
std::shared_ptr<InstancedRenderable> renderable;
UInt32 renderMask;
};
private: private:
std::vector<std::shared_ptr<InstancedRenderable>> m_renderables; std::vector<Renderable> m_renderables;
WorldInstancePtr m_worldInstance; WorldInstancePtr m_worldInstance;
}; };
} }

View File

@ -12,25 +12,27 @@ namespace Nz
m_worldInstance = std::make_shared<WorldInstance>(); //< FIXME: Use pools m_worldInstance = std::make_shared<WorldInstance>(); //< FIXME: Use pools
} }
inline void GraphicsComponent::AttachRenderable(std::shared_ptr<InstancedRenderable> renderable) inline void GraphicsComponent::AttachRenderable(std::shared_ptr<InstancedRenderable> 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()); OnRenderableAttached(this, m_renderables.back());
} }
inline void GraphicsComponent::DetachRenderable(const std::shared_ptr<InstancedRenderable>& renderable) inline void GraphicsComponent::DetachRenderable(const std::shared_ptr<InstancedRenderable>& 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()) if (it != m_renderables.end())
{ {
OnRenderableDetach(this, renderable); OnRenderableDetach(this, *it);
m_renderables.erase(it); m_renderables.erase(it);
} }
} }
inline const std::vector<std::shared_ptr<InstancedRenderable>>& GraphicsComponent::GetRenderables() const inline auto GraphicsComponent::GetRenderables() const -> const std::vector<Renderable>&
{ {
return m_renderables; return m_renderables;
} }

View File

@ -38,7 +38,7 @@ namespace Nz
void InvalidateViewer(AbstractViewer* viewerInstance) override; void InvalidateViewer(AbstractViewer* viewerInstance) override;
void InvalidateWorldInstance(WorldInstance* worldInstance) 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 RegisterViewer(AbstractViewer* viewerInstance) override;
void Render(RenderFrame& renderFrame) override; void Render(RenderFrame& renderFrame) override;
@ -65,6 +65,8 @@ namespace Nz
struct RenderableData struct RenderableData
{ {
UInt32 renderMask = 0;
NazaraSlot(InstancedRenderable, OnMaterialInvalidated, onMaterialInvalidated); NazaraSlot(InstancedRenderable, OnMaterialInvalidated, onMaterialInvalidated);
}; };

View File

@ -28,7 +28,7 @@ namespace Nz
virtual void InvalidateViewer(AbstractViewer* viewerInstance) = 0; virtual void InvalidateViewer(AbstractViewer* viewerInstance) = 0;
virtual void InvalidateWorldInstance(WorldInstance* worldInstance) = 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 RegisterViewer(AbstractViewer* viewerInstance) = 0;
virtual void Render(RenderFrame& renderFrame) = 0; virtual void Render(RenderFrame& renderFrame) = 0;

View File

@ -8,6 +8,11 @@
namespace Nz namespace Nz
{ {
UInt32 Camera::GetRenderMask() const
{
return m_renderMask;
}
const RenderTarget& Camera::GetRenderTarget() const RenderTarget& Camera::GetRenderTarget()
{ {
if (!m_renderTarget) if (!m_renderTarget)

View File

@ -46,7 +46,7 @@ namespace Nz
m_invalidatedWorldInstances.insert(worldInstance); 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); m_removedWorldInstances.erase(worldInstance);
@ -57,6 +57,8 @@ namespace Nz
if (auto it = renderableMap.find(instancedRenderable); it == renderableMap.end()) if (auto it = renderableMap.find(instancedRenderable); it == renderableMap.end())
{ {
auto& renderableData = renderableMap.emplace(instancedRenderable, RenderableData{}).first->second; 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<Material>& newMaterial) renderableData.onMaterialInvalidated.Connect(instancedRenderable->OnMaterialInvalidated, [this](InstancedRenderable* instancedRenderable, std::size_t materialIndex, const std::shared_ptr<Material>& newMaterial)
{ {
if (newMaterial) if (newMaterial)
@ -100,8 +102,11 @@ namespace Nz
for (auto&& [viewer, viewerData] : m_viewers) for (auto&& [viewer, viewerData] : m_viewers)
{ {
viewerData.rebuildDepthPrepass = true; if (viewer->GetRenderMask() & renderMask)
viewerData.rebuildForwardPass = true; {
viewerData.rebuildDepthPrepass = true;
viewerData.rebuildForwardPass = true;
}
} }
} }
} }
@ -178,6 +183,8 @@ namespace Nz
{ {
auto& viewerData = data; auto& viewerData = data;
UInt32 renderMask = viewer->GetRenderMask();
// Frustum culling // Frustum culling
const Matrix4f& viewProjMatrix = viewer->GetViewerInstance().GetViewProjMatrix(); const Matrix4f& viewProjMatrix = viewer->GetViewerInstance().GetViewProjMatrix();
@ -192,6 +199,9 @@ namespace Nz
for (const auto& [renderable, renderableData] : renderables) for (const auto& [renderable, renderableData] : renderables)
{ {
if (renderMask & renderableData.renderMask == 0)
continue;
// Get global AABB // Get global AABB
BoundingVolumef boundingVolume(renderable->GetAABB()); BoundingVolumef boundingVolume(renderable->GetAABB());
boundingVolume.Update(worldInstance->GetWorldMatrix()); boundingVolume.Update(worldInstance->GetWorldMatrix());

View File

@ -61,8 +61,8 @@ namespace Nz
NodeComponent& entityNode = registry.get<NodeComponent>(entity); NodeComponent& entityNode = registry.get<NodeComponent>(entity);
const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance(); const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance();
for (const auto& renderable : entityGfx.GetRenderables()) for (const auto& renderableEntry : entityGfx.GetRenderables())
m_pipeline->RegisterInstancedDrawable(worldInstance, renderable.get()); m_pipeline->RegisterInstancedDrawable(worldInstance, renderableEntry.renderable.get(), renderableEntry.renderMask);
m_invalidatedWorldNode.insert(entity); m_invalidatedWorldNode.insert(entity);
@ -73,16 +73,16 @@ namespace Nz
m_invalidatedWorldNode.insert(entity); m_invalidatedWorldNode.insert(entity);
}); });
graphicsEntity.onRenderableAttached.Connect(entityGfx.OnRenderableAttached, [this](GraphicsComponent* gfx, const std::shared_ptr<InstancedRenderable>& renderable) graphicsEntity.onRenderableAttached.Connect(entityGfx.OnRenderableAttached, [this](GraphicsComponent* gfx, const GraphicsComponent::Renderable& renderableEntry)
{ {
const WorldInstancePtr& worldInstance = gfx->GetWorldInstance(); 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<InstancedRenderable>& renderable) graphicsEntity.onRenderableDetach.Connect(entityGfx.OnRenderableDetach, [this](GraphicsComponent* gfx, const GraphicsComponent::Renderable& renderableEntry)
{ {
const WorldInstancePtr& worldInstance = gfx->GetWorldInstance(); 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<GraphicsComponent>(entity); GraphicsComponent& entityGfx = registry.get<GraphicsComponent>(entity);
const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance(); const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance();
for (const auto& renderable : entityGfx.GetRenderables()) for (const auto& renderableEntry : entityGfx.GetRenderables())
m_pipeline->UnregisterInstancedDrawable(worldInstance, renderable.get()); m_pipeline->UnregisterInstancedDrawable(worldInstance, renderableEntry.renderable.get());
} }
void RenderSystem::OnNodeDestroy(entt::registry& registry, entt::entity entity) void RenderSystem::OnNodeDestroy(entt::registry& registry, entt::entity entity)