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);
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<Nz::LabelWidget>();
//labelWidget->EnableBackground(true);
labelWidget->UpdateText(Nz::SimpleTextDrawer::Draw("Bonjour Paris !", 72), 0.1f);
entt::entity viewer2D = registry2D.create();
registry2D.emplace<Nz::NodeComponent>(viewer2D);
registry2D.emplace<Nz::CameraComponent>(viewer2D, window.GetRenderTarget(), Nz::ProjectionType::Orthographic);
/*entt::entity viewer2D = registry.create();
{
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();
registry2D.emplace<Nz::GraphicsComponent>(text2D).AttachRenderable(sprite);
registry2D.emplace<Nz::NodeComponent>(text2D).SetPosition(Nz::Vector3f(0.f, 200.f, 0.f));
entt::entity text2D = registry.create();
{
registry.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();
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);
@ -187,7 +193,6 @@ int main()
colliderModel->SetMaterial(i, colliderMat);
}
entt::entity textEntity = registry.create();
{
auto& entityGfx = registry.emplace<Nz::GraphicsComponent>(textEntity);
@ -201,7 +206,7 @@ int main()
entt::entity headingEntity = registry.create();
{
auto& entityGfx = registry.emplace<Nz::GraphicsComponent>(playerEntity);
entityGfx.AttachRenderable(model);
entityGfx.AttachRenderable(model, 1);
auto& entityNode = registry.emplace<Nz::NodeComponent>(playerEntity);
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).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<Nz::GraphicsComponent>(entity);
entityGfx.AttachRenderable(model);
entityGfx.AttachRenderable(model, 1);
//entityGfx.AttachRenderable(sprite);
auto& entityNode = registry.emplace<Nz::NodeComponent>(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<Nz::NodeComponent, Nz::RigidBody3DComponent>();
@ -392,7 +395,6 @@ int main()
continue;
renderSystem.Render(registry, frame);
//renderSystem2D.Render(registry2D, frame);
frame.Present();

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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<InstancedRenderable> renderable);
inline void AttachRenderable(std::shared_ptr<InstancedRenderable> renderable, UInt32 renderMask = 0xFFFFFFFF);
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;
GraphicsComponent& operator=(const GraphicsComponent&) = default;
GraphicsComponent& operator=(GraphicsComponent&&) = default;
NazaraSignal(OnRenderableAttached, GraphicsComponent* /*graphicsComponent*/, const std::shared_ptr<InstancedRenderable>& /*renderable*/);
NazaraSignal(OnRenderableDetach, GraphicsComponent* /*graphicsComponent*/, const std::shared_ptr<InstancedRenderable>& /*renderable*/);
NazaraSignal(OnRenderableAttached, GraphicsComponent* /*graphicsComponent*/, const Renderable& /*renderable*/);
NazaraSignal(OnRenderableDetach, GraphicsComponent* /*graphicsComponent*/, const Renderable& /*renderable*/);
struct Renderable
{
std::shared_ptr<InstancedRenderable> renderable;
UInt32 renderMask;
};
private:
std::vector<std::shared_ptr<InstancedRenderable>> m_renderables;
std::vector<Renderable> m_renderables;
WorldInstancePtr m_worldInstance;
};
}

View File

@ -12,25 +12,27 @@ namespace Nz
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());
}
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())
{
OnRenderableDetach(this, renderable);
OnRenderableDetach(this, *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;
}

View File

@ -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);
};

View File

@ -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;

View File

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

View File

@ -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<Material>& 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());

View File

@ -61,8 +61,8 @@ namespace Nz
NodeComponent& entityNode = registry.get<NodeComponent>(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<InstancedRenderable>& 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<InstancedRenderable>& 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<GraphicsComponent>(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)