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:
parent
14248bb6c6
commit
2da086b7df
|
|
@ -125,6 +125,9 @@ Nazara Development Kit:
|
||||||
- ListenerSystem now handles velocity in a generic way (no longer require a VelocityComponent and is compatible with physics)
|
- ListenerSystem now handles velocity in a generic way (no longer require a VelocityComponent and is compatible with physics)
|
||||||
- World now has const getters for systems
|
- World now has const getters for systems
|
||||||
- Add World::ForEachSystem method, allowing iteration on every active system on a specific world
|
- Add World::ForEachSystem method, allowing iteration on every active system on a specific world
|
||||||
|
- Fix GraphicsComponent bounding volume not taking local matrix in account
|
||||||
|
- ⚠️ Rewrote all render queue system, which should be more efficient, take scissor box into account
|
||||||
|
- ⚠️ All widgets are now bound to a scissor box when rendering
|
||||||
|
|
||||||
# 0.4:
|
# 0.4:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,9 +83,10 @@ namespace Ndk
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const EntityHandle& CreateEntity();
|
const EntityHandle& CreateEntity(bool isContentEntity);
|
||||||
void DestroyEntity(Entity* entity);
|
void DestroyEntity(Entity* entity);
|
||||||
virtual void Layout();
|
virtual void Layout();
|
||||||
|
|
||||||
void InvalidateNode() override;
|
void InvalidateNode() override;
|
||||||
|
|
||||||
virtual bool IsFocusable() const;
|
virtual bool IsFocusable() const;
|
||||||
|
|
@ -111,11 +112,18 @@ namespace Ndk
|
||||||
void RegisterToCanvas();
|
void RegisterToCanvas();
|
||||||
inline void UpdateCanvasIndex(std::size_t index);
|
inline void UpdateCanvasIndex(std::size_t index);
|
||||||
void UnregisterFromCanvas();
|
void UnregisterFromCanvas();
|
||||||
|
void UpdatePositionAndSize();
|
||||||
|
|
||||||
|
struct WidgetEntity
|
||||||
|
{
|
||||||
|
EntityOwner handle;
|
||||||
|
bool isContent;
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr std::size_t InvalidCanvasIndex = std::numeric_limits<std::size_t>::max();
|
static constexpr std::size_t InvalidCanvasIndex = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
std::size_t m_canvasIndex;
|
std::size_t m_canvasIndex;
|
||||||
std::vector<EntityOwner> m_entities;
|
std::vector<WidgetEntity> m_entities;
|
||||||
std::vector<std::unique_ptr<BaseWidget>> m_children;
|
std::vector<std::unique_ptr<BaseWidget>> m_children;
|
||||||
Canvas* m_canvas;
|
Canvas* m_canvas;
|
||||||
EntityOwner m_backgroundEntity;
|
EntityOwner m_backgroundEntity;
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ namespace Ndk
|
||||||
WidgetEntry& entry = m_widgetEntries[index];
|
WidgetEntry& entry = m_widgetEntries[index];
|
||||||
|
|
||||||
Nz::Vector3f pos = entry.widget->GetPosition();
|
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);
|
entry.box.Set(pos.x, pos.y, pos.z, size.x, size.y, 1.f);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Ndk
|
||||||
public:
|
public:
|
||||||
using RenderableList = std::vector<Nz::InstancedRenderableRef>;
|
using RenderableList = std::vector<Nz::InstancedRenderableRef>;
|
||||||
|
|
||||||
GraphicsComponent() = default;
|
GraphicsComponent();
|
||||||
inline GraphicsComponent(const GraphicsComponent& graphicsComponent);
|
inline GraphicsComponent(const GraphicsComponent& graphicsComponent);
|
||||||
~GraphicsComponent() = default;
|
~GraphicsComponent() = default;
|
||||||
|
|
||||||
|
|
@ -54,6 +54,8 @@ namespace Ndk
|
||||||
|
|
||||||
inline void RemoveFromCullingList(GraphicsComponentCullingList* cullingList) const;
|
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 UpdateLocalMatrix(const Nz::InstancedRenderable* instancedRenderable, const Nz::Matrix4f& localMatrix);
|
||||||
inline void UpdateRenderOrder(const Nz::InstancedRenderable* instancedRenderable, int renderOrder);
|
inline void UpdateRenderOrder(const Nz::InstancedRenderable* instancedRenderable, int renderOrder);
|
||||||
|
|
||||||
|
|
@ -144,6 +146,7 @@ namespace Ndk
|
||||||
std::unordered_map<const Nz::Material*, MaterialEntry> m_materialEntries;
|
std::unordered_map<const Nz::Material*, MaterialEntry> m_materialEntries;
|
||||||
mutable Nz::BoundingVolumef m_boundingVolume;
|
mutable Nz::BoundingVolumef m_boundingVolume;
|
||||||
mutable Nz::Matrix4f m_transformMatrix;
|
mutable Nz::Matrix4f m_transformMatrix;
|
||||||
|
Nz::Recti m_scissorRect;
|
||||||
Nz::TextureRef m_reflectionMap;
|
Nz::TextureRef m_reflectionMap;
|
||||||
mutable bool m_boundingVolumeUpdated;
|
mutable bool m_boundingVolumeUpdated;
|
||||||
mutable bool m_transformMatrixUpdated;
|
mutable bool m_transformMatrixUpdated;
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,16 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
inline GraphicsComponent::GraphicsComponent() :
|
||||||
|
m_scissorRect(-1, -1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Constructs a GraphicsComponent object by copy semantic
|
* \brief Constructs a GraphicsComponent object by copy semantic
|
||||||
*
|
*
|
||||||
* \param graphicsComponent GraphicsComponent to copy
|
* \param graphicsComponent GraphicsComponent to copy
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline GraphicsComponent::GraphicsComponent(const GraphicsComponent& graphicsComponent) :
|
inline GraphicsComponent::GraphicsComponent(const GraphicsComponent& graphicsComponent) :
|
||||||
Component(graphicsComponent),
|
Component(graphicsComponent),
|
||||||
HandledObject(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)
|
inline void GraphicsComponent::UpdateLocalMatrix(const Nz::InstancedRenderable* instancedRenderable, const Nz::Matrix4f& localMatrix)
|
||||||
{
|
{
|
||||||
for (auto& renderable : m_renderables)
|
for (auto& renderable : m_renderables)
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Ndk
|
||||||
|
|
||||||
//virtual LabelWidget* Clone() const = 0;
|
//virtual LabelWidget* Clone() const = 0;
|
||||||
|
|
||||||
void ResizeToContent();
|
void ResizeToContent() override;
|
||||||
|
|
||||||
inline void UpdateText(const Nz::AbstractTextDrawer& drawer);
|
inline void UpdateText(const Nz::AbstractTextDrawer& drawer);
|
||||||
|
|
||||||
|
|
@ -36,6 +36,8 @@ namespace Ndk
|
||||||
LabelWidget& operator=(LabelWidget&&) = default;
|
LabelWidget& operator=(LabelWidget&&) = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void Layout() override;
|
||||||
|
|
||||||
EntityHandle m_textEntity;
|
EntityHandle m_textEntity;
|
||||||
Nz::TextSpriteRef m_textSprite;
|
Nz::TextSpriteRef m_textSprite;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -426,7 +426,7 @@ namespace Ndk
|
||||||
m_orderedSystems = std::move(world.m_orderedSystems);
|
m_orderedSystems = std::move(world.m_orderedSystems);
|
||||||
m_orderedSystemsUpdated = world.m_orderedSystemsUpdated;
|
m_orderedSystemsUpdated = world.m_orderedSystemsUpdated;
|
||||||
m_profilerData = std::move(world.m_profilerData);
|
m_profilerData = std::move(world.m_profilerData);
|
||||||
m_isProfilerEnabled = m_isProfilerEnabled;
|
m_isProfilerEnabled = world.m_isProfilerEnabled;
|
||||||
|
|
||||||
m_entities = std::move(world.m_entities);
|
m_entities = std::move(world.m_entities);
|
||||||
for (EntityBlock& block : m_entities)
|
for (EntityBlock& block : m_entities)
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ namespace Ndk
|
||||||
m_backgroundSprite->SetColor(m_backgroundColor);
|
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_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<GraphicsComponent>().Attach(m_backgroundSprite, -1);
|
||||||
m_backgroundEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_backgroundEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
|
|
||||||
|
|
@ -147,26 +147,30 @@ namespace Ndk
|
||||||
else
|
else
|
||||||
UnregisterFromCanvas();
|
UnregisterFromCanvas();
|
||||||
|
|
||||||
for (const EntityHandle& entity : m_entities)
|
for (WidgetEntity& entity : m_entities)
|
||||||
entity->Enable(show);
|
entity.handle->Enable(show);
|
||||||
|
|
||||||
for (const auto& widgetPtr : m_children)
|
for (const auto& widgetPtr : m_children)
|
||||||
widgetPtr->Show(show);
|
widgetPtr->Show(show);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Ndk::EntityHandle& BaseWidget::CreateEntity()
|
const Ndk::EntityHandle& BaseWidget::CreateEntity(bool isContentEntity)
|
||||||
{
|
{
|
||||||
const EntityHandle& newEntity = m_world->CreateEntity();
|
const EntityHandle& newEntity = m_world->CreateEntity();
|
||||||
newEntity->Enable(m_visible);
|
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;
|
return newEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseWidget::DestroyEntity(Entity* entity)
|
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");
|
NazaraAssert(it != m_entities.end(), "Entity does not belong to this widget");
|
||||||
|
|
||||||
m_entities.erase(it);
|
m_entities.erase(it);
|
||||||
|
|
@ -174,19 +178,17 @@ namespace Ndk
|
||||||
|
|
||||||
void BaseWidget::Layout()
|
void BaseWidget::Layout()
|
||||||
{
|
{
|
||||||
if (IsRegisteredToCanvas())
|
|
||||||
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
|
|
||||||
|
|
||||||
if (m_backgroundEntity)
|
if (m_backgroundEntity)
|
||||||
m_backgroundSprite->SetSize(m_contentSize.x + m_padding.left + m_padding.right, m_contentSize.y + m_padding.top + m_padding.bottom);
|
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()
|
void BaseWidget::InvalidateNode()
|
||||||
{
|
{
|
||||||
Node::InvalidateNode();
|
Node::InvalidateNode();
|
||||||
|
|
||||||
if (IsRegisteredToCanvas())
|
UpdatePositionAndSize();
|
||||||
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseWidget::IsFocusable() const
|
bool BaseWidget::IsFocusable() const
|
||||||
|
|
@ -271,4 +273,25 @@ namespace Ndk
|
||||||
m_canvasIndex = InvalidCanvasIndex;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Ndk
|
||||||
object.dataUpdated = true;
|
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));
|
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>();
|
RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>();
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,13 @@ namespace Ndk
|
||||||
m_gradientSprite->SetCornerColor(Nz::RectCorner_RightBottom, m_cornerColor);
|
m_gradientSprite->SetCornerColor(Nz::RectCorner_RightBottom, m_cornerColor);
|
||||||
m_gradientSprite->SetMaterial(Nz::Material::New("Basic2D"));
|
m_gradientSprite->SetMaterial(Nz::Material::New("Basic2D"));
|
||||||
|
|
||||||
m_gradientEntity = CreateEntity();
|
m_gradientEntity = CreateEntity(false);
|
||||||
m_gradientEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_gradientEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_gradientEntity->AddComponent<GraphicsComponent>().Attach(m_gradientSprite);
|
m_gradientEntity->AddComponent<GraphicsComponent>().Attach(m_gradientSprite);
|
||||||
|
|
||||||
m_textSprite = Nz::TextSprite::New();
|
m_textSprite = Nz::TextSprite::New();
|
||||||
|
|
||||||
m_textEntity = CreateEntity();
|
m_textEntity = CreateEntity(true);
|
||||||
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite, 1);
|
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite, 1);
|
||||||
|
|
||||||
|
|
@ -82,12 +82,11 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
BaseWidget::Layout();
|
BaseWidget::Layout();
|
||||||
|
|
||||||
|
m_gradientSprite->SetSize(GetSize());
|
||||||
|
|
||||||
Nz::Vector2f origin = GetContentOrigin();
|
Nz::Vector2f origin = GetContentOrigin();
|
||||||
const Nz::Vector2f& contentSize = GetContentSize();
|
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;
|
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);
|
m_textEntity->GetComponent<NodeComponent>().SetPosition(origin.x + contentSize.x / 2 - textBox.width / 2, origin.y + contentSize.y / 2 - textBox.height / 2);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,19 +28,19 @@ namespace Ndk
|
||||||
m_checkboxContentSprite = Nz::Sprite::New(Nz::Material::New("Translucent2D"));
|
m_checkboxContentSprite = Nz::Sprite::New(Nz::Material::New("Translucent2D"));
|
||||||
m_textSprite = Nz::TextSprite::New();
|
m_textSprite = Nz::TextSprite::New();
|
||||||
|
|
||||||
m_checkboxBorderEntity = CreateEntity();
|
m_checkboxBorderEntity = CreateEntity(false);
|
||||||
m_checkboxBorderEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_checkboxBorderEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_checkboxBorderEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxBorderSprite);
|
m_checkboxBorderEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxBorderSprite);
|
||||||
|
|
||||||
m_checkboxBackgroundEntity = CreateEntity();
|
m_checkboxBackgroundEntity = CreateEntity(false);
|
||||||
m_checkboxBackgroundEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_checkboxBackgroundEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_checkboxBackgroundEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxBackgroundSprite, 1);
|
m_checkboxBackgroundEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxBackgroundSprite, 1);
|
||||||
|
|
||||||
m_checkboxContentEntity = CreateEntity();
|
m_checkboxContentEntity = CreateEntity(true);
|
||||||
m_checkboxContentEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_checkboxContentEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_checkboxContentEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxContentSprite, 2);
|
m_checkboxContentEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxContentSprite, 2);
|
||||||
|
|
||||||
m_textEntity = CreateEntity();
|
m_textEntity = CreateEntity(true);
|
||||||
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace Ndk
|
||||||
ImageWidget::ImageWidget(BaseWidget* parent) :
|
ImageWidget::ImageWidget(BaseWidget* parent) :
|
||||||
BaseWidget(parent)
|
BaseWidget(parent)
|
||||||
{
|
{
|
||||||
m_entity = CreateEntity();
|
m_entity = CreateEntity(true);
|
||||||
m_entity->AddComponent<NodeComponent>();
|
m_entity->AddComponent<NodeComponent>();
|
||||||
auto& gfx = m_entity->AddComponent<GraphicsComponent>();
|
auto& gfx = m_entity->AddComponent<GraphicsComponent>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,20 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
m_textSprite = Nz::TextSprite::New();
|
m_textSprite = Nz::TextSprite::New();
|
||||||
|
|
||||||
m_textEntity = CreateEntity();
|
m_textEntity = CreateEntity(true);
|
||||||
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
||||||
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LabelWidget::Layout()
|
||||||
|
{
|
||||||
|
BaseWidget::Layout();
|
||||||
|
|
||||||
|
m_textEntity->GetComponent<NodeComponent>().SetPosition(GetContentOrigin());
|
||||||
|
}
|
||||||
|
|
||||||
void LabelWidget::ResizeToContent()
|
void LabelWidget::ResizeToContent()
|
||||||
{
|
{
|
||||||
SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
|
SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (C) 2017 Samy Bensaid
|
// Copyright (C) 2017 Samy Bensaid
|
||||||
// This file is part of the "Nazara Development Kit"
|
// This file is part of the "Nazara Development Kit"
|
||||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
|
@ -30,11 +30,11 @@ namespace Ndk
|
||||||
SetBarColor(s_barColor, s_barCornerColor);
|
SetBarColor(s_barColor, s_barCornerColor);
|
||||||
|
|
||||||
|
|
||||||
m_borderEntity = CreateEntity();
|
m_borderEntity = CreateEntity(false);
|
||||||
m_borderEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_borderEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_borderEntity->AddComponent<GraphicsComponent>().Attach(m_borderSprite);
|
m_borderEntity->AddComponent<GraphicsComponent>().Attach(m_borderSprite);
|
||||||
|
|
||||||
m_barEntity = CreateEntity();
|
m_barEntity = CreateEntity(true);
|
||||||
m_barEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_barEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
GraphicsComponent& graphics = m_barEntity->AddComponent<GraphicsComponent>();
|
GraphicsComponent& graphics = m_barEntity->AddComponent<GraphicsComponent>();
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ namespace Ndk
|
||||||
|
|
||||||
|
|
||||||
m_textSprite = Nz::TextSprite::New();
|
m_textSprite = Nz::TextSprite::New();
|
||||||
m_textEntity = CreateEntity();
|
m_textEntity = CreateEntity(true);
|
||||||
|
|
||||||
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
||||||
|
|
|
||||||
|
|
@ -20,14 +20,14 @@ namespace Ndk
|
||||||
m_cursorSprite->SetColor(Nz::Color::Black);
|
m_cursorSprite->SetColor(Nz::Color::Black);
|
||||||
m_cursorSprite->SetSize(1.f, float(m_drawer.GetFont()->GetSizeInfo(m_drawer.GetCharacterSize()).lineHeight));
|
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<GraphicsComponent>().Attach(m_cursorSprite, 10);
|
||||||
m_cursorEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_cursorEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_cursorEntity->Enable(false);
|
m_cursorEntity->Enable(false);
|
||||||
|
|
||||||
m_textSprite = Nz::TextSprite::New();
|
m_textSprite = Nz::TextSprite::New();
|
||||||
|
|
||||||
m_textEntity = CreateEntity();
|
m_textEntity = CreateEntity(true);
|
||||||
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
||||||
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
|
|
||||||
|
|
@ -236,7 +236,8 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
SetFocus();
|
SetFocus();
|
||||||
|
|
||||||
SetCursorPosition(GetHoveredGlyph(float(x), float(y)));
|
const Padding& padding = GetPadding();
|
||||||
|
SetCursorPosition(GetHoveredGlyph(float(x - padding.left), float(y - padding.top)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ class SpriteRenderer : public Nz::ParticleRenderer
|
||||||
Nz::SparsePtr<const Nz::Vector2f> sizePtr(&size, 0);
|
Nz::SparsePtr<const Nz::Vector2f> sizePtr(&size, 0);
|
||||||
Nz::SparsePtr<const Nz::Vector2f> sinCosPtr(nullptr, 0);
|
Nz::SparsePtr<const Nz::Vector2f> sinCosPtr(nullptr, 0);
|
||||||
|
|
||||||
renderQueue->AddBillboards(0, m_material, endId - startId + 1, mapper.GetComponentPtr<const Nz::Vector3f>(Nz::ParticleComponent_Position), sizePtr, sinCosPtr, mapper.GetComponentPtr<const Nz::Color>(Nz::ParticleComponent_Color));
|
renderQueue->AddBillboards(0, m_material, endId - startId + 1, Nz::Recti(-1, -1), mapper.GetComponentPtr<const Nz::Vector3f>(Nz::ParticleComponent_Position), sizePtr, sinCosPtr, mapper.GetComponentPtr<const Nz::Color>(Nz::ParticleComponent_Color));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -267,6 +267,8 @@ ParticleDemo("Space battle", sharedData)
|
||||||
if (!m_spacestationModel.LoadFromFile("resources/SpaceStation/space_station.obj", parameters))
|
if (!m_spacestationModel.LoadFromFile("resources/SpaceStation/space_station.obj", parameters))
|
||||||
NazaraWarning("Failed to load space_station.obj");
|
NazaraWarning("Failed to load space_station.obj");
|
||||||
|
|
||||||
|
m_spacestationModel.GetMesh()->GenerateNormalsAndTangents();
|
||||||
|
|
||||||
parameters.mesh.texCoordScale.Set(1.f, -1.f);
|
parameters.mesh.texCoordScale.Set(1.f, -1.f);
|
||||||
parameters.mesh.matrix.MakeRotation(Nz::EulerAnglesf(0.f, -90.f, 0.f));
|
parameters.mesh.matrix.MakeRotation(Nz::EulerAnglesf(0.f, -90.f, 0.f));
|
||||||
|
|
||||||
|
|
@ -471,7 +473,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
|
||||||
auto rotationPtr = mapper.GetComponentPtr<const float>(Nz::ParticleComponent_Rotation);
|
auto rotationPtr = mapper.GetComponentPtr<const float>(Nz::ParticleComponent_Rotation);
|
||||||
auto sizePtr = mapper.GetComponentPtr<const Nz::Vector2f>(Nz::ParticleComponent_Size);
|
auto sizePtr = mapper.GetComponentPtr<const Nz::Vector2f>(Nz::ParticleComponent_Size);
|
||||||
|
|
||||||
renderQueue->AddBillboards(0, sparkleMat1, endId - startId + 1, positionPtr, sizePtr, rotationPtr);
|
renderQueue->AddBillboards(0, sparkleMat1, endId - startId + 1, Nz::Recti(-1, -1), positionPtr, sizePtr, rotationPtr);
|
||||||
for (unsigned int i = startId; i <= endId; ++i)
|
for (unsigned int i = startId; i <= endId; ++i)
|
||||||
{
|
{
|
||||||
Nz::AbstractRenderQueue::PointLight pointLight;
|
Nz::AbstractRenderQueue::PointLight pointLight;
|
||||||
|
|
@ -607,6 +609,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
|
||||||
fireMat->EnableFaceCulling(true);
|
fireMat->EnableFaceCulling(true);
|
||||||
fireMat->SetDiffuseMap("resources/fire_particle.png");
|
fireMat->SetDiffuseMap("resources/fire_particle.png");
|
||||||
// Additive blending for fire
|
// Additive blending for fire
|
||||||
|
fireMat->EnableDepthSorting(false); //< No need for depth sort
|
||||||
fireMat->SetDstBlend(Nz::BlendFunc_One);
|
fireMat->SetDstBlend(Nz::BlendFunc_One);
|
||||||
fireMat->SetSrcBlend(Nz::BlendFunc_SrcAlpha);
|
fireMat->SetSrcBlend(Nz::BlendFunc_SrcAlpha);
|
||||||
|
|
||||||
|
|
@ -622,7 +625,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
|
||||||
auto rotPtr = mapper.GetComponentPtr<const float>(Nz::ParticleComponent_Rotation);
|
auto rotPtr = mapper.GetComponentPtr<const float>(Nz::ParticleComponent_Rotation);
|
||||||
auto sizePtr = mapper.GetComponentPtr<const Nz::Vector2f>(Nz::ParticleComponent_Size);
|
auto sizePtr = mapper.GetComponentPtr<const Nz::Vector2f>(Nz::ParticleComponent_Size);
|
||||||
|
|
||||||
renderQueue->AddBillboards(0, fireMat, endId - startId + 1, posPtr, sizePtr, rotPtr, colorPtr);
|
renderQueue->AddBillboards(0, fireMat, endId - startId + 1, Nz::Recti(-1, -1), posPtr, sizePtr, rotPtr, colorPtr);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
m_smokeGroup->SetRenderer(Nz::ParticleFunctionRenderer::New([smokeMat] (const Nz::ParticleGroup& /*group*/, const Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, Nz::AbstractRenderQueue* renderQueue)
|
m_smokeGroup->SetRenderer(Nz::ParticleFunctionRenderer::New([smokeMat] (const Nz::ParticleGroup& /*group*/, const Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, Nz::AbstractRenderQueue* renderQueue)
|
||||||
|
|
@ -632,7 +635,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
|
||||||
auto rotPtr = mapper.GetComponentPtr<const float>(Nz::ParticleComponent_Rotation);
|
auto rotPtr = mapper.GetComponentPtr<const float>(Nz::ParticleComponent_Rotation);
|
||||||
auto sizePtr = mapper.GetComponentPtr<const Nz::Vector2f>(Nz::ParticleComponent_Size);
|
auto sizePtr = mapper.GetComponentPtr<const Nz::Vector2f>(Nz::ParticleComponent_Size);
|
||||||
|
|
||||||
renderQueue->AddBillboards(0, smokeMat, endId - startId + 1, posPtr, sizePtr, rotPtr, colorPtr);
|
renderQueue->AddBillboards(0, smokeMat, endId - startId + 1, Nz::Recti(-1, -1), posPtr, sizePtr, rotPtr, colorPtr);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -647,6 +650,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Nz::TextSpriteRef introText = Nz::TextSprite::New();
|
Nz::TextSpriteRef introText = Nz::TextSprite::New();
|
||||||
|
introText->SetMaterial(Nz::Material::New("Translucent3D"));
|
||||||
introText->Update(Nz::SimpleTextDrawer::Draw("--Tourelle de défense du secteur A407M2--\nLes contrôles ont été adaptés à vos contrôleurs:\nLa souris contrôle l'orientation de la tourelle, cliquez pour tirer.\n", 72));
|
introText->Update(Nz::SimpleTextDrawer::Draw("--Tourelle de défense du secteur A407M2--\nLes contrôles ont été adaptés à vos contrôleurs:\nLa souris contrôle l'orientation de la tourelle, cliquez pour tirer.\n", 72));
|
||||||
introText->SetScale(0.5f);
|
introText->SetScale(0.5f);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ int main()
|
||||||
shared.particleCount->Update(Nz::SimpleTextDrawer::Draw("XXXXX particles", 36));
|
shared.particleCount->Update(Nz::SimpleTextDrawer::Draw("XXXXX particles", 36));
|
||||||
|
|
||||||
world2D.GetSystem<Ndk::RenderSystem>().SetGlobalUp(Nz::Vector3f::Down());
|
world2D.GetSystem<Ndk::RenderSystem>().SetGlobalUp(Nz::Vector3f::Down());
|
||||||
//world3D.GetSystem<Ndk::RenderSystem>().ChangeRenderTechnique<Nz::DeferredRenderTechnique>();
|
world3D.GetSystem<Ndk::RenderSystem>().ChangeRenderTechnique<Nz::DeferredRenderTechnique>();
|
||||||
|
|
||||||
|
|
||||||
Ndk::EntityHandle viewEntity = world2D.CreateEntity();
|
Ndk::EntityHandle viewEntity = world2D.CreateEntity();
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
#include <Nazara/Graphics/AbstractRenderQueue.hpp>
|
#include <Nazara/Graphics/AbstractRenderQueue.hpp>
|
||||||
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
|
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
|
||||||
#include <Nazara/Graphics/AbstractViewer.hpp>
|
#include <Nazara/Graphics/AbstractViewer.hpp>
|
||||||
|
#include <Nazara/Graphics/BasicRenderQueue.hpp>
|
||||||
#include <Nazara/Graphics/Billboard.hpp>
|
#include <Nazara/Graphics/Billboard.hpp>
|
||||||
#include <Nazara/Graphics/ColorBackground.hpp>
|
#include <Nazara/Graphics/ColorBackground.hpp>
|
||||||
#include <Nazara/Graphics/Config.hpp>
|
#include <Nazara/Graphics/Config.hpp>
|
||||||
|
|
@ -45,14 +46,13 @@
|
||||||
#include <Nazara/Graphics/DeferredFXAAPass.hpp>
|
#include <Nazara/Graphics/DeferredFXAAPass.hpp>
|
||||||
#include <Nazara/Graphics/DeferredGeometryPass.hpp>
|
#include <Nazara/Graphics/DeferredGeometryPass.hpp>
|
||||||
#include <Nazara/Graphics/DeferredPhongLightingPass.hpp>
|
#include <Nazara/Graphics/DeferredPhongLightingPass.hpp>
|
||||||
|
#include <Nazara/Graphics/DeferredProxyRenderQueue.hpp>
|
||||||
#include <Nazara/Graphics/DeferredRenderPass.hpp>
|
#include <Nazara/Graphics/DeferredRenderPass.hpp>
|
||||||
#include <Nazara/Graphics/DeferredRenderQueue.hpp>
|
|
||||||
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
|
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
|
||||||
#include <Nazara/Graphics/DepthRenderQueue.hpp>
|
#include <Nazara/Graphics/DepthRenderQueue.hpp>
|
||||||
#include <Nazara/Graphics/DepthRenderTechnique.hpp>
|
#include <Nazara/Graphics/DepthRenderTechnique.hpp>
|
||||||
#include <Nazara/Graphics/Drawable.hpp>
|
#include <Nazara/Graphics/Drawable.hpp>
|
||||||
#include <Nazara/Graphics/Enums.hpp>
|
#include <Nazara/Graphics/Enums.hpp>
|
||||||
#include <Nazara/Graphics/ForwardRenderQueue.hpp>
|
|
||||||
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
||||||
#include <Nazara/Graphics/Graphics.hpp>
|
#include <Nazara/Graphics/Graphics.hpp>
|
||||||
#include <Nazara/Graphics/GuillotineTextureAtlas.hpp>
|
#include <Nazara/Graphics/GuillotineTextureAtlas.hpp>
|
||||||
|
|
@ -73,6 +73,7 @@
|
||||||
#include <Nazara/Graphics/ParticleRenderer.hpp>
|
#include <Nazara/Graphics/ParticleRenderer.hpp>
|
||||||
#include <Nazara/Graphics/ParticleStruct.hpp>
|
#include <Nazara/Graphics/ParticleStruct.hpp>
|
||||||
#include <Nazara/Graphics/Renderable.hpp>
|
#include <Nazara/Graphics/Renderable.hpp>
|
||||||
|
#include <Nazara/Graphics/RenderQueue.hpp>
|
||||||
#include <Nazara/Graphics/RenderTechniques.hpp>
|
#include <Nazara/Graphics/RenderTechniques.hpp>
|
||||||
#include <Nazara/Graphics/SceneData.hpp>
|
#include <Nazara/Graphics/SceneData.hpp>
|
||||||
#include <Nazara/Graphics/SkeletalModel.hpp>
|
#include <Nazara/Graphics/SkeletalModel.hpp>
|
||||||
|
|
|
||||||
|
|
@ -37,20 +37,20 @@ namespace Nz
|
||||||
|
|
||||||
// Je ne suis vraiment pas fan du nombre de surcharges pour AddBillboards,
|
// Je ne suis vraiment pas fan du nombre de surcharges pour AddBillboards,
|
||||||
// mais je n'ai pas d'autre solution tout aussi performante pour le moment...
|
// mais je n'ai pas d'autre solution tout aussi performante pour le moment...
|
||||||
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) = 0;
|
virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) = 0;
|
||||||
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) = 0;
|
virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) = 0;
|
||||||
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) = 0;
|
virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) = 0;
|
||||||
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) = 0;
|
virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) = 0;
|
||||||
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) = 0;
|
virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) = 0;
|
||||||
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) = 0;
|
virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) = 0;
|
||||||
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) = 0;
|
virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) = 0;
|
||||||
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) = 0;
|
virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) = 0;
|
||||||
virtual void AddDrawable(int renderOrder, const Drawable* drawable) = 0;
|
virtual void AddDrawable(int renderOrder, const Drawable* drawable) = 0;
|
||||||
virtual void AddDirectionalLight(const DirectionalLight& light);
|
virtual void AddDirectionalLight(const DirectionalLight& light);
|
||||||
virtual void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) = 0;
|
virtual void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix, const Recti& scissorRect) = 0;
|
||||||
virtual void AddPointLight(const PointLight& light);
|
virtual void AddPointLight(const PointLight& light);
|
||||||
virtual void AddSpotLight(const SpotLight& light);
|
virtual void AddSpotLight(const SpotLight& light);
|
||||||
virtual void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay = nullptr) = 0;
|
virtual void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay = nullptr) = 0;
|
||||||
|
|
||||||
virtual void Clear(bool fully = false);
|
virtual void Clear(bool fully = false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,142 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_BASICRENDERQUEUE_HPP
|
||||||
|
#define NAZARA_BASICRENDERQUEUE_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Core/Color.hpp>
|
||||||
|
#include <Nazara/Core/MovablePtr.hpp>
|
||||||
|
#include <Nazara/Graphics/AbstractRenderQueue.hpp>
|
||||||
|
#include <Nazara/Graphics/Material.hpp>
|
||||||
|
#include <Nazara/Graphics/RenderQueue.hpp>
|
||||||
|
#include <Nazara/Math/Box.hpp>
|
||||||
|
#include <Nazara/Math/Matrix4.hpp>
|
||||||
|
#include <Nazara/Math/Plane.hpp>
|
||||||
|
#include <Nazara/Utility/IndexBuffer.hpp>
|
||||||
|
#include <Nazara/Utility/MeshData.hpp>
|
||||||
|
#include <Nazara/Utility/VertexBuffer.hpp>
|
||||||
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class AbstractViewer;
|
||||||
|
|
||||||
|
class NAZARA_GRAPHICS_API BasicRenderQueue : public AbstractRenderQueue
|
||||||
|
{
|
||||||
|
friend class ForwardRenderTechnique;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct BillboardData;
|
||||||
|
|
||||||
|
BasicRenderQueue() = default;
|
||||||
|
~BasicRenderQueue() = default;
|
||||||
|
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
|
||||||
|
void AddDrawable(int renderOrder, const Drawable* drawable) override;
|
||||||
|
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix, const Recti& scissorRect) override;
|
||||||
|
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay = nullptr) override;
|
||||||
|
|
||||||
|
void Clear(bool fully = false) override;
|
||||||
|
|
||||||
|
inline const BillboardData* GetBillboardData(std::size_t billboardIndex) const;
|
||||||
|
|
||||||
|
void Sort(const AbstractViewer* viewer);
|
||||||
|
|
||||||
|
struct BillboardData
|
||||||
|
{
|
||||||
|
Color color;
|
||||||
|
Vector3f center;
|
||||||
|
Vector2f size;
|
||||||
|
Vector2f sinCos;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Billboard
|
||||||
|
{
|
||||||
|
int layerIndex;
|
||||||
|
MovablePtr<const Nz::Material> material;
|
||||||
|
Nz::Recti scissorRect;
|
||||||
|
BillboardData data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BillboardChain
|
||||||
|
{
|
||||||
|
int layerIndex;
|
||||||
|
MovablePtr<const Nz::Material> material;
|
||||||
|
Nz::Recti scissorRect;
|
||||||
|
std::size_t billboardCount;
|
||||||
|
std::size_t billboardIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
RenderQueue<BillboardChain> billboards;
|
||||||
|
RenderQueue<Billboard> depthSortedBillboards;
|
||||||
|
|
||||||
|
struct CustomDrawable
|
||||||
|
{
|
||||||
|
int layerIndex;
|
||||||
|
MovablePtr<const Drawable> drawable;
|
||||||
|
};
|
||||||
|
|
||||||
|
RenderQueue<CustomDrawable> customDrawables;
|
||||||
|
|
||||||
|
struct Model
|
||||||
|
{
|
||||||
|
int layerIndex;
|
||||||
|
MeshData meshData;
|
||||||
|
MovablePtr<const Nz::Material> material;
|
||||||
|
Nz::Matrix4f matrix;
|
||||||
|
Nz::Recti scissorRect;
|
||||||
|
Nz::Spheref obbSphere;
|
||||||
|
};
|
||||||
|
|
||||||
|
RenderQueue<Model> models;
|
||||||
|
RenderQueue<Model> depthSortedModels;
|
||||||
|
|
||||||
|
struct SpriteChain
|
||||||
|
{
|
||||||
|
int layerIndex;
|
||||||
|
std::size_t spriteCount;
|
||||||
|
MovablePtr<const Material> material;
|
||||||
|
MovablePtr<const Texture> overlay;
|
||||||
|
MovablePtr<const VertexStruct_XYZ_Color_UV> vertices;
|
||||||
|
Nz::Recti scissorRect;
|
||||||
|
};
|
||||||
|
|
||||||
|
RenderQueue<SpriteChain> basicSprites;
|
||||||
|
RenderQueue<SpriteChain> depthSortedSprites;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline Color ComputeColor(float alpha);
|
||||||
|
inline Vector2f ComputeSinCos(float angle);
|
||||||
|
inline Vector2f ComputeSize(float size);
|
||||||
|
|
||||||
|
inline void RegisterLayer(int layerIndex);
|
||||||
|
|
||||||
|
std::unordered_map<const MaterialPipeline*, std::size_t> m_pipelineCache;
|
||||||
|
std::unordered_map<const Material*, std::size_t> m_materialCache;
|
||||||
|
std::unordered_map<const Texture*, std::size_t> m_overlayCache;
|
||||||
|
std::unordered_map<const UberShader*, std::size_t> m_shaderCache;
|
||||||
|
std::unordered_map<const Texture*, std::size_t> m_textureCache;
|
||||||
|
std::unordered_map<const VertexBuffer*, std::size_t> m_vertexBufferCache;
|
||||||
|
std::unordered_map<int, std::size_t> m_layerCache;
|
||||||
|
|
||||||
|
std::vector<BillboardData> m_billboards;
|
||||||
|
std::vector<int> m_renderLayers;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/BasicRenderQueue.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_BASICRENDERQUEUE_HPP
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/BasicRenderQueue.hpp>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
inline const BasicRenderQueue::BillboardData* BasicRenderQueue::GetBillboardData(std::size_t billboardIndex) const
|
||||||
|
{
|
||||||
|
assert(billboardIndex < m_billboards.size());
|
||||||
|
return &m_billboards[billboardIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Color BasicRenderQueue::ComputeColor(float alpha)
|
||||||
|
{
|
||||||
|
return Color(255, 255, 255, static_cast<UInt8>(255.f * alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vector2f BasicRenderQueue::ComputeSinCos(float angle)
|
||||||
|
{
|
||||||
|
float radians = ToRadians(angle);
|
||||||
|
return { std::sin(radians), std::cos(radians) };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vector2f BasicRenderQueue::ComputeSize(float size)
|
||||||
|
{
|
||||||
|
return Vector2f(size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BasicRenderQueue::RegisterLayer(int layerIndex)
|
||||||
|
{
|
||||||
|
auto it = std::lower_bound(m_renderLayers.begin(), m_renderLayers.end(), layerIndex);
|
||||||
|
if (it == m_renderLayers.end() || *it != layerIndex)
|
||||||
|
m_renderLayers.insert(it, layerIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Nz
|
||||||
Billboard(Billboard&&) = delete;
|
Billboard(Billboard&&) = delete;
|
||||||
~Billboard() = default;
|
~Billboard() = default;
|
||||||
|
|
||||||
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override;
|
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
|
||||||
|
|
||||||
inline const Color& GetColor() const;
|
inline const Color& GetColor() const;
|
||||||
inline float GetRotation() const;
|
inline float GetRotation() const;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#define NAZARA_DEFERREDGEOMETRYPASS_HPP
|
#define NAZARA_DEFERREDGEOMETRYPASS_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Graphics/BasicRenderQueue.hpp>
|
||||||
#include <Nazara/Graphics/DeferredRenderPass.hpp>
|
#include <Nazara/Graphics/DeferredRenderPass.hpp>
|
||||||
#include <Nazara/Renderer/RenderStates.hpp>
|
#include <Nazara/Renderer/RenderStates.hpp>
|
||||||
#include <Nazara/Renderer/Shader.hpp>
|
#include <Nazara/Renderer/Shader.hpp>
|
||||||
|
|
@ -17,6 +18,8 @@ namespace Nz
|
||||||
{
|
{
|
||||||
class NAZARA_GRAPHICS_API DeferredGeometryPass : public DeferredRenderPass
|
class NAZARA_GRAPHICS_API DeferredGeometryPass : public DeferredRenderPass
|
||||||
{
|
{
|
||||||
|
friend class DeferredRenderTechnique;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DeferredGeometryPass();
|
DeferredGeometryPass();
|
||||||
virtual ~DeferredGeometryPass();
|
virtual ~DeferredGeometryPass();
|
||||||
|
|
@ -27,9 +30,17 @@ namespace Nz
|
||||||
protected:
|
protected:
|
||||||
struct ShaderUniforms;
|
struct ShaderUniforms;
|
||||||
|
|
||||||
|
void DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Billboard>& billboards) const;
|
||||||
|
void DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::BillboardChain>& billboards) const;
|
||||||
|
void DrawModels(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Model>& models) const;
|
||||||
|
void DrawSprites(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::SpriteChain>& sprites) const;
|
||||||
|
|
||||||
const ShaderUniforms* GetShaderUniforms(const Shader* shader) const;
|
const ShaderUniforms* GetShaderUniforms(const Shader* shader) const;
|
||||||
void OnShaderInvalidated(const Shader* shader) const;
|
void OnShaderInvalidated(const Shader* shader) const;
|
||||||
|
|
||||||
|
static bool Initialize();
|
||||||
|
static void Uninitialize();
|
||||||
|
|
||||||
struct ShaderUniforms
|
struct ShaderUniforms
|
||||||
{
|
{
|
||||||
NazaraSlot(Shader, OnShaderUniformInvalidated, shaderUniformInvalidatedSlot);
|
NazaraSlot(Shader, OnShaderUniformInvalidated, shaderUniformInvalidatedSlot);
|
||||||
|
|
@ -41,8 +52,18 @@ namespace Nz
|
||||||
};
|
};
|
||||||
|
|
||||||
mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
|
mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
|
||||||
|
mutable std::vector<std::pair<const VertexStruct_XYZ_Color_UV*, std::size_t>> m_spriteChains;
|
||||||
|
Buffer m_vertexBuffer;
|
||||||
RenderStates m_clearStates;
|
RenderStates m_clearStates;
|
||||||
ShaderRef m_clearShader;
|
ShaderRef m_clearShader;
|
||||||
|
Texture m_whiteTexture;
|
||||||
|
VertexBuffer m_billboardPointBuffer;
|
||||||
|
VertexBuffer m_spriteBuffer;
|
||||||
|
|
||||||
|
static IndexBuffer s_quadIndexBuffer;
|
||||||
|
static VertexBuffer s_quadVertexBuffer;
|
||||||
|
static VertexDeclaration s_billboardInstanceDeclaration;
|
||||||
|
static VertexDeclaration s_billboardVertexDeclaration;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_DEFERREDRENDERQUEUE_HPP
|
||||||
|
#define NAZARA_DEFERREDRENDERQUEUE_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Graphics/BasicRenderQueue.hpp>
|
||||||
|
#include <Nazara/Graphics/Material.hpp>
|
||||||
|
#include <Nazara/Math/Box.hpp>
|
||||||
|
#include <Nazara/Math/Matrix4.hpp>
|
||||||
|
#include <Nazara/Utility/IndexBuffer.hpp>
|
||||||
|
#include <Nazara/Utility/MeshData.hpp>
|
||||||
|
#include <Nazara/Utility/VertexBuffer.hpp>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class BasicRenderQueue;
|
||||||
|
|
||||||
|
class NAZARA_GRAPHICS_API DeferredProxyRenderQueue final : public AbstractRenderQueue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct BillboardData;
|
||||||
|
|
||||||
|
inline DeferredProxyRenderQueue(BasicRenderQueue* deferredQueue, BasicRenderQueue* forwardQueue);
|
||||||
|
~DeferredProxyRenderQueue() = default;
|
||||||
|
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
|
||||||
|
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
|
||||||
|
void AddDrawable(int renderOrder, const Drawable* drawable) override;
|
||||||
|
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix, const Recti& scissorRect) override;
|
||||||
|
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay = nullptr) override;
|
||||||
|
|
||||||
|
void Clear(bool fully = false) override;
|
||||||
|
|
||||||
|
inline BasicRenderQueue* GetDeferredRenderQueue();
|
||||||
|
inline BasicRenderQueue* GetForwardRenderQueue();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BasicRenderQueue * m_deferredRenderQueue;
|
||||||
|
BasicRenderQueue* m_forwardRenderQueue;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/DeferredProxyRenderQueue.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_DEFERREDRENDERQUEUE_HPP
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/DeferredProxyRenderQueue.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* \brief Constructs a DeferredProxyRenderQueue using a deferred and a forward queues
|
||||||
|
*
|
||||||
|
* \param deferredQueue Deferred queue which will be used for non-blended objects
|
||||||
|
* \param forwardQueue Forward queue which will be used for blended objects
|
||||||
|
*/
|
||||||
|
inline DeferredProxyRenderQueue::DeferredProxyRenderQueue(BasicRenderQueue* deferredQueue, BasicRenderQueue* forwardQueue) :
|
||||||
|
m_deferredRenderQueue(deferredQueue),
|
||||||
|
m_forwardRenderQueue(forwardQueue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BasicRenderQueue* DeferredProxyRenderQueue::GetDeferredRenderQueue()
|
||||||
|
{
|
||||||
|
return m_deferredRenderQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BasicRenderQueue* DeferredProxyRenderQueue::GetForwardRenderQueue()
|
||||||
|
{
|
||||||
|
return m_forwardRenderQueue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,10 +14,10 @@
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class DeferredRenderTechnique;
|
class DeferredRenderTechnique;
|
||||||
class DeferredRenderQueue;
|
class DeferredProxyRenderQueue;
|
||||||
struct SceneData;
|
|
||||||
class RenderTexture;
|
class RenderTexture;
|
||||||
class Texture;
|
class Texture;
|
||||||
|
struct SceneData;
|
||||||
|
|
||||||
class NAZARA_GRAPHICS_API DeferredRenderPass
|
class NAZARA_GRAPHICS_API DeferredRenderPass
|
||||||
{
|
{
|
||||||
|
|
@ -42,7 +42,7 @@ namespace Nz
|
||||||
protected:
|
protected:
|
||||||
Vector2ui m_dimensions;
|
Vector2ui m_dimensions;
|
||||||
DeferredRenderTechnique* m_deferredTechnique;
|
DeferredRenderTechnique* m_deferredTechnique;
|
||||||
DeferredRenderQueue* m_renderQueue;
|
DeferredProxyRenderQueue* m_renderQueue;
|
||||||
RenderTexture* m_GBufferRTT;
|
RenderTexture* m_GBufferRTT;
|
||||||
RenderTexture* m_workRTT;
|
RenderTexture* m_workRTT;
|
||||||
Texture* m_depthStencilTexture;
|
Texture* m_depthStencilTexture;
|
||||||
|
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
// Copyright (C) 2017 Jérôme Leclercq
|
|
||||||
// This file is part of the "Nazara Engine - Graphics module"
|
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef NAZARA_DEFERREDRENDERQUEUE_HPP
|
|
||||||
#define NAZARA_DEFERREDRENDERQUEUE_HPP
|
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
|
||||||
#include <Nazara/Graphics/ForwardRenderQueue.hpp>
|
|
||||||
#include <Nazara/Graphics/Material.hpp>
|
|
||||||
#include <Nazara/Math/Box.hpp>
|
|
||||||
#include <Nazara/Math/Matrix4.hpp>
|
|
||||||
#include <Nazara/Utility/IndexBuffer.hpp>
|
|
||||||
#include <Nazara/Utility/MeshData.hpp>
|
|
||||||
#include <Nazara/Utility/VertexBuffer.hpp>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace Nz
|
|
||||||
{
|
|
||||||
class NAZARA_GRAPHICS_API DeferredRenderQueue : public AbstractRenderQueue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DeferredRenderQueue(ForwardRenderQueue* forwardQueue);
|
|
||||||
~DeferredRenderQueue() = default;
|
|
||||||
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
|
|
||||||
void AddDrawable(int renderOrder, const Drawable* drawable) override;
|
|
||||||
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override;
|
|
||||||
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay = nullptr) override;
|
|
||||||
|
|
||||||
void Clear(bool fully = false) override;
|
|
||||||
|
|
||||||
struct MeshInstanceEntry
|
|
||||||
{
|
|
||||||
NazaraSlot(IndexBuffer, OnIndexBufferRelease, indexBufferReleaseSlot);
|
|
||||||
NazaraSlot(VertexBuffer, OnVertexBufferRelease, vertexBufferReleaseSlot);
|
|
||||||
|
|
||||||
std::vector<Matrix4f> instances;
|
|
||||||
};
|
|
||||||
|
|
||||||
using MeshInstanceContainer = std::map<MeshData, MeshInstanceEntry, ForwardRenderQueue::MeshDataComparator>;
|
|
||||||
|
|
||||||
struct BatchedModelEntry
|
|
||||||
{
|
|
||||||
NazaraSlot(Material, OnMaterialRelease, materialReleaseSlot);
|
|
||||||
|
|
||||||
MeshInstanceContainer meshMap;
|
|
||||||
bool enabled = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
using MeshMaterialBatches = std::map<const Material*, BatchedModelEntry, ForwardRenderQueue::MaterialComparator>;
|
|
||||||
|
|
||||||
struct BatchedMaterialEntry
|
|
||||||
{
|
|
||||||
std::size_t maxInstanceCount = 0;
|
|
||||||
MeshMaterialBatches materialMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
using MeshPipelineBatches = std::map<const MaterialPipeline*, BatchedMaterialEntry, ForwardRenderQueue::MaterialPipelineComparator>;
|
|
||||||
|
|
||||||
struct Layer
|
|
||||||
{
|
|
||||||
MeshPipelineBatches opaqueModels;
|
|
||||||
unsigned int clearCount = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<int, Layer> layers;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Layer& GetLayer(unsigned int i); ///TODO: Inline
|
|
||||||
|
|
||||||
ForwardRenderQueue* m_forwardQueue;
|
|
||||||
|
|
||||||
void OnIndexBufferInvalidation(const IndexBuffer* indexBuffer);
|
|
||||||
void OnMaterialInvalidation(const Material* material);
|
|
||||||
void OnVertexBufferInvalidation(const VertexBuffer* vertexBuffer);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NAZARA_DEFERREDRENDERQUEUE_HPP
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
|
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
|
||||||
#include <Nazara/Graphics/DeferredRenderQueue.hpp>
|
#include <Nazara/Graphics/DeferredProxyRenderQueue.hpp>
|
||||||
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
||||||
#include <Nazara/Math/Vector2.hpp>
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
#include <Nazara/Renderer/RenderTexture.hpp>
|
#include <Nazara/Renderer/RenderTexture.hpp>
|
||||||
|
|
@ -64,8 +64,9 @@ namespace Nz
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<RenderPassType, std::map<int, std::unique_ptr<DeferredRenderPass>>, RenderPassComparator> m_passes;
|
std::map<RenderPassType, std::map<int, std::unique_ptr<DeferredRenderPass>>, RenderPassComparator> m_passes;
|
||||||
ForwardRenderTechnique m_forwardTechnique; // Must be initialized before the RenderQueue
|
BasicRenderQueue m_deferredRenderQueue; // Must be initialized before the ProxyRenderQueue
|
||||||
DeferredRenderQueue m_renderQueue;
|
ForwardRenderTechnique m_forwardTechnique; // Must be initialized before the ProxyRenderQueue
|
||||||
|
DeferredProxyRenderQueue m_renderQueue;
|
||||||
mutable TextureRef m_depthStencilTexture;
|
mutable TextureRef m_depthStencilTexture;
|
||||||
mutable RenderTexture m_GBufferRTT;
|
mutable RenderTexture m_GBufferRTT;
|
||||||
mutable RenderTexture m_workRTT;
|
mutable RenderTexture m_workRTT;
|
||||||
|
|
|
||||||
|
|
@ -8,33 +8,33 @@
|
||||||
#define NAZARA_DEPTHRENDERQUEUE_HPP
|
#define NAZARA_DEPTHRENDERQUEUE_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
#include <Nazara/Graphics/ForwardRenderQueue.hpp>
|
#include <Nazara/Graphics/BasicRenderQueue.hpp>
|
||||||
#include <Nazara/Math/Box.hpp>
|
#include <Nazara/Math/Box.hpp>
|
||||||
#include <Nazara/Math/Matrix4.hpp>
|
#include <Nazara/Math/Matrix4.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class NAZARA_GRAPHICS_API DepthRenderQueue : public ForwardRenderQueue
|
class NAZARA_GRAPHICS_API DepthRenderQueue : public BasicRenderQueue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DepthRenderQueue();
|
DepthRenderQueue();
|
||||||
~DepthRenderQueue() = default;
|
~DepthRenderQueue() = default;
|
||||||
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
|
void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
|
void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
|
void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
|
void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
|
void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
|
void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
|
void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
|
void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
|
||||||
void AddDirectionalLight(const DirectionalLight& light) override;
|
void AddDirectionalLight(const DirectionalLight& light) override;
|
||||||
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override;
|
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix, const Recti& scissorRect) override;
|
||||||
void AddPointLight(const PointLight& light) override;
|
void AddPointLight(const PointLight& light) override;
|
||||||
void AddSpotLight(const SpotLight& light) override;
|
void AddSpotLight(const SpotLight& light) override;
|
||||||
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay = nullptr) override;
|
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay = nullptr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline bool IsMaterialSuitable(const Material* material) const;
|
inline bool IsMaterialSuitable(const Material* material) const;
|
||||||
|
|
||||||
MaterialRef m_baseMaterial;
|
MaterialRef m_baseMaterial;
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,12 @@ namespace Nz
|
||||||
private:
|
private:
|
||||||
struct ShaderUniforms;
|
struct ShaderUniforms;
|
||||||
|
|
||||||
void DrawBasicSprites(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
|
void DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Billboard>& billboards) const;
|
||||||
void DrawBillboards(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
|
void DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::BillboardChain>& billboards) const;
|
||||||
void DrawOpaqueModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
|
void DrawCustomDrawables(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::CustomDrawable>& customDrawables) const;
|
||||||
|
void DrawModels(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Model>& models) const;
|
||||||
|
void DrawSprites(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::SpriteChain>& sprites) const;
|
||||||
|
|
||||||
const ShaderUniforms* GetShaderUniforms(const Shader* shader) const;
|
const ShaderUniforms* GetShaderUniforms(const Shader* shader) const;
|
||||||
void OnShaderInvalidated(const Shader* shader) const;
|
void OnShaderInvalidated(const Shader* shader) const;
|
||||||
|
|
||||||
|
|
@ -59,11 +62,14 @@ namespace Nz
|
||||||
};
|
};
|
||||||
|
|
||||||
mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
|
mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
|
||||||
|
mutable std::vector<std::pair<const VertexStruct_XYZ_Color_UV*, std::size_t>> m_spriteChains;
|
||||||
Buffer m_vertexBuffer;
|
Buffer m_vertexBuffer;
|
||||||
mutable DepthRenderQueue m_renderQueue;
|
RenderStates m_clearStates;
|
||||||
|
ShaderRef m_clearShader;
|
||||||
Texture m_whiteTexture;
|
Texture m_whiteTexture;
|
||||||
VertexBuffer m_billboardPointBuffer;
|
VertexBuffer m_billboardPointBuffer;
|
||||||
VertexBuffer m_spriteBuffer;
|
VertexBuffer m_spriteBuffer;
|
||||||
|
mutable DepthRenderQueue m_renderQueue;
|
||||||
|
|
||||||
static IndexBuffer s_quadIndexBuffer;
|
static IndexBuffer s_quadIndexBuffer;
|
||||||
static VertexBuffer s_quadVertexBuffer;
|
static VertexBuffer s_quadVertexBuffer;
|
||||||
|
|
|
||||||
|
|
@ -1,201 +0,0 @@
|
||||||
// Copyright (C) 2017 Jérôme Leclercq
|
|
||||||
// This file is part of the "Nazara Engine - Graphics module"
|
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef NAZARA_FORWARDRENDERQUEUE_HPP
|
|
||||||
#define NAZARA_FORWARDRENDERQUEUE_HPP
|
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
|
||||||
#include <Nazara/Core/Color.hpp>
|
|
||||||
#include <Nazara/Graphics/AbstractRenderQueue.hpp>
|
|
||||||
#include <Nazara/Graphics/Material.hpp>
|
|
||||||
#include <Nazara/Math/Box.hpp>
|
|
||||||
#include <Nazara/Math/Matrix4.hpp>
|
|
||||||
#include <Nazara/Math/Plane.hpp>
|
|
||||||
#include <Nazara/Utility/IndexBuffer.hpp>
|
|
||||||
#include <Nazara/Utility/MeshData.hpp>
|
|
||||||
#include <Nazara/Utility/VertexBuffer.hpp>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace Nz
|
|
||||||
{
|
|
||||||
class AbstractViewer;
|
|
||||||
|
|
||||||
class NAZARA_GRAPHICS_API ForwardRenderQueue : public AbstractRenderQueue
|
|
||||||
{
|
|
||||||
friend class ForwardRenderTechnique;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ForwardRenderQueue() = default;
|
|
||||||
~ForwardRenderQueue() = default;
|
|
||||||
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
|
|
||||||
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
|
|
||||||
void AddDrawable(int renderOrder, const Drawable* drawable) override;
|
|
||||||
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override;
|
|
||||||
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay = nullptr) override;
|
|
||||||
|
|
||||||
void Clear(bool fully = false) override;
|
|
||||||
|
|
||||||
void Sort(const AbstractViewer* viewer);
|
|
||||||
|
|
||||||
struct MaterialComparator
|
|
||||||
{
|
|
||||||
bool operator()(const Material* mat1, const Material* mat2) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MaterialPipelineComparator
|
|
||||||
{
|
|
||||||
bool operator()(const MaterialPipeline* pipeline1, const MaterialPipeline* pipeline2) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Billboards
|
|
||||||
struct BillboardData
|
|
||||||
{
|
|
||||||
Color color;
|
|
||||||
Vector3f center;
|
|
||||||
Vector2f size;
|
|
||||||
Vector2f sinCos;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BatchedBillboardEntry
|
|
||||||
{
|
|
||||||
NazaraSlot(Material, OnMaterialRelease, materialReleaseSlot);
|
|
||||||
|
|
||||||
std::vector<BillboardData> billboards;
|
|
||||||
};
|
|
||||||
|
|
||||||
using BatchedBillboardContainer = std::map<const Material*, BatchedBillboardEntry, MaterialComparator>;
|
|
||||||
|
|
||||||
struct BatchedBillboardPipelineEntry
|
|
||||||
{
|
|
||||||
BatchedBillboardContainer materialMap;
|
|
||||||
bool enabled = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
using BillboardPipelineBatches = std::map<const MaterialPipeline*, BatchedBillboardPipelineEntry, MaterialPipelineComparator>;
|
|
||||||
|
|
||||||
/// Sprites
|
|
||||||
struct SpriteChain_XYZ_Color_UV
|
|
||||||
{
|
|
||||||
const VertexStruct_XYZ_Color_UV* vertices;
|
|
||||||
std::size_t spriteCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BatchedSpriteEntry
|
|
||||||
{
|
|
||||||
NazaraSlot(Texture, OnTextureRelease, textureReleaseSlot);
|
|
||||||
|
|
||||||
std::vector<SpriteChain_XYZ_Color_UV> spriteChains;
|
|
||||||
};
|
|
||||||
|
|
||||||
using SpriteOverlayBatches = std::map<const Texture*, BatchedSpriteEntry>;
|
|
||||||
|
|
||||||
struct BatchedBasicSpriteEntry
|
|
||||||
{
|
|
||||||
NazaraSlot(Material, OnMaterialRelease, materialReleaseSlot);
|
|
||||||
|
|
||||||
SpriteOverlayBatches overlayMap;
|
|
||||||
bool enabled = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
using SpriteMaterialBatches = std::map<const Material*, BatchedBasicSpriteEntry, MaterialComparator>;
|
|
||||||
|
|
||||||
struct BatchedSpritePipelineEntry
|
|
||||||
{
|
|
||||||
SpriteMaterialBatches materialMap;
|
|
||||||
bool enabled = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
using SpritePipelineBatches = std::map<const MaterialPipeline*, BatchedSpritePipelineEntry, MaterialPipelineComparator>;
|
|
||||||
|
|
||||||
/// Meshes
|
|
||||||
struct MeshDataComparator
|
|
||||||
{
|
|
||||||
bool operator()(const MeshData& data1, const MeshData& data2) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MeshInstanceEntry
|
|
||||||
{
|
|
||||||
NazaraSlot(IndexBuffer, OnIndexBufferRelease, indexBufferReleaseSlot);
|
|
||||||
NazaraSlot(VertexBuffer, OnVertexBufferRelease, vertexBufferReleaseSlot);
|
|
||||||
|
|
||||||
std::vector<Matrix4f> instances;
|
|
||||||
Spheref squaredBoundingSphere;
|
|
||||||
};
|
|
||||||
|
|
||||||
using MeshInstanceContainer = std::map<MeshData, MeshInstanceEntry, MeshDataComparator>;
|
|
||||||
|
|
||||||
struct BatchedModelEntry
|
|
||||||
{
|
|
||||||
NazaraSlot(Material, OnMaterialRelease, materialReleaseSlot);
|
|
||||||
|
|
||||||
MeshInstanceContainer meshMap;
|
|
||||||
bool enabled = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
using MeshMaterialBatches = std::map<const Material*, BatchedModelEntry, MaterialComparator>;
|
|
||||||
|
|
||||||
struct BatchedMaterialEntry
|
|
||||||
{
|
|
||||||
std::size_t maxInstanceCount = 0;
|
|
||||||
MeshMaterialBatches materialMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
using MeshPipelineBatches = std::map<const MaterialPipeline*, BatchedMaterialEntry, MaterialPipelineComparator>;
|
|
||||||
|
|
||||||
struct UnbatchedModelData
|
|
||||||
{
|
|
||||||
Matrix4f transformMatrix;
|
|
||||||
MeshData meshData;
|
|
||||||
Spheref obbSphere;
|
|
||||||
const Material* material;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct UnbatchedSpriteData
|
|
||||||
{
|
|
||||||
std::size_t spriteCount;
|
|
||||||
const Material* material;
|
|
||||||
const Texture* overlay;
|
|
||||||
const VertexStruct_XYZ_Color_UV* vertices;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Layer
|
|
||||||
{
|
|
||||||
BillboardPipelineBatches billboards;
|
|
||||||
SpritePipelineBatches opaqueSprites;
|
|
||||||
MeshPipelineBatches opaqueModels;
|
|
||||||
std::vector<std::size_t> depthSortedMeshes;
|
|
||||||
std::vector<std::size_t> depthSortedSprites;
|
|
||||||
std::vector<UnbatchedModelData> depthSortedMeshData;
|
|
||||||
std::vector<UnbatchedSpriteData> depthSortedSpriteData;
|
|
||||||
std::vector<const Drawable*> otherDrawables;
|
|
||||||
unsigned int clearCount = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<int, Layer> layers;
|
|
||||||
|
|
||||||
private:
|
|
||||||
BillboardData* GetBillboardData(int renderOrder, const Material* material, unsigned int count);
|
|
||||||
Layer& GetLayer(int i); ///TODO: Inline
|
|
||||||
|
|
||||||
void SortBillboards(Layer& layer, const Planef& nearPlane);
|
|
||||||
void SortForOrthographic(const AbstractViewer* viewer);
|
|
||||||
void SortForPerspective(const AbstractViewer* viewer);
|
|
||||||
|
|
||||||
void OnIndexBufferInvalidation(const IndexBuffer* indexBuffer);
|
|
||||||
void OnMaterialInvalidation(const Material* material);
|
|
||||||
void OnTextureInvalidation(const Texture* texture);
|
|
||||||
void OnVertexBufferInvalidation(const VertexBuffer* vertexBuffer);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NAZARA_FORWARDRENDERQUEUE_HPP
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
|
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
|
||||||
#include <Nazara/Graphics/Config.hpp>
|
#include <Nazara/Graphics/Config.hpp>
|
||||||
#include <Nazara/Graphics/ForwardRenderQueue.hpp>
|
#include <Nazara/Graphics/BasicRenderQueue.hpp>
|
||||||
#include <Nazara/Graphics/Light.hpp>
|
#include <Nazara/Graphics/Light.hpp>
|
||||||
#include <Nazara/Renderer/Shader.hpp>
|
#include <Nazara/Renderer/Shader.hpp>
|
||||||
#include <Nazara/Utility/IndexBuffer.hpp>
|
#include <Nazara/Utility/IndexBuffer.hpp>
|
||||||
|
|
@ -40,11 +40,12 @@ namespace Nz
|
||||||
struct ShaderUniforms;
|
struct ShaderUniforms;
|
||||||
|
|
||||||
void ChooseLights(const Spheref& object, bool includeDirectionalLights = true) const;
|
void ChooseLights(const Spheref& object, bool includeDirectionalLights = true) const;
|
||||||
void DrawBasicSprites(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
|
void DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Billboard>& billboards) const;
|
||||||
void DrawBillboards(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
|
void DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::BillboardChain>& billboards) const;
|
||||||
void DrawOpaqueModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
|
void DrawCustomDrawables(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::CustomDrawable>& customDrawables) const;
|
||||||
void DrawOrderedSprites(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
|
void DrawModels(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Model>& models) const;
|
||||||
void DrawTransparentModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
|
void DrawSprites(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::SpriteChain>& sprites) const;
|
||||||
|
|
||||||
const ShaderUniforms* GetShaderUniforms(const Shader* shader) const;
|
const ShaderUniforms* GetShaderUniforms(const Shader* shader) const;
|
||||||
void OnShaderInvalidated(const Shader* shader) const;
|
void OnShaderInvalidated(const Shader* shader) const;
|
||||||
void SendLightUniforms(const Shader* shader, const LightUniforms& uniforms, unsigned int index, unsigned int lightIndex, unsigned int uniformOffset) const;
|
void SendLightUniforms(const Shader* shader, const LightUniforms& uniforms, unsigned int index, unsigned int lightIndex, unsigned int uniformOffset) const;
|
||||||
|
|
@ -84,8 +85,9 @@ namespace Nz
|
||||||
|
|
||||||
mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
|
mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
|
||||||
mutable std::vector<LightIndex> m_lights;
|
mutable std::vector<LightIndex> m_lights;
|
||||||
|
mutable std::vector<std::pair<const VertexStruct_XYZ_Color_UV*, std::size_t>> m_spriteChains;
|
||||||
Buffer m_vertexBuffer;
|
Buffer m_vertexBuffer;
|
||||||
mutable ForwardRenderQueue m_renderQueue;
|
mutable BasicRenderQueue m_renderQueue;
|
||||||
Texture m_whiteTexture;
|
Texture m_whiteTexture;
|
||||||
VertexBuffer m_billboardPointBuffer;
|
VertexBuffer m_billboardPointBuffer;
|
||||||
VertexBuffer m_spriteBuffer;
|
VertexBuffer m_spriteBuffer;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// This file is part of the "Nazara Engine - Graphics module"
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ namespace Nz
|
||||||
InstancedRenderable(InstancedRenderable&& renderable) = delete;
|
InstancedRenderable(InstancedRenderable&& renderable) = delete;
|
||||||
virtual ~InstancedRenderable();
|
virtual ~InstancedRenderable();
|
||||||
|
|
||||||
virtual void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const = 0;
|
virtual void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const = 0;
|
||||||
|
|
||||||
virtual bool Cull(const Frustumf& frustum, const InstanceData& instanceData) const;
|
virtual bool Cull(const Frustumf& frustum, const InstanceData& instanceData) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <Nazara/Core/Resource.hpp>
|
#include <Nazara/Core/Resource.hpp>
|
||||||
#include <Nazara/Core/ResourceLoader.hpp>
|
#include <Nazara/Core/ResourceLoader.hpp>
|
||||||
#include <Nazara/Core/ResourceParameters.hpp>
|
#include <Nazara/Core/ResourceParameters.hpp>
|
||||||
|
#include <Nazara/Math/Rect.hpp>
|
||||||
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
||||||
#include <Nazara/Graphics/Material.hpp>
|
#include <Nazara/Graphics/Material.hpp>
|
||||||
#include <Nazara/Utility/Mesh.hpp>
|
#include <Nazara/Utility/Mesh.hpp>
|
||||||
|
|
@ -44,8 +45,8 @@ namespace Nz
|
||||||
Model(Model&& model) = default;
|
Model(Model&& model) = default;
|
||||||
virtual ~Model();
|
virtual ~Model();
|
||||||
|
|
||||||
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override;
|
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
|
||||||
inline void AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, unsigned int renderOrder = 0);
|
inline void AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, int renderOrder = 0, const Recti& scissorRect = Recti(-1, -1, -1, -1)) const;
|
||||||
|
|
||||||
using InstancedRenderable::GetMaterial;
|
using InstancedRenderable::GetMaterial;
|
||||||
const MaterialRef& GetMaterial(const String& subMeshName) const;
|
const MaterialRef& GetMaterial(const String& subMeshName) const;
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,15 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param renderQueue Queue to be added
|
* \param renderQueue Queue to be added
|
||||||
* \param transformMatrix Transform matrix to be used for rendering the model
|
* \param transformMatrix Transform matrix to be used for rendering the model
|
||||||
* \param renderOrder Specify the renderqueue layer to be used
|
* \param renderOrder Specify the render queue layer to be used
|
||||||
|
* \param scissorRect The Scissor rect to uses for rendering
|
||||||
*/
|
*/
|
||||||
inline void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, unsigned int renderOrder)
|
void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, int renderOrder, const Recti& scissorRect) const
|
||||||
{
|
{
|
||||||
InstanceData instanceData(Nz::Matrix4f::Identity());
|
InstanceData instanceData(Nz::Matrix4f::Identity());
|
||||||
instanceData.renderOrder = renderOrder;
|
instanceData.renderOrder = renderOrder;
|
||||||
instanceData.transformMatrix = transformMatrix;
|
instanceData.transformMatrix = transformMatrix;
|
||||||
return AddToRenderQueue(renderQueue, instanceData);
|
return AddToRenderQueue(renderQueue, instanceData, scissorRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_RENDERQUEUE_HPP
|
||||||
|
#define NAZARA_RENDERQUEUE_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class RenderQueueInternal
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Index = Nz::UInt64;
|
||||||
|
|
||||||
|
RenderQueueInternal() = default;
|
||||||
|
~RenderQueueInternal() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using RenderDataPair = std::pair<Index, std::size_t>;
|
||||||
|
|
||||||
|
void Sort();
|
||||||
|
|
||||||
|
std::vector<RenderDataPair> m_orderedRenderQueue;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
class RenderQueue : public RenderQueueInternal
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class const_iterator;
|
||||||
|
friend const_iterator;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
|
||||||
|
RenderQueue() = default;
|
||||||
|
RenderQueue(const RenderQueue&) = default;
|
||||||
|
RenderQueue(RenderQueue&&) = default;
|
||||||
|
~RenderQueue() = default;
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
void Insert(RenderData&& data);
|
||||||
|
|
||||||
|
template<typename IndexFunc> void Sort(IndexFunc&& func);
|
||||||
|
|
||||||
|
// STL API
|
||||||
|
inline const_iterator begin() const;
|
||||||
|
inline bool empty() const;
|
||||||
|
inline const_iterator end() const;
|
||||||
|
inline size_type size() const;
|
||||||
|
|
||||||
|
RenderQueue& operator=(const RenderQueue&) = default;
|
||||||
|
RenderQueue& operator=(RenderQueue&&) = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const RenderData& GetData(std::size_t i) const;
|
||||||
|
|
||||||
|
std::vector<RenderData> m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
class RenderQueue<RenderData>::const_iterator : public std::iterator<std::forward_iterator_tag, const RenderData>
|
||||||
|
{
|
||||||
|
friend RenderQueue;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const_iterator(const const_iterator& it);
|
||||||
|
|
||||||
|
const RenderData& operator*() const;
|
||||||
|
|
||||||
|
const_iterator& operator=(const const_iterator& it);
|
||||||
|
const_iterator& operator++();
|
||||||
|
const_iterator operator++(int);
|
||||||
|
|
||||||
|
bool operator==(const const_iterator& rhs) const;
|
||||||
|
bool operator!=(const const_iterator& rhs) const;
|
||||||
|
|
||||||
|
void swap(const_iterator& rhs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const_iterator(const RenderQueue* queue, std::size_t nextId);
|
||||||
|
|
||||||
|
std::size_t m_nextDataId;
|
||||||
|
const RenderQueue* m_queue;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/RenderQueue.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_RENDERQUEUE_HPP
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/RenderQueue.hpp>
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
template<typename RenderData>
|
||||||
|
void RenderQueue<RenderData>::Clear()
|
||||||
|
{
|
||||||
|
m_orderedRenderQueue.clear();
|
||||||
|
m_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
void RenderQueue<RenderData>::Insert(RenderData&& data)
|
||||||
|
{
|
||||||
|
m_data.emplace_back(std::move(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
template<typename IndexFunc>
|
||||||
|
void RenderQueue<RenderData>::Sort(IndexFunc&& func)
|
||||||
|
{
|
||||||
|
m_orderedRenderQueue.clear();
|
||||||
|
m_orderedRenderQueue.reserve(m_data.size());
|
||||||
|
|
||||||
|
std::size_t dataIndex = 0;
|
||||||
|
for (const RenderData& renderData : m_data)
|
||||||
|
m_orderedRenderQueue.emplace_back(func(renderData), dataIndex++);
|
||||||
|
|
||||||
|
RenderQueueInternal::Sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
typename RenderQueue<RenderData>::const_iterator RenderQueue<RenderData>::begin() const
|
||||||
|
{
|
||||||
|
return const_iterator(this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
bool RenderQueue<RenderData>::empty() const
|
||||||
|
{
|
||||||
|
return m_orderedRenderQueue.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
typename RenderQueue<RenderData>::const_iterator RenderQueue<RenderData>::end() const
|
||||||
|
{
|
||||||
|
return const_iterator(this, m_orderedRenderQueue.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
typename RenderQueue<RenderData>::size_type RenderQueue<RenderData>::size() const
|
||||||
|
{
|
||||||
|
return m_orderedRenderQueue.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
const RenderData& RenderQueue<RenderData>::GetData(std::size_t i) const
|
||||||
|
{
|
||||||
|
NazaraAssert(i < m_orderedRenderQueue.size(), "Cannot dereference post-end iterator");
|
||||||
|
|
||||||
|
return m_data[m_orderedRenderQueue[i].second];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
RenderQueue<RenderData>::const_iterator::const_iterator(const RenderQueue* queue, std::size_t nextId) :
|
||||||
|
m_nextDataId(nextId),
|
||||||
|
m_queue(queue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
RenderQueue<RenderData>::const_iterator::const_iterator(const const_iterator& it) :
|
||||||
|
m_nextDataId(it.m_nextDataId),
|
||||||
|
m_queue(it.m_queue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
const RenderData& RenderQueue<RenderData>::const_iterator::operator*() const
|
||||||
|
{
|
||||||
|
return m_queue->GetData(m_nextDataId);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
typename RenderQueue<RenderData>::const_iterator& RenderQueue<RenderData>::const_iterator::operator=(const const_iterator& it)
|
||||||
|
{
|
||||||
|
m_nextDataId = it.m_nextDataId;
|
||||||
|
m_queue = it.m_queue;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
typename RenderQueue<RenderData>::const_iterator& RenderQueue<RenderData>::const_iterator::operator++()
|
||||||
|
{
|
||||||
|
++m_nextDataId;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
typename RenderQueue<RenderData>::const_iterator RenderQueue<RenderData>::const_iterator::operator++(int)
|
||||||
|
{
|
||||||
|
return iterator(m_queue, m_nextDataId++);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
bool RenderQueue<RenderData>::const_iterator::operator==(const typename RenderQueue<RenderData>::const_iterator& rhs) const
|
||||||
|
{
|
||||||
|
NazaraAssert(m_queue == rhs.m_queue, "Cannot compare iterator coming from different queues");
|
||||||
|
|
||||||
|
return m_nextDataId == rhs.m_nextDataId;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
bool RenderQueue<RenderData>::const_iterator::operator!=(const typename RenderQueue<RenderData>::const_iterator& rhs) const
|
||||||
|
{
|
||||||
|
return !operator==(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RenderData>
|
||||||
|
void RenderQueue<RenderData>::const_iterator::swap(typename RenderQueue<RenderData>::const_iterator& rhs)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_queue == rhs.m_queue, "Cannot swap iterator coming from different queues");
|
||||||
|
|
||||||
|
using std::swap;
|
||||||
|
|
||||||
|
swap(m_nextDataId, rhs.m_nextDataId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ namespace Nz
|
||||||
SkeletalModel(SkeletalModel&& model) = default;
|
SkeletalModel(SkeletalModel&& model) = default;
|
||||||
~SkeletalModel() = default;
|
~SkeletalModel() = default;
|
||||||
|
|
||||||
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override;
|
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
|
||||||
void AdvanceAnimation(float elapsedTime);
|
void AdvanceAnimation(float elapsedTime);
|
||||||
|
|
||||||
SkeletalModel* Clone() const;
|
SkeletalModel* Clone() const;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace Nz
|
||||||
Sprite(Sprite&&) = delete;
|
Sprite(Sprite&&) = delete;
|
||||||
~Sprite() = default;
|
~Sprite() = default;
|
||||||
|
|
||||||
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override;
|
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
|
||||||
|
|
||||||
inline const Color& GetColor() const;
|
inline const Color& GetColor() const;
|
||||||
inline const Color& GetCornerColor(RectCorner corner) const;
|
inline const Color& GetCornerColor(RectCorner corner) const;
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
MaterialRef material = Material::New();
|
MaterialRef material = Material::New();
|
||||||
material->EnableFaceCulling(false);
|
material->EnableFaceCulling(false);
|
||||||
|
material->EnableScissorTest(true);
|
||||||
|
|
||||||
SetMaterial(std::move(material));
|
SetMaterial(std::move(material));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ namespace Nz
|
||||||
inline TextSprite(const TextSprite& sprite);
|
inline TextSprite(const TextSprite& sprite);
|
||||||
~TextSprite() = default;
|
~TextSprite() = default;
|
||||||
|
|
||||||
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override;
|
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
|
||||||
|
|
||||||
inline void Clear();
|
inline void Clear();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,14 +110,7 @@ namespace Nz
|
||||||
|
|
||||||
inline void TextSprite::SetDefaultMaterial()
|
inline void TextSprite::SetDefaultMaterial()
|
||||||
{
|
{
|
||||||
MaterialRef material = Material::New();
|
SetMaterial(Material::New("Translucent2D"));
|
||||||
material->EnableBlending(true);
|
|
||||||
material->EnableDepthWrite(false);
|
|
||||||
material->EnableFaceCulling(false);
|
|
||||||
material->SetDstBlend(BlendFunc_InvSrcAlpha);
|
|
||||||
material->SetSrcBlend(BlendFunc_SrcAlpha);
|
|
||||||
|
|
||||||
SetMaterial(material);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace Nz
|
||||||
TileMap(TileMap&&) = delete;
|
TileMap(TileMap&&) = delete;
|
||||||
~TileMap() = default;
|
~TileMap() = default;
|
||||||
|
|
||||||
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override;
|
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
|
||||||
|
|
||||||
inline void DisableTile(const Vector2ui& tilePos);
|
inline void DisableTile(const Vector2ui& tilePos);
|
||||||
inline void DisableTiles();
|
inline void DisableTiles();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,947 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/BasicRenderQueue.hpp>
|
||||||
|
#include <Nazara/Graphics/AbstractViewer.hpp>
|
||||||
|
#include <Nazara/Utility/VertexStruct.hpp>
|
||||||
|
#include <limits>
|
||||||
|
#include <Nazara/Graphics/Debug.hpp>
|
||||||
|
|
||||||
|
///TODO: Replace sinus/cosinus by a lookup table (which will lead to a speed up about 10x)
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* \ingroup graphics
|
||||||
|
* \class Nz::BasicRenderQueue
|
||||||
|
* \brief Graphics class that represents a simple rendering queue
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Sizes of the billboards
|
||||||
|
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||||
|
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
|
*/
|
||||||
|
|
||||||
|
void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1
|
||||||
|
|
||||||
|
if (!sinCosPtr)
|
||||||
|
sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||||
|
|
||||||
|
if (!colorPtr)
|
||||||
|
colorPtr.Reset(&Color::White, 0); // Same
|
||||||
|
|
||||||
|
if (material->IsDepthSortingEnabled())
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
depthSortedBillboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
{
|
||||||
|
*colorPtr++,
|
||||||
|
*positionPtr++,
|
||||||
|
*sizePtr++,
|
||||||
|
*sinCosPtr++
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::size_t billboardIndex = m_billboards.size();
|
||||||
|
m_billboards.resize(billboardIndex + billboardCount);
|
||||||
|
BillboardData* data = &m_billboards[billboardIndex];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
data->center = *positionPtr++;
|
||||||
|
data->color = *colorPtr++;
|
||||||
|
data->sinCos = *sinCosPtr++;
|
||||||
|
data->size = *sizePtr++;
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
billboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
billboardCount,
|
||||||
|
billboardIndex
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Sizes of the billboards
|
||||||
|
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||||
|
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
|
*/
|
||||||
|
|
||||||
|
void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1
|
||||||
|
|
||||||
|
if (!sinCosPtr)
|
||||||
|
sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||||
|
|
||||||
|
float defaultAlpha = 1.f;
|
||||||
|
|
||||||
|
if (!alphaPtr)
|
||||||
|
alphaPtr.Reset(&defaultAlpha, 0); // Same
|
||||||
|
|
||||||
|
if (material->IsDepthSortingEnabled())
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
depthSortedBillboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
{
|
||||||
|
ComputeColor(*alphaPtr++),
|
||||||
|
*positionPtr++,
|
||||||
|
*sizePtr++,
|
||||||
|
*sinCosPtr++
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::size_t billboardIndex = m_billboards.size();
|
||||||
|
m_billboards.resize(billboardIndex + billboardCount);
|
||||||
|
BillboardData* data = &m_billboards[billboardIndex];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
data->center = *positionPtr++;
|
||||||
|
data->color = ComputeColor(*alphaPtr++);
|
||||||
|
data->sinCos = *sinCosPtr++;
|
||||||
|
data->size = *sizePtr++;
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
billboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
billboardCount,
|
||||||
|
billboardIndex
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Sizes of the billboards
|
||||||
|
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||||
|
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
|
*/
|
||||||
|
|
||||||
|
void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
float defaultRotation = 0.f;
|
||||||
|
|
||||||
|
if (!anglePtr)
|
||||||
|
anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||||
|
|
||||||
|
if (!colorPtr)
|
||||||
|
colorPtr.Reset(&Color::White, 0); // Same
|
||||||
|
|
||||||
|
if (material->IsDepthSortingEnabled())
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
depthSortedBillboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
{
|
||||||
|
*colorPtr++,
|
||||||
|
*positionPtr++,
|
||||||
|
*sizePtr++,
|
||||||
|
ComputeSinCos(*anglePtr++)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::size_t billboardIndex = m_billboards.size();
|
||||||
|
m_billboards.resize(billboardIndex + billboardCount);
|
||||||
|
BillboardData* data = &m_billboards[billboardIndex];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
data->center = *positionPtr++;
|
||||||
|
data->color = *colorPtr++;
|
||||||
|
data->sinCos = ComputeSinCos(*anglePtr++);
|
||||||
|
data->size = *sizePtr++;
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
billboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
billboardCount,
|
||||||
|
billboardIndex
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Sizes of the billboards
|
||||||
|
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||||
|
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
|
*/
|
||||||
|
|
||||||
|
void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
float defaultRotation = 0.f;
|
||||||
|
|
||||||
|
if (!anglePtr)
|
||||||
|
anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||||
|
|
||||||
|
float defaultAlpha = 1.f;
|
||||||
|
|
||||||
|
if (!alphaPtr)
|
||||||
|
alphaPtr.Reset(&defaultAlpha, 0); // Same
|
||||||
|
|
||||||
|
if (material->IsDepthSortingEnabled())
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
depthSortedBillboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
{
|
||||||
|
ComputeColor(*alphaPtr++),
|
||||||
|
*positionPtr++,
|
||||||
|
*sizePtr++,
|
||||||
|
ComputeSinCos(*anglePtr++)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::size_t billboardIndex = m_billboards.size();
|
||||||
|
m_billboards.resize(billboardIndex + billboardCount);
|
||||||
|
BillboardData* data = &m_billboards[billboardIndex];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
data->center = *positionPtr++;
|
||||||
|
data->color = ComputeColor(*alphaPtr++);
|
||||||
|
data->sinCos = ComputeSinCos(*anglePtr++);
|
||||||
|
data->size = *sizePtr++;
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
billboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
billboardCount,
|
||||||
|
billboardIndex
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Size of the billboards
|
||||||
|
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||||
|
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
|
*/
|
||||||
|
|
||||||
|
void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1
|
||||||
|
|
||||||
|
if (!sinCosPtr)
|
||||||
|
sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||||
|
|
||||||
|
if (!colorPtr)
|
||||||
|
colorPtr.Reset(&Color::White, 0); // Same
|
||||||
|
|
||||||
|
if (material->IsDepthSortingEnabled())
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
depthSortedBillboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
{
|
||||||
|
*colorPtr++,
|
||||||
|
*positionPtr++,
|
||||||
|
ComputeSize(*sizePtr++),
|
||||||
|
*sinCosPtr++
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::size_t billboardIndex = m_billboards.size();
|
||||||
|
m_billboards.resize(billboardIndex + billboardCount);
|
||||||
|
BillboardData* data = &m_billboards[billboardIndex];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
data->center = *positionPtr++;
|
||||||
|
data->color = *colorPtr++;
|
||||||
|
data->sinCos = *sinCosPtr++;
|
||||||
|
data->size = ComputeSize(*sizePtr++);
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
billboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
billboardCount,
|
||||||
|
billboardIndex
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Size of the billboards
|
||||||
|
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||||
|
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
|
*/
|
||||||
|
|
||||||
|
void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1
|
||||||
|
|
||||||
|
if (!sinCosPtr)
|
||||||
|
sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||||
|
|
||||||
|
float defaultAlpha = 1.f;
|
||||||
|
|
||||||
|
if (!alphaPtr)
|
||||||
|
alphaPtr.Reset(&defaultAlpha, 0); // Same
|
||||||
|
|
||||||
|
if (material->IsDepthSortingEnabled())
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
depthSortedBillboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
{
|
||||||
|
ComputeColor(*alphaPtr++),
|
||||||
|
*positionPtr++,
|
||||||
|
ComputeSize(*sizePtr++),
|
||||||
|
*sinCosPtr++
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::size_t billboardIndex = m_billboards.size();
|
||||||
|
m_billboards.resize(billboardIndex + billboardCount);
|
||||||
|
BillboardData* data = &m_billboards[billboardIndex];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
data->center = *positionPtr++;
|
||||||
|
data->color = ComputeColor(*alphaPtr++);
|
||||||
|
data->sinCos = *sinCosPtr++;
|
||||||
|
data->size = ComputeSize(*sizePtr++);
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
billboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
billboardCount,
|
||||||
|
billboardIndex
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Size of the billboards
|
||||||
|
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||||
|
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
|
*/
|
||||||
|
|
||||||
|
void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
float defaultRotation = 0.f;
|
||||||
|
|
||||||
|
if (!anglePtr)
|
||||||
|
anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||||
|
|
||||||
|
if (!colorPtr)
|
||||||
|
colorPtr.Reset(&Color::White, 0); // Same
|
||||||
|
|
||||||
|
if (material->IsDepthSortingEnabled())
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
depthSortedBillboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
{
|
||||||
|
*colorPtr++,
|
||||||
|
*positionPtr++,
|
||||||
|
ComputeSize(*sizePtr++),
|
||||||
|
ComputeSinCos(*anglePtr++)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::size_t billboardIndex = m_billboards.size();
|
||||||
|
m_billboards.resize(billboardIndex + billboardCount);
|
||||||
|
BillboardData* data = &m_billboards[billboardIndex];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
data->center = *positionPtr++;
|
||||||
|
data->color = *colorPtr++;
|
||||||
|
data->sinCos = ComputeSinCos(*anglePtr++);
|
||||||
|
data->size = ComputeSize(*sizePtr++);
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
billboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
billboardCount,
|
||||||
|
billboardIndex
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Size of the billboards
|
||||||
|
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||||
|
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
|
*/
|
||||||
|
|
||||||
|
void BasicRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
float defaultRotation = 0.f;
|
||||||
|
|
||||||
|
if (!anglePtr)
|
||||||
|
anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||||
|
|
||||||
|
float defaultAlpha = 1.f;
|
||||||
|
|
||||||
|
if (!alphaPtr)
|
||||||
|
alphaPtr.Reset(&defaultAlpha, 0); // Same
|
||||||
|
|
||||||
|
if (material->IsDepthSortingEnabled())
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
depthSortedBillboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
{
|
||||||
|
ComputeColor(*alphaPtr++),
|
||||||
|
*positionPtr++,
|
||||||
|
ComputeSize(*sizePtr++),
|
||||||
|
ComputeSinCos(*anglePtr++)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::size_t billboardIndex = m_billboards.size();
|
||||||
|
m_billboards.resize(billboardIndex + billboardCount);
|
||||||
|
BillboardData* data = &m_billboards[billboardIndex];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < billboardCount; ++i)
|
||||||
|
{
|
||||||
|
data->center = *positionPtr++;
|
||||||
|
data->color = ComputeColor(*alphaPtr++);
|
||||||
|
data->sinCos = ComputeSinCos(*anglePtr++);
|
||||||
|
data->size = ComputeSize(*sizePtr++);
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
billboards.Insert({
|
||||||
|
renderOrder,
|
||||||
|
material,
|
||||||
|
scissorRect,
|
||||||
|
billboardCount,
|
||||||
|
billboardIndex
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds drawable to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param drawable Drawable user defined
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraError if drawable is invalid
|
||||||
|
*/
|
||||||
|
void BasicRenderQueue::AddDrawable(int renderOrder, const Drawable* drawable)
|
||||||
|
{
|
||||||
|
NazaraAssert(drawable, "Invalid material");
|
||||||
|
|
||||||
|
RegisterLayer(renderOrder);
|
||||||
|
|
||||||
|
customDrawables.Insert({
|
||||||
|
renderOrder,
|
||||||
|
drawable
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds mesh to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the mesh
|
||||||
|
* \param meshData Data of the mesh
|
||||||
|
* \param meshAABB Box of the mesh
|
||||||
|
* \param transformMatrix Matrix of the mesh
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
|
*/
|
||||||
|
void BasicRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix, const Recti& scissorRect)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
RegisterLayer(renderOrder);
|
||||||
|
|
||||||
|
Spheref obbSphere(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius());
|
||||||
|
|
||||||
|
if (material->IsDepthSortingEnabled())
|
||||||
|
{
|
||||||
|
depthSortedModels.Insert({
|
||||||
|
renderOrder,
|
||||||
|
meshData,
|
||||||
|
material,
|
||||||
|
transformMatrix,
|
||||||
|
scissorRect,
|
||||||
|
obbSphere
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
models.Insert({
|
||||||
|
renderOrder,
|
||||||
|
meshData,
|
||||||
|
material,
|
||||||
|
transformMatrix,
|
||||||
|
scissorRect,
|
||||||
|
obbSphere
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds sprites to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the sprites
|
||||||
|
* \param vertices Buffer of data for the sprites
|
||||||
|
* \param spriteCount Number of sprites
|
||||||
|
* \param overlay Texture of the sprites
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
|
*/
|
||||||
|
void BasicRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay /*= nullptr*/)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
RegisterLayer(renderOrder);
|
||||||
|
|
||||||
|
if (material->IsDepthSortingEnabled())
|
||||||
|
{
|
||||||
|
depthSortedSprites.Insert({
|
||||||
|
renderOrder,
|
||||||
|
spriteCount,
|
||||||
|
material,
|
||||||
|
overlay,
|
||||||
|
vertices,
|
||||||
|
scissorRect
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
basicSprites.Insert({
|
||||||
|
renderOrder,
|
||||||
|
spriteCount,
|
||||||
|
material,
|
||||||
|
overlay,
|
||||||
|
vertices,
|
||||||
|
scissorRect
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Clears the queue
|
||||||
|
*
|
||||||
|
* \param fully Should everything be cleared or we can keep layers
|
||||||
|
*/
|
||||||
|
|
||||||
|
void BasicRenderQueue::Clear(bool fully)
|
||||||
|
{
|
||||||
|
AbstractRenderQueue::Clear(fully);
|
||||||
|
|
||||||
|
basicSprites.Clear();
|
||||||
|
billboards.Clear();
|
||||||
|
depthSortedBillboards.Clear();
|
||||||
|
depthSortedModels.Clear();
|
||||||
|
depthSortedSprites.Clear();
|
||||||
|
models.Clear();
|
||||||
|
|
||||||
|
m_pipelineCache.clear();
|
||||||
|
m_materialCache.clear();
|
||||||
|
m_overlayCache.clear();
|
||||||
|
m_shaderCache.clear();
|
||||||
|
m_textureCache.clear();
|
||||||
|
m_vertexBufferCache.clear();
|
||||||
|
|
||||||
|
m_billboards.clear();
|
||||||
|
m_renderLayers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sorts the object according to the viewer position, furthest to nearest
|
||||||
|
*
|
||||||
|
* \param viewer Viewer of the scene
|
||||||
|
*/
|
||||||
|
|
||||||
|
void BasicRenderQueue::Sort(const AbstractViewer* viewer)
|
||||||
|
{
|
||||||
|
m_layerCache.clear();
|
||||||
|
for (int layer : m_renderLayers)
|
||||||
|
m_layerCache.emplace(layer, m_layerCache.size());
|
||||||
|
|
||||||
|
auto GetOrInsert = [](auto& container, auto&& value)
|
||||||
|
{
|
||||||
|
auto it = container.find(value);
|
||||||
|
if (it == container.end())
|
||||||
|
it = container.emplace(value, container.size()).first;
|
||||||
|
|
||||||
|
return it->second;
|
||||||
|
};
|
||||||
|
|
||||||
|
basicSprites.Sort([&](const SpriteChain& vertices)
|
||||||
|
{
|
||||||
|
// RQ index:
|
||||||
|
// - Layer (4bits)
|
||||||
|
// - Pipeline (8bits)
|
||||||
|
// - Material (8bits)
|
||||||
|
// - Shader? (8bits)
|
||||||
|
// - Textures (8bits)
|
||||||
|
// - Overlay (8bits)
|
||||||
|
// - Scissor (4bits)
|
||||||
|
// - Depth? (16bits)
|
||||||
|
|
||||||
|
UInt64 layerIndex = m_layerCache[vertices.layerIndex];
|
||||||
|
UInt64 pipelineIndex = GetOrInsert(m_pipelineCache, vertices.material->GetPipeline());
|
||||||
|
UInt64 materialIndex = GetOrInsert(m_materialCache, vertices.material);
|
||||||
|
UInt64 shaderIndex = GetOrInsert(m_shaderCache, vertices.material->GetShader());
|
||||||
|
UInt64 textureIndex = GetOrInsert(m_textureCache, vertices.material->GetDiffuseMap());
|
||||||
|
UInt64 overlayIndex = GetOrInsert(m_overlayCache, vertices.overlay);
|
||||||
|
UInt64 scissorIndex = 0; //< TODO
|
||||||
|
UInt64 depthIndex = 0; //< TODO
|
||||||
|
|
||||||
|
UInt64 index = (layerIndex & 0x0F) << 60 |
|
||||||
|
(pipelineIndex & 0xFF) << 52 |
|
||||||
|
(materialIndex & 0xFF) << 44 |
|
||||||
|
(shaderIndex & 0xFF) << 36 |
|
||||||
|
(textureIndex & 0xFF) << 28 |
|
||||||
|
(overlayIndex & 0xFF) << 20 |
|
||||||
|
(scissorIndex & 0x0F) << 16 |
|
||||||
|
(depthIndex & 0xFFFF) << 0;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
});
|
||||||
|
|
||||||
|
billboards.Sort([&](const BillboardChain& billboard)
|
||||||
|
{
|
||||||
|
// RQ index:
|
||||||
|
// - Layer (4bits)
|
||||||
|
// - Pipeline (8bits)
|
||||||
|
// - Material (8bits)
|
||||||
|
// - Shader? (8bits)
|
||||||
|
// - Textures (8bits)
|
||||||
|
// - ??? (8bits)
|
||||||
|
// - Scissor (4bits)
|
||||||
|
// - Depth? (16bits)
|
||||||
|
|
||||||
|
UInt64 layerIndex = m_layerCache[billboard.layerIndex];
|
||||||
|
UInt64 pipelineIndex = GetOrInsert(m_pipelineCache, billboard.material->GetPipeline());
|
||||||
|
UInt64 materialIndex = GetOrInsert(m_materialCache, billboard.material);
|
||||||
|
UInt64 shaderIndex = GetOrInsert(m_shaderCache, billboard.material->GetShader());
|
||||||
|
UInt64 textureIndex = GetOrInsert(m_textureCache, billboard.material->GetDiffuseMap());
|
||||||
|
UInt64 unknownIndex = 0; //< ???
|
||||||
|
UInt64 scissorIndex = 0; //< TODO
|
||||||
|
UInt64 depthIndex = 0; //< TODO?
|
||||||
|
|
||||||
|
UInt64 index = (layerIndex & 0x0F) << 60 |
|
||||||
|
(pipelineIndex & 0xFF) << 52 |
|
||||||
|
(materialIndex & 0xFF) << 44 |
|
||||||
|
(shaderIndex & 0xFF) << 36 |
|
||||||
|
(textureIndex & 0xFF) << 28 |
|
||||||
|
(unknownIndex & 0xFF) << 20 |
|
||||||
|
(scissorIndex & 0x0F) << 16 |
|
||||||
|
(depthIndex & 0xFFFF) << 0;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
});
|
||||||
|
|
||||||
|
customDrawables.Sort([&](const CustomDrawable& drawable)
|
||||||
|
{
|
||||||
|
// RQ index:
|
||||||
|
// - Layer (4bits)
|
||||||
|
|
||||||
|
UInt64 layerIndex = m_layerCache[drawable.layerIndex];
|
||||||
|
|
||||||
|
UInt64 index = (layerIndex & 0x0F) << 60;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
models.Sort([&](const Model& renderData)
|
||||||
|
{
|
||||||
|
// RQ index:
|
||||||
|
// - Layer (4bits)
|
||||||
|
// - Pipeline (8bits)
|
||||||
|
// - Material (8bits)
|
||||||
|
// - Shader? (8bits)
|
||||||
|
// - Textures (8bits)
|
||||||
|
// - Buffers (8bits)
|
||||||
|
// - Scissor (4bits)
|
||||||
|
// - Depth? (16bits)
|
||||||
|
|
||||||
|
UInt64 layerIndex = m_layerCache[renderData.layerIndex];
|
||||||
|
UInt64 pipelineIndex = GetOrInsert(m_pipelineCache, renderData.material->GetPipeline());
|
||||||
|
UInt64 materialIndex = GetOrInsert(m_materialCache, renderData.material);
|
||||||
|
UInt64 shaderIndex = GetOrInsert(m_shaderCache, renderData.material->GetShader());
|
||||||
|
UInt64 textureIndex = GetOrInsert(m_textureCache, renderData.material->GetDiffuseMap());
|
||||||
|
UInt64 bufferIndex = GetOrInsert(m_vertexBufferCache, renderData.meshData.vertexBuffer);
|
||||||
|
UInt64 scissorIndex = 0; //< TODO
|
||||||
|
UInt64 depthIndex = 0; //< TODO
|
||||||
|
|
||||||
|
UInt64 index = (layerIndex & 0x0F) << 60 |
|
||||||
|
(pipelineIndex & 0xFF) << 52 |
|
||||||
|
(materialIndex & 0xFF) << 44 |
|
||||||
|
(shaderIndex & 0xFF) << 36 |
|
||||||
|
(textureIndex & 0xFF) << 28 |
|
||||||
|
(bufferIndex & 0xFF) << 20 |
|
||||||
|
(scissorIndex & 0x0F) << 16 |
|
||||||
|
(depthIndex & 0xFFFF) << 0;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
});
|
||||||
|
|
||||||
|
static_assert(std::numeric_limits<float>::is_iec559, "The following sorting functions relies on IEEE 754 floatings-points");
|
||||||
|
|
||||||
|
#if defined(arm) && \
|
||||||
|
((defined(__MAVERICK__) && defined(NAZARA_BIG_ENDIAN)) || \
|
||||||
|
(!defined(__SOFTFP__) && !defined(__VFP_FP__) && !defined(__MAVERICK__)))
|
||||||
|
#error The following code relies on native-endian IEEE-754 representation, which your platform does not guarantee
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near);
|
||||||
|
|
||||||
|
depthSortedBillboards.Sort([&](const Billboard& billboard)
|
||||||
|
{
|
||||||
|
// RQ index:
|
||||||
|
// - Layer (4bits)
|
||||||
|
// - Depth (32bits)
|
||||||
|
// - ?? (28bits)
|
||||||
|
|
||||||
|
// Reinterpret depth as UInt32 (this will work as long as they're all either positive or negative,
|
||||||
|
// a negative distance may happen with billboard behind the camera which we don't care about since they'll be rendered)
|
||||||
|
float depth = nearPlane.Distance(billboard.data.center);
|
||||||
|
|
||||||
|
UInt64 layerIndex = m_layerCache[billboard.layerIndex];
|
||||||
|
UInt64 depthIndex = ~reinterpret_cast<UInt32&>(depth);
|
||||||
|
|
||||||
|
UInt64 index = (layerIndex & 0x0F) << 60 |
|
||||||
|
(depthIndex & 0xFFFFFFFF) << 28;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (viewer->GetProjectionType() == ProjectionType_Orthogonal)
|
||||||
|
{
|
||||||
|
depthSortedModels.Sort([&](const Model& model)
|
||||||
|
{
|
||||||
|
// RQ index:
|
||||||
|
// - Layer (4bits)
|
||||||
|
// - Depth (32bits)
|
||||||
|
// - ?? (28bits)
|
||||||
|
|
||||||
|
float depth = nearPlane.Distance(model.obbSphere.GetPosition());
|
||||||
|
|
||||||
|
UInt64 layerIndex = m_layerCache[model.layerIndex];
|
||||||
|
UInt64 depthIndex = ~reinterpret_cast<UInt32&>(depth);
|
||||||
|
|
||||||
|
UInt64 index = (layerIndex & 0x0F) << 60 |
|
||||||
|
(depthIndex & 0xFFFFFFFF) << 28;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
});
|
||||||
|
|
||||||
|
depthSortedSprites.Sort([&](const SpriteChain& spriteChain)
|
||||||
|
{
|
||||||
|
// RQ index:
|
||||||
|
// - Layer (4bits)
|
||||||
|
// - Depth (32bits)
|
||||||
|
// - ?? (28bits)
|
||||||
|
|
||||||
|
float depth = nearPlane.Distance(spriteChain.vertices[0].position);
|
||||||
|
|
||||||
|
UInt64 layerIndex = m_layerCache[spriteChain.layerIndex];
|
||||||
|
UInt64 depthIndex = ~reinterpret_cast<UInt32&>(depth);
|
||||||
|
|
||||||
|
UInt64 index = (layerIndex & 0x0F) << 60 |
|
||||||
|
(depthIndex & 0xFFFFFFFF) << 28;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vector3f viewerPos = viewer->GetEyePosition();
|
||||||
|
|
||||||
|
depthSortedModels.Sort([&](const Model& model)
|
||||||
|
{
|
||||||
|
// RQ index:
|
||||||
|
// - Layer (4bits)
|
||||||
|
// - Depth (32bits)
|
||||||
|
// - ?? (28bits)
|
||||||
|
|
||||||
|
float depth = viewerPos.SquaredDistance(model.obbSphere.GetPosition());
|
||||||
|
|
||||||
|
UInt64 layerIndex = m_layerCache[model.layerIndex];
|
||||||
|
UInt64 depthIndex = ~reinterpret_cast<UInt32&>(depth);
|
||||||
|
|
||||||
|
UInt64 index = (layerIndex & 0x0F) << 60 |
|
||||||
|
(depthIndex & 0xFFFFFFFF) << 28;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
});
|
||||||
|
|
||||||
|
depthSortedSprites.Sort([&](const SpriteChain& sprites)
|
||||||
|
{
|
||||||
|
// RQ index:
|
||||||
|
// - Layer (4bits)
|
||||||
|
// - Depth (32bits)
|
||||||
|
// - ?? (28bits)
|
||||||
|
|
||||||
|
float depth = viewerPos.SquaredDistance(sprites.vertices[0].position);
|
||||||
|
|
||||||
|
UInt64 layerIndex = m_layerCache[sprites.layerIndex];
|
||||||
|
UInt64 depthIndex = ~reinterpret_cast<UInt32&>(depth);
|
||||||
|
|
||||||
|
UInt64 index = (layerIndex & 0x0F) << 60 |
|
||||||
|
(depthIndex & 0xFFFFFFFF) << 28;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,10 +21,10 @@ namespace Nz
|
||||||
* \param instanceData Data used for instance
|
* \param instanceData Data used for instance
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Billboard::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
void Billboard::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const
|
||||||
{
|
{
|
||||||
Nz::Vector3f position = instanceData.transformMatrix.GetTranslation();
|
Nz::Vector3f position = instanceData.transformMatrix.GetTranslation();
|
||||||
renderQueue->AddBillboards(instanceData.renderOrder, GetMaterial(), 1, &position, &m_size, &m_sinCos, &m_color);
|
renderQueue->AddBillboards(instanceData.renderOrder, GetMaterial(), 1, scissorRect, &position, &m_size, &m_sinCos, &m_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,34 @@
|
||||||
#include <Nazara/Graphics/DeferredGeometryPass.hpp>
|
#include <Nazara/Graphics/DeferredGeometryPass.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Core/ErrorFlags.hpp>
|
#include <Nazara/Core/ErrorFlags.hpp>
|
||||||
|
#include <Nazara/Core/OffsetOf.hpp>
|
||||||
#include <Nazara/Graphics/AbstractViewer.hpp>
|
#include <Nazara/Graphics/AbstractViewer.hpp>
|
||||||
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
|
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
|
||||||
|
#include <Nazara/Graphics/DeferredProxyRenderQueue.hpp>
|
||||||
#include <Nazara/Graphics/Material.hpp>
|
#include <Nazara/Graphics/Material.hpp>
|
||||||
#include <Nazara/Graphics/SceneData.hpp>
|
#include <Nazara/Graphics/SceneData.hpp>
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
#include <Nazara/Renderer/RenderTexture.hpp>
|
#include <Nazara/Renderer/RenderTexture.hpp>
|
||||||
|
#include <Nazara/Utility/VertexStruct.hpp>
|
||||||
#include <Nazara/Graphics/Debug.hpp>
|
#include <Nazara/Graphics/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct BillboardPoint
|
||||||
|
{
|
||||||
|
Color color;
|
||||||
|
Vector3f position;
|
||||||
|
Vector2f size;
|
||||||
|
Vector2f sinCos; // must follow `size` (both will be sent as a Vector4f)
|
||||||
|
Vector2f uv;
|
||||||
|
};
|
||||||
|
|
||||||
|
UInt32 s_maxQuads = std::numeric_limits<UInt16>::max() / 6;
|
||||||
|
UInt32 s_vertexBufferSize = 4 * 1024 * 1024; // 4 MiB
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \ingroup graphics
|
* \ingroup graphics
|
||||||
* \class Nz::DeferredGeometryPass
|
* \class Nz::DeferredGeometryPass
|
||||||
|
|
@ -25,8 +43,20 @@ namespace Nz
|
||||||
* \brief Constructs a DeferredGeometryPass object by default
|
* \brief Constructs a DeferredGeometryPass object by default
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DeferredGeometryPass::DeferredGeometryPass()
|
DeferredGeometryPass::DeferredGeometryPass() :
|
||||||
|
m_vertexBuffer(BufferType_Vertex)
|
||||||
{
|
{
|
||||||
|
ErrorFlags flags(ErrorFlag_ThrowException, true);
|
||||||
|
|
||||||
|
std::array<UInt8, 4> whitePixel = { { 255, 255, 255, 255 } };
|
||||||
|
m_whiteTexture.Create(ImageType_2D, PixelFormatType_RGBA8, 1, 1);
|
||||||
|
m_whiteTexture.Update(whitePixel.data());
|
||||||
|
|
||||||
|
m_vertexBuffer.Create(s_vertexBufferSize, DataStorage_Hardware, BufferUsage_Dynamic);
|
||||||
|
|
||||||
|
m_billboardPointBuffer.Reset(&s_billboardVertexDeclaration, &m_vertexBuffer);
|
||||||
|
m_spriteBuffer.Reset(VertexDeclaration::Get(VertexLayout_XYZ_Color_UV), &m_vertexBuffer);
|
||||||
|
|
||||||
m_clearShader = ShaderLibrary::Get("DeferredGBufferClear");
|
m_clearShader = ShaderLibrary::Get("DeferredGBufferClear");
|
||||||
m_clearStates.depthBuffer = true;
|
m_clearStates.depthBuffer = true;
|
||||||
m_clearStates.faceCulling = true;
|
m_clearStates.faceCulling = true;
|
||||||
|
|
@ -67,131 +97,27 @@ namespace Nz
|
||||||
Renderer::SetMatrix(MatrixType_Projection, sceneData.viewer->GetProjectionMatrix());
|
Renderer::SetMatrix(MatrixType_Projection, sceneData.viewer->GetProjectionMatrix());
|
||||||
Renderer::SetMatrix(MatrixType_View, sceneData.viewer->GetViewMatrix());
|
Renderer::SetMatrix(MatrixType_View, sceneData.viewer->GetViewMatrix());
|
||||||
|
|
||||||
const Shader* lastShader = nullptr;
|
BasicRenderQueue& renderQueue = *m_renderQueue->GetDeferredRenderQueue();
|
||||||
const ShaderUniforms* shaderUniforms = nullptr;
|
|
||||||
|
|
||||||
for (auto& layerPair : m_renderQueue->layers)
|
renderQueue.Sort(sceneData.viewer);
|
||||||
{
|
|
||||||
for (auto& pipelinePair : layerPair.second.opaqueModels)
|
|
||||||
{
|
|
||||||
const MaterialPipeline* pipeline = pipelinePair.first;
|
|
||||||
auto& pipelineEntry = pipelinePair.second;
|
|
||||||
|
|
||||||
if (pipelineEntry.maxInstanceCount > 0)
|
if (!renderQueue.models.empty())
|
||||||
{
|
DrawModels(sceneData, renderQueue, renderQueue.models);
|
||||||
bool instancing = instancingEnabled && (pipelineEntry.maxInstanceCount > NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT);
|
|
||||||
|
|
||||||
UInt32 flags = ShaderFlags_Deferred;
|
if (!renderQueue.basicSprites.empty())
|
||||||
if (instancing)
|
DrawSprites(sceneData, renderQueue, renderQueue.basicSprites);
|
||||||
flags |= ShaderFlags_Instancing;
|
|
||||||
|
|
||||||
const MaterialPipeline::Instance& pipelineInstance = pipeline->Apply(flags);
|
if (!renderQueue.billboards.empty())
|
||||||
|
DrawBillboards(sceneData, renderQueue, renderQueue.billboards);
|
||||||
|
|
||||||
const Shader* shader = pipelineInstance.uberInstance->GetShader();
|
if (!renderQueue.depthSortedModels.empty())
|
||||||
|
DrawModels(sceneData, renderQueue, renderQueue.depthSortedModels);
|
||||||
|
|
||||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
if (!renderQueue.depthSortedSprites.empty())
|
||||||
if (shader != lastShader)
|
DrawSprites(sceneData, renderQueue, renderQueue.depthSortedSprites);
|
||||||
{
|
|
||||||
// Index of uniforms in the shader
|
|
||||||
shaderUniforms = GetShaderUniforms(shader);
|
|
||||||
|
|
||||||
// Ambiant color of the scene
|
if (!renderQueue.depthSortedBillboards.empty())
|
||||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
DrawBillboards(sceneData, renderQueue, renderQueue.depthSortedBillboards);
|
||||||
// Position of the camera
|
|
||||||
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
|
||||||
|
|
||||||
lastShader = shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& materialPair : pipelineEntry.materialMap)
|
|
||||||
{
|
|
||||||
const Material* material = materialPair.first;
|
|
||||||
auto& matEntry = materialPair.second;
|
|
||||||
|
|
||||||
if (matEntry.enabled)
|
|
||||||
{
|
|
||||||
DeferredRenderQueue::MeshInstanceContainer& meshInstances = matEntry.meshMap;
|
|
||||||
|
|
||||||
if (!meshInstances.empty())
|
|
||||||
{
|
|
||||||
material->Apply(pipelineInstance);
|
|
||||||
|
|
||||||
// Meshes
|
|
||||||
for (auto& meshIt : meshInstances)
|
|
||||||
{
|
|
||||||
const MeshData& meshData = meshIt.first;
|
|
||||||
auto& meshEntry = meshIt.second;
|
|
||||||
|
|
||||||
std::vector<Matrix4f>& instances = meshEntry.instances;
|
|
||||||
if (!instances.empty())
|
|
||||||
{
|
|
||||||
const IndexBuffer* indexBuffer = meshData.indexBuffer;
|
|
||||||
const VertexBuffer* vertexBuffer = meshData.vertexBuffer;
|
|
||||||
|
|
||||||
// Handle draw call before rendering loop
|
|
||||||
Renderer::DrawCall drawFunc;
|
|
||||||
Renderer::DrawCallInstanced instancedDrawFunc;
|
|
||||||
unsigned int indexCount;
|
|
||||||
|
|
||||||
if (indexBuffer)
|
|
||||||
{
|
|
||||||
drawFunc = Renderer::DrawIndexedPrimitives;
|
|
||||||
instancedDrawFunc = Renderer::DrawIndexedPrimitivesInstanced;
|
|
||||||
indexCount = indexBuffer->GetIndexCount();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
drawFunc = Renderer::DrawPrimitives;
|
|
||||||
instancedDrawFunc = Renderer::DrawPrimitivesInstanced;
|
|
||||||
indexCount = vertexBuffer->GetVertexCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer::SetIndexBuffer(indexBuffer);
|
|
||||||
Renderer::SetVertexBuffer(vertexBuffer);
|
|
||||||
|
|
||||||
if (instancing)
|
|
||||||
{
|
|
||||||
// We get the buffer for instance of Renderer and we configure it to work with matrices
|
|
||||||
VertexBuffer* instanceBuffer = Renderer::GetInstanceBuffer();
|
|
||||||
instanceBuffer->SetVertexDeclaration(VertexDeclaration::Get(VertexLayout_Matrix4));
|
|
||||||
|
|
||||||
const Matrix4f* instanceMatrices = &instances[0];
|
|
||||||
std::size_t instanceCount = instances.size();
|
|
||||||
std::size_t maxInstanceCount = instanceBuffer->GetVertexCount(); // The number of matrices that can be hold in the buffer
|
|
||||||
|
|
||||||
while (instanceCount > 0)
|
|
||||||
{
|
|
||||||
// We compute the number of instances that we will be able to show this time (Depending on the instance buffer size)
|
|
||||||
std::size_t renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
|
|
||||||
instanceCount -= renderedInstanceCount;
|
|
||||||
|
|
||||||
// We fill the instancing buffer with our world matrices
|
|
||||||
instanceBuffer->Fill(instanceMatrices, 0, renderedInstanceCount);
|
|
||||||
instanceMatrices += renderedInstanceCount;
|
|
||||||
|
|
||||||
// And we show
|
|
||||||
instancedDrawFunc(renderedInstanceCount, meshData.primitiveMode, 0, indexCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Without instancing, we must do one draw call for each instance
|
|
||||||
// This may be faster than instancing under a threshold
|
|
||||||
// Due to the time to modify the instancing buffer
|
|
||||||
for (const Matrix4f& matrix : instances)
|
|
||||||
{
|
|
||||||
Renderer::SetMatrix(MatrixType_World, matrix);
|
|
||||||
drawFunc(meshData.primitiveMode, 0, indexCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // We only fill the G-Buffer, the work texture are unchanged
|
return false; // We only fill the G-Buffer, the work texture are unchanged
|
||||||
}
|
}
|
||||||
|
|
@ -266,13 +192,409 @@ namespace Nz
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeferredGeometryPass::DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Billboard>& billboards) const
|
||||||
|
{
|
||||||
|
VertexBuffer* instanceBuffer = Renderer::GetInstanceBuffer();
|
||||||
|
instanceBuffer->SetVertexDeclaration(&s_billboardInstanceDeclaration);
|
||||||
|
|
||||||
/*!
|
Renderer::SetVertexBuffer(&s_quadVertexBuffer);
|
||||||
* \brief Gets the uniforms of a shader
|
|
||||||
* \return Uniforms of the shader
|
Nz::BufferMapper<VertexBuffer> instanceBufferMapper;
|
||||||
*
|
std::size_t billboardCount = 0;
|
||||||
* \param shader Shader to get uniforms from
|
std::size_t maxBillboardPerDraw = instanceBuffer->GetVertexCount();
|
||||||
*/
|
|
||||||
|
auto Commit = [&]()
|
||||||
|
{
|
||||||
|
if (billboardCount > 0)
|
||||||
|
{
|
||||||
|
instanceBufferMapper.Unmap();
|
||||||
|
|
||||||
|
Renderer::DrawPrimitivesInstanced(billboardCount, PrimitiveMode_TriangleStrip, 0, 4);
|
||||||
|
|
||||||
|
billboardCount = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const RenderTarget* renderTarget = sceneData.viewer->GetTarget();
|
||||||
|
Recti fullscreenScissorRect = Recti(Vector2i(renderTarget->GetSize()));
|
||||||
|
|
||||||
|
const Material* lastMaterial = nullptr;
|
||||||
|
const MaterialPipeline* lastPipeline = nullptr;
|
||||||
|
const Shader* lastShader = nullptr;
|
||||||
|
const ShaderUniforms* shaderUniforms = nullptr;
|
||||||
|
const Texture* lastOverlay = nullptr;
|
||||||
|
Recti lastScissorRect = Recti(-1, -1);
|
||||||
|
|
||||||
|
const MaterialPipeline::Instance* pipelineInstance = nullptr;
|
||||||
|
|
||||||
|
for (const BasicRenderQueue::Billboard& billboard : billboards)
|
||||||
|
{
|
||||||
|
const Nz::Recti& scissorRect = (billboard.scissorRect.width > 0) ? billboard.scissorRect : fullscreenScissorRect;
|
||||||
|
|
||||||
|
if (billboard.material != lastMaterial || (billboard.material->IsScissorTestEnabled() && scissorRect != lastScissorRect))
|
||||||
|
{
|
||||||
|
Commit();
|
||||||
|
|
||||||
|
const MaterialPipeline* pipeline = billboard.material->GetPipeline();
|
||||||
|
if (lastPipeline != pipeline)
|
||||||
|
{
|
||||||
|
pipelineInstance = &billboard.material->GetPipeline()->Apply(ShaderFlags_Billboard | ShaderFlags_Deferred | ShaderFlags_Instancing | ShaderFlags_VertexColor);
|
||||||
|
|
||||||
|
const Shader* shader = pipelineInstance->uberInstance->GetShader();
|
||||||
|
if (shader != lastShader)
|
||||||
|
{
|
||||||
|
// Index of uniforms in the shader
|
||||||
|
shaderUniforms = GetShaderUniforms(shader);
|
||||||
|
|
||||||
|
// Ambient color of the scene
|
||||||
|
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||||
|
// Position of the camera
|
||||||
|
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||||
|
|
||||||
|
lastShader = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPipeline = pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastMaterial != billboard.material)
|
||||||
|
{
|
||||||
|
billboard.material->Apply(*pipelineInstance);
|
||||||
|
lastMaterial = billboard.material;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (billboard.material->IsScissorTestEnabled() && scissorRect != lastScissorRect)
|
||||||
|
{
|
||||||
|
Renderer::SetScissorRect(scissorRect);
|
||||||
|
lastScissorRect = scissorRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!instanceBufferMapper.GetBuffer())
|
||||||
|
instanceBufferMapper.Map(instanceBuffer, BufferAccess_DiscardAndWrite);
|
||||||
|
|
||||||
|
std::memcpy(static_cast<Nz::UInt8*>(instanceBufferMapper.GetPointer()) + sizeof(BasicRenderQueue::BillboardData) * billboardCount, &billboard.data, sizeof(BasicRenderQueue::BillboardData));
|
||||||
|
if (++billboardCount >= maxBillboardPerDraw)
|
||||||
|
Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeferredGeometryPass::DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::BillboardChain>& billboards) const
|
||||||
|
{
|
||||||
|
VertexBuffer* instanceBuffer = Renderer::GetInstanceBuffer();
|
||||||
|
instanceBuffer->SetVertexDeclaration(&s_billboardInstanceDeclaration);
|
||||||
|
|
||||||
|
Renderer::SetVertexBuffer(&s_quadVertexBuffer);
|
||||||
|
|
||||||
|
Nz::BufferMapper<VertexBuffer> instanceBufferMapper;
|
||||||
|
std::size_t billboardCount = 0;
|
||||||
|
std::size_t maxBillboardPerDraw = instanceBuffer->GetVertexCount();
|
||||||
|
|
||||||
|
auto Commit = [&]()
|
||||||
|
{
|
||||||
|
if (billboardCount > 0)
|
||||||
|
{
|
||||||
|
instanceBufferMapper.Unmap();
|
||||||
|
|
||||||
|
Renderer::DrawPrimitivesInstanced(billboardCount, PrimitiveMode_TriangleStrip, 0, 4);
|
||||||
|
|
||||||
|
billboardCount = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const RenderTarget* renderTarget = sceneData.viewer->GetTarget();
|
||||||
|
Recti fullscreenScissorRect = Recti(Vector2i(renderTarget->GetSize()));
|
||||||
|
|
||||||
|
const Material* lastMaterial = nullptr;
|
||||||
|
const MaterialPipeline* lastPipeline = nullptr;
|
||||||
|
const Shader* lastShader = nullptr;
|
||||||
|
const ShaderUniforms* shaderUniforms = nullptr;
|
||||||
|
const Texture* lastOverlay = nullptr;
|
||||||
|
Recti lastScissorRect = Recti(-1, -1);
|
||||||
|
|
||||||
|
const MaterialPipeline::Instance* pipelineInstance = nullptr;
|
||||||
|
|
||||||
|
for (const BasicRenderQueue::BillboardChain& billboard : billboards)
|
||||||
|
{
|
||||||
|
const Nz::Recti& scissorRect = (billboard.scissorRect.width > 0) ? billboard.scissorRect : fullscreenScissorRect;
|
||||||
|
|
||||||
|
if (billboard.material != lastMaterial || (billboard.material->IsScissorTestEnabled() && scissorRect != lastScissorRect))
|
||||||
|
{
|
||||||
|
Commit();
|
||||||
|
|
||||||
|
const MaterialPipeline* pipeline = billboard.material->GetPipeline();
|
||||||
|
if (lastPipeline != pipeline)
|
||||||
|
{
|
||||||
|
pipelineInstance = &billboard.material->GetPipeline()->Apply(ShaderFlags_Billboard | ShaderFlags_Deferred | ShaderFlags_Instancing | ShaderFlags_VertexColor);
|
||||||
|
|
||||||
|
const Shader* shader = pipelineInstance->uberInstance->GetShader();
|
||||||
|
if (shader != lastShader)
|
||||||
|
{
|
||||||
|
// Index of uniforms in the shader
|
||||||
|
shaderUniforms = GetShaderUniforms(shader);
|
||||||
|
|
||||||
|
// Ambient color of the scene
|
||||||
|
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||||
|
// Position of the camera
|
||||||
|
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||||
|
|
||||||
|
lastShader = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPipeline = pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastMaterial != billboard.material)
|
||||||
|
{
|
||||||
|
billboard.material->Apply(*pipelineInstance);
|
||||||
|
lastMaterial = billboard.material;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (billboard.material->IsScissorTestEnabled() && scissorRect != lastScissorRect)
|
||||||
|
{
|
||||||
|
Renderer::SetScissorRect(scissorRect);
|
||||||
|
lastScissorRect = scissorRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t billboardRemaining = billboard.billboardCount;
|
||||||
|
const BasicRenderQueue::BillboardData* billboardData = renderQueue.GetBillboardData(billboard.billboardIndex);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::size_t renderedBillboardCount = std::min(billboardRemaining, maxBillboardPerDraw - billboardCount);
|
||||||
|
billboardRemaining -= renderedBillboardCount;
|
||||||
|
|
||||||
|
if (!instanceBufferMapper.GetBuffer())
|
||||||
|
instanceBufferMapper.Map(instanceBuffer, BufferAccess_DiscardAndWrite);
|
||||||
|
|
||||||
|
std::memcpy(static_cast<Nz::UInt8*>(instanceBufferMapper.GetPointer()) + sizeof(BasicRenderQueue::BillboardData) * billboardCount, billboardData, renderedBillboardCount * sizeof(BasicRenderQueue::BillboardData));
|
||||||
|
billboardCount += renderedBillboardCount;
|
||||||
|
billboardData += renderedBillboardCount;
|
||||||
|
|
||||||
|
if (billboardCount >= maxBillboardPerDraw)
|
||||||
|
Commit();
|
||||||
|
}
|
||||||
|
while (billboardRemaining > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeferredGeometryPass::DrawModels(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const Nz::RenderQueue<Nz::BasicRenderQueue::Model>& models) const
|
||||||
|
{
|
||||||
|
const RenderTarget* renderTarget = sceneData.viewer->GetTarget();
|
||||||
|
Recti fullscreenScissorRect = Recti(Vector2i(renderTarget->GetSize()));
|
||||||
|
|
||||||
|
const Material* lastMaterial = nullptr;
|
||||||
|
const MaterialPipeline* lastPipeline = nullptr;
|
||||||
|
const Shader* lastShader = nullptr;
|
||||||
|
const ShaderUniforms* shaderUniforms = nullptr;
|
||||||
|
Recti lastScissorRect = Recti(-1, -1);
|
||||||
|
|
||||||
|
const MaterialPipeline::Instance* pipelineInstance = nullptr;
|
||||||
|
|
||||||
|
///TODO: Reimplement instancing
|
||||||
|
|
||||||
|
for (const BasicRenderQueue::Model& model : models)
|
||||||
|
{
|
||||||
|
const MaterialPipeline* pipeline = model.material->GetPipeline();
|
||||||
|
if (lastPipeline != pipeline)
|
||||||
|
{
|
||||||
|
pipelineInstance = &model.material->GetPipeline()->Apply(ShaderFlags_Deferred);
|
||||||
|
|
||||||
|
const Shader* shader = pipelineInstance->uberInstance->GetShader();
|
||||||
|
if (shader != lastShader)
|
||||||
|
{
|
||||||
|
// Index of uniforms in the shader
|
||||||
|
shaderUniforms = GetShaderUniforms(shader);
|
||||||
|
|
||||||
|
// Ambient color of the scene
|
||||||
|
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||||
|
// Position of the camera
|
||||||
|
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||||
|
|
||||||
|
lastShader = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPipeline = pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastMaterial != model.material)
|
||||||
|
{
|
||||||
|
model.material->Apply(*pipelineInstance);
|
||||||
|
lastMaterial = model.material;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.material->IsScissorTestEnabled())
|
||||||
|
{
|
||||||
|
const Nz::Recti& scissorRect = (model.scissorRect.width > 0) ? model.scissorRect : fullscreenScissorRect;
|
||||||
|
if (scissorRect != lastScissorRect)
|
||||||
|
{
|
||||||
|
Renderer::SetScissorRect(scissorRect);
|
||||||
|
lastScissorRect = scissorRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle draw call before rendering loop
|
||||||
|
Renderer::DrawCall drawFunc;
|
||||||
|
Renderer::DrawCallInstanced instancedDrawFunc;
|
||||||
|
unsigned int indexCount;
|
||||||
|
|
||||||
|
if (model.meshData.indexBuffer)
|
||||||
|
{
|
||||||
|
drawFunc = Renderer::DrawIndexedPrimitives;
|
||||||
|
instancedDrawFunc = Renderer::DrawIndexedPrimitivesInstanced;
|
||||||
|
indexCount = model.meshData.indexBuffer->GetIndexCount();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drawFunc = Renderer::DrawPrimitives;
|
||||||
|
instancedDrawFunc = Renderer::DrawPrimitivesInstanced;
|
||||||
|
indexCount = model.meshData.vertexBuffer->GetVertexCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::SetIndexBuffer(model.meshData.indexBuffer);
|
||||||
|
Renderer::SetVertexBuffer(model.meshData.vertexBuffer);
|
||||||
|
|
||||||
|
Renderer::SetMatrix(MatrixType_World, model.matrix);
|
||||||
|
drawFunc(model.meshData.primitiveMode, 0, indexCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeferredGeometryPass::DrawSprites(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::SpriteChain>& spriteList) const
|
||||||
|
{
|
||||||
|
const RenderTarget* renderTarget = sceneData.viewer->GetTarget();
|
||||||
|
Recti fullscreenScissorRect = Recti(Vector2i(renderTarget->GetSize()));
|
||||||
|
|
||||||
|
Renderer::SetIndexBuffer(&s_quadIndexBuffer);
|
||||||
|
Renderer::SetMatrix(MatrixType_World, Matrix4f::Identity());
|
||||||
|
Renderer::SetVertexBuffer(&m_spriteBuffer);
|
||||||
|
|
||||||
|
const unsigned int overlayTextureUnit = Material::GetTextureUnit(TextureMap_Overlay);
|
||||||
|
const std::size_t maxSpriteCount = std::min<std::size_t>(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
|
||||||
|
|
||||||
|
m_spriteChains.clear();
|
||||||
|
|
||||||
|
auto Commit = [&]()
|
||||||
|
{
|
||||||
|
std::size_t spriteChainCount = m_spriteChains.size();
|
||||||
|
if (spriteChainCount > 0)
|
||||||
|
{
|
||||||
|
std::size_t spriteChain = 0; // Which chain of sprites are we treating
|
||||||
|
std::size_t spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// We open the buffer in writing mode
|
||||||
|
BufferMapper<VertexBuffer> vertexMapper(m_spriteBuffer, BufferAccess_DiscardAndWrite);
|
||||||
|
VertexStruct_XYZ_Color_UV* vertices = static_cast<VertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
|
||||||
|
|
||||||
|
std::size_t spriteCount = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const VertexStruct_XYZ_Color_UV* currentChain = m_spriteChains[spriteChain].first;
|
||||||
|
std::size_t currentChainSpriteCount = m_spriteChains[spriteChain].second;
|
||||||
|
std::size_t count = std::min(maxSpriteCount - spriteCount, currentChainSpriteCount - spriteChainOffset);
|
||||||
|
|
||||||
|
std::memcpy(vertices, currentChain + spriteChainOffset * 4, 4 * count * sizeof(VertexStruct_XYZ_Color_UV));
|
||||||
|
vertices += count * 4;
|
||||||
|
|
||||||
|
spriteCount += count;
|
||||||
|
spriteChainOffset += count;
|
||||||
|
|
||||||
|
// Have we treated the entire chain ?
|
||||||
|
if (spriteChainOffset == currentChainSpriteCount)
|
||||||
|
{
|
||||||
|
spriteChain++;
|
||||||
|
spriteChainOffset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (spriteCount < maxSpriteCount && spriteChain < spriteChainCount);
|
||||||
|
|
||||||
|
vertexMapper.Unmap();
|
||||||
|
|
||||||
|
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, spriteCount * 6);
|
||||||
|
}
|
||||||
|
while (spriteChain < spriteChainCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_spriteChains.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
const Material* lastMaterial = nullptr;
|
||||||
|
const MaterialPipeline* lastPipeline = nullptr;
|
||||||
|
const Shader* lastShader = nullptr;
|
||||||
|
const ShaderUniforms* shaderUniforms = nullptr;
|
||||||
|
const Texture* lastOverlay = nullptr;
|
||||||
|
Recti lastScissorRect = Recti(-1, -1);
|
||||||
|
|
||||||
|
const MaterialPipeline::Instance* pipelineInstance = nullptr;
|
||||||
|
|
||||||
|
for (const BasicRenderQueue::SpriteChain& basicSprites : spriteList)
|
||||||
|
{
|
||||||
|
const Nz::Recti& scissorRect = (basicSprites.scissorRect.width > 0) ? basicSprites.scissorRect : fullscreenScissorRect;
|
||||||
|
|
||||||
|
if (basicSprites.material != lastMaterial || basicSprites.overlay != lastOverlay || (basicSprites.material->IsScissorTestEnabled() && scissorRect != lastScissorRect))
|
||||||
|
{
|
||||||
|
Commit();
|
||||||
|
|
||||||
|
const MaterialPipeline* pipeline = basicSprites.material->GetPipeline();
|
||||||
|
if (lastPipeline != pipeline)
|
||||||
|
{
|
||||||
|
pipelineInstance = &basicSprites.material->GetPipeline()->Apply(ShaderFlags_Deferred | ShaderFlags_TextureOverlay | ShaderFlags_VertexColor);
|
||||||
|
|
||||||
|
const Shader* shader = pipelineInstance->uberInstance->GetShader();
|
||||||
|
if (shader != lastShader)
|
||||||
|
{
|
||||||
|
// Index of uniforms in the shader
|
||||||
|
shaderUniforms = GetShaderUniforms(shader);
|
||||||
|
|
||||||
|
// Ambient color of the scene
|
||||||
|
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||||
|
// Position of the camera
|
||||||
|
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||||
|
|
||||||
|
// Overlay texture unit
|
||||||
|
shader->SendInteger(shaderUniforms->textureOverlay, overlayTextureUnit);
|
||||||
|
|
||||||
|
lastShader = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPipeline = pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastMaterial != basicSprites.material)
|
||||||
|
{
|
||||||
|
basicSprites.material->Apply(*pipelineInstance);
|
||||||
|
|
||||||
|
Renderer::SetTextureSampler(overlayTextureUnit, basicSprites.material->GetDiffuseSampler());
|
||||||
|
|
||||||
|
lastMaterial = basicSprites.material;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Nz::Texture* overlayTexture = (basicSprites.overlay) ? basicSprites.overlay.Get() : &m_whiteTexture;
|
||||||
|
if (overlayTexture != lastOverlay)
|
||||||
|
{
|
||||||
|
Renderer::SetTexture(overlayTextureUnit, overlayTexture);
|
||||||
|
lastOverlay = overlayTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basicSprites.material->IsScissorTestEnabled() && scissorRect != lastScissorRect)
|
||||||
|
{
|
||||||
|
Renderer::SetScissorRect(scissorRect);
|
||||||
|
lastScissorRect = scissorRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_spriteChains.emplace_back(basicSprites.vertices, basicSprites.spriteCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
Commit();
|
||||||
|
}
|
||||||
|
|
||||||
const DeferredGeometryPass::ShaderUniforms* DeferredGeometryPass::GetShaderUniforms(const Shader* shader) const
|
const DeferredGeometryPass::ShaderUniforms* DeferredGeometryPass::GetShaderUniforms(const Shader* shader) const
|
||||||
{
|
{
|
||||||
|
|
@ -303,4 +625,73 @@ namespace Nz
|
||||||
{
|
{
|
||||||
m_shaderUniforms.erase(shader);
|
m_shaderUniforms.erase(shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DeferredGeometryPass::Initialize()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ErrorFlags flags(ErrorFlag_ThrowException, true);
|
||||||
|
|
||||||
|
s_quadIndexBuffer.Reset(false, s_maxQuads * 6, DataStorage_Hardware, 0);
|
||||||
|
|
||||||
|
BufferMapper<IndexBuffer> mapper(s_quadIndexBuffer, BufferAccess_WriteOnly);
|
||||||
|
UInt16* indices = static_cast<UInt16*>(mapper.GetPointer());
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < s_maxQuads; ++i)
|
||||||
|
{
|
||||||
|
*indices++ = i * 4 + 0;
|
||||||
|
*indices++ = i * 4 + 2;
|
||||||
|
*indices++ = i * 4 + 1;
|
||||||
|
|
||||||
|
*indices++ = i * 4 + 2;
|
||||||
|
*indices++ = i * 4 + 3;
|
||||||
|
*indices++ = i * 4 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapper.Unmap(); // No point to keep the buffer open any longer
|
||||||
|
|
||||||
|
// Quad buffer (used for instancing of billboards and sprites)
|
||||||
|
//Note: UV are computed in the shader
|
||||||
|
s_quadVertexBuffer.Reset(VertexDeclaration::Get(VertexLayout_XY), 4, DataStorage_Hardware, 0);
|
||||||
|
|
||||||
|
float vertices[2 * 4] = {
|
||||||
|
-0.5f, -0.5f,
|
||||||
|
0.5f, -0.5f,
|
||||||
|
-0.5f, 0.5f,
|
||||||
|
0.5f, 0.5f,
|
||||||
|
};
|
||||||
|
|
||||||
|
s_quadVertexBuffer.FillRaw(vertices, 0, sizeof(vertices));
|
||||||
|
|
||||||
|
// Declaration used when rendering the vertex billboards
|
||||||
|
s_billboardVertexDeclaration.EnableComponent(VertexComponent_Color, ComponentType_Color, NazaraOffsetOf(BillboardPoint, color));
|
||||||
|
s_billboardVertexDeclaration.EnableComponent(VertexComponent_Position, ComponentType_Float3, NazaraOffsetOf(BillboardPoint, position));
|
||||||
|
s_billboardVertexDeclaration.EnableComponent(VertexComponent_TexCoord, ComponentType_Float2, NazaraOffsetOf(BillboardPoint, uv));
|
||||||
|
s_billboardVertexDeclaration.EnableComponent(VertexComponent_Userdata0, ComponentType_Float4, NazaraOffsetOf(BillboardPoint, size)); // Includes sincos
|
||||||
|
|
||||||
|
// Declaration used when rendering the billboards with intancing
|
||||||
|
// The main advantage is the direct copy (std::memcpy) of data in the RenderQueue to the GPU buffer
|
||||||
|
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData0, ComponentType_Float3, NazaraOffsetOf(BasicRenderQueue::BillboardData, center));
|
||||||
|
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData1, ComponentType_Float4, NazaraOffsetOf(BasicRenderQueue::BillboardData, size)); // Englobe sincos
|
||||||
|
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData2, ComponentType_Color, NazaraOffsetOf(BasicRenderQueue::BillboardData, color));
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to initialise: " + String(e.what()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeferredGeometryPass::Uninitialize()
|
||||||
|
{
|
||||||
|
s_quadIndexBuffer.Reset();
|
||||||
|
s_quadVertexBuffer.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
IndexBuffer DeferredGeometryPass::s_quadIndexBuffer;
|
||||||
|
VertexBuffer DeferredGeometryPass::s_quadVertexBuffer;
|
||||||
|
VertexDeclaration DeferredGeometryPass::s_billboardInstanceDeclaration;
|
||||||
|
VertexDeclaration DeferredGeometryPass::s_billboardVertexDeclaration;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
#include <Nazara/Graphics/DeferredPhongLightingPass.hpp>
|
#include <Nazara/Graphics/DeferredPhongLightingPass.hpp>
|
||||||
#include <Nazara/Core/Primitive.hpp>
|
#include <Nazara/Core/Primitive.hpp>
|
||||||
#include <Nazara/Graphics/AbstractViewer.hpp>
|
#include <Nazara/Graphics/AbstractViewer.hpp>
|
||||||
#include <Nazara/Graphics/DeferredRenderQueue.hpp>
|
#include <Nazara/Graphics/DeferredProxyRenderQueue.hpp>
|
||||||
#include <Nazara/Graphics/SceneData.hpp>
|
#include <Nazara/Graphics/SceneData.hpp>
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
#include <Nazara/Renderer/RenderTexture.hpp>
|
#include <Nazara/Renderer/RenderTexture.hpp>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,261 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/DeferredProxyRenderQueue.hpp>
|
||||||
|
#include <Nazara/Graphics/AbstractViewer.hpp>
|
||||||
|
#include <Nazara/Graphics/BasicRenderQueue.hpp>
|
||||||
|
#include <Nazara/Graphics/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* \ingroup graphics
|
||||||
|
* \class Nz::DeferredProxyRenderQueue
|
||||||
|
* \brief Graphics class sorting the objects into a deferred and forward render queue (depending on blending)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Sizes of the billboards
|
||||||
|
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||||
|
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DeferredProxyRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
if (!material->IsBlendingEnabled())
|
||||||
|
m_deferredRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
||||||
|
else
|
||||||
|
m_forwardRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Sizes of the billboards
|
||||||
|
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||||
|
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DeferredProxyRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
if (!material->IsBlendingEnabled())
|
||||||
|
m_deferredRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
||||||
|
else
|
||||||
|
m_forwardRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Sizes of the billboards
|
||||||
|
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||||
|
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DeferredProxyRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
if (!material->IsBlendingEnabled())
|
||||||
|
m_deferredRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, anglePtr, colorPtr);
|
||||||
|
else
|
||||||
|
m_forwardRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, anglePtr, colorPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Sizes of the billboards
|
||||||
|
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||||
|
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DeferredProxyRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
if (!material->IsBlendingEnabled())
|
||||||
|
m_deferredRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, anglePtr, alphaPtr);
|
||||||
|
else
|
||||||
|
m_forwardRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, anglePtr, alphaPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Size of the billboards
|
||||||
|
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||||
|
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DeferredProxyRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
if (!material->IsBlendingEnabled())
|
||||||
|
m_deferredRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
||||||
|
else
|
||||||
|
m_forwardRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Size of the billboards
|
||||||
|
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||||
|
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DeferredProxyRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
if (!material->IsBlendingEnabled())
|
||||||
|
m_deferredRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
||||||
|
else
|
||||||
|
m_forwardRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Size of the billboards
|
||||||
|
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||||
|
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DeferredProxyRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
if (!material->IsBlendingEnabled())
|
||||||
|
m_deferredRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, anglePtr, colorPtr);
|
||||||
|
else
|
||||||
|
m_forwardRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, anglePtr, colorPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds multiple billboards to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the billboards
|
||||||
|
* \param count Number of billboards
|
||||||
|
* \param positionPtr Position of the billboards
|
||||||
|
* \param sizePtr Size of the billboards
|
||||||
|
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||||
|
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DeferredProxyRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
if (!material->IsBlendingEnabled())
|
||||||
|
m_deferredRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, anglePtr, alphaPtr);
|
||||||
|
else
|
||||||
|
m_forwardRenderQueue->AddBillboards(renderOrder, material, billboardCount, scissorRect, positionPtr, sizePtr, anglePtr, alphaPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds drawable to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param drawable Drawable user defined
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraError if drawable is invalid
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DeferredProxyRenderQueue::AddDrawable(int renderOrder, const Drawable* drawable)
|
||||||
|
{
|
||||||
|
m_forwardRenderQueue->AddDrawable(renderOrder, drawable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds mesh to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the mesh
|
||||||
|
* \param meshData Data of the mesh
|
||||||
|
* \param meshAABB Box of the mesh
|
||||||
|
* \param transformMatrix Matrix of the mesh
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DeferredProxyRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix, const Recti& scissorRect)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
if (!material->IsBlendingEnabled())
|
||||||
|
m_deferredRenderQueue->AddMesh(renderOrder, material, meshData, meshAABB, transformMatrix, scissorRect);
|
||||||
|
else
|
||||||
|
m_forwardRenderQueue->AddMesh(renderOrder, material, meshData, meshAABB, transformMatrix, scissorRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds sprites to the queue
|
||||||
|
*
|
||||||
|
* \param renderOrder Order of rendering
|
||||||
|
* \param material Material of the sprites
|
||||||
|
* \param vertices Buffer of data for the sprites
|
||||||
|
* \param spriteCount Number of sprites
|
||||||
|
* \param overlay Texture of the sprites
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DeferredProxyRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay)
|
||||||
|
{
|
||||||
|
NazaraAssert(material, "Invalid material");
|
||||||
|
|
||||||
|
if (!material->IsBlendingEnabled())
|
||||||
|
m_deferredRenderQueue->AddSprites(renderOrder, material, vertices, spriteCount, scissorRect, overlay);
|
||||||
|
else
|
||||||
|
m_forwardRenderQueue->AddSprites(renderOrder, material, vertices, spriteCount, scissorRect, overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Clears the queue
|
||||||
|
*
|
||||||
|
* \param fully Should everything be cleared or we can keep layers
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DeferredProxyRenderQueue::Clear(bool fully)
|
||||||
|
{
|
||||||
|
AbstractRenderQueue::Clear(fully);
|
||||||
|
|
||||||
|
m_deferredRenderQueue->Clear(fully);
|
||||||
|
m_forwardRenderQueue->Clear(fully);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Graphics/DeferredRenderPass.hpp>
|
#include <Nazara/Graphics/DeferredRenderPass.hpp>
|
||||||
|
#include <Nazara/Graphics/DeferredProxyRenderQueue.hpp>
|
||||||
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
|
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
|
||||||
#include <Nazara/Graphics/DeferredRenderQueue.hpp>
|
|
||||||
#include <Nazara/Math/Vector2.hpp>
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
#include <Nazara/Graphics/Debug.hpp>
|
#include <Nazara/Graphics/Debug.hpp>
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ namespace Nz
|
||||||
void DeferredRenderPass::Initialize(DeferredRenderTechnique* technique)
|
void DeferredRenderPass::Initialize(DeferredRenderTechnique* technique)
|
||||||
{
|
{
|
||||||
m_deferredTechnique = technique;
|
m_deferredTechnique = technique;
|
||||||
m_renderQueue = static_cast<DeferredRenderQueue*>(technique->GetRenderQueue());
|
m_renderQueue = static_cast<DeferredProxyRenderQueue*>(technique->GetRenderQueue());
|
||||||
|
|
||||||
m_depthStencilTexture = technique->GetDepthStencilTexture();
|
m_depthStencilTexture = technique->GetDepthStencilTexture();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,410 +0,0 @@
|
||||||
// Copyright (C) 2017 Jérôme Leclercq
|
|
||||||
// This file is part of the "Nazara Engine - Graphics module"
|
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
||||||
|
|
||||||
#include <Nazara/Graphics/DeferredRenderQueue.hpp>
|
|
||||||
#include <Nazara/Graphics/ForwardRenderQueue.hpp>
|
|
||||||
#include <Nazara/Graphics/Debug.hpp>
|
|
||||||
|
|
||||||
///TODO: Render billboards using Deferred Shading if possible
|
|
||||||
|
|
||||||
namespace Nz
|
|
||||||
{
|
|
||||||
/*!
|
|
||||||
* \ingroup graphics
|
|
||||||
* \class Nz::DeferredRenderQueue
|
|
||||||
* \brief Graphics class that represents the rendering queue for deferred rendering
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Constructs a DeferredRenderQueue object with the rendering queue of forward rendering
|
|
||||||
*
|
|
||||||
* \param forwardQueue Queue of data to render
|
|
||||||
*/
|
|
||||||
|
|
||||||
DeferredRenderQueue::DeferredRenderQueue(ForwardRenderQueue* forwardQueue) :
|
|
||||||
m_forwardQueue(forwardQueue)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Sizes of the billboards
|
|
||||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
|
||||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
|
||||||
{
|
|
||||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Sizes of the billboards
|
|
||||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
|
||||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
|
||||||
{
|
|
||||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Sizes of the billboards
|
|
||||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
|
||||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
|
||||||
{
|
|
||||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, anglePtr, colorPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Sizes of the billboards
|
|
||||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
|
||||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
|
||||||
{
|
|
||||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, anglePtr, alphaPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Size of the billboards
|
|
||||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
|
||||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
|
||||||
{
|
|
||||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Size of the billboards
|
|
||||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
|
||||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
|
||||||
{
|
|
||||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Size of the billboards
|
|
||||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
|
||||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
|
||||||
{
|
|
||||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, anglePtr, colorPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Size of the billboards
|
|
||||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
|
||||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
|
||||||
{
|
|
||||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, anglePtr, alphaPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds drawable to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param drawable Drawable user defined
|
|
||||||
*
|
|
||||||
* \remark Produces a NazaraError if drawable is invalid
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::AddDrawable(int renderOrder, const Drawable* drawable)
|
|
||||||
{
|
|
||||||
m_forwardQueue->AddDrawable(renderOrder, drawable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds mesh to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the mesh
|
|
||||||
* \param meshData Data of the mesh
|
|
||||||
* \param meshAABB Box of the mesh
|
|
||||||
* \param transformMatrix Matrix of the mesh
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix)
|
|
||||||
{
|
|
||||||
if (material->IsBlendingEnabled() || material->IsDepthSortingEnabled()) //< Fixme: Deferred Shading should be able to handle depth sorting
|
|
||||||
// Deferred Shading cannot handle blended objects, put them in the forward list
|
|
||||||
m_forwardQueue->AddMesh(renderOrder, material, meshData, meshAABB, transformMatrix);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Layer& currentLayer = GetLayer(renderOrder);
|
|
||||||
MeshPipelineBatches& opaqueModels = currentLayer.opaqueModels;
|
|
||||||
|
|
||||||
const MaterialPipeline* materialPipeline = material->GetPipeline();
|
|
||||||
|
|
||||||
auto pipelineIt = opaqueModels.find(materialPipeline);
|
|
||||||
if (pipelineIt == opaqueModels.end())
|
|
||||||
{
|
|
||||||
BatchedMaterialEntry materialEntry;
|
|
||||||
pipelineIt = opaqueModels.insert(MeshPipelineBatches::value_type(materialPipeline, std::move(materialEntry))).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
BatchedMaterialEntry& materialEntry = pipelineIt->second;
|
|
||||||
MeshMaterialBatches& materialMap = materialEntry.materialMap;
|
|
||||||
|
|
||||||
auto materialIt = materialMap.find(material);
|
|
||||||
if (materialIt == materialMap.end())
|
|
||||||
{
|
|
||||||
BatchedModelEntry entry;
|
|
||||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &DeferredRenderQueue::OnMaterialInvalidation);
|
|
||||||
|
|
||||||
materialIt = materialMap.insert(MeshMaterialBatches::value_type(material, std::move(entry))).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
BatchedModelEntry& entry = materialIt->second;
|
|
||||||
entry.enabled = true;
|
|
||||||
|
|
||||||
MeshInstanceContainer& meshMap = entry.meshMap;
|
|
||||||
|
|
||||||
auto it2 = meshMap.find(meshData);
|
|
||||||
if (it2 == meshMap.end())
|
|
||||||
{
|
|
||||||
MeshInstanceEntry instanceEntry;
|
|
||||||
if (meshData.indexBuffer)
|
|
||||||
instanceEntry.indexBufferReleaseSlot.Connect(meshData.indexBuffer->OnIndexBufferRelease, this, &DeferredRenderQueue::OnIndexBufferInvalidation);
|
|
||||||
|
|
||||||
instanceEntry.vertexBufferReleaseSlot.Connect(meshData.vertexBuffer->OnVertexBufferRelease, this, &DeferredRenderQueue::OnVertexBufferInvalidation);
|
|
||||||
|
|
||||||
it2 = meshMap.insert(std::make_pair(meshData, std::move(instanceEntry))).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Matrix4f>& instances = it2->second.instances;
|
|
||||||
instances.push_back(transformMatrix);
|
|
||||||
|
|
||||||
materialEntry.maxInstanceCount = std::max(materialEntry.maxInstanceCount, instances.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds sprites to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the sprites
|
|
||||||
* \param vertices Buffer of data for the sprites
|
|
||||||
* \param spriteCount Number of sprites
|
|
||||||
* \param overlay Texture of the sprites
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay)
|
|
||||||
{
|
|
||||||
m_forwardQueue->AddSprites(renderOrder, material, vertices, spriteCount, overlay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Clears the queue
|
|
||||||
*
|
|
||||||
* \param fully Should everything be cleared or we can keep layers
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::Clear(bool fully)
|
|
||||||
{
|
|
||||||
AbstractRenderQueue::Clear(fully);
|
|
||||||
|
|
||||||
if (fully)
|
|
||||||
layers.clear();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (auto it = layers.begin(); it != layers.end();)
|
|
||||||
{
|
|
||||||
Layer& layer = it->second;
|
|
||||||
if (layer.clearCount++ >= 100)
|
|
||||||
it = layers.erase(it);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (auto& pipelinePair : layer.opaqueModels)
|
|
||||||
{
|
|
||||||
auto& pipelineEntry = pipelinePair.second;
|
|
||||||
|
|
||||||
if (pipelineEntry.maxInstanceCount > 0)
|
|
||||||
{
|
|
||||||
for (auto& materialPair : pipelineEntry.materialMap)
|
|
||||||
{
|
|
||||||
auto& matEntry = materialPair.second;
|
|
||||||
|
|
||||||
if (matEntry.enabled)
|
|
||||||
{
|
|
||||||
MeshInstanceContainer& meshInstances = matEntry.meshMap;
|
|
||||||
|
|
||||||
for (auto& meshIt : meshInstances)
|
|
||||||
{
|
|
||||||
auto& meshEntry = meshIt.second;
|
|
||||||
|
|
||||||
meshEntry.instances.clear();
|
|
||||||
}
|
|
||||||
matEntry.enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pipelineEntry.maxInstanceCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_forwardQueue->Clear(fully);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Gets the ith layer
|
|
||||||
* \return Reference to the ith layer for the queue
|
|
||||||
*
|
|
||||||
* \param i Index of the layer
|
|
||||||
*/
|
|
||||||
|
|
||||||
DeferredRenderQueue::Layer& DeferredRenderQueue::GetLayer(unsigned int i)
|
|
||||||
{
|
|
||||||
auto it = layers.find(i);
|
|
||||||
if (it == layers.end())
|
|
||||||
it = layers.insert(std::make_pair(i, Layer())).first;
|
|
||||||
|
|
||||||
Layer& layer = it->second;
|
|
||||||
layer.clearCount = 0;
|
|
||||||
|
|
||||||
return layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Handle the invalidation of an index buffer
|
|
||||||
*
|
|
||||||
* \param indexBuffer Index buffer being invalidated
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::OnIndexBufferInvalidation(const IndexBuffer* indexBuffer)
|
|
||||||
{
|
|
||||||
for (auto& pair : layers)
|
|
||||||
{
|
|
||||||
Layer& layer = pair.second;
|
|
||||||
|
|
||||||
for (auto& pipelineEntry : layer.opaqueModels)
|
|
||||||
{
|
|
||||||
for (auto& materialEntry : pipelineEntry.second.materialMap)
|
|
||||||
{
|
|
||||||
MeshInstanceContainer& meshes = materialEntry.second.meshMap;
|
|
||||||
for (auto it = meshes.begin(); it != meshes.end();)
|
|
||||||
{
|
|
||||||
const MeshData& renderData = it->first;
|
|
||||||
if (renderData.indexBuffer == indexBuffer)
|
|
||||||
it = meshes.erase(it);
|
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Handle the invalidation of a material
|
|
||||||
*
|
|
||||||
* \param material Material being invalidated
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::OnMaterialInvalidation(const Material* material)
|
|
||||||
{
|
|
||||||
for (auto& pair : layers)
|
|
||||||
{
|
|
||||||
Layer& layer = pair.second;
|
|
||||||
|
|
||||||
for (auto& pipelineEntry : layer.opaqueModels)
|
|
||||||
pipelineEntry.second.materialMap.erase(material);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Handle the invalidation of a vertex buffer
|
|
||||||
*
|
|
||||||
* \param vertexBuffer Vertex buffer being invalidated
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DeferredRenderQueue::OnVertexBufferInvalidation(const VertexBuffer* vertexBuffer)
|
|
||||||
{
|
|
||||||
for (auto& pair : layers)
|
|
||||||
{
|
|
||||||
Layer& layer = pair.second;
|
|
||||||
for (auto& pipelineEntry : layer.opaqueModels)
|
|
||||||
{
|
|
||||||
for (auto& materialEntry : pipelineEntry.second.materialMap)
|
|
||||||
{
|
|
||||||
MeshInstanceContainer& meshes = materialEntry.second.meshMap;
|
|
||||||
for (auto it = meshes.begin(); it != meshes.end();)
|
|
||||||
{
|
|
||||||
const MeshData& renderData = it->first;
|
|
||||||
if (renderData.vertexBuffer == vertexBuffer)
|
|
||||||
it = meshes.erase(it);
|
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -127,7 +127,7 @@ namespace Nz
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DeferredRenderTechnique::DeferredRenderTechnique() :
|
DeferredRenderTechnique::DeferredRenderTechnique() :
|
||||||
m_renderQueue(static_cast<ForwardRenderQueue*>(m_forwardTechnique.GetRenderQueue())),
|
m_renderQueue(&m_deferredRenderQueue, static_cast<BasicRenderQueue*>(m_forwardTechnique.GetRenderQueue())),
|
||||||
m_GBufferSize(0U)
|
m_GBufferSize(0U)
|
||||||
{
|
{
|
||||||
m_depthStencilTexture = Texture::New();
|
m_depthStencilTexture = Texture::New();
|
||||||
|
|
@ -455,35 +455,35 @@ namespace Nz
|
||||||
switch (renderPass)
|
switch (renderPass)
|
||||||
{
|
{
|
||||||
case RenderPassType_AA:
|
case RenderPassType_AA:
|
||||||
smartPtr.reset(new DeferredFXAAPass);
|
smartPtr = std::make_unique<DeferredFXAAPass>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderPassType_Bloom:
|
case RenderPassType_Bloom:
|
||||||
smartPtr.reset(new DeferredBloomPass);
|
smartPtr = std::make_unique<DeferredBloomPass>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderPassType_DOF:
|
case RenderPassType_DOF:
|
||||||
smartPtr.reset(new DeferredDOFPass);
|
smartPtr = std::make_unique<DeferredDOFPass>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderPassType_Final:
|
case RenderPassType_Final:
|
||||||
smartPtr.reset(new DeferredFinalPass);
|
smartPtr = std::make_unique<DeferredFinalPass>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderPassType_Fog:
|
case RenderPassType_Fog:
|
||||||
smartPtr.reset(new DeferredFogPass);
|
smartPtr = std::make_unique<DeferredFogPass>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderPassType_Forward:
|
case RenderPassType_Forward:
|
||||||
smartPtr.reset(new DeferredForwardPass);
|
smartPtr = std::make_unique<DeferredForwardPass>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderPassType_Geometry:
|
case RenderPassType_Geometry:
|
||||||
smartPtr.reset(new DeferredGeometryPass);
|
smartPtr = std::make_unique<DeferredGeometryPass>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderPassType_Lighting:
|
case RenderPassType_Lighting:
|
||||||
smartPtr.reset(new DeferredPhongLightingPass);
|
smartPtr = std::make_unique<DeferredPhongLightingPass>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderPassType_SSAO:
|
case RenderPassType_SSAO:
|
||||||
|
|
@ -701,6 +701,12 @@ namespace Nz
|
||||||
NazaraWarning("Failed to register gaussian blur shader, certain features will not work: " + error);
|
NazaraWarning("Failed to register gaussian blur shader, certain features will not work: " + error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!DeferredGeometryPass::Initialize())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to initialize geometry pass");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -710,6 +716,8 @@ namespace Nz
|
||||||
|
|
||||||
void DeferredRenderTechnique::Uninitialize()
|
void DeferredRenderTechnique::Uninitialize()
|
||||||
{
|
{
|
||||||
|
DeferredGeometryPass::Uninitialize();
|
||||||
|
|
||||||
ShaderLibrary::Unregister("DeferredGBufferClear");
|
ShaderLibrary::Unregister("DeferredGBufferClear");
|
||||||
ShaderLibrary::Unregister("DeferredDirectionnalLight");
|
ShaderLibrary::Unregister("DeferredDirectionnalLight");
|
||||||
ShaderLibrary::Unregister("DeferredPointSpotLight");
|
ShaderLibrary::Unregister("DeferredPointSpotLight");
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ namespace Nz
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
||||||
{
|
{
|
||||||
NazaraAssert(material, "Invalid material");
|
NazaraAssert(material, "Invalid material");
|
||||||
NazaraUnused(renderOrder);
|
NazaraUnused(renderOrder);
|
||||||
|
|
@ -56,7 +56,7 @@ namespace Nz
|
||||||
else
|
else
|
||||||
material = m_baseMaterial;
|
material = m_baseMaterial;
|
||||||
|
|
||||||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
BasicRenderQueue::AddBillboards(0, material, billboardCount, scissorRect, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -73,7 +73,7 @@ namespace Nz
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
||||||
{
|
{
|
||||||
NazaraAssert(material, "Invalid material");
|
NazaraAssert(material, "Invalid material");
|
||||||
NazaraUnused(renderOrder);
|
NazaraUnused(renderOrder);
|
||||||
|
|
@ -86,7 +86,7 @@ namespace Nz
|
||||||
else
|
else
|
||||||
material = m_baseMaterial;
|
material = m_baseMaterial;
|
||||||
|
|
||||||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
BasicRenderQueue::AddBillboards(0, material, billboardCount, scissorRect, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -103,7 +103,7 @@ namespace Nz
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
||||||
{
|
{
|
||||||
NazaraAssert(material, "Invalid material");
|
NazaraAssert(material, "Invalid material");
|
||||||
NazaraUnused(renderOrder);
|
NazaraUnused(renderOrder);
|
||||||
|
|
@ -116,7 +116,7 @@ namespace Nz
|
||||||
else
|
else
|
||||||
material = m_baseMaterial;
|
material = m_baseMaterial;
|
||||||
|
|
||||||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, anglePtr, colorPtr);
|
BasicRenderQueue::AddBillboards(0, material, billboardCount, scissorRect, positionPtr, sizePtr, anglePtr, colorPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -133,7 +133,7 @@ namespace Nz
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
||||||
{
|
{
|
||||||
NazaraAssert(material, "Invalid material");
|
NazaraAssert(material, "Invalid material");
|
||||||
NazaraUnused(renderOrder);
|
NazaraUnused(renderOrder);
|
||||||
|
|
@ -146,7 +146,7 @@ namespace Nz
|
||||||
else
|
else
|
||||||
material = m_baseMaterial;
|
material = m_baseMaterial;
|
||||||
|
|
||||||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, anglePtr, alphaPtr);
|
BasicRenderQueue::AddBillboards(0, material, billboardCount, scissorRect, positionPtr, sizePtr, anglePtr, alphaPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -163,7 +163,7 @@ namespace Nz
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
||||||
{
|
{
|
||||||
NazaraAssert(material, "Invalid material");
|
NazaraAssert(material, "Invalid material");
|
||||||
NazaraUnused(renderOrder);
|
NazaraUnused(renderOrder);
|
||||||
|
|
@ -176,7 +176,7 @@ namespace Nz
|
||||||
else
|
else
|
||||||
material = m_baseMaterial;
|
material = m_baseMaterial;
|
||||||
|
|
||||||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
BasicRenderQueue::AddBillboards(0, material, billboardCount, scissorRect, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -193,7 +193,7 @@ namespace Nz
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
||||||
{
|
{
|
||||||
NazaraAssert(material, "Invalid material");
|
NazaraAssert(material, "Invalid material");
|
||||||
NazaraUnused(renderOrder);
|
NazaraUnused(renderOrder);
|
||||||
|
|
@ -206,7 +206,7 @@ namespace Nz
|
||||||
else
|
else
|
||||||
material = m_baseMaterial;
|
material = m_baseMaterial;
|
||||||
|
|
||||||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
BasicRenderQueue::AddBillboards(0, material, billboardCount, scissorRect, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -223,7 +223,7 @@ namespace Nz
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
||||||
{
|
{
|
||||||
NazaraAssert(material, "Invalid material");
|
NazaraAssert(material, "Invalid material");
|
||||||
NazaraUnused(renderOrder);
|
NazaraUnused(renderOrder);
|
||||||
|
|
@ -236,7 +236,7 @@ namespace Nz
|
||||||
else
|
else
|
||||||
material = m_baseMaterial;
|
material = m_baseMaterial;
|
||||||
|
|
||||||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, anglePtr, colorPtr);
|
BasicRenderQueue::AddBillboards(0, material, billboardCount, scissorRect, positionPtr, sizePtr, anglePtr, colorPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -253,7 +253,7 @@ namespace Nz
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
||||||
{
|
{
|
||||||
NazaraAssert(material, "Invalid material");
|
NazaraAssert(material, "Invalid material");
|
||||||
NazaraUnused(renderOrder);
|
NazaraUnused(renderOrder);
|
||||||
|
|
@ -266,11 +266,11 @@ namespace Nz
|
||||||
else
|
else
|
||||||
material = m_baseMaterial;
|
material = m_baseMaterial;
|
||||||
|
|
||||||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, anglePtr, alphaPtr);
|
BasicRenderQueue::AddBillboards(0, material, billboardCount, scissorRect, positionPtr, sizePtr, anglePtr, alphaPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Adds a direcitonal light to the queue
|
* \brief Adds a directional light to the queue
|
||||||
*
|
*
|
||||||
* \param light Light to add
|
* \param light Light to add
|
||||||
*
|
*
|
||||||
|
|
@ -295,7 +295,7 @@ namespace Nz
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DepthRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix)
|
void DepthRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix, const Recti& scissorRect)
|
||||||
{
|
{
|
||||||
NazaraAssert(material, "Invalid material");
|
NazaraAssert(material, "Invalid material");
|
||||||
NazaraUnused(renderOrder);
|
NazaraUnused(renderOrder);
|
||||||
|
|
@ -309,7 +309,7 @@ namespace Nz
|
||||||
else
|
else
|
||||||
material = m_baseMaterial;
|
material = m_baseMaterial;
|
||||||
|
|
||||||
ForwardRenderQueue::AddMesh(0, material, meshData, meshAABB, transformMatrix);
|
BasicRenderQueue::AddMesh(0, material, meshData, meshAABB, transformMatrix, scissorRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -352,7 +352,7 @@ namespace Nz
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
* \remark Produces a NazaraAssert if material is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DepthRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay)
|
void DepthRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay /*= nullptr*/)
|
||||||
{
|
{
|
||||||
NazaraAssert(material, "Invalid material");
|
NazaraAssert(material, "Invalid material");
|
||||||
NazaraUnused(renderOrder);
|
NazaraUnused(renderOrder);
|
||||||
|
|
@ -366,7 +366,7 @@ namespace Nz
|
||||||
else
|
else
|
||||||
material = m_baseMaterial;
|
material = m_baseMaterial;
|
||||||
|
|
||||||
ForwardRenderQueue::AddSprites(0, material, vertices, spriteCount, overlay);
|
BasicRenderQueue::AddSprites(0, material, vertices, spriteCount, scissorRect, overlay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,13 @@
|
||||||
#include <Nazara/Graphics/DepthRenderTechnique.hpp>
|
#include <Nazara/Graphics/DepthRenderTechnique.hpp>
|
||||||
#include <Nazara/Core/ErrorFlags.hpp>
|
#include <Nazara/Core/ErrorFlags.hpp>
|
||||||
#include <Nazara/Core/OffsetOf.hpp>
|
#include <Nazara/Core/OffsetOf.hpp>
|
||||||
|
#include <Nazara/Graphics/AbstractViewer.hpp>
|
||||||
#include <Nazara/Graphics/Drawable.hpp>
|
#include <Nazara/Graphics/Drawable.hpp>
|
||||||
#include <Nazara/Graphics/Material.hpp>
|
#include <Nazara/Graphics/Material.hpp>
|
||||||
#include <Nazara/Graphics/SceneData.hpp>
|
#include <Nazara/Graphics/SceneData.hpp>
|
||||||
#include <Nazara/Renderer/Config.hpp>
|
#include <Nazara/Renderer/Config.hpp>
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderTarget.hpp>
|
||||||
#include <Nazara/Utility/BufferMapper.hpp>
|
#include <Nazara/Utility/BufferMapper.hpp>
|
||||||
#include <Nazara/Utility/VertexStruct.hpp>
|
#include <Nazara/Utility/VertexStruct.hpp>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
@ -83,22 +85,28 @@ namespace Nz
|
||||||
|
|
||||||
bool DepthRenderTechnique::Draw(const SceneData& sceneData) const
|
bool DepthRenderTechnique::Draw(const SceneData& sceneData) const
|
||||||
{
|
{
|
||||||
for (auto& pair : m_renderQueue.layers)
|
m_renderQueue.Sort(sceneData.viewer);
|
||||||
{
|
|
||||||
ForwardRenderQueue::Layer& layer = pair.second;
|
|
||||||
|
|
||||||
if (!layer.opaqueModels.empty())
|
if (!m_renderQueue.models.empty())
|
||||||
DrawOpaqueModels(sceneData, layer);
|
DrawModels(sceneData, m_renderQueue, m_renderQueue.models);
|
||||||
|
|
||||||
if (!layer.opaqueSprites.empty())
|
if (!m_renderQueue.basicSprites.empty())
|
||||||
DrawBasicSprites(sceneData, layer);
|
DrawSprites(sceneData, m_renderQueue, m_renderQueue.basicSprites);
|
||||||
|
|
||||||
if (!layer.billboards.empty())
|
if (!m_renderQueue.billboards.empty())
|
||||||
DrawBillboards(sceneData, layer);
|
DrawBillboards(sceneData, m_renderQueue, m_renderQueue.billboards);
|
||||||
|
|
||||||
for (const Drawable* drawable : layer.otherDrawables)
|
if (!m_renderQueue.depthSortedModels.empty())
|
||||||
drawable->Draw();
|
DrawModels(sceneData, m_renderQueue, m_renderQueue.depthSortedModels);
|
||||||
}
|
|
||||||
|
if (!m_renderQueue.depthSortedSprites.empty())
|
||||||
|
DrawSprites(sceneData, m_renderQueue, m_renderQueue.depthSortedSprites);
|
||||||
|
|
||||||
|
if (!m_renderQueue.depthSortedBillboards.empty())
|
||||||
|
DrawBillboards(sceneData, m_renderQueue, m_renderQueue.depthSortedBillboards);
|
||||||
|
|
||||||
|
if (!m_renderQueue.customDrawables.empty())
|
||||||
|
DrawCustomDrawables(sceneData, m_renderQueue, m_renderQueue.customDrawables);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -175,9 +183,9 @@ namespace Nz
|
||||||
|
|
||||||
// Declaration utilisée lors du rendu des billboards par instancing
|
// Declaration utilisée lors du rendu des billboards par instancing
|
||||||
// L'avantage ici est la copie directe (std::memcpy) des données de la RenderQueue vers le buffer GPU
|
// L'avantage ici est la copie directe (std::memcpy) des données de la RenderQueue vers le buffer GPU
|
||||||
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData0, ComponentType_Float3, NazaraOffsetOf(ForwardRenderQueue::BillboardData, center));
|
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData0, ComponentType_Float3, NazaraOffsetOf(BasicRenderQueue::BillboardData, center));
|
||||||
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData1, ComponentType_Float4, NazaraOffsetOf(ForwardRenderQueue::BillboardData, size)); // Englobe sincos
|
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData1, ComponentType_Float4, NazaraOffsetOf(BasicRenderQueue::BillboardData, size)); // Englobe sincos
|
||||||
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData2, ComponentType_Color, NazaraOffsetOf(ForwardRenderQueue::BillboardData, color));
|
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData2, ComponentType_Color, NazaraOffsetOf(BasicRenderQueue::BillboardData, color));
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
@ -197,411 +205,406 @@ namespace Nz
|
||||||
s_quadIndexBuffer.Reset();
|
s_quadIndexBuffer.Reset();
|
||||||
s_quadVertexBuffer.Reset();
|
s_quadVertexBuffer.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
void DepthRenderTechnique::DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Billboard>& billboards) const
|
||||||
* \brief Draws basic sprites
|
|
||||||
*
|
|
||||||
* \param sceneData Data of the scene
|
|
||||||
* \param layer Layer of the rendering
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DepthRenderTechnique::DrawBasicSprites(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const
|
|
||||||
{
|
{
|
||||||
|
VertexBuffer* instanceBuffer = Renderer::GetInstanceBuffer();
|
||||||
|
instanceBuffer->SetVertexDeclaration(&s_billboardInstanceDeclaration);
|
||||||
|
|
||||||
|
Renderer::SetVertexBuffer(&s_quadVertexBuffer);
|
||||||
|
|
||||||
|
Nz::BufferMapper<VertexBuffer> instanceBufferMapper;
|
||||||
|
std::size_t billboardCount = 0;
|
||||||
|
std::size_t maxBillboardPerDraw = instanceBuffer->GetVertexCount();
|
||||||
|
|
||||||
|
auto Commit = [&]()
|
||||||
|
{
|
||||||
|
if (billboardCount > 0)
|
||||||
|
{
|
||||||
|
instanceBufferMapper.Unmap();
|
||||||
|
|
||||||
|
Renderer::DrawPrimitivesInstanced(billboardCount, PrimitiveMode_TriangleStrip, 0, 4);
|
||||||
|
|
||||||
|
billboardCount = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const RenderTarget* renderTarget = sceneData.viewer->GetTarget();
|
||||||
|
Recti fullscreenScissorRect = Recti(Vector2i(renderTarget->GetSize()));
|
||||||
|
|
||||||
|
const Material* lastMaterial = nullptr;
|
||||||
|
const MaterialPipeline* lastPipeline = nullptr;
|
||||||
const Shader* lastShader = nullptr;
|
const Shader* lastShader = nullptr;
|
||||||
const ShaderUniforms* shaderUniforms = nullptr;
|
const ShaderUniforms* shaderUniforms = nullptr;
|
||||||
|
const Texture* lastOverlay = nullptr;
|
||||||
|
Recti lastScissorRect = Recti(-1, -1);
|
||||||
|
|
||||||
|
const MaterialPipeline::Instance* pipelineInstance = nullptr;
|
||||||
|
|
||||||
|
for (const BasicRenderQueue::Billboard& billboard : billboards)
|
||||||
|
{
|
||||||
|
const Nz::Recti& scissorRect = (billboard.scissorRect.width > 0) ? billboard.scissorRect : fullscreenScissorRect;
|
||||||
|
|
||||||
|
if (billboard.material != lastMaterial || (billboard.material->IsScissorTestEnabled() && scissorRect != lastScissorRect))
|
||||||
|
{
|
||||||
|
Commit();
|
||||||
|
|
||||||
|
const MaterialPipeline* pipeline = billboard.material->GetPipeline();
|
||||||
|
if (lastPipeline != pipeline)
|
||||||
|
{
|
||||||
|
pipelineInstance = &billboard.material->GetPipeline()->Apply(ShaderFlags_Billboard | ShaderFlags_Deferred | ShaderFlags_Instancing | ShaderFlags_VertexColor);
|
||||||
|
|
||||||
|
const Shader* shader = pipelineInstance->uberInstance->GetShader();
|
||||||
|
if (shader != lastShader)
|
||||||
|
{
|
||||||
|
// Index of uniforms in the shader
|
||||||
|
shaderUniforms = GetShaderUniforms(shader);
|
||||||
|
|
||||||
|
// Ambient color of the scene
|
||||||
|
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||||
|
|
||||||
|
lastShader = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPipeline = pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastMaterial != billboard.material)
|
||||||
|
{
|
||||||
|
billboard.material->Apply(*pipelineInstance);
|
||||||
|
lastMaterial = billboard.material;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (billboard.material->IsScissorTestEnabled() && scissorRect != lastScissorRect)
|
||||||
|
{
|
||||||
|
Renderer::SetScissorRect(scissorRect);
|
||||||
|
lastScissorRect = scissorRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!instanceBufferMapper.GetBuffer())
|
||||||
|
instanceBufferMapper.Map(instanceBuffer, BufferAccess_DiscardAndWrite);
|
||||||
|
|
||||||
|
std::memcpy(static_cast<Nz::UInt8*>(instanceBufferMapper.GetPointer()) + sizeof(BasicRenderQueue::BillboardData) * billboardCount, &billboard.data, sizeof(BasicRenderQueue::BillboardData));
|
||||||
|
if (++billboardCount >= maxBillboardPerDraw)
|
||||||
|
Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DepthRenderTechnique::DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::BillboardChain>& billboards) const
|
||||||
|
{
|
||||||
|
VertexBuffer* instanceBuffer = Renderer::GetInstanceBuffer();
|
||||||
|
instanceBuffer->SetVertexDeclaration(&s_billboardInstanceDeclaration);
|
||||||
|
|
||||||
|
Renderer::SetVertexBuffer(&s_quadVertexBuffer);
|
||||||
|
|
||||||
|
Nz::BufferMapper<VertexBuffer> instanceBufferMapper;
|
||||||
|
std::size_t billboardCount = 0;
|
||||||
|
std::size_t maxBillboardPerDraw = instanceBuffer->GetVertexCount();
|
||||||
|
|
||||||
|
auto Commit = [&]()
|
||||||
|
{
|
||||||
|
if (billboardCount > 0)
|
||||||
|
{
|
||||||
|
instanceBufferMapper.Unmap();
|
||||||
|
|
||||||
|
Renderer::DrawPrimitivesInstanced(billboardCount, PrimitiveMode_TriangleStrip, 0, 4);
|
||||||
|
|
||||||
|
billboardCount = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const RenderTarget* renderTarget = sceneData.viewer->GetTarget();
|
||||||
|
Recti fullscreenScissorRect = Recti(Vector2i(renderTarget->GetSize()));
|
||||||
|
|
||||||
|
const Material* lastMaterial = nullptr;
|
||||||
|
const MaterialPipeline* lastPipeline = nullptr;
|
||||||
|
const Shader* lastShader = nullptr;
|
||||||
|
const ShaderUniforms* shaderUniforms = nullptr;
|
||||||
|
const Texture* lastOverlay = nullptr;
|
||||||
|
Recti lastScissorRect = Recti(-1, -1);
|
||||||
|
|
||||||
|
const MaterialPipeline::Instance* pipelineInstance = nullptr;
|
||||||
|
|
||||||
|
for (const BasicRenderQueue::BillboardChain& billboard : billboards)
|
||||||
|
{
|
||||||
|
const Nz::Recti& scissorRect = (billboard.scissorRect.width > 0) ? billboard.scissorRect : fullscreenScissorRect;
|
||||||
|
|
||||||
|
if (billboard.material != lastMaterial || (billboard.material->IsScissorTestEnabled() && scissorRect != lastScissorRect))
|
||||||
|
{
|
||||||
|
Commit();
|
||||||
|
|
||||||
|
const MaterialPipeline* pipeline = billboard.material->GetPipeline();
|
||||||
|
if (lastPipeline != pipeline)
|
||||||
|
{
|
||||||
|
pipelineInstance = &billboard.material->GetPipeline()->Apply(ShaderFlags_Billboard | ShaderFlags_Deferred | ShaderFlags_Instancing | ShaderFlags_VertexColor);
|
||||||
|
|
||||||
|
const Shader* shader = pipelineInstance->uberInstance->GetShader();
|
||||||
|
if (shader != lastShader)
|
||||||
|
{
|
||||||
|
// Index of uniforms in the shader
|
||||||
|
shaderUniforms = GetShaderUniforms(shader);
|
||||||
|
|
||||||
|
// Ambient color of the scene
|
||||||
|
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||||
|
|
||||||
|
lastShader = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPipeline = pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastMaterial != billboard.material)
|
||||||
|
{
|
||||||
|
billboard.material->Apply(*pipelineInstance);
|
||||||
|
lastMaterial = billboard.material;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (billboard.material->IsScissorTestEnabled() && scissorRect != lastScissorRect)
|
||||||
|
{
|
||||||
|
Renderer::SetScissorRect(scissorRect);
|
||||||
|
lastScissorRect = scissorRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t billboardRemaining = billboard.billboardCount;
|
||||||
|
const BasicRenderQueue::BillboardData* billboardData = renderQueue.GetBillboardData(billboard.billboardIndex);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::size_t renderedBillboardCount = std::min(billboardRemaining, maxBillboardPerDraw - billboardCount);
|
||||||
|
billboardRemaining -= renderedBillboardCount;
|
||||||
|
|
||||||
|
if (!instanceBufferMapper.GetBuffer())
|
||||||
|
instanceBufferMapper.Map(instanceBuffer, BufferAccess_DiscardAndWrite);
|
||||||
|
|
||||||
|
std::memcpy(static_cast<Nz::UInt8*>(instanceBufferMapper.GetPointer()) + sizeof(BasicRenderQueue::BillboardData) * billboardCount, billboardData, renderedBillboardCount * sizeof(BasicRenderQueue::BillboardData));
|
||||||
|
billboardCount += renderedBillboardCount;
|
||||||
|
billboardData += renderedBillboardCount;
|
||||||
|
|
||||||
|
if (billboardCount >= maxBillboardPerDraw)
|
||||||
|
Commit();
|
||||||
|
}
|
||||||
|
while (billboardRemaining > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DepthRenderTechnique::DrawCustomDrawables(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::CustomDrawable>& customDrawables) const
|
||||||
|
{
|
||||||
|
for (const BasicRenderQueue::CustomDrawable& customDrawable : customDrawables)
|
||||||
|
customDrawable.drawable->Draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DepthRenderTechnique::DrawModels(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const Nz::RenderQueue<Nz::BasicRenderQueue::Model>& models) const
|
||||||
|
{
|
||||||
|
const RenderTarget* renderTarget = sceneData.viewer->GetTarget();
|
||||||
|
Recti fullscreenScissorRect = Recti(Vector2i(renderTarget->GetSize()));
|
||||||
|
|
||||||
|
const Material* lastMaterial = nullptr;
|
||||||
|
const MaterialPipeline* lastPipeline = nullptr;
|
||||||
|
const Shader* lastShader = nullptr;
|
||||||
|
const ShaderUniforms* shaderUniforms = nullptr;
|
||||||
|
Recti lastScissorRect = Recti(-1, -1);
|
||||||
|
|
||||||
|
const MaterialPipeline::Instance* pipelineInstance = nullptr;
|
||||||
|
|
||||||
|
///TODO: Reimplement instancing
|
||||||
|
|
||||||
|
for (const BasicRenderQueue::Model& model : models)
|
||||||
|
{
|
||||||
|
const MaterialPipeline* pipeline = model.material->GetPipeline();
|
||||||
|
if (lastPipeline != pipeline)
|
||||||
|
{
|
||||||
|
pipelineInstance = &model.material->GetPipeline()->Apply(ShaderFlags_Deferred);
|
||||||
|
|
||||||
|
const Shader* shader = pipelineInstance->uberInstance->GetShader();
|
||||||
|
if (shader != lastShader)
|
||||||
|
{
|
||||||
|
// Index of uniforms in the shader
|
||||||
|
shaderUniforms = GetShaderUniforms(shader);
|
||||||
|
|
||||||
|
// Ambient color of the scene
|
||||||
|
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||||
|
|
||||||
|
lastShader = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPipeline = pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastMaterial != model.material)
|
||||||
|
{
|
||||||
|
model.material->Apply(*pipelineInstance);
|
||||||
|
lastMaterial = model.material;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.material->IsScissorTestEnabled())
|
||||||
|
{
|
||||||
|
const Nz::Recti& scissorRect = (model.scissorRect.width > 0) ? model.scissorRect : fullscreenScissorRect;
|
||||||
|
if (scissorRect != lastScissorRect)
|
||||||
|
{
|
||||||
|
Renderer::SetScissorRect(scissorRect);
|
||||||
|
lastScissorRect = scissorRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle draw call before rendering loop
|
||||||
|
Renderer::DrawCall drawFunc;
|
||||||
|
Renderer::DrawCallInstanced instancedDrawFunc;
|
||||||
|
unsigned int indexCount;
|
||||||
|
|
||||||
|
if (model.meshData.indexBuffer)
|
||||||
|
{
|
||||||
|
drawFunc = Renderer::DrawIndexedPrimitives;
|
||||||
|
instancedDrawFunc = Renderer::DrawIndexedPrimitivesInstanced;
|
||||||
|
indexCount = model.meshData.indexBuffer->GetIndexCount();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drawFunc = Renderer::DrawPrimitives;
|
||||||
|
instancedDrawFunc = Renderer::DrawPrimitivesInstanced;
|
||||||
|
indexCount = model.meshData.vertexBuffer->GetVertexCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::SetIndexBuffer(model.meshData.indexBuffer);
|
||||||
|
Renderer::SetVertexBuffer(model.meshData.vertexBuffer);
|
||||||
|
|
||||||
|
Renderer::SetMatrix(MatrixType_World, model.matrix);
|
||||||
|
drawFunc(model.meshData.primitiveMode, 0, indexCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DepthRenderTechnique::DrawSprites(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::SpriteChain>& spriteList) const
|
||||||
|
{
|
||||||
|
const RenderTarget* renderTarget = sceneData.viewer->GetTarget();
|
||||||
|
Recti fullscreenScissorRect = Recti(Vector2i(renderTarget->GetSize()));
|
||||||
|
|
||||||
Renderer::SetIndexBuffer(&s_quadIndexBuffer);
|
Renderer::SetIndexBuffer(&s_quadIndexBuffer);
|
||||||
Renderer::SetMatrix(MatrixType_World, Matrix4f::Identity());
|
Renderer::SetMatrix(MatrixType_World, Matrix4f::Identity());
|
||||||
Renderer::SetVertexBuffer(&m_spriteBuffer);
|
Renderer::SetVertexBuffer(&m_spriteBuffer);
|
||||||
|
|
||||||
for (auto& pipelinePair : layer.opaqueSprites)
|
const unsigned int overlayTextureUnit = Material::GetTextureUnit(TextureMap_Overlay);
|
||||||
|
const std::size_t maxSpriteCount = std::min<std::size_t>(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
|
||||||
|
|
||||||
|
m_spriteChains.clear();
|
||||||
|
|
||||||
|
auto Commit = [&]()
|
||||||
{
|
{
|
||||||
const MaterialPipeline* pipeline = pipelinePair.first;
|
std::size_t spriteChainCount = m_spriteChains.size();
|
||||||
auto& pipelineEntry = pipelinePair.second;
|
if (spriteChainCount > 0)
|
||||||
|
|
||||||
if (pipelineEntry.enabled)
|
|
||||||
{
|
{
|
||||||
const MaterialPipeline::Instance& pipelineInstance = pipeline->Apply(ShaderFlags_TextureOverlay | ShaderFlags_VertexColor);
|
std::size_t spriteChain = 0; // Which chain of sprites are we treating
|
||||||
|
std::size_t spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain
|
||||||
|
|
||||||
const Shader* shader = pipelineInstance.uberInstance->GetShader();
|
do
|
||||||
|
|
||||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
|
||||||
if (shader != lastShader)
|
|
||||||
{
|
{
|
||||||
// Index of uniforms in the shader
|
// We open the buffer in writing mode
|
||||||
shaderUniforms = GetShaderUniforms(shader);
|
BufferMapper<VertexBuffer> vertexMapper(m_spriteBuffer, BufferAccess_DiscardAndWrite);
|
||||||
|
VertexStruct_XYZ_Color_UV* vertices = static_cast<VertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
|
||||||
|
|
||||||
// Ambiant color of the scene
|
std::size_t spriteCount = 0;
|
||||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
|
||||||
|
|
||||||
lastShader = shader;
|
do
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& materialPair : pipelineEntry.materialMap)
|
|
||||||
{
|
|
||||||
const Material* material = materialPair.first;
|
|
||||||
auto& matEntry = materialPair.second;
|
|
||||||
|
|
||||||
if (matEntry.enabled)
|
|
||||||
{
|
{
|
||||||
unsigned int overlayTextureUnit = Material::GetTextureUnit(TextureMap_Overlay);
|
const VertexStruct_XYZ_Color_UV* currentChain = m_spriteChains[spriteChain].first;
|
||||||
material->Apply(pipelineInstance);
|
std::size_t currentChainSpriteCount = m_spriteChains[spriteChain].second;
|
||||||
|
std::size_t count = std::min(maxSpriteCount - spriteCount, currentChainSpriteCount - spriteChainOffset);
|
||||||
|
|
||||||
|
std::memcpy(vertices, currentChain + spriteChainOffset * 4, 4 * count * sizeof(VertexStruct_XYZ_Color_UV));
|
||||||
|
vertices += count * 4;
|
||||||
|
|
||||||
|
spriteCount += count;
|
||||||
|
spriteChainOffset += count;
|
||||||
|
|
||||||
|
// Have we treated the entire chain ?
|
||||||
|
if (spriteChainOffset == currentChainSpriteCount)
|
||||||
|
{
|
||||||
|
spriteChain++;
|
||||||
|
spriteChainOffset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (spriteCount < maxSpriteCount && spriteChain < spriteChainCount);
|
||||||
|
|
||||||
|
vertexMapper.Unmap();
|
||||||
|
|
||||||
|
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, spriteCount * 6);
|
||||||
|
}
|
||||||
|
while (spriteChain < spriteChainCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_spriteChains.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
const Material* lastMaterial = nullptr;
|
||||||
|
const MaterialPipeline* lastPipeline = nullptr;
|
||||||
|
const Shader* lastShader = nullptr;
|
||||||
|
const ShaderUniforms* shaderUniforms = nullptr;
|
||||||
|
const Texture* lastOverlay = nullptr;
|
||||||
|
Recti lastScissorRect = Recti(-1, -1);
|
||||||
|
|
||||||
|
const MaterialPipeline::Instance* pipelineInstance = nullptr;
|
||||||
|
|
||||||
|
for (const BasicRenderQueue::SpriteChain& basicSprites : spriteList)
|
||||||
|
{
|
||||||
|
const Nz::Recti& scissorRect = (basicSprites.scissorRect.width > 0) ? basicSprites.scissorRect : fullscreenScissorRect;
|
||||||
|
|
||||||
|
if (basicSprites.material != lastMaterial || basicSprites.overlay != lastOverlay || (basicSprites.material->IsScissorTestEnabled() && scissorRect != lastScissorRect))
|
||||||
|
{
|
||||||
|
Commit();
|
||||||
|
|
||||||
|
const MaterialPipeline* pipeline = basicSprites.material->GetPipeline();
|
||||||
|
if (lastPipeline != pipeline)
|
||||||
|
{
|
||||||
|
pipelineInstance = &basicSprites.material->GetPipeline()->Apply(ShaderFlags_Deferred | ShaderFlags_TextureOverlay | ShaderFlags_VertexColor);
|
||||||
|
|
||||||
|
const Shader* shader = pipelineInstance->uberInstance->GetShader();
|
||||||
|
if (shader != lastShader)
|
||||||
|
{
|
||||||
|
// Index of uniforms in the shader
|
||||||
|
shaderUniforms = GetShaderUniforms(shader);
|
||||||
|
|
||||||
|
// Ambient color of the scene
|
||||||
|
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||||
|
|
||||||
|
// Overlay texture unit
|
||||||
shader->SendInteger(shaderUniforms->textureOverlay, overlayTextureUnit);
|
shader->SendInteger(shaderUniforms->textureOverlay, overlayTextureUnit);
|
||||||
|
|
||||||
Renderer::SetTextureSampler(overlayTextureUnit, material->GetDiffuseSampler());
|
|
||||||
|
|
||||||
auto& overlayMap = matEntry.overlayMap;
|
|
||||||
for (auto& overlayIt : overlayMap)
|
|
||||||
{
|
|
||||||
const Texture* overlay = overlayIt.first;
|
|
||||||
auto& spriteChainVector = overlayIt.second.spriteChains;
|
|
||||||
|
|
||||||
std::size_t spriteChainCount = spriteChainVector.size();
|
|
||||||
if (spriteChainCount > 0)
|
|
||||||
{
|
|
||||||
Renderer::SetTexture(overlayTextureUnit, (overlay) ? overlay : &m_whiteTexture);
|
|
||||||
|
|
||||||
std::size_t spriteChain = 0; // Which chain of sprites are we treating
|
|
||||||
std::size_t spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// We open the buffer in writing mode
|
|
||||||
BufferMapper<VertexBuffer> vertexMapper(m_spriteBuffer, BufferAccess_DiscardAndWrite);
|
|
||||||
VertexStruct_XYZ_Color_UV* vertices = static_cast<VertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
|
|
||||||
|
|
||||||
std::size_t spriteCount = 0;
|
|
||||||
std::size_t maxSpriteCount = std::min(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain];
|
|
||||||
std::size_t count = std::min(maxSpriteCount - spriteCount, currentChain.spriteCount - spriteChainOffset);
|
|
||||||
|
|
||||||
std::memcpy(vertices, currentChain.vertices + spriteChainOffset * 4, 4 * count * sizeof(VertexStruct_XYZ_Color_UV));
|
|
||||||
vertices += count * 4;
|
|
||||||
|
|
||||||
spriteCount += count;
|
|
||||||
spriteChainOffset += count;
|
|
||||||
|
|
||||||
// Have we treated the entire chain ?
|
|
||||||
if (spriteChainOffset == currentChain.spriteCount)
|
|
||||||
{
|
|
||||||
spriteChain++;
|
|
||||||
spriteChainOffset = 0;
|
|
||||||
}
|
|
||||||
} while (spriteCount < maxSpriteCount && spriteChain < spriteChainCount);
|
|
||||||
|
|
||||||
vertexMapper.Unmap();
|
|
||||||
|
|
||||||
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, spriteCount * 6);
|
|
||||||
} while (spriteChain < spriteChainCount);
|
|
||||||
|
|
||||||
spriteChainVector.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We set it back to zero
|
|
||||||
matEntry.enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pipelineEntry.enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Draws billboards
|
|
||||||
*
|
|
||||||
* \param sceneData Data of the scene
|
|
||||||
* \param layer Layer of the rendering
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DepthRenderTechnique::DrawBillboards(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const
|
|
||||||
{
|
|
||||||
const Shader* lastShader = nullptr;
|
|
||||||
const ShaderUniforms* shaderUniforms = nullptr;
|
|
||||||
|
|
||||||
if (Renderer::HasCapability(RendererCap_Instancing))
|
|
||||||
{
|
|
||||||
VertexBuffer* instanceBuffer = Renderer::GetInstanceBuffer();
|
|
||||||
instanceBuffer->SetVertexDeclaration(&s_billboardInstanceDeclaration);
|
|
||||||
|
|
||||||
Renderer::SetVertexBuffer(&s_quadVertexBuffer);
|
|
||||||
|
|
||||||
for (auto& pipelinePair : layer.billboards)
|
|
||||||
{
|
|
||||||
const MaterialPipeline* pipeline = pipelinePair.first;
|
|
||||||
auto& pipelineEntry = pipelinePair.second;
|
|
||||||
|
|
||||||
if (pipelineEntry.enabled)
|
|
||||||
{
|
|
||||||
const MaterialPipeline::Instance& pipelineInstance = pipeline->Apply(ShaderFlags_Billboard | ShaderFlags_Instancing | ShaderFlags_VertexColor);
|
|
||||||
|
|
||||||
const Shader* shader = pipelineInstance.uberInstance->GetShader();
|
|
||||||
|
|
||||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
|
||||||
if (shader != lastShader)
|
|
||||||
{
|
|
||||||
// Index of uniforms in the shader
|
|
||||||
shaderUniforms = GetShaderUniforms(shader);
|
|
||||||
|
|
||||||
// Ambiant color of the scene
|
|
||||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
|
||||||
|
|
||||||
lastShader = shader;
|
lastShader = shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& matIt : pipelinePair.second.materialMap)
|
lastPipeline = pipeline;
|
||||||
{
|
}
|
||||||
const Material* material = matIt.first;
|
|
||||||
auto& entry = matIt.second;
|
|
||||||
auto& billboardVector = entry.billboards;
|
|
||||||
|
|
||||||
std::size_t billboardCount = billboardVector.size();
|
if (lastMaterial != basicSprites.material)
|
||||||
if (billboardCount > 0)
|
{
|
||||||
{
|
basicSprites.material->Apply(*pipelineInstance);
|
||||||
// We begin to apply the material (and get the shader activated doing so)
|
|
||||||
material->Apply(pipelineInstance);
|
|
||||||
|
|
||||||
const ForwardRenderQueue::BillboardData* data = &billboardVector[0];
|
Renderer::SetTextureSampler(overlayTextureUnit, basicSprites.material->GetDiffuseSampler());
|
||||||
std::size_t maxBillboardPerDraw = instanceBuffer->GetVertexCount();
|
|
||||||
do
|
|
||||||
{
|
|
||||||
std::size_t renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
|
|
||||||
billboardCount -= renderedBillboardCount;
|
|
||||||
|
|
||||||
instanceBuffer->Fill(data, 0, renderedBillboardCount);
|
lastMaterial = basicSprites.material;
|
||||||
data += renderedBillboardCount;
|
}
|
||||||
|
|
||||||
Renderer::DrawPrimitivesInstanced(renderedBillboardCount, PrimitiveMode_TriangleStrip, 0, 4);
|
const Nz::Texture* overlayTexture = (basicSprites.overlay) ? basicSprites.overlay.Get() : &m_whiteTexture;
|
||||||
}
|
if (overlayTexture != lastOverlay)
|
||||||
while (billboardCount > 0);
|
{
|
||||||
|
Renderer::SetTexture(overlayTextureUnit, overlayTexture);
|
||||||
|
lastOverlay = overlayTexture;
|
||||||
|
}
|
||||||
|
|
||||||
billboardVector.clear();
|
if (basicSprites.material->IsScissorTestEnabled() && scissorRect != lastScissorRect)
|
||||||
}
|
{
|
||||||
}
|
Renderer::SetScissorRect(scissorRect);
|
||||||
|
lastScissorRect = scissorRect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_spriteChains.emplace_back(basicSprites.vertices, basicSprites.spriteCount);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Renderer::SetIndexBuffer(&s_quadIndexBuffer);
|
|
||||||
Renderer::SetVertexBuffer(&m_billboardPointBuffer);
|
|
||||||
|
|
||||||
for (auto& pipelinePair : layer.billboards)
|
Commit();
|
||||||
{
|
|
||||||
const MaterialPipeline* pipeline = pipelinePair.first;
|
|
||||||
auto& pipelineEntry = pipelinePair.second;
|
|
||||||
|
|
||||||
if (pipelineEntry.enabled)
|
|
||||||
{
|
|
||||||
const MaterialPipeline::Instance& pipelineInstance = pipeline->Apply(ShaderFlags_Billboard | ShaderFlags_VertexColor);
|
|
||||||
|
|
||||||
const Shader* shader = pipelineInstance.uberInstance->GetShader();
|
|
||||||
|
|
||||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
|
||||||
if (shader != lastShader)
|
|
||||||
{
|
|
||||||
// Index of uniforms in the shader
|
|
||||||
shaderUniforms = GetShaderUniforms(shader);
|
|
||||||
|
|
||||||
// Ambiant color of the scene
|
|
||||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
|
||||||
|
|
||||||
lastShader = shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& matIt : pipelinePair.second.materialMap)
|
|
||||||
{
|
|
||||||
auto& entry = matIt.second;
|
|
||||||
auto& billboardVector = entry.billboards;
|
|
||||||
|
|
||||||
const ForwardRenderQueue::BillboardData* data = &billboardVector[0];
|
|
||||||
std::size_t maxBillboardPerDraw = std::min(s_maxQuads, m_billboardPointBuffer.GetVertexCount() / 4);
|
|
||||||
|
|
||||||
std::size_t billboardCount = billboardVector.size();
|
|
||||||
do
|
|
||||||
{
|
|
||||||
std::size_t renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
|
|
||||||
billboardCount -= renderedBillboardCount;
|
|
||||||
|
|
||||||
BufferMapper<VertexBuffer> vertexMapper(m_billboardPointBuffer, BufferAccess_DiscardAndWrite, 0, renderedBillboardCount * 4);
|
|
||||||
BillboardPoint* vertices = static_cast<BillboardPoint*>(vertexMapper.GetPointer());
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < renderedBillboardCount; ++i)
|
|
||||||
{
|
|
||||||
const ForwardRenderQueue::BillboardData& billboard = *data++;
|
|
||||||
|
|
||||||
vertices->color = billboard.color;
|
|
||||||
vertices->position = billboard.center;
|
|
||||||
vertices->sinCos = billboard.sinCos;
|
|
||||||
vertices->size = billboard.size;
|
|
||||||
vertices->uv.Set(0.f, 1.f);
|
|
||||||
vertices++;
|
|
||||||
|
|
||||||
vertices->color = billboard.color;
|
|
||||||
vertices->position = billboard.center;
|
|
||||||
vertices->sinCos = billboard.sinCos;
|
|
||||||
vertices->size = billboard.size;
|
|
||||||
vertices->uv.Set(1.f, 1.f);
|
|
||||||
vertices++;
|
|
||||||
|
|
||||||
vertices->color = billboard.color;
|
|
||||||
vertices->position = billboard.center;
|
|
||||||
vertices->sinCos = billboard.sinCos;
|
|
||||||
vertices->size = billboard.size;
|
|
||||||
vertices->uv.Set(0.f, 0.f);
|
|
||||||
vertices++;
|
|
||||||
|
|
||||||
vertices->color = billboard.color;
|
|
||||||
vertices->position = billboard.center;
|
|
||||||
vertices->sinCos = billboard.sinCos;
|
|
||||||
vertices->size = billboard.size;
|
|
||||||
vertices->uv.Set(1.f, 0.f);
|
|
||||||
vertices++;
|
|
||||||
}
|
|
||||||
|
|
||||||
vertexMapper.Unmap();
|
|
||||||
|
|
||||||
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, renderedBillboardCount * 6);
|
|
||||||
}
|
|
||||||
while (billboardCount > 0);
|
|
||||||
|
|
||||||
billboardVector.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Draws opaques models
|
|
||||||
*
|
|
||||||
* \param sceneData Data of the scene
|
|
||||||
* \param layer Layer of the rendering
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DepthRenderTechnique::DrawOpaqueModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const
|
|
||||||
{
|
|
||||||
const Shader* lastShader = nullptr;
|
|
||||||
const ShaderUniforms* shaderUniforms = nullptr;
|
|
||||||
|
|
||||||
for (auto& pipelinePair : layer.opaqueModels)
|
|
||||||
{
|
|
||||||
const MaterialPipeline* pipeline = pipelinePair.first;
|
|
||||||
auto& pipelineEntry = pipelinePair.second;
|
|
||||||
|
|
||||||
if (pipelineEntry.maxInstanceCount > 0)
|
|
||||||
{
|
|
||||||
bool instancing = (pipelineEntry.maxInstanceCount > NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT);
|
|
||||||
const MaterialPipeline::Instance& pipelineInstance = pipeline->Apply((instancing) ? ShaderFlags_Instancing : 0);
|
|
||||||
|
|
||||||
const Shader* shader = pipelineInstance.uberInstance->GetShader();
|
|
||||||
|
|
||||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
|
||||||
if (shader != lastShader)
|
|
||||||
{
|
|
||||||
// Index of uniforms in the shader
|
|
||||||
shaderUniforms = GetShaderUniforms(shader);
|
|
||||||
|
|
||||||
// Ambiant color of the scene
|
|
||||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
|
||||||
|
|
||||||
lastShader = shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& materialPair : pipelineEntry.materialMap)
|
|
||||||
{
|
|
||||||
const Material* material = materialPair.first;
|
|
||||||
auto& matEntry = materialPair.second;
|
|
||||||
|
|
||||||
if (matEntry.enabled)
|
|
||||||
{
|
|
||||||
material->Apply(pipelineInstance);
|
|
||||||
|
|
||||||
ForwardRenderQueue::MeshInstanceContainer& meshInstances = matEntry.meshMap;
|
|
||||||
|
|
||||||
// Meshes
|
|
||||||
for (auto& meshIt : meshInstances)
|
|
||||||
{
|
|
||||||
const MeshData& meshData = meshIt.first;
|
|
||||||
auto& meshEntry = meshIt.second;
|
|
||||||
|
|
||||||
std::vector<Matrix4f>& instances = meshEntry.instances;
|
|
||||||
if (!instances.empty())
|
|
||||||
{
|
|
||||||
const IndexBuffer* indexBuffer = meshData.indexBuffer;
|
|
||||||
const VertexBuffer* vertexBuffer = meshData.vertexBuffer;
|
|
||||||
|
|
||||||
// Handle draw call before rendering loop
|
|
||||||
Renderer::DrawCall drawFunc;
|
|
||||||
Renderer::DrawCallInstanced instancedDrawFunc;
|
|
||||||
unsigned int indexCount;
|
|
||||||
|
|
||||||
if (indexBuffer)
|
|
||||||
{
|
|
||||||
drawFunc = Renderer::DrawIndexedPrimitives;
|
|
||||||
instancedDrawFunc = Renderer::DrawIndexedPrimitivesInstanced;
|
|
||||||
indexCount = indexBuffer->GetIndexCount();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
drawFunc = Renderer::DrawPrimitives;
|
|
||||||
instancedDrawFunc = Renderer::DrawPrimitivesInstanced;
|
|
||||||
indexCount = vertexBuffer->GetVertexCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer::SetIndexBuffer(indexBuffer);
|
|
||||||
Renderer::SetVertexBuffer(vertexBuffer);
|
|
||||||
|
|
||||||
if (instancing)
|
|
||||||
{
|
|
||||||
// We compute the number of instances that we will be able to draw this time (depending on the instancing buffer size)
|
|
||||||
VertexBuffer* instanceBuffer = Renderer::GetInstanceBuffer();
|
|
||||||
instanceBuffer->SetVertexDeclaration(VertexDeclaration::Get(VertexLayout_Matrix4));
|
|
||||||
|
|
||||||
const Matrix4f* instanceMatrices = &instances[0];
|
|
||||||
std::size_t instanceCount = instances.size();
|
|
||||||
std::size_t maxInstanceCount = instanceBuffer->GetVertexCount(); // Maximum number of instance in one batch
|
|
||||||
|
|
||||||
while (instanceCount > 0)
|
|
||||||
{
|
|
||||||
// We compute the number of instances that we will be able to draw this time (depending on the instancing buffer size)
|
|
||||||
std::size_t renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
|
|
||||||
instanceCount -= renderedInstanceCount;
|
|
||||||
|
|
||||||
// We fill the instancing buffer with our world matrices
|
|
||||||
instanceBuffer->Fill(instanceMatrices, 0, renderedInstanceCount);
|
|
||||||
instanceMatrices += renderedInstanceCount;
|
|
||||||
|
|
||||||
// And we draw
|
|
||||||
instancedDrawFunc(renderedInstanceCount, meshData.primitiveMode, 0, indexCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Without instancing, we must do a draw call for each instance
|
|
||||||
// This may be faster than instancing under a certain number
|
|
||||||
// Due to the time to modify the instancing buffer
|
|
||||||
for (const Matrix4f& matrix : instances)
|
|
||||||
{
|
|
||||||
Renderer::SetMatrix(MatrixType_World, matrix);
|
|
||||||
drawFunc(meshData.primitiveMode, 0, indexCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
instances.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
matEntry.enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pipelineEntry.maxInstanceCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -1,931 +0,0 @@
|
||||||
// Copyright (C) 2017 Jérôme Leclercq
|
|
||||||
// This file is part of the "Nazara Engine - Graphics module"
|
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
||||||
|
|
||||||
#include <Nazara/Graphics/ForwardRenderQueue.hpp>
|
|
||||||
#include <Nazara/Graphics/AbstractViewer.hpp>
|
|
||||||
#include <Nazara/Utility/VertexStruct.hpp>
|
|
||||||
#include <Nazara/Graphics/Debug.hpp>
|
|
||||||
|
|
||||||
///TODO: Replace sinus/cosinus by a lookup table (which will lead to a speed up about 10x)
|
|
||||||
|
|
||||||
namespace Nz
|
|
||||||
{
|
|
||||||
/*!
|
|
||||||
* \ingroup graphics
|
|
||||||
* \class Nz::ForwardRenderQueue
|
|
||||||
* \brief Graphics class that represents the rendering queue for forward rendering
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Sizes of the billboards
|
|
||||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
|
||||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
|
||||||
*
|
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
|
||||||
{
|
|
||||||
NazaraAssert(material, "Invalid material");
|
|
||||||
|
|
||||||
Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1
|
|
||||||
|
|
||||||
if (!sinCosPtr)
|
|
||||||
sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
|
||||||
|
|
||||||
if (!colorPtr)
|
|
||||||
colorPtr.Reset(&Color::White, 0); // Same
|
|
||||||
|
|
||||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
|
||||||
for (unsigned int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
billboardData->center = *positionPtr++;
|
|
||||||
billboardData->color = *colorPtr++;
|
|
||||||
billboardData->sinCos = *sinCosPtr++;
|
|
||||||
billboardData->size = *sizePtr++;
|
|
||||||
billboardData++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Sizes of the billboards
|
|
||||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
|
||||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
|
||||||
*
|
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
|
||||||
{
|
|
||||||
NazaraAssert(material, "Invalid material");
|
|
||||||
|
|
||||||
Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1
|
|
||||||
|
|
||||||
if (!sinCosPtr)
|
|
||||||
sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
|
||||||
|
|
||||||
float defaultAlpha = 1.f;
|
|
||||||
|
|
||||||
if (!alphaPtr)
|
|
||||||
alphaPtr.Reset(&defaultAlpha, 0); // Same
|
|
||||||
|
|
||||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
|
||||||
for (unsigned int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
billboardData->center = *positionPtr++;
|
|
||||||
billboardData->color = Color(255, 255, 255, static_cast<UInt8>(255.f * (*alphaPtr++)));
|
|
||||||
billboardData->sinCos = *sinCosPtr++;
|
|
||||||
billboardData->size = *sizePtr++;
|
|
||||||
billboardData++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Sizes of the billboards
|
|
||||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
|
||||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
|
||||||
*
|
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
|
||||||
{
|
|
||||||
NazaraAssert(material, "Invalid material");
|
|
||||||
|
|
||||||
float defaultRotation = 0.f;
|
|
||||||
|
|
||||||
if (!anglePtr)
|
|
||||||
anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
|
||||||
|
|
||||||
if (!colorPtr)
|
|
||||||
colorPtr.Reset(&Color::White, 0); // Same
|
|
||||||
|
|
||||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
|
||||||
for (unsigned int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
float sin = std::sin(ToRadians(*anglePtr));
|
|
||||||
float cos = std::cos(ToRadians(*anglePtr));
|
|
||||||
anglePtr++;
|
|
||||||
|
|
||||||
billboardData->center = *positionPtr++;
|
|
||||||
billboardData->color = *colorPtr++;
|
|
||||||
billboardData->sinCos.Set(sin, cos);
|
|
||||||
billboardData->size = *sizePtr++;
|
|
||||||
billboardData++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Sizes of the billboards
|
|
||||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
|
||||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
|
||||||
*
|
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
|
||||||
{
|
|
||||||
NazaraAssert(material, "Invalid material");
|
|
||||||
|
|
||||||
float defaultRotation = 0.f;
|
|
||||||
|
|
||||||
if (!anglePtr)
|
|
||||||
anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
|
||||||
|
|
||||||
float defaultAlpha = 1.f;
|
|
||||||
|
|
||||||
if (!alphaPtr)
|
|
||||||
alphaPtr.Reset(&defaultAlpha, 0); // Same
|
|
||||||
|
|
||||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
|
||||||
for (unsigned int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
float sin = std::sin(ToRadians(*anglePtr));
|
|
||||||
float cos = std::cos(ToRadians(*anglePtr));
|
|
||||||
anglePtr++;
|
|
||||||
|
|
||||||
billboardData->center = *positionPtr++;
|
|
||||||
billboardData->color = Color(255, 255, 255, static_cast<UInt8>(255.f * (*alphaPtr++)));
|
|
||||||
billboardData->sinCos.Set(sin, cos);
|
|
||||||
billboardData->size = *sizePtr++;
|
|
||||||
billboardData++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Size of the billboards
|
|
||||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
|
||||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
|
||||||
*
|
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
|
||||||
{
|
|
||||||
NazaraAssert(material, "Invalid material");
|
|
||||||
|
|
||||||
Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1
|
|
||||||
|
|
||||||
if (!sinCosPtr)
|
|
||||||
sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
|
||||||
|
|
||||||
if (!colorPtr)
|
|
||||||
colorPtr.Reset(&Color::White, 0); // Same
|
|
||||||
|
|
||||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
|
||||||
for (unsigned int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
billboardData->center = *positionPtr++;
|
|
||||||
billboardData->color = *colorPtr++;
|
|
||||||
billboardData->sinCos = *sinCosPtr++;
|
|
||||||
billboardData->size.Set(*sizePtr++);
|
|
||||||
billboardData++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Size of the billboards
|
|
||||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
|
||||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
|
||||||
*
|
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
|
||||||
{
|
|
||||||
NazaraAssert(material, "Invalid material");
|
|
||||||
|
|
||||||
Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1
|
|
||||||
|
|
||||||
if (!sinCosPtr)
|
|
||||||
sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
|
||||||
|
|
||||||
float defaultAlpha = 1.f;
|
|
||||||
|
|
||||||
if (!alphaPtr)
|
|
||||||
alphaPtr.Reset(&defaultAlpha, 0); // Same
|
|
||||||
|
|
||||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
|
||||||
for (unsigned int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
billboardData->center = *positionPtr++;
|
|
||||||
billboardData->color = Color(255, 255, 255, static_cast<UInt8>(255.f * (*alphaPtr++)));
|
|
||||||
billboardData->sinCos = *sinCosPtr++;
|
|
||||||
billboardData->size.Set(*sizePtr++);
|
|
||||||
billboardData++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Size of the billboards
|
|
||||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
|
||||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
|
||||||
*
|
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
|
||||||
{
|
|
||||||
NazaraAssert(material, "Invalid material");
|
|
||||||
|
|
||||||
float defaultRotation = 0.f;
|
|
||||||
|
|
||||||
if (!anglePtr)
|
|
||||||
anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
|
||||||
|
|
||||||
if (!colorPtr)
|
|
||||||
colorPtr.Reset(&Color::White, 0); // Same
|
|
||||||
|
|
||||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
|
||||||
for (unsigned int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
float sin = std::sin(ToRadians(*anglePtr));
|
|
||||||
float cos = std::cos(ToRadians(*anglePtr));
|
|
||||||
anglePtr++;
|
|
||||||
|
|
||||||
billboardData->center = *positionPtr++;
|
|
||||||
billboardData->color = *colorPtr++;
|
|
||||||
billboardData->sinCos.Set(sin, cos);
|
|
||||||
billboardData->size.Set(*sizePtr++);
|
|
||||||
billboardData++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds multiple billboards to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboards
|
|
||||||
* \param count Number of billboards
|
|
||||||
* \param positionPtr Position of the billboards
|
|
||||||
* \param sizePtr Size of the billboards
|
|
||||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
|
||||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
|
||||||
*
|
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
|
||||||
{
|
|
||||||
NazaraAssert(material, "Invalid material");
|
|
||||||
|
|
||||||
float defaultRotation = 0.f;
|
|
||||||
|
|
||||||
if (!anglePtr)
|
|
||||||
anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
|
||||||
|
|
||||||
float defaultAlpha = 1.f;
|
|
||||||
|
|
||||||
if (!alphaPtr)
|
|
||||||
alphaPtr.Reset(&defaultAlpha, 0); // Same
|
|
||||||
|
|
||||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
|
||||||
for (unsigned int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
float sin = std::sin(ToRadians(*anglePtr));
|
|
||||||
float cos = std::cos(ToRadians(*anglePtr));
|
|
||||||
anglePtr++;
|
|
||||||
|
|
||||||
billboardData->center = *positionPtr++;
|
|
||||||
billboardData->color = Color(255, 255, 255, static_cast<UInt8>(255.f * (*alphaPtr++)));
|
|
||||||
billboardData->sinCos.Set(sin, cos);
|
|
||||||
billboardData->size.Set(*sizePtr++);
|
|
||||||
billboardData++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds drawable to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param drawable Drawable user defined
|
|
||||||
*
|
|
||||||
* \remark Produces a NazaraError if drawable is invalid
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::AddDrawable(int renderOrder, const Drawable* drawable)
|
|
||||||
{
|
|
||||||
#if NAZARA_GRAPHICS_SAFE
|
|
||||||
if (!drawable)
|
|
||||||
{
|
|
||||||
NazaraError("Invalid drawable");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto& otherDrawables = GetLayer(renderOrder).otherDrawables;
|
|
||||||
|
|
||||||
otherDrawables.push_back(drawable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds mesh to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the mesh
|
|
||||||
* \param meshData Data of the mesh
|
|
||||||
* \param meshAABB Box of the mesh
|
|
||||||
* \param transformMatrix Matrix of the mesh
|
|
||||||
*
|
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
|
||||||
*/
|
|
||||||
void ForwardRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix)
|
|
||||||
{
|
|
||||||
NazaraAssert(material, "Invalid material");
|
|
||||||
|
|
||||||
if (material->IsDepthSortingEnabled())
|
|
||||||
{
|
|
||||||
Layer& currentLayer = GetLayer(renderOrder);
|
|
||||||
auto& transparentMeshes = currentLayer.depthSortedMeshes;
|
|
||||||
auto& transparentData = currentLayer.depthSortedMeshData;
|
|
||||||
|
|
||||||
// The material is marked for depth sorting, we must draw this mesh using another way (after the rendering of opaques objects while sorting them)
|
|
||||||
std::size_t index = transparentData.size();
|
|
||||||
transparentData.resize(index+1);
|
|
||||||
|
|
||||||
UnbatchedModelData& data = transparentData.back();
|
|
||||||
data.material = material;
|
|
||||||
data.meshData = meshData;
|
|
||||||
data.obbSphere = Spheref(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius());
|
|
||||||
data.transformMatrix = transformMatrix;
|
|
||||||
|
|
||||||
transparentMeshes.push_back(index);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Layer& currentLayer = GetLayer(renderOrder);
|
|
||||||
MeshPipelineBatches& opaqueModels = currentLayer.opaqueModels;
|
|
||||||
|
|
||||||
const MaterialPipeline* materialPipeline = material->GetPipeline();
|
|
||||||
|
|
||||||
auto pipelineIt = opaqueModels.find(materialPipeline);
|
|
||||||
if (pipelineIt == opaqueModels.end())
|
|
||||||
{
|
|
||||||
BatchedMaterialEntry materialEntry;
|
|
||||||
pipelineIt = opaqueModels.insert(MeshPipelineBatches::value_type(materialPipeline, std::move(materialEntry))).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
BatchedMaterialEntry& materialEntry = pipelineIt->second;
|
|
||||||
MeshMaterialBatches& materialMap = materialEntry.materialMap;
|
|
||||||
|
|
||||||
auto materialIt = materialMap.find(material);
|
|
||||||
if (materialIt == materialMap.end())
|
|
||||||
{
|
|
||||||
BatchedModelEntry entry;
|
|
||||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
|
||||||
|
|
||||||
materialIt = materialMap.insert(MeshMaterialBatches::value_type(material, std::move(entry))).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
BatchedModelEntry& entry = materialIt->second;
|
|
||||||
entry.enabled = true;
|
|
||||||
|
|
||||||
MeshInstanceContainer& meshMap = entry.meshMap;
|
|
||||||
|
|
||||||
auto it2 = meshMap.find(meshData);
|
|
||||||
if (it2 == meshMap.end())
|
|
||||||
{
|
|
||||||
MeshInstanceEntry instanceEntry;
|
|
||||||
instanceEntry.squaredBoundingSphere = meshAABB.GetSquaredBoundingSphere();
|
|
||||||
|
|
||||||
if (meshData.indexBuffer)
|
|
||||||
instanceEntry.indexBufferReleaseSlot.Connect(meshData.indexBuffer->OnIndexBufferRelease, this, &ForwardRenderQueue::OnIndexBufferInvalidation);
|
|
||||||
|
|
||||||
instanceEntry.vertexBufferReleaseSlot.Connect(meshData.vertexBuffer->OnVertexBufferRelease, this, &ForwardRenderQueue::OnVertexBufferInvalidation);
|
|
||||||
|
|
||||||
it2 = meshMap.insert(std::make_pair(meshData, std::move(instanceEntry))).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Matrix4f>& instances = it2->second.instances;
|
|
||||||
instances.push_back(transformMatrix);
|
|
||||||
|
|
||||||
materialEntry.maxInstanceCount = std::max(materialEntry.maxInstanceCount, instances.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds sprites to the queue
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the sprites
|
|
||||||
* \param vertices Buffer of data for the sprites
|
|
||||||
* \param spriteCount Number of sprites
|
|
||||||
* \param overlay Texture of the sprites
|
|
||||||
*
|
|
||||||
* \remark Produces a NazaraAssert if material is invalid
|
|
||||||
*/
|
|
||||||
void ForwardRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay)
|
|
||||||
{
|
|
||||||
NazaraAssert(material, "Invalid material");
|
|
||||||
|
|
||||||
Layer& currentLayer = GetLayer(renderOrder);
|
|
||||||
|
|
||||||
if (material->IsDepthSortingEnabled())
|
|
||||||
{
|
|
||||||
auto& transparentSprites = currentLayer.depthSortedSprites;
|
|
||||||
auto& transparentData = currentLayer.depthSortedSpriteData;
|
|
||||||
|
|
||||||
// The material is marked for depth sorting, we must draw this mesh using another way (after the rendering of opaques objects while sorting them)
|
|
||||||
std::size_t index = transparentData.size();
|
|
||||||
transparentData.resize(index + 1);
|
|
||||||
|
|
||||||
UnbatchedSpriteData& data = transparentData.back();
|
|
||||||
data.material = material;
|
|
||||||
data.overlay = overlay;
|
|
||||||
data.spriteCount = spriteCount;
|
|
||||||
data.vertices = vertices;
|
|
||||||
|
|
||||||
transparentSprites.push_back(index);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SpritePipelineBatches& sprites = currentLayer.opaqueSprites;
|
|
||||||
|
|
||||||
const MaterialPipeline* materialPipeline = material->GetPipeline();
|
|
||||||
|
|
||||||
auto pipelineIt = sprites.find(materialPipeline);
|
|
||||||
if (pipelineIt == sprites.end())
|
|
||||||
{
|
|
||||||
BatchedSpritePipelineEntry materialEntry;
|
|
||||||
pipelineIt = sprites.insert(SpritePipelineBatches::value_type(materialPipeline, std::move(materialEntry))).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
BatchedSpritePipelineEntry& pipelineEntry = pipelineIt->second;
|
|
||||||
pipelineEntry.enabled = true;
|
|
||||||
|
|
||||||
SpriteMaterialBatches& materialMap = pipelineEntry.materialMap;
|
|
||||||
|
|
||||||
auto matIt = materialMap.find(material);
|
|
||||||
if (matIt == materialMap.end())
|
|
||||||
{
|
|
||||||
BatchedBasicSpriteEntry entry;
|
|
||||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
|
||||||
|
|
||||||
matIt = materialMap.insert(SpriteMaterialBatches::value_type(material, std::move(entry))).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
BatchedBasicSpriteEntry& entry = matIt->second;
|
|
||||||
entry.enabled = true;
|
|
||||||
|
|
||||||
auto& overlayMap = entry.overlayMap;
|
|
||||||
|
|
||||||
auto overlayIt = overlayMap.find(overlay);
|
|
||||||
if (overlayIt == overlayMap.end())
|
|
||||||
{
|
|
||||||
BatchedSpriteEntry overlayEntry;
|
|
||||||
if (overlay)
|
|
||||||
overlayEntry.textureReleaseSlot.Connect(overlay->OnTextureRelease, this, &ForwardRenderQueue::OnTextureInvalidation);
|
|
||||||
|
|
||||||
overlayIt = overlayMap.insert(std::make_pair(overlay, std::move(overlayEntry))).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& spriteVector = overlayIt->second.spriteChains;
|
|
||||||
spriteVector.push_back(SpriteChain_XYZ_Color_UV({vertices, spriteCount}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Clears the queue
|
|
||||||
*
|
|
||||||
* \param fully Should everything be cleared or we can keep layers
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::Clear(bool fully)
|
|
||||||
{
|
|
||||||
AbstractRenderQueue::Clear(fully);
|
|
||||||
|
|
||||||
if (fully)
|
|
||||||
layers.clear();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (auto it = layers.begin(); it != layers.end();)
|
|
||||||
{
|
|
||||||
Layer& layer = it->second;
|
|
||||||
if (layer.clearCount++ >= 100)
|
|
||||||
layers.erase(it++);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (auto& pipelinePair : layer.billboards)
|
|
||||||
{
|
|
||||||
auto& pipelineEntry = pipelinePair.second;
|
|
||||||
|
|
||||||
if (pipelineEntry.enabled)
|
|
||||||
{
|
|
||||||
for (auto& matIt : pipelinePair.second.materialMap)
|
|
||||||
{
|
|
||||||
auto& entry = matIt.second;
|
|
||||||
auto& billboardVector = entry.billboards;
|
|
||||||
|
|
||||||
billboardVector.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pipelineEntry.enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& pipelinePair : layer.opaqueSprites)
|
|
||||||
{
|
|
||||||
auto& pipelineEntry = pipelinePair.second;
|
|
||||||
|
|
||||||
if (pipelineEntry.enabled)
|
|
||||||
{
|
|
||||||
for (auto& materialPair : pipelineEntry.materialMap)
|
|
||||||
{
|
|
||||||
auto& matEntry = materialPair.second;
|
|
||||||
|
|
||||||
if (matEntry.enabled)
|
|
||||||
{
|
|
||||||
auto& overlayMap = matEntry.overlayMap;
|
|
||||||
for (auto& overlayIt : overlayMap)
|
|
||||||
{
|
|
||||||
auto& spriteChainVector = overlayIt.second.spriteChains;
|
|
||||||
spriteChainVector.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
matEntry.enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pipelineEntry.enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& pipelinePair : layer.opaqueModels)
|
|
||||||
{
|
|
||||||
auto& pipelineEntry = pipelinePair.second;
|
|
||||||
|
|
||||||
if (pipelineEntry.maxInstanceCount > 0)
|
|
||||||
{
|
|
||||||
for (auto& materialPair : pipelineEntry.materialMap)
|
|
||||||
{
|
|
||||||
auto& matEntry = materialPair.second;
|
|
||||||
if (matEntry.enabled)
|
|
||||||
{
|
|
||||||
MeshInstanceContainer& meshInstances = matEntry.meshMap;
|
|
||||||
|
|
||||||
for (auto& meshIt : meshInstances)
|
|
||||||
{
|
|
||||||
auto& meshEntry = meshIt.second;
|
|
||||||
meshEntry.instances.clear();
|
|
||||||
}
|
|
||||||
matEntry.enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pipelineEntry.maxInstanceCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layer.depthSortedMeshes.clear();
|
|
||||||
layer.depthSortedMeshData.clear();
|
|
||||||
layer.depthSortedSpriteData.clear();
|
|
||||||
layer.depthSortedSprites.clear();
|
|
||||||
layer.otherDrawables.clear();
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Sorts the object according to the viewer position, furthest to nearest
|
|
||||||
*
|
|
||||||
* \param viewer Viewer of the scene
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::Sort(const AbstractViewer* viewer)
|
|
||||||
{
|
|
||||||
if (viewer->GetProjectionType() == ProjectionType_Orthogonal)
|
|
||||||
SortForOrthographic(viewer);
|
|
||||||
else
|
|
||||||
SortForPerspective(viewer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Gets the billboard data
|
|
||||||
* \return Pointer to the data of the billboards
|
|
||||||
*
|
|
||||||
* \param renderOrder Order of rendering
|
|
||||||
* \param material Material of the billboard
|
|
||||||
*/
|
|
||||||
|
|
||||||
ForwardRenderQueue::BillboardData* ForwardRenderQueue::GetBillboardData(int renderOrder, const Material* material, unsigned int count)
|
|
||||||
{
|
|
||||||
auto& billboards = GetLayer(renderOrder).billboards;
|
|
||||||
|
|
||||||
const MaterialPipeline* materialPipeline = material->GetPipeline();
|
|
||||||
|
|
||||||
auto pipelineIt = billboards.find(materialPipeline);
|
|
||||||
if (pipelineIt == billboards.end())
|
|
||||||
{
|
|
||||||
BatchedBillboardPipelineEntry pipelineEntry;
|
|
||||||
pipelineIt = billboards.insert(BillboardPipelineBatches::value_type(materialPipeline, std::move(pipelineEntry))).first;
|
|
||||||
}
|
|
||||||
BatchedBillboardPipelineEntry& pipelineEntry = pipelineIt->second;
|
|
||||||
pipelineEntry.enabled = true;
|
|
||||||
|
|
||||||
BatchedBillboardContainer& materialMap = pipelineEntry.materialMap;
|
|
||||||
|
|
||||||
auto it = materialMap.find(material);
|
|
||||||
if (it == materialMap.end())
|
|
||||||
{
|
|
||||||
BatchedBillboardEntry entry;
|
|
||||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
|
||||||
|
|
||||||
it = materialMap.insert(BatchedBillboardContainer::value_type(material, std::move(entry))).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
BatchedBillboardEntry& entry = it->second;
|
|
||||||
|
|
||||||
auto& billboardVector = entry.billboards;
|
|
||||||
std::size_t prevSize = billboardVector.size();
|
|
||||||
billboardVector.resize(prevSize + count);
|
|
||||||
|
|
||||||
return &billboardVector[prevSize];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Gets the ith layer
|
|
||||||
* \return Reference to the ith layer for the queue
|
|
||||||
*
|
|
||||||
* \param i Index of the layer
|
|
||||||
*/
|
|
||||||
|
|
||||||
ForwardRenderQueue::Layer& ForwardRenderQueue::GetLayer(int i)
|
|
||||||
{
|
|
||||||
auto it = layers.find(i);
|
|
||||||
if (it == layers.end())
|
|
||||||
it = layers.insert(std::make_pair(i, Layer())).first;
|
|
||||||
|
|
||||||
Layer& layer = it->second;
|
|
||||||
layer.clearCount = 0;
|
|
||||||
|
|
||||||
return layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ForwardRenderQueue::SortBillboards(Layer& layer, const Planef& nearPlane)
|
|
||||||
{
|
|
||||||
for (auto& pipelinePair : layer.billboards)
|
|
||||||
{
|
|
||||||
for (auto& matPair : pipelinePair.second.materialMap)
|
|
||||||
{
|
|
||||||
const Material* mat = matPair.first;
|
|
||||||
|
|
||||||
if (mat->IsDepthSortingEnabled())
|
|
||||||
{
|
|
||||||
BatchedBillboardEntry& entry = matPair.second;
|
|
||||||
auto& billboardVector = entry.billboards;
|
|
||||||
|
|
||||||
std::sort(billboardVector.begin(), billboardVector.end(), [&nearPlane] (const BillboardData& data1, const BillboardData& data2)
|
|
||||||
{
|
|
||||||
return nearPlane.Distance(data1.center) > nearPlane.Distance(data2.center);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ForwardRenderQueue::SortForOrthographic(const AbstractViewer * viewer)
|
|
||||||
{
|
|
||||||
Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near);
|
|
||||||
|
|
||||||
for (auto& pair : layers)
|
|
||||||
{
|
|
||||||
Layer& layer = pair.second;
|
|
||||||
|
|
||||||
std::sort(layer.depthSortedMeshes.begin(), layer.depthSortedMeshes.end(), [&layer, &nearPlane] (std::size_t index1, std::size_t index2)
|
|
||||||
{
|
|
||||||
const Spheref& sphere1 = layer.depthSortedMeshData[index1].obbSphere;
|
|
||||||
const Spheref& sphere2 = layer.depthSortedMeshData[index2].obbSphere;
|
|
||||||
|
|
||||||
return nearPlane.Distance(sphere1.GetPosition()) < nearPlane.Distance(sphere2.GetPosition());
|
|
||||||
});
|
|
||||||
|
|
||||||
std::sort(layer.depthSortedSprites.begin(), layer.depthSortedSprites.end(), [&layer, &nearPlane] (std::size_t index1, std::size_t index2)
|
|
||||||
{
|
|
||||||
const Vector3f& pos1 = layer.depthSortedSpriteData[index1].vertices[0].position;
|
|
||||||
const Vector3f& pos2 = layer.depthSortedSpriteData[index2].vertices[0].position;
|
|
||||||
|
|
||||||
return nearPlane.Distance(pos1) < nearPlane.Distance(pos2);
|
|
||||||
});
|
|
||||||
|
|
||||||
SortBillboards(layer, nearPlane);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ForwardRenderQueue::SortForPerspective(const AbstractViewer* viewer)
|
|
||||||
{
|
|
||||||
Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near);
|
|
||||||
Vector3f viewerPos = viewer->GetEyePosition();
|
|
||||||
|
|
||||||
for (auto& pair : layers)
|
|
||||||
{
|
|
||||||
Layer& layer = pair.second;
|
|
||||||
|
|
||||||
std::sort(layer.depthSortedMeshes.begin(), layer.depthSortedMeshes.end(), [&layer, &viewerPos] (std::size_t index1, std::size_t index2)
|
|
||||||
{
|
|
||||||
const Spheref& sphere1 = layer.depthSortedMeshData[index1].obbSphere;
|
|
||||||
const Spheref& sphere2 = layer.depthSortedMeshData[index2].obbSphere;
|
|
||||||
|
|
||||||
return viewerPos.SquaredDistance(sphere1.GetPosition()) > viewerPos.SquaredDistance(sphere2.GetPosition());
|
|
||||||
});
|
|
||||||
|
|
||||||
std::sort(layer.depthSortedSprites.begin(), layer.depthSortedSprites.end(), [&layer, &viewerPos] (std::size_t index1, std::size_t index2)
|
|
||||||
{
|
|
||||||
const Vector3f& pos1 = layer.depthSortedSpriteData[index1].vertices[0].position;
|
|
||||||
const Vector3f& pos2 = layer.depthSortedSpriteData[index2].vertices[0].position;
|
|
||||||
|
|
||||||
return viewerPos.SquaredDistance(pos1) > viewerPos.SquaredDistance(pos2);
|
|
||||||
});
|
|
||||||
|
|
||||||
SortBillboards(layer, nearPlane);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Handle the invalidation of an index buffer
|
|
||||||
*
|
|
||||||
* \param indexBuffer Index buffer being invalidated
|
|
||||||
*/
|
|
||||||
void ForwardRenderQueue::OnIndexBufferInvalidation(const IndexBuffer* indexBuffer)
|
|
||||||
{
|
|
||||||
for (auto& pair : layers)
|
|
||||||
{
|
|
||||||
Layer& layer = pair.second;
|
|
||||||
|
|
||||||
for (auto& pipelineEntry : layer.opaqueModels)
|
|
||||||
{
|
|
||||||
for (auto& materialEntry : pipelineEntry.second.materialMap)
|
|
||||||
{
|
|
||||||
MeshInstanceContainer& meshes = materialEntry.second.meshMap;
|
|
||||||
for (auto it = meshes.begin(); it != meshes.end();)
|
|
||||||
{
|
|
||||||
const MeshData& renderData = it->first;
|
|
||||||
if (renderData.indexBuffer == indexBuffer)
|
|
||||||
it = meshes.erase(it);
|
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Handle the invalidation of a material
|
|
||||||
*
|
|
||||||
* \param material Material being invalidated
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::OnMaterialInvalidation(const Material* material)
|
|
||||||
{
|
|
||||||
for (auto& pair : layers)
|
|
||||||
{
|
|
||||||
Layer& layer = pair.second;
|
|
||||||
|
|
||||||
for (auto& pipelineEntry : layer.opaqueSprites)
|
|
||||||
pipelineEntry.second.materialMap.erase(material);
|
|
||||||
|
|
||||||
for (auto& pipelineEntry : layer.billboards)
|
|
||||||
pipelineEntry.second.materialMap.erase(material);
|
|
||||||
|
|
||||||
for (auto& pipelineEntry : layer.opaqueModels)
|
|
||||||
pipelineEntry.second.materialMap.erase(material);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Handle the invalidation of a texture
|
|
||||||
*
|
|
||||||
* \param texture Texture being invalidated
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::OnTextureInvalidation(const Texture* texture)
|
|
||||||
{
|
|
||||||
for (auto& pair : layers)
|
|
||||||
{
|
|
||||||
Layer& layer = pair.second;
|
|
||||||
for (auto& pipelineEntry : layer.opaqueSprites)
|
|
||||||
{
|
|
||||||
for (auto& materialEntry : pipelineEntry.second.materialMap)
|
|
||||||
materialEntry.second.overlayMap.erase(texture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Handle the invalidation of a vertex buffer
|
|
||||||
*
|
|
||||||
* \param vertexBuffer Vertex buffer being invalidated
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ForwardRenderQueue::OnVertexBufferInvalidation(const VertexBuffer* vertexBuffer)
|
|
||||||
{
|
|
||||||
for (auto& pair : layers)
|
|
||||||
{
|
|
||||||
Layer& layer = pair.second;
|
|
||||||
for (auto& pipelineEntry : layer.opaqueModels)
|
|
||||||
{
|
|
||||||
for (auto& materialEntry : pipelineEntry.second.materialMap)
|
|
||||||
{
|
|
||||||
MeshInstanceContainer& meshes = materialEntry.second.meshMap;
|
|
||||||
for (auto it = meshes.begin(); it != meshes.end();)
|
|
||||||
{
|
|
||||||
const MeshData& renderData = it->first;
|
|
||||||
if (renderData.vertexBuffer == vertexBuffer)
|
|
||||||
it = meshes.erase(it);
|
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ForwardRenderQueue::MaterialComparator::operator()(const Material* mat1, const Material* mat2) const
|
|
||||||
{
|
|
||||||
const Texture* diffuseMap1 = mat1->GetDiffuseMap();
|
|
||||||
const Texture* diffuseMap2 = mat2->GetDiffuseMap();
|
|
||||||
if (diffuseMap1 != diffuseMap2)
|
|
||||||
return diffuseMap1 < diffuseMap2;
|
|
||||||
|
|
||||||
return mat1 < mat2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ForwardRenderQueue::MaterialPipelineComparator::operator()(const MaterialPipeline* pipeline1, const MaterialPipeline* pipeline2) const
|
|
||||||
{
|
|
||||||
const Shader* shader1 = pipeline1->GetInstance().renderPipeline.GetInfo().shader;
|
|
||||||
const Shader* shader2 = pipeline2->GetInstance().renderPipeline.GetInfo().shader;
|
|
||||||
if (shader1 != shader2)
|
|
||||||
return shader1 < shader2;
|
|
||||||
|
|
||||||
return pipeline1 < pipeline2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Functor to compare two mesh data
|
|
||||||
* \return true If first mesh is "smaller" than the second one
|
|
||||||
*
|
|
||||||
* \param data1 First mesh to compare
|
|
||||||
* \param data2 Second mesh to compare
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool ForwardRenderQueue::MeshDataComparator::operator()(const MeshData& data1, const MeshData& data2) const
|
|
||||||
{
|
|
||||||
const Buffer* buffer1;
|
|
||||||
const Buffer* buffer2;
|
|
||||||
|
|
||||||
buffer1 = (data1.indexBuffer) ? data1.indexBuffer->GetBuffer() : nullptr;
|
|
||||||
buffer2 = (data2.indexBuffer) ? data2.indexBuffer->GetBuffer() : nullptr;
|
|
||||||
if (buffer1 != buffer2)
|
|
||||||
return buffer1 < buffer2;
|
|
||||||
|
|
||||||
buffer1 = data1.vertexBuffer->GetBuffer();
|
|
||||||
buffer2 = data2.vertexBuffer->GetBuffer();
|
|
||||||
if (buffer1 != buffer2)
|
|
||||||
return buffer1 < buffer2;
|
|
||||||
|
|
||||||
return data1.primitiveMode < data2.primitiveMode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -188,17 +188,19 @@ namespace Nz
|
||||||
MaterialPipelineInfo pipelineInfo;
|
MaterialPipelineInfo pipelineInfo;
|
||||||
pipelineInfo.uberShader = UberShaderLibrary::Get("Basic");
|
pipelineInfo.uberShader = UberShaderLibrary::Get("Basic");
|
||||||
|
|
||||||
// Basic 2D - No depth write/face culling
|
// Basic 2D - No depth write/face culling with scissoring
|
||||||
pipelineInfo.depthWrite = false;
|
pipelineInfo.depthWrite = false;
|
||||||
pipelineInfo.faceCulling = false;
|
pipelineInfo.faceCulling = false;
|
||||||
|
pipelineInfo.scissorTest = true;
|
||||||
|
|
||||||
MaterialPipelineLibrary::Register("Basic2D", GetPipeline(pipelineInfo));
|
MaterialPipelineLibrary::Register("Basic2D", GetPipeline(pipelineInfo));
|
||||||
|
|
||||||
// Translucent 2D - Alpha blending with no depth write/face culling
|
// Translucent 2D - Alpha blending with no depth write/face culling and scissoring
|
||||||
pipelineInfo.blending = true;
|
pipelineInfo.blending = true;
|
||||||
pipelineInfo.depthWrite = false;
|
pipelineInfo.depthWrite = false;
|
||||||
pipelineInfo.faceCulling = false;
|
pipelineInfo.faceCulling = false;
|
||||||
pipelineInfo.depthSorting = true;
|
pipelineInfo.depthSorting = true;
|
||||||
|
pipelineInfo.scissorTest = true;
|
||||||
pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha;
|
pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha;
|
||||||
pipelineInfo.srcBlend = BlendFunc_SrcAlpha;
|
pipelineInfo.srcBlend = BlendFunc_SrcAlpha;
|
||||||
|
|
||||||
|
|
@ -210,6 +212,7 @@ namespace Nz
|
||||||
pipelineInfo.depthWrite = false;
|
pipelineInfo.depthWrite = false;
|
||||||
pipelineInfo.faceCulling = false;
|
pipelineInfo.faceCulling = false;
|
||||||
pipelineInfo.depthSorting = true;
|
pipelineInfo.depthSorting = true;
|
||||||
|
pipelineInfo.scissorTest = false;
|
||||||
pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha;
|
pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha;
|
||||||
pipelineInfo.srcBlend = BlendFunc_SrcAlpha;
|
pipelineInfo.srcBlend = BlendFunc_SrcAlpha;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ namespace Nz
|
||||||
* \param instanceData Data used for this instance
|
* \param instanceData Data used for this instance
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const
|
||||||
{
|
{
|
||||||
unsigned int submeshCount = m_mesh->GetSubMeshCount();
|
unsigned int submeshCount = m_mesh->GetSubMeshCount();
|
||||||
for (unsigned int i = 0; i < submeshCount; ++i)
|
for (unsigned int i = 0; i < submeshCount; ++i)
|
||||||
|
|
@ -65,7 +65,7 @@ namespace Nz
|
||||||
meshData.primitiveMode = mesh->GetPrimitiveMode();
|
meshData.primitiveMode = mesh->GetPrimitiveMode();
|
||||||
meshData.vertexBuffer = mesh->GetVertexBuffer();
|
meshData.vertexBuffer = mesh->GetVertexBuffer();
|
||||||
|
|
||||||
renderQueue->AddMesh(instanceData.renderOrder, material, meshData, mesh->GetAABB(), instanceData.transformMatrix);
|
renderQueue->AddMesh(instanceData.renderOrder, material, meshData, mesh->GetAABB(), instanceData.transformMatrix, scissorRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/RenderQueue.hpp>
|
||||||
|
#include <Nazara/Core/TaskScheduler.hpp>
|
||||||
|
#include <Nazara/Graphics/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
void RenderQueueInternal::Sort()
|
||||||
|
{
|
||||||
|
std::sort(m_orderedRenderQueue.begin(), m_orderedRenderQueue.end(), [](const RenderDataPair& lhs, const RenderDataPair& rhs)
|
||||||
|
{
|
||||||
|
return lhs.first < rhs.first;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -53,7 +53,7 @@ namespace Nz
|
||||||
* \param instanceData Data for the instance
|
* \param instanceData Data for the instance
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void SkeletalModel::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
void SkeletalModel::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const
|
||||||
{
|
{
|
||||||
if (!m_mesh)
|
if (!m_mesh)
|
||||||
return;
|
return;
|
||||||
|
|
@ -69,7 +69,7 @@ namespace Nz
|
||||||
meshData.primitiveMode = mesh->GetPrimitiveMode();
|
meshData.primitiveMode = mesh->GetPrimitiveMode();
|
||||||
meshData.vertexBuffer = SkinningManager::GetBuffer(mesh, &m_skeleton);
|
meshData.vertexBuffer = SkinningManager::GetBuffer(mesh, &m_skeleton);
|
||||||
|
|
||||||
renderQueue->AddMesh(instanceData.renderOrder, material, meshData, m_skeleton.GetAABB(), instanceData.transformMatrix);
|
renderQueue->AddMesh(instanceData.renderOrder, material, meshData, m_skeleton.GetAABB(), instanceData.transformMatrix, scissorRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,10 @@ namespace Nz
|
||||||
* \param instanceData Data for the instance
|
* \param instanceData Data for the instance
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Sprite::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
void Sprite::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const
|
||||||
{
|
{
|
||||||
const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data());
|
const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data());
|
||||||
renderQueue->AddSprites(instanceData.renderOrder, GetMaterial(), vertices, 1);
|
renderQueue->AddSprites(instanceData.renderOrder, GetMaterial(), vertices, 1, scissorRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace Nz
|
||||||
* \param instanceData Data for the instance
|
* \param instanceData Data for the instance
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void TextSprite::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
void TextSprite::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const
|
||||||
{
|
{
|
||||||
for (auto& pair : m_renderInfos)
|
for (auto& pair : m_renderInfos)
|
||||||
{
|
{
|
||||||
|
|
@ -36,7 +36,7 @@ namespace Nz
|
||||||
if (indices.count > 0)
|
if (indices.count > 0)
|
||||||
{
|
{
|
||||||
const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data());
|
const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data());
|
||||||
renderQueue->AddSprites(instanceData.renderOrder, GetMaterial(), &vertices[indices.first * 4], indices.count, overlay);
|
renderQueue->AddSprites(instanceData.renderOrder, GetMaterial(), &vertices[indices.first * 4], indices.count, scissorRect, overlay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Nz
|
||||||
* \param renderQueue Queue to be added
|
* \param renderQueue Queue to be added
|
||||||
* \param instanceData Data for the instance
|
* \param instanceData Data for the instance
|
||||||
*/
|
*/
|
||||||
void TileMap::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
void TileMap::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const
|
||||||
{
|
{
|
||||||
const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data());
|
const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data());
|
||||||
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace Nz
|
||||||
std::size_t spriteCount = 0;
|
std::size_t spriteCount = 0;
|
||||||
for (const Layer& layer : m_layers)
|
for (const Layer& layer : m_layers)
|
||||||
{
|
{
|
||||||
renderQueue->AddSprites(instanceData.renderOrder, GetMaterial(matCount++), &vertices[spriteCount], layer.tiles.size());
|
renderQueue->AddSprites(instanceData.renderOrder, GetMaterial(matCount++), &vertices[spriteCount], layer.tiles.size(), scissorRect);
|
||||||
|
|
||||||
spriteCount += layer.tiles.size();
|
spriteCount += layer.tiles.size();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue