New Render queues (#161)

* Add new render queues proof of concept + scissoring support (WIP)

* Graphics: Adapt basic sprites rendering to new render queue system

* Graphics: Fix layers when rendering sprites

* Graphics/RenderQueue: Fix sprite default overlay

* Graphics: Enable scissor test by default

* SDK/Widgets: Enable scissoring on widgets

* Graphics: Handle almost everything with the new renderqueues system

Todo:
- Billboard rendering
- Proper model rendering

* Graphics/RenderQueue: Billboard drawing now works (WIP)

At 1/4 of previous code performances due to individually process of billboards

* Add new render queues proof of concept + scissoring support (WIP)

* Graphics: Adapt basic sprites rendering to new render queue system

* Graphics: Fix layers when rendering sprites

* Graphics/RenderQueue: Fix sprite default overlay

* Graphics: Enable scissor test by default

* SDK/Widgets: Enable scissoring on widgets

* Graphics: Handle almost everything with the new renderqueues system

Todo:
- Billboard rendering
- Proper model rendering

* Graphics/RenderQueue: Billboard drawing now works (WIP)

At 1/4 of previous code performances due to individually process of billboards

* Graphics/RenderQueues: Add full support for billboards

* Graphics/RenderQueue: Cleanup and improve billboard rendering

* Graphics/RenderQueue: Fix model drawing

* Examples/Particles: Fix lighting on space station

* Graphics: Cleanup forward render queue/technique

* Fix compilation under Linux

* Graphics/ForwardRenderTechnique: Fix case when scissoring is enabled on material but disabled on element

* Add support for Deferred Shading

* SDK/Widgets: Fix widget rendering

* Graphics: Remove legacy code from render queues

* Graphics: Fix some objects sometimes not showing up due to broken scissor box

* Fix compilation error

* Sdk/GraphicsGraphics: Fix bounding volume

* SDK/World: Fix self-assignation

* Update changelog for render queues
This commit is contained in:
Jérôme Leclercq
2018-04-11 19:36:52 +02:00
committed by GitHub
parent 14248bb6c6
commit 2da086b7df
65 changed files with 3290 additions and 2998 deletions

View File

@@ -83,9 +83,10 @@ namespace Ndk
};
protected:
const EntityHandle& CreateEntity();
const EntityHandle& CreateEntity(bool isContentEntity);
void DestroyEntity(Entity* entity);
virtual void Layout();
void InvalidateNode() override;
virtual bool IsFocusable() const;
@@ -111,11 +112,18 @@ namespace Ndk
void RegisterToCanvas();
inline void UpdateCanvasIndex(std::size_t index);
void UnregisterFromCanvas();
void UpdatePositionAndSize();
struct WidgetEntity
{
EntityOwner handle;
bool isContent;
};
static constexpr std::size_t InvalidCanvasIndex = std::numeric_limits<std::size_t>::max();
std::size_t m_canvasIndex;
std::vector<EntityOwner> m_entities;
std::vector<WidgetEntity> m_entities;
std::vector<std::unique_ptr<BaseWidget>> m_children;
Canvas* m_canvas;
EntityOwner m_backgroundEntity;

View File

@@ -62,7 +62,7 @@ namespace Ndk
WidgetEntry& entry = m_widgetEntries[index];
Nz::Vector3f pos = entry.widget->GetPosition();
Nz::Vector2f size = entry.widget->GetContentSize();
Nz::Vector2f size = entry.widget->GetSize();
entry.box.Set(pos.x, pos.y, pos.z, size.x, size.y, 1.f);
}

View File

@@ -28,7 +28,7 @@ namespace Ndk
public:
using RenderableList = std::vector<Nz::InstancedRenderableRef>;
GraphicsComponent() = default;
GraphicsComponent();
inline GraphicsComponent(const GraphicsComponent& graphicsComponent);
~GraphicsComponent() = default;
@@ -54,6 +54,8 @@ namespace Ndk
inline void RemoveFromCullingList(GraphicsComponentCullingList* cullingList) const;
inline void SetScissorRect(const Nz::Recti& scissorRect);
inline void UpdateLocalMatrix(const Nz::InstancedRenderable* instancedRenderable, const Nz::Matrix4f& localMatrix);
inline void UpdateRenderOrder(const Nz::InstancedRenderable* instancedRenderable, int renderOrder);
@@ -144,6 +146,7 @@ namespace Ndk
std::unordered_map<const Nz::Material*, MaterialEntry> m_materialEntries;
mutable Nz::BoundingVolumef m_boundingVolume;
mutable Nz::Matrix4f m_transformMatrix;
Nz::Recti m_scissorRect;
Nz::TextureRef m_reflectionMap;
mutable bool m_boundingVolumeUpdated;
mutable bool m_transformMatrixUpdated;

View File

@@ -9,12 +9,16 @@
namespace Ndk
{
inline GraphicsComponent::GraphicsComponent() :
m_scissorRect(-1, -1)
{
}
/*!
* \brief Constructs a GraphicsComponent object by copy semantic
*
* \param graphicsComponent GraphicsComponent to copy
*/
inline GraphicsComponent::GraphicsComponent(const GraphicsComponent& graphicsComponent) :
Component(graphicsComponent),
HandledObject(graphicsComponent),
@@ -177,6 +181,14 @@ namespace Ndk
}
}
inline void GraphicsComponent::SetScissorRect(const Nz::Recti& scissorRect)
{
m_scissorRect = scissorRect;
for (VolumeCullingEntry& entry : m_volumeCullingEntries)
entry.listEntry.ForceInvalidation(); //< Invalidate render queues
}
inline void GraphicsComponent::UpdateLocalMatrix(const Nz::InstancedRenderable* instancedRenderable, const Nz::Matrix4f& localMatrix)
{
for (auto& renderable : m_renderables)

View File

@@ -28,7 +28,7 @@ namespace Ndk
//virtual LabelWidget* Clone() const = 0;
void ResizeToContent();
void ResizeToContent() override;
inline void UpdateText(const Nz::AbstractTextDrawer& drawer);
@@ -36,6 +36,8 @@ namespace Ndk
LabelWidget& operator=(LabelWidget&&) = default;
private:
void Layout() override;
EntityHandle m_textEntity;
Nz::TextSpriteRef m_textSprite;
};

View File

@@ -426,7 +426,7 @@ namespace Ndk
m_orderedSystems = std::move(world.m_orderedSystems);
m_orderedSystemsUpdated = world.m_orderedSystemsUpdated;
m_profilerData = std::move(world.m_profilerData);
m_isProfilerEnabled = m_isProfilerEnabled;
m_isProfilerEnabled = world.m_isProfilerEnabled;
m_entities = std::move(world.m_entities);
for (EntityBlock& block : m_entities)

View File

@@ -81,7 +81,7 @@ namespace Ndk
m_backgroundSprite->SetColor(m_backgroundColor);
m_backgroundSprite->SetMaterial(Nz::Material::New((m_backgroundColor.IsOpaque()) ? "Basic2D" : "Translucent2D")); //< TODO: Use a shared material instead of creating one everytime
m_backgroundEntity = CreateEntity();
m_backgroundEntity = CreateEntity(false);
m_backgroundEntity->AddComponent<GraphicsComponent>().Attach(m_backgroundSprite, -1);
m_backgroundEntity->AddComponent<NodeComponent>().SetParent(this);
@@ -147,26 +147,30 @@ namespace Ndk
else
UnregisterFromCanvas();
for (const EntityHandle& entity : m_entities)
entity->Enable(show);
for (WidgetEntity& entity : m_entities)
entity.handle->Enable(show);
for (const auto& widgetPtr : m_children)
widgetPtr->Show(show);
}
}
const Ndk::EntityHandle& BaseWidget::CreateEntity()
const Ndk::EntityHandle& BaseWidget::CreateEntity(bool isContentEntity)
{
const EntityHandle& newEntity = m_world->CreateEntity();
newEntity->Enable(m_visible);
m_entities.emplace_back(newEntity);
m_entities.emplace_back();
WidgetEntity& widgetEntity = m_entities.back();
widgetEntity.handle = newEntity;
widgetEntity.isContent = isContentEntity;
return newEntity;
}
void BaseWidget::DestroyEntity(Entity* entity)
{
auto it = std::find(m_entities.begin(), m_entities.end(), entity);
auto it = std::find_if(m_entities.begin(), m_entities.end(), [&](const WidgetEntity& widgetEntity) { return widgetEntity.handle == entity; });
NazaraAssert(it != m_entities.end(), "Entity does not belong to this widget");
m_entities.erase(it);
@@ -174,19 +178,17 @@ namespace Ndk
void BaseWidget::Layout()
{
if (IsRegisteredToCanvas())
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
if (m_backgroundEntity)
m_backgroundSprite->SetSize(m_contentSize.x + m_padding.left + m_padding.right, m_contentSize.y + m_padding.top + m_padding.bottom);
UpdatePositionAndSize();
}
void BaseWidget::InvalidateNode()
{
Node::InvalidateNode();
if (IsRegisteredToCanvas())
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
UpdatePositionAndSize();
}
bool BaseWidget::IsFocusable() const
@@ -271,4 +273,25 @@ namespace Ndk
m_canvasIndex = InvalidCanvasIndex;
}
}
void BaseWidget::UpdatePositionAndSize()
{
if (IsRegisteredToCanvas())
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
Nz::Vector2f widgetPos = Nz::Vector2f(GetPosition());
Nz::Vector2f widgetSize = GetSize();
Nz::Vector2f contentPos = widgetPos + GetContentOrigin();
Nz::Vector2f contentSize = GetContentSize();
Nz::Recti fullBounds(Nz::Rectf(widgetPos.x, widgetPos.y, widgetSize.x, widgetSize.y));
Nz::Recti contentBounds(Nz::Rectf(contentPos.x, contentPos.y, contentSize.x, contentSize.y));
for (WidgetEntity& widgetEntity : m_entities)
{
const Ndk::EntityHandle& entity = widgetEntity.handle;
if (entity->HasComponent<GraphicsComponent>())
entity->GetComponent<GraphicsComponent>().SetScissorRect((widgetEntity.isContent) ? contentBounds : fullBounds);
}
}
}

View File

@@ -35,7 +35,7 @@ namespace Ndk
object.dataUpdated = true;
}
object.renderable->AddToRenderQueue(renderQueue, object.data);
object.renderable->AddToRenderQueue(renderQueue, object.data, m_scissorRect);
}
}
@@ -282,7 +282,7 @@ namespace Ndk
boundingVolume.Set(Nz::Boxf(newPos.x, newPos.y, newPos.z, newLengths.x, newLengths.y, newLengths.z));
}
m_boundingVolume.ExtendTo(r.renderable->GetBoundingVolume());
m_boundingVolume.ExtendTo(boundingVolume);
}
RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>();

View File

@@ -30,13 +30,13 @@ namespace Ndk
m_gradientSprite->SetCornerColor(Nz::RectCorner_RightBottom, m_cornerColor);
m_gradientSprite->SetMaterial(Nz::Material::New("Basic2D"));
m_gradientEntity = CreateEntity();
m_gradientEntity = CreateEntity(false);
m_gradientEntity->AddComponent<NodeComponent>().SetParent(this);
m_gradientEntity->AddComponent<GraphicsComponent>().Attach(m_gradientSprite);
m_textSprite = Nz::TextSprite::New();
m_textEntity = CreateEntity();
m_textEntity = CreateEntity(true);
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite, 1);
@@ -82,12 +82,11 @@ namespace Ndk
{
BaseWidget::Layout();
m_gradientSprite->SetSize(GetSize());
Nz::Vector2f origin = GetContentOrigin();
const Nz::Vector2f& contentSize = GetContentSize();
m_gradientEntity->GetComponent<NodeComponent>().SetPosition(origin);
m_gradientSprite->SetSize(contentSize);
Nz::Boxf textBox = m_textEntity->GetComponent<GraphicsComponent>().GetBoundingVolume().obb.localBox;
m_textEntity->GetComponent<NodeComponent>().SetPosition(origin.x + contentSize.x / 2 - textBox.width / 2, origin.y + contentSize.y / 2 - textBox.height / 2);
}

View File

@@ -28,19 +28,19 @@ namespace Ndk
m_checkboxContentSprite = Nz::Sprite::New(Nz::Material::New("Translucent2D"));
m_textSprite = Nz::TextSprite::New();
m_checkboxBorderEntity = CreateEntity();
m_checkboxBorderEntity = CreateEntity(false);
m_checkboxBorderEntity->AddComponent<NodeComponent>().SetParent(this);
m_checkboxBorderEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxBorderSprite);
m_checkboxBackgroundEntity = CreateEntity();
m_checkboxBackgroundEntity = CreateEntity(false);
m_checkboxBackgroundEntity->AddComponent<NodeComponent>().SetParent(this);
m_checkboxBackgroundEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxBackgroundSprite, 1);
m_checkboxContentEntity = CreateEntity();
m_checkboxContentEntity = CreateEntity(true);
m_checkboxContentEntity->AddComponent<NodeComponent>().SetParent(this);
m_checkboxContentEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxContentSprite, 2);
m_textEntity = CreateEntity();
m_textEntity = CreateEntity(true);
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);

View File

@@ -11,7 +11,7 @@ namespace Ndk
ImageWidget::ImageWidget(BaseWidget* parent) :
BaseWidget(parent)
{
m_entity = CreateEntity();
m_entity = CreateEntity(true);
m_entity->AddComponent<NodeComponent>();
auto& gfx = m_entity->AddComponent<GraphicsComponent>();

View File

@@ -13,13 +13,20 @@ namespace Ndk
{
m_textSprite = Nz::TextSprite::New();
m_textEntity = CreateEntity();
m_textEntity = CreateEntity(true);
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
Layout();
}
void LabelWidget::Layout()
{
BaseWidget::Layout();
m_textEntity->GetComponent<NodeComponent>().SetPosition(GetContentOrigin());
}
void LabelWidget::ResizeToContent()
{
SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2017 Samy Bensaid
// Copyright (C) 2017 Samy Bensaid
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
@@ -30,11 +30,11 @@ namespace Ndk
SetBarColor(s_barColor, s_barCornerColor);
m_borderEntity = CreateEntity();
m_borderEntity = CreateEntity(false);
m_borderEntity->AddComponent<NodeComponent>().SetParent(this);
m_borderEntity->AddComponent<GraphicsComponent>().Attach(m_borderSprite);
m_barEntity = CreateEntity();
m_barEntity = CreateEntity(true);
m_barEntity->AddComponent<NodeComponent>().SetParent(this);
GraphicsComponent& graphics = m_barEntity->AddComponent<GraphicsComponent>();
@@ -43,7 +43,7 @@ namespace Ndk
m_textSprite = Nz::TextSprite::New();
m_textEntity = CreateEntity();
m_textEntity = CreateEntity(true);
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);

View File

@@ -20,14 +20,14 @@ namespace Ndk
m_cursorSprite->SetColor(Nz::Color::Black);
m_cursorSprite->SetSize(1.f, float(m_drawer.GetFont()->GetSizeInfo(m_drawer.GetCharacterSize()).lineHeight));
m_cursorEntity = CreateEntity();
m_cursorEntity = CreateEntity(true);
m_cursorEntity->AddComponent<GraphicsComponent>().Attach(m_cursorSprite, 10);
m_cursorEntity->AddComponent<NodeComponent>().SetParent(this);
m_cursorEntity->Enable(false);
m_textSprite = Nz::TextSprite::New();
m_textEntity = CreateEntity();
m_textEntity = CreateEntity(true);
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
@@ -236,7 +236,8 @@ namespace Ndk
{
SetFocus();
SetCursorPosition(GetHoveredGlyph(float(x), float(y)));
const Padding& padding = GetPadding();
SetCursorPosition(GetHoveredGlyph(float(x - padding.left), float(y - padding.top)));
}
}