From 8b41f1d9765b9c7a85bfd5c4e4c26ba6a567ae5b Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Mon, 4 Aug 2025 21:30:24 +0300 Subject: [PATCH 1/4] Pipeline Context refactoring --- engine/includes/commandbuffer.h | 10 -- engine/includes/components/actor.h | 5 - engine/includes/components/effectrender.h | 2 +- engine/includes/components/meshrender.h | 2 +- engine/includes/components/renderable.h | 14 +-- .../includes/components/skinnedmeshrender.h | 2 - engine/includes/components/spriterender.h | 2 +- engine/includes/components/textrender.h | 2 +- engine/includes/components/tilemaprender.h | 2 +- .../editor/viewport/tasks/debugrender.h | 2 +- .../editor/viewport/tasks/gizmorender.h | 4 +- .../editor/viewport/tasks/gridrender.h | 2 +- .../editor/viewport/tasks/outlinerender.h | 32 +++--- engine/includes/pipelinecontext.h | 18 ++-- engine/includes/pipelinetask.h | 16 ++- engine/includes/pipelinetasks/gbuffer.h | 4 + engine/includes/pipelinetasks/shadowmap.h | 10 +- engine/includes/pipelinetasks/translucent.h | 4 + engine/includes/resources/material.h | 11 +++ engine/src/components/actor.cpp | 16 --- engine/src/components/effectrender.cpp | 3 +- engine/src/components/meshrender.cpp | 3 +- engine/src/components/renderable.cpp | 34 +++---- engine/src/components/skinnedmeshrender.cpp | 15 --- engine/src/components/spriterender.cpp | 2 +- engine/src/components/textrender.cpp | 3 +- engine/src/components/tilemaprender.cpp | 3 +- engine/src/components/transform.cpp | 2 +- engine/src/gizmos.cpp | 6 +- engine/src/pipelinecontext.cpp | 86 +++------------- engine/src/pipelinetask.cpp | 61 ++++++++++++ engine/src/pipelinetasks/ambientocclusion.cpp | 4 +- engine/src/pipelinetasks/antialiasing.cpp | 2 +- engine/src/pipelinetasks/bloom.cpp | 4 +- engine/src/pipelinetasks/deferredlighting.cpp | 9 +- engine/src/pipelinetasks/depthoffield.cpp | 2 +- engine/src/pipelinetasks/downsample.cpp | 2 +- engine/src/pipelinetasks/gbuffer.cpp | 11 ++- engine/src/pipelinetasks/indirect.cpp | 4 +- engine/src/pipelinetasks/reflections.cpp | 2 +- engine/src/pipelinetasks/shadowmap.cpp | 98 ++++++++++++------- engine/src/pipelinetasks/tonemap.cpp | 2 +- engine/src/pipelinetasks/translucent.cpp | 39 +++++++- engine/src/resources/material.cpp | 16 ++- engine/tests/tst_actor.h | 4 - .../editor/graph/graphwidgets/linksrender.cpp | 4 +- .../shadertools/converter/shadergraph.cpp | 2 +- .../shadertools/editor/materialedit.cpp | 2 +- .../converter/textureconverter.cpp | 2 +- .../editor/texturetools/editor/spriteedit.cpp | 2 +- modules/network/src/objects/webrequest.cpp | 3 +- .../rendergl/includes/resources/materialgl.h | 9 +- .../rendergl/src/resources/materialgl.cpp | 83 +++++++--------- .../rendervk/src/resources/materialvk.cpp | 9 +- modules/uikit/includes/uisystem.h | 2 - modules/uikit/src/components/frame.cpp | 2 +- modules/uikit/src/components/image.cpp | 2 +- modules/uikit/src/components/label.cpp | 2 +- modules/uikit/src/uisystem.cpp | 9 -- thirdparty/next/inc/math/matrix4.h | 1 + thirdparty/next/src/math/matrix4.cpp | 6 ++ .../screens/contentbrowser/contentbrowser.cpp | 4 +- .../screens/contentbrowser/contenttree.cpp | 6 +- .../scenecomposer/objectcontroller.cpp | 16 ++- 64 files changed, 393 insertions(+), 350 deletions(-) diff --git a/engine/includes/commandbuffer.h b/engine/includes/commandbuffer.h index 30b5292b2..93a90f490 100644 --- a/engine/includes/commandbuffer.h +++ b/engine/includes/commandbuffer.h @@ -38,16 +38,6 @@ struct Global { class ENGINE_EXPORT CommandBuffer: public Object { A_OBJECT(CommandBuffer, Object, System) -public: - enum LayerTypes { - DEFAULT = (1<<0), - RAYCAST = (1<<1), - SHADOWCAST = (1<<2), - LIGHT = (1<<3), - TRANSLUCENT = (1<<4), - UI = (1<<6) - }; - public: CommandBuffer(); diff --git a/engine/includes/components/actor.h b/engine/includes/components/actor.h index 8f3239c6d..22bbc410a 100644 --- a/engine/includes/components/actor.h +++ b/engine/includes/components/actor.h @@ -72,9 +72,6 @@ class ENGINE_EXPORT Actor : public Object { bool isStatic() const; void setStatic(const bool flag); - int layers() const; - void setLayers(const int layers); - void setParent(Object *parent, int32_t position = -1, bool force = false) override; bool isInstance() const; @@ -116,8 +113,6 @@ class ENGINE_EXPORT Actor : public Object { Scene *m_scene; - int32_t m_layers; - int m_flags; bool m_hierarchyEnable; diff --git a/engine/includes/components/effectrender.h b/engine/includes/components/effectrender.h index 6f64de95e..ee214fe6f 100644 --- a/engine/includes/components/effectrender.h +++ b/engine/includes/components/effectrender.h @@ -25,7 +25,7 @@ class ENGINE_EXPORT EffectRender : public Renderable { private: AABBox localBound() const override; - Mesh *meshToDraw() const override; + Mesh *meshToDraw(int instance) const override; void update() override; diff --git a/engine/includes/components/meshrender.h b/engine/includes/components/meshrender.h index d0b07d5b2..f3f8203f7 100644 --- a/engine/includes/components/meshrender.h +++ b/engine/includes/components/meshrender.h @@ -32,7 +32,7 @@ class ENGINE_EXPORT MeshRender : public Renderable { AABBox localBound() const override; - Mesh *meshToDraw() const override; + Mesh *meshToDraw(int instance) const override; void composeComponent() override; diff --git a/engine/includes/components/renderable.h b/engine/includes/components/renderable.h index 14cd6ce08..2b011672c 100644 --- a/engine/includes/components/renderable.h +++ b/engine/includes/components/renderable.h @@ -26,27 +26,29 @@ class ENGINE_EXPORT Renderable : public NativeBehaviour { virtual AABBox bound() const; - virtual int priority() const; - Material *material() const; virtual void setMaterial(Material *material); - MaterialInstance *materialInstance() const; + int32_t materialsCount() const; + MaterialInstance *materialInstance(int index) const; + + virtual int priority() const; protected: - virtual Mesh *meshToDraw() const; + virtual Mesh *meshToDraw(int instance) const; + + virtual uint32_t subMesh(int instance) const; virtual AABBox localBound() const; virtual void setMaterialsList(const std::list &materials); private: - uint32_t instanceHash(int index) const; - void setSystem(ObjectSystem *system) override; protected: friend class PipelineContext; + friend class PipelineTask; std::vector m_materials; diff --git a/engine/includes/components/skinnedmeshrender.h b/engine/includes/components/skinnedmeshrender.h index 01b9342f6..6df785f23 100644 --- a/engine/includes/components/skinnedmeshrender.h +++ b/engine/includes/components/skinnedmeshrender.h @@ -36,8 +36,6 @@ class ENGINE_EXPORT SkinnedMeshRender : public MeshRender { AABBox localBound() const override; - void setMaterial(Material *material) override; - void onReferenceDestroyed() override; private: diff --git a/engine/includes/components/spriterender.h b/engine/includes/components/spriterender.h index a34235646..cb57205bc 100644 --- a/engine/includes/components/spriterender.h +++ b/engine/includes/components/spriterender.h @@ -66,7 +66,7 @@ class ENGINE_EXPORT SpriteRender : public Renderable { static Mesh *composeMesh(Sprite *sprite, int key, Vector2 &size, int mode, bool resetSize, float scale = 1.0f); private: - Mesh *meshToDraw() const override; + Mesh *meshToDraw(int instance) const override; void setMaterialsList(const std::list &materials) override; diff --git a/engine/includes/components/textrender.h b/engine/includes/components/textrender.h index 15de0df79..e66375faf 100644 --- a/engine/includes/components/textrender.h +++ b/engine/includes/components/textrender.h @@ -70,7 +70,7 @@ class ENGINE_EXPORT TextRender : public Renderable { static Vector2 cursorPosition(Font *font, int size, const TString &text, bool kerning, const Vector2 &boundaries); private: - Mesh *meshToDraw() const override; + Mesh *meshToDraw(int instance) const override; AABBox localBound() const override; diff --git a/engine/includes/components/tilemaprender.h b/engine/includes/components/tilemaprender.h index 6fbf45ce4..62c23a47e 100644 --- a/engine/includes/components/tilemaprender.h +++ b/engine/includes/components/tilemaprender.h @@ -34,7 +34,7 @@ class ENGINE_EXPORT TileMapRender : public Renderable { private: AABBox localBound() const override; - Mesh *meshToDraw() const override; + Mesh *meshToDraw(int instance) const override; void setMaterialsList(const std::list &materials) override; diff --git a/engine/includes/editor/viewport/tasks/debugrender.h b/engine/includes/editor/viewport/tasks/debugrender.h index 04ff567da..44532998e 100644 --- a/engine/includes/editor/viewport/tasks/debugrender.h +++ b/engine/includes/editor/viewport/tasks/debugrender.h @@ -59,7 +59,7 @@ class DebugRender : public PipelineTask { } it.second->setTransform(m); - buffer->drawMesh(m_mesh, 0, CommandBuffer::UI, *it.second); + buffer->drawMesh(m_mesh, 0, Material::Default, *it.second); i++; } diff --git a/engine/includes/editor/viewport/tasks/gizmorender.h b/engine/includes/editor/viewport/tasks/gizmorender.h index 0ae26e080..313fa0d17 100644 --- a/engine/includes/editor/viewport/tasks/gizmorender.h +++ b/engine/includes/editor/viewport/tasks/gizmorender.h @@ -126,10 +126,10 @@ class GizmoRender : public PipelineTask { buffer->setViewport(m_width-gNaviCubeSize, m_height-gNaviCubeSize, gNaviCubeSize, gNaviCubeSize); buffer->setViewProjection(m_camera->viewMatrix(), m_camera->projectionMatrix()); - buffer->drawMesh(PipelineContext::defaultCube(), 0, CommandBuffer::UI, *m_cubeMaterial); + buffer->drawMesh(PipelineContext::defaultCube(), 0, Material::Default, *m_cubeMaterial); if(m_side != -1) { - buffer->drawMesh(m_solidCube, m_side, CommandBuffer::UI, *m_solidMaterial); + buffer->drawMesh(m_solidCube, m_side, Material::Default, *m_solidMaterial); } buffer->setViewport(0, 0, m_width, m_height); diff --git a/engine/includes/editor/viewport/tasks/gridrender.h b/engine/includes/editor/viewport/tasks/gridrender.h index e234b21e2..81f136cf1 100644 --- a/engine/includes/editor/viewport/tasks/gridrender.h +++ b/engine/includes/editor/viewport/tasks/gridrender.h @@ -173,7 +173,7 @@ class GridRender : public PipelineTask { buffer->beginDebugMarker("GridRender"); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(m_plane, 0, CommandBuffer::TRANSLUCENT, *m_grid); + buffer->drawMesh(m_plane, 0, Material::Translucent, *m_grid); buffer->endDebugMarker(); } diff --git a/engine/includes/editor/viewport/tasks/outlinerender.h b/engine/includes/editor/viewport/tasks/outlinerender.h index bd3ee0dbe..ec04bd0b6 100644 --- a/engine/includes/editor/viewport/tasks/outlinerender.h +++ b/engine/includes/editor/viewport/tasks/outlinerender.h @@ -88,19 +88,13 @@ class Outline : public PipelineTask { buffer->beginDebugMarker("Outline"); buffer->setRenderTarget(m_outlineTarget); - RenderList filter; - for(auto actor : m_controller->selected()) { - for(auto it : m_context->culledComponents()) { - Renderable *component = dynamic_cast(it); - if(component && component->actor()->isInHierarchy(static_cast(actor))) { - filter.push_back(component); - } - } + + for(auto &it : m_outline) { + buffer->drawMesh(it.mesh, it.subMesh, Material::Visibility, *it.instance); } - m_context->drawRenderers(filter, CommandBuffer::RAYCAST); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_combineMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_combineMaterial); buffer->endDebugMarker(); } @@ -113,10 +107,24 @@ class Outline : public PipelineTask { PipelineTask::resize(width, height); } + void analyze(World *world) override { + RenderList outline; + + for(auto actor : m_controller->selected()) { + for(auto it : m_context->culledRenderables()) { + if(it->actor()->isInHierarchy(static_cast(actor))) { + outline.push_back(it); + } + } + } + + filterAndGroup(outline, m_outline, Material::Visibility); + } + protected: Vector4 m_color; - float m_width; + std::list m_outline; Texture *m_outlineMap; Texture *m_outlineDepth; @@ -128,6 +136,8 @@ class Outline : public PipelineTask { CameraController *m_controller; + float m_width; + }; #endif // OUTLINERENDER_H diff --git a/engine/includes/pipelinecontext.h b/engine/includes/pipelinecontext.h index 6fc143d23..508c7cb25 100644 --- a/engine/includes/pipelinecontext.h +++ b/engine/includes/pipelinecontext.h @@ -27,6 +27,7 @@ class InstancingBatch; class Frustum; typedef std::list RenderList; +typedef std::list LightList; class ENGINE_EXPORT PipelineContext : public Object { A_OBJECT(PipelineContext, Object, System) @@ -44,8 +45,6 @@ class ENGINE_EXPORT PipelineContext : public Object { void cameraReset(); - void drawRenderers(const RenderList &list, uint32_t layer, uint32_t flags = 0); - World *world(); void setWorld(World *world); @@ -59,9 +58,10 @@ class ENGINE_EXPORT PipelineContext : public Object { StringList renderTextures() const; - RenderList &sceneComponents(); - RenderList &culledComponents(); - std::list &sceneLights(); + RenderList &sceneRenderables(); + RenderList &culledRenderables(); + + LightList &sceneLights(); std::list > &culledPostEffectSettings(); @@ -103,10 +103,10 @@ class ENGINE_EXPORT PipelineContext : public Object { AABBox m_worldBound; - RenderList m_sceneComponents; - RenderList m_culledComponents; + RenderList m_sceneRenderables; + RenderList m_culledRenderables; - std::list m_sceneLights; + LightList m_sceneLights; std::list> m_culledPostProcessSettings; @@ -131,8 +131,6 @@ class ENGINE_EXPORT PipelineContext : public Object { bool m_frustumCulling; - bool m_renderablesSorting; - }; #endif // PIPELINECONTEXT diff --git a/engine/includes/pipelinetask.h b/engine/includes/pipelinetask.h index 8c0c5f76b..dc56e3666 100644 --- a/engine/includes/pipelinetask.h +++ b/engine/includes/pipelinetask.h @@ -3,11 +3,10 @@ #include +#include #include class Texture; -class PipelineContext; -class PostProcessSettings; class ENGINE_EXPORT PipelineTask : public Object { A_OBJECT(PipelineTask, Object, System) @@ -34,6 +33,19 @@ class ENGINE_EXPORT PipelineTask : public Object { void setEnabled(bool enable); bool isEnabled() const; +protected: + struct Group { + MaterialInstance *instance = nullptr; + + Mesh *mesh = nullptr; + + uint32_t subMesh = 0; + }; + + void filterByLayer(const RenderList &in, RenderList &out, int layer) const; + + void filterAndGroup(const RenderList &in, std::list &out, int layer); + protected: std::vector m_inputs; std::vector> m_outputs; diff --git a/engine/includes/pipelinetasks/gbuffer.h b/engine/includes/pipelinetasks/gbuffer.h index e2e85d74f..eb9974009 100644 --- a/engine/includes/pipelinetasks/gbuffer.h +++ b/engine/includes/pipelinetasks/gbuffer.h @@ -14,7 +14,11 @@ class GBuffer : public PipelineTask { private: void exec() override; + void analyze(World *world) override; + private: + std::list m_opaque; + RenderTarget *m_gbuffer; }; diff --git a/engine/includes/pipelinetasks/shadowmap.h b/engine/includes/pipelinetasks/shadowmap.h index ca8779e22..99af56a4f 100644 --- a/engine/includes/pipelinetasks/shadowmap.h +++ b/engine/includes/pipelinetasks/shadowmap.h @@ -1,6 +1,7 @@ #ifndef SHADOWMAP_H #define SHADOWMAP_H +#include "pipelinecontext.h" #include "pipelinetask.h" class CommandBuffer; @@ -14,7 +15,6 @@ class AreaLight; class DirectLight; class SpotLight; class PointLight; -class Renderable; class ShadowMap : public PipelineTask { A_OBJECT(ShadowMap, PipelineTask, Pipeline) @@ -25,10 +25,10 @@ class ShadowMap : public PipelineTask { private: void exec() override; - void areaLightUpdate(AreaLight *light, std::list &components); - void directLightUpdate(DirectLight *light, std::list &components); - void pointLightUpdate(PointLight *light, std::list &components); - void spotLightUpdate(SpotLight *light, std::list &components); + void areaLightUpdate(AreaLight *light, const RenderList &components); + void directLightUpdate(DirectLight *light, const RenderList &components); + void pointLightUpdate(PointLight *light, const RenderList &components); + void spotLightUpdate(SpotLight *light, const RenderList &components); void cleanShadowCache(); diff --git a/engine/includes/pipelinetasks/translucent.h b/engine/includes/pipelinetasks/translucent.h index 76ee241d0..1750d6181 100644 --- a/engine/includes/pipelinetasks/translucent.h +++ b/engine/includes/pipelinetasks/translucent.h @@ -14,9 +14,13 @@ class Translucent : public PipelineTask { private: void exec() override; + void analyze(World *world) override; + void setInput(int index, Texture *texture) override; private: + std::list m_translucent; + RenderTarget *m_translucentPass; }; diff --git a/engine/includes/resources/material.h b/engine/includes/resources/material.h index d24554672..1d95ebcee 100644 --- a/engine/includes/resources/material.h +++ b/engine/includes/resources/material.h @@ -31,6 +31,13 @@ class ENGINE_EXPORT Material : public Resource { ) public: + enum Layer { + Default = (1<<0), + Translucent = (1<<1), + Visibility = (1<<2), + Shadowcast = (1<<3) + }; + enum Type { Surface, PostProcess, @@ -196,6 +203,8 @@ class ENGINE_EXPORT Material : public Resource { bool wireframe() const; void setWireframe(bool wireframe); + int layers() const; + virtual MaterialInstance *createInstance(SurfaceType type = SurfaceType::Static); void loadUserData(const VariantMap &data) override; @@ -242,6 +251,8 @@ class ENGINE_EXPORT Material : public Resource { int32_t m_materialType; + int32_t m_layers; + bool m_doubleSided; bool m_wireframe; diff --git a/engine/src/components/actor.cpp b/engine/src/components/actor.cpp index 76a0fef8f..651632fb5 100644 --- a/engine/src/components/actor.cpp +++ b/engine/src/components/actor.cpp @@ -67,7 +67,6 @@ Actor::Actor() : m_transform(nullptr), m_prefab(nullptr), m_scene(nullptr), - m_layers(CommandBuffer::DEFAULT | CommandBuffer::RAYCAST | CommandBuffer::SHADOWCAST | CommandBuffer::TRANSLUCENT), m_flags(Actor::Enable | Actor::Selectable), m_hierarchyEnable(m_flags & Actor::Enable), m_muteUpdates(false) { @@ -185,21 +184,6 @@ void Actor::setStatic(const bool flag) { m_flags &= ~Static; } } -/*! - Returns the layers list for the this Actor as a bit mask. - The layers used for the various purposes like filtering objects before rendering. -*/ -int Actor::layers() const { - PROFILE_FUNCTION(); - return m_layers; -} -/*! - Assigns the list of \a layers for this Actor as a bitmask. -*/ -void Actor::setLayers(const int layers) { - PROFILE_FUNCTION(); - m_layers = layers; -} /*! Returns the Transform component attached to this Actor. */ diff --git a/engine/src/components/effectrender.cpp b/engine/src/components/effectrender.cpp index 04a7283b9..56b6c3406 100644 --- a/engine/src/components/effectrender.cpp +++ b/engine/src/components/effectrender.cpp @@ -89,7 +89,8 @@ void EffectRender::deltaUpdate(float dt) { /*! \internal */ -Mesh *EffectRender::meshToDraw() const { +Mesh *EffectRender::meshToDraw(int instance) const { + A_UNUSED(instance); return m_effect ? m_effect->mesh() : nullptr; } /*! diff --git a/engine/src/components/meshrender.cpp b/engine/src/components/meshrender.cpp index b3ebb740c..7f8844ad7 100644 --- a/engine/src/components/meshrender.cpp +++ b/engine/src/components/meshrender.cpp @@ -27,7 +27,8 @@ MeshRender::~MeshRender() { /*! \internal */ -Mesh *MeshRender::meshToDraw() const { +Mesh *MeshRender::meshToDraw(int instance) const { + A_UNUSED(instance); return m_mesh; } /*! diff --git a/engine/src/components/renderable.cpp b/engine/src/components/renderable.cpp index 30c8f16cd..fa388d758 100644 --- a/engine/src/components/renderable.cpp +++ b/engine/src/components/renderable.cpp @@ -45,11 +45,17 @@ AABBox Renderable::bound() const { return m_worldBox; } /*! - Returns a mesh wich will be drawn. + Returns a mesh which will be drawn for the particular material \a instance. */ -Mesh *Renderable::meshToDraw() const { +Mesh *Renderable::meshToDraw(int instance) const { return nullptr; } +/*! + Returns a sub mesh index which will be drawn for the particular material \a instance. +*/ +uint32_t Renderable::subMesh(int instance) const { + return instance; +} /*! Returns the prority value used to sort renadarble components before drawing. Lower values are rendered first and higher are rendered last. @@ -57,19 +63,6 @@ Mesh *Renderable::meshToDraw() const { int Renderable::priority() const { return 0; } -/*! - Returns instance hash. - Renerables with the same hash will be grouped together to be drawn as a single GPU draw call. -*/ -uint32_t Renderable::instanceHash(int index) const { - uint32_t result = m_materials[index]->hash(); - Mesh *mesh = meshToDraw(); - if(mesh) { - Mathf::hashCombine(result, mesh->uuid()); - } - - return result; -} /*! Returns a first instantiated Material assigned to this Renderable. */ @@ -97,12 +90,15 @@ void Renderable::setMaterial(Material *material) { } } } +int32_t Renderable::materialsCount() const { + return m_materials.size(); +} /*! - Returns a first Material instance assigned to this Renderable. + Returns a Material instance with \a index assigned to this Renderable. */ -MaterialInstance *Renderable::materialInstance() const { - if(!m_materials.empty()) { - return m_materials.front(); +MaterialInstance *Renderable::materialInstance(int index) const { + if(m_materials.size() > index) { + return m_materials[index]; } return nullptr; } diff --git a/engine/src/components/skinnedmeshrender.cpp b/engine/src/components/skinnedmeshrender.cpp index 70a284ca3..6b876cb9b 100644 --- a/engine/src/components/skinnedmeshrender.cpp +++ b/engine/src/components/skinnedmeshrender.cpp @@ -54,21 +54,6 @@ Vector3 SkinnedMeshRender::boundsExtent() const { void SkinnedMeshRender::setBoundsExtent(Vector3 extent) { m_bounds.extent = extent; } -/*! - Creates a new instance of \a material and assigns it. -*/ -void SkinnedMeshRender::setMaterial(Material *material) { - Renderable::setMaterial(material); - - for(auto it : m_materials) { - if(it) { - if(m_armature) { - it->setTexture(gMatrices, m_armature->texture()); - } - it->setTransform(transform()); - } - } -} /*! Returns a Armature component for the attached skeleton. */ diff --git a/engine/src/components/spriterender.cpp b/engine/src/components/spriterender.cpp index 7c91140d7..dce9be018 100644 --- a/engine/src/components/spriterender.cpp +++ b/engine/src/components/spriterender.cpp @@ -57,7 +57,7 @@ SpriteRender::~SpriteRender() { /*! \internal */ -Mesh *SpriteRender::meshToDraw() const { +Mesh *SpriteRender::meshToDraw(int instance) const { return (m_customMesh) ? m_customMesh : m_mesh; } /*! diff --git a/engine/src/components/textrender.cpp b/engine/src/components/textrender.cpp index 1038d2929..864804c53 100644 --- a/engine/src/components/textrender.cpp +++ b/engine/src/components/textrender.cpp @@ -54,7 +54,8 @@ TextRender::~TextRender() { /*! \internal */ -Mesh *TextRender::meshToDraw() const { +Mesh *TextRender::meshToDraw(int instance) const { + A_UNUSED(instance); return m_text.isEmpty() ? nullptr : m_mesh; } /*! diff --git a/engine/src/components/tilemaprender.cpp b/engine/src/components/tilemaprender.cpp index d9d17eb6c..b68112c43 100644 --- a/engine/src/components/tilemaprender.cpp +++ b/engine/src/components/tilemaprender.cpp @@ -37,7 +37,8 @@ TileMapRender::~TileMapRender() { } } -Mesh *TileMapRender::meshToDraw() const { +Mesh *TileMapRender::meshToDraw(int instance) const { + A_UNUSED(instance); return m_tileMap ? m_tileMap->tileMesh() : nullptr; } /*! diff --git a/engine/src/components/transform.cpp b/engine/src/components/transform.cpp index 960482bc7..2bc9a8f6c 100644 --- a/engine/src/components/transform.cpp +++ b/engine/src/components/transform.cpp @@ -207,7 +207,7 @@ const Matrix4 &Transform::worldTransform() const { */ Vector3 Transform::worldPosition() const { cleanDirty(); - return Vector3(m_worldTransform[12], m_worldTransform[13], m_worldTransform[14]); + return m_worldTransform.position(); } /*! Returns current rotation of the transform in world space as Euler angles in degrees. diff --git a/engine/src/gizmos.cpp b/engine/src/gizmos.cpp index e49acd0c5..99ca95a4c 100644 --- a/engine/src/gizmos.cpp +++ b/engine/src/gizmos.cpp @@ -81,7 +81,7 @@ void Gizmos::clear() { void Gizmos::drawSpriteBatch(CommandBuffer *buffer) { for(auto &it : s_sprites) { if(!it.second.mesh->isEmpty()) { - buffer->drawMesh(it.second.mesh, 0, CommandBuffer::TRANSLUCENT, *it.second.material); + buffer->drawMesh(it.second.mesh, 0, Material::Translucent, *it.second.material); } } } @@ -91,7 +91,7 @@ void Gizmos::drawSpriteBatch(CommandBuffer *buffer) { */ void Gizmos::drawSolidBatch(CommandBuffer *buffer) { if(!s_solid->isEmpty()) { - buffer->drawMesh(s_solid, 0, CommandBuffer::TRANSLUCENT, *s_solidMaterial); + buffer->drawMesh(s_solid, 0, Material::Translucent, *s_solidMaterial); } } /*! @@ -100,7 +100,7 @@ void Gizmos::drawSolidBatch(CommandBuffer *buffer) { */ void Gizmos::drawWireBatch(CommandBuffer *buffer) { if(!s_wire->isEmpty()) { - buffer->drawMesh(s_wire, 0, CommandBuffer::TRANSLUCENT, *s_wireMaterial); + buffer->drawMesh(s_wire, 0, Material::Translucent, *s_wireMaterial); } } /*! diff --git a/engine/src/pipelinecontext.cpp b/engine/src/pipelinecontext.cpp index dcd04394a..1c3ffe238 100644 --- a/engine/src/pipelinecontext.cpp +++ b/engine/src/pipelinecontext.cpp @@ -49,8 +49,7 @@ PipelineContext::PipelineContext() : m_camera(nullptr), m_width(64), m_height(64), - m_frustumCulling(true), - m_renderablesSorting(true) { + m_frustumCulling(true) { Material *mtl = Engine::loadResource(".embedded/DefaultPostEffect.shader"); if(mtl) { @@ -97,7 +96,7 @@ void PipelineContext::draw(Camera *camera) { // Finish m_buffer->setRenderTarget(m_defaultTarget); - m_buffer->drawMesh(defaultPlane(), 0, CommandBuffer::UI, *m_finalMaterial); + m_buffer->drawMesh(defaultPlane(), 0, Material::Default, *m_finalMaterial); for(auto it : m_postObservers) { (*it.first)(it.second); @@ -196,39 +195,23 @@ void PipelineContext::unsubscribePost(void *object) { */ void PipelineContext::analizeGraph() { Camera *camera = Camera::current(); - Transform *cameraTransform = camera->transform(); + Vector3 cameraWorldPosition(camera->transform()->worldPosition()); bool update = m_world->isToBeUpdated(); // Add renderables - m_sceneComponents.clear(); + m_sceneRenderables.clear(); for(auto it : RenderSystem::renderables()) { if(it->world() == m_world && it->isEnabledInHierarchy()) { if(update) { it->update(); } - m_sceneComponents.push_back(it); + m_sceneRenderables.push_back(it); } } // Renderables frustum culling if(m_frustumCulling) { - frustumCulling(camera->frustum(), m_sceneComponents, m_culledComponents, &m_worldBound); - } - - // Renderables sort - if(m_renderablesSorting) { - Vector3 origin(cameraTransform->worldPosition()); - culledComponents().sort([origin](const Renderable *left, const Renderable *right) { - int p1 = left->priority(); - int p2 = right->priority(); - if(p1 == p2) { - const Matrix4 &m1 = left->transform()->worldTransform(); - const Matrix4 &m2 = right->transform()->worldTransform(); - - return origin.dot(Vector3(m1[12], m1[13], m1[14])) < origin.dot(Vector3(m2[12], m2[13], m2[14])); - } - return p1 < p2; - }); + frustumCulling(camera->frustum(), m_sceneRenderables, m_culledRenderables, &m_worldBound); } // Add lights @@ -243,7 +226,7 @@ void PipelineContext::analizeGraph() { m_culledPostProcessSettings.clear(); for(auto it : RenderSystem::postProcessVolumes()) { if(it->world() == m_world && it->isEnabledInHierarchy()) { - if(!it->unbound() && !it->bound().intersect(cameraTransform->worldPosition(), camera->nearPlane())) { + if(!it->unbound() && !it->bound().intersect(cameraWorldPosition, camera->nearPlane())) { continue; } m_culledPostProcessSettings.push_back(std::make_pair(it->settings(), it->blendWeight())); @@ -387,67 +370,22 @@ StringList PipelineContext::renderTextures() const { return result; } -/*! - Draws the specified \a list of Renderable compoenents on the given \a layer and \a flags. -*/ -void PipelineContext::drawRenderers(const RenderList &list, uint32_t layer, uint32_t flags) { - uint32_t lastHash = 0; - uint32_t lastSub = 0; - Mesh *lastMesh = nullptr; - MaterialInstance *lastInstance = nullptr; - - for(auto it : list) { - if(it) { - Actor *actor = it->actor(); - - if((flags == 0 || actor->flags() & flags) && actor->layers() & layer) { - for(int32_t i = 0; i < it->m_materials.size(); i++) { - MaterialInstance *instance = it->m_materials[i]; - if(instance->transform() == nullptr) { - instance->setTransform(it->transform()); - } - - uint32_t hash = it->instanceHash(i); - if(lastHash != hash || (lastInstance != nullptr && lastInstance->material() != instance->material())) { - if(lastInstance != nullptr) { - m_buffer->drawMesh(lastMesh, lastSub, layer, *lastInstance); - lastInstance->resetBatches(); - } - - lastHash = hash; - lastMesh = it->meshToDraw(); - lastInstance = instance; - lastSub = i; - } else if(lastInstance != nullptr) { - lastInstance->batch(*instance); - } - } - } - } - } - - // do the last call - if(lastInstance != nullptr) { - m_buffer->drawMesh(lastMesh, lastSub, layer, *lastInstance); - lastInstance->resetBatches(); - } -} /*! Returns the list of scene components relevant for rendering. */ -RenderList &PipelineContext::sceneComponents() { - return m_sceneComponents; +RenderList &PipelineContext::sceneRenderables() { + return m_sceneRenderables; } /*! Returns the list of culled scene components based on frustum culling. */ -RenderList &PipelineContext::culledComponents() { - return m_frustumCulling ? m_culledComponents : m_sceneComponents; +RenderList &PipelineContext::culledRenderables() { + return m_frustumCulling ? m_culledRenderables : m_sceneRenderables; } /*! Returns the list of scene lights relevant for rendering. */ -std::list &PipelineContext::sceneLights() { +LightList &PipelineContext::sceneLights() { return m_sceneLights; } /*! diff --git a/engine/src/pipelinetask.cpp b/engine/src/pipelinetask.cpp index 0fc5773ad..7f8a9729a 100644 --- a/engine/src/pipelinetask.cpp +++ b/engine/src/pipelinetask.cpp @@ -3,6 +3,10 @@ #include "pipelinecontext.h" #include "commandbuffer.h" +#include "components/renderable.h" + +#include "resources/mesh.h" + /*! \class PipelineTask \brief A base class for all render tasks. @@ -117,3 +121,60 @@ void PipelineTask::setEnabled(bool enable) { bool PipelineTask::isEnabled() const { return m_enabled; } +/*! + Filters \a out an \a in renderable components by it's material \a layer. +*/ +void PipelineTask::filterByLayer(const RenderList &in, RenderList &out, int layer) const { + for(auto it : in) { + for(int i = 0; i < it->materialsCount(); i++) { + MaterialInstance *instance = it->materialInstance(i); + if(instance && instance->material()->layers() & layer) { + if(instance->transform() == nullptr) { + instance->setTransform(it->transform()); + } + + out.push_back(it); + } + } + } +} + +void PipelineTask::filterAndGroup(const RenderList &in, std::list &out, int layer) { + uint32_t lastHash = 0; + Group last; + + for(auto it : in) { + for(int i = 0; i < it->materialsCount(); i++) { + MaterialInstance *instance = it->materialInstance(i); + if(instance && (layer == 0 || instance->material()->layers() & layer)) { + if(instance->transform() == nullptr) { + instance->setTransform(it->transform()); + } + + Mesh *mesh = it->meshToDraw(i); + if(mesh) { + uint32_t hash = instance->hash(); + Mathf::hashCombine(hash, mesh->uuid()); + + if(lastHash != hash || (last.instance != nullptr && last.instance->material() != instance->material())) { + if(last.instance != nullptr) { + out.push_back(last); + } + + lastHash = hash; + last.mesh = mesh; + last.instance = instance; + last.subMesh = it->subMesh(i); + } else if(last.instance != nullptr) { + last.instance->batch(*instance); + } + } + } + } + } + + // do the last insert + if(last.instance != nullptr) { + out.push_back(last); + } +} diff --git a/engine/src/pipelinetasks/ambientocclusion.cpp b/engine/src/pipelinetasks/ambientocclusion.cpp index c07e506f1..785d68897 100644 --- a/engine/src/pipelinetasks/ambientocclusion.cpp +++ b/engine/src/pipelinetasks/ambientocclusion.cpp @@ -165,14 +165,14 @@ void AmbientOcclusion::exec() { buffer->setViewport(0, 0, m_aoTexture->width(), m_aoTexture->height()); buffer->setRenderTarget(m_aoTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_occlusion); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_occlusion); } if(m_blur) { buffer->setViewport(0, 0, m_blurTexture->width(), m_blurTexture->height()); buffer->setRenderTarget(m_blurTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_blur); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_blur); } buffer->endDebugMarker(); diff --git a/engine/src/pipelinetasks/antialiasing.cpp b/engine/src/pipelinetasks/antialiasing.cpp index ee776f9a5..dd344c82b 100644 --- a/engine/src/pipelinetasks/antialiasing.cpp +++ b/engine/src/pipelinetasks/antialiasing.cpp @@ -46,7 +46,7 @@ void AntiAliasing::exec() { buffer->beginDebugMarker("AntiAliasing"); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_resultMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_resultMaterial); buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/bloom.cpp b/engine/src/pipelinetasks/bloom.cpp index d3085adb5..1ce9e6f59 100644 --- a/engine/src/pipelinetasks/bloom.cpp +++ b/engine/src/pipelinetasks/bloom.cpp @@ -118,10 +118,10 @@ void Bloom::exec() { for(uint8_t i = 0; i < BLOOM_PASSES; i++) { buffer->setRenderTarget(m_blurTempTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_bloomPasses[i].blurMaterialH); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_bloomPasses[i].blurMaterialH); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_bloomPasses[i].blurMaterialV); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_bloomPasses[i].blurMaterialV); } buffer->endDebugMarker(); diff --git a/engine/src/pipelinetasks/deferredlighting.cpp b/engine/src/pipelinetasks/deferredlighting.cpp index a7e4ac4e3..ece23089b 100644 --- a/engine/src/pipelinetasks/deferredlighting.cpp +++ b/engine/src/pipelinetasks/deferredlighting.cpp @@ -51,7 +51,7 @@ void DeferredLighting::exec() { if(instance) { Matrix4 m(light->transform()->worldTransform()); - Vector3 position(m[12], m[13], m[14]); + Vector3 position(m.position()); float d = static_cast(light)->radius() * 2.0f; @@ -73,7 +73,7 @@ void DeferredLighting::exec() { float d = static_cast(light)->attenuationRadius() * 2.0f; - Vector3 position(m[12], m[13], m[14]); + Vector3 position(m.position()); Vector3 direction(m.rotation() * Vector3(0.0f, 1.0f, 0.0f)); instance->setTransform(Matrix4(position, Quaternion(), Vector3(d))); @@ -86,10 +86,9 @@ void DeferredLighting::exec() { if(instance) { Transform *t = light->transform(); - Matrix4 m(t->worldTransform()); Quaternion q(t->worldQuaternion()); - Vector3 position(m[12], m[13], m[14]); + Vector3 position(t->worldPosition()); Vector3 direction(q * Vector3(0.0f, 0.0f, 1.0f)); float distance = static_cast(light)->attenuationDistance(); @@ -118,7 +117,7 @@ void DeferredLighting::exec() { default: break; } - buffer->drawMesh(mesh, 0, CommandBuffer::LIGHT, *light->material()); + buffer->drawMesh(mesh, 0, Material::Translucent, *light->material()); } buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/depthoffield.cpp b/engine/src/pipelinetasks/depthoffield.cpp index da98f249a..bd3179a7e 100644 --- a/engine/src/pipelinetasks/depthoffield.cpp +++ b/engine/src/pipelinetasks/depthoffield.cpp @@ -140,7 +140,7 @@ void DepthOfField::exec() { buffer->beginDebugMarker("DepthOfField"); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_dofMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_dofMaterial); buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/downsample.cpp b/engine/src/pipelinetasks/downsample.cpp index 66ce63973..0121f2bbf 100644 --- a/engine/src/pipelinetasks/downsample.cpp +++ b/engine/src/pipelinetasks/downsample.cpp @@ -68,7 +68,7 @@ void Downsample::exec() { buffer->setRenderTarget(m_downPasses[i].downTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_downPasses[i].downMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_downPasses[i].downMaterial); } buffer->setViewport(0, 0, m_width, m_height); diff --git a/engine/src/pipelinetasks/gbuffer.cpp b/engine/src/pipelinetasks/gbuffer.cpp index 412fd751a..372970a20 100644 --- a/engine/src/pipelinetasks/gbuffer.cpp +++ b/engine/src/pipelinetasks/gbuffer.cpp @@ -65,7 +65,16 @@ void GBuffer::exec() { buffer->setRenderTarget(m_gbuffer); - m_context->drawRenderers(m_context->culledComponents(), CommandBuffer::DEFAULT); + for(auto &it : m_opaque) { + buffer->drawMesh(it.mesh, it.subMesh, Material::Default, *it.instance); + it.instance->resetBatches(); + } buffer->endDebugMarker(); } + +void GBuffer::analyze(World *world) { + m_opaque.clear(); + + filterAndGroup(m_context->culledRenderables(), m_opaque, Material::Default); +} diff --git a/engine/src/pipelinetasks/indirect.cpp b/engine/src/pipelinetasks/indirect.cpp index fadf0ef10..213bb1be7 100644 --- a/engine/src/pipelinetasks/indirect.cpp +++ b/engine/src/pipelinetasks/indirect.cpp @@ -74,8 +74,6 @@ void DeferredIndirect::analyze(World *world) { m_cameraTexture->setDirty(); } } - - } void DeferredIndirect::exec() { @@ -94,7 +92,7 @@ void DeferredIndirect::exec() { buffer->beginDebugMarker("ReflectionIndirect"); if(m_iblMaterial) { buffer->setRenderTarget(m_iblTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_iblMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_iblMaterial); } buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/reflections.cpp b/engine/src/pipelinetasks/reflections.cpp index b54acd2a9..96cd203ec 100644 --- a/engine/src/pipelinetasks/reflections.cpp +++ b/engine/src/pipelinetasks/reflections.cpp @@ -46,7 +46,7 @@ void Reflections::exec() { buffer->beginDebugMarker("ScreenReflections"); buffer->setRenderTarget(m_sslrTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_sslrMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_sslrMaterial); buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/shadowmap.cpp b/engine/src/pipelinetasks/shadowmap.cpp index fd4cdc8e9..ae1fae365 100644 --- a/engine/src/pipelinetasks/shadowmap.cpp +++ b/engine/src/pipelinetasks/shadowmap.cpp @@ -3,8 +3,6 @@ #include "engine.h" #include "commandbuffer.h" -#include "pipelinecontext.h" -#include "material.h" #include "components/actor.h" #include "components/transform.h" @@ -17,6 +15,7 @@ #include "utils/atlas.h" #include "resources/rendertarget.h" +#include "resources/material.h" #include @@ -68,7 +67,7 @@ void ShadowMap::exec() { buffer->beginDebugMarker("ShadowMap"); cleanShadowCache(); - std::list &components = m_context->sceneComponents(); + RenderList &components = m_context->sceneRenderables(); for(auto &it : m_context->sceneLights()) { BaseLight *base = static_cast(it); @@ -93,8 +92,7 @@ void ShadowMap::exec() { buffer->endDebugMarker(); } -void ShadowMap::areaLightUpdate(AreaLight *light, std::list &components) { - CommandBuffer *buffer = m_context->buffer(); +void ShadowMap::areaLightUpdate(AreaLight *light, const RenderList &components) { Transform *t = light->transform(); int32_t x[SIDES], y[SIDES], w[SIDES], h[SIDES]; @@ -104,8 +102,7 @@ void ShadowMap::areaLightUpdate(AreaLight *light, std::list &compo float zFar = light->radius(); Matrix4 crop(Matrix4::perspective(90.0f, 1.0f, zNear, zFar)); - Matrix4 wt(t->worldTransform()); - Vector3 position(wt[12], wt[13], wt[14]); + Vector3 position(t->worldTransform().position()); Matrix4 wp; wp.translate(position); @@ -115,6 +112,7 @@ void ShadowMap::areaLightUpdate(AreaLight *light, std::list &compo uint32_t pageSize = Texture::maxTextureSize(); + CommandBuffer *buffer = m_context->buffer(); buffer->setRenderTarget(shadowTarget); for(int32_t i = 0; i < m_directions.size(); i++) { @@ -126,14 +124,23 @@ void ShadowMap::areaLightUpdate(AreaLight *light, std::list &compo static_cast(w[i]) / pageSize, static_cast(h[i]) / pageSize); - buffer->setViewProjection(mat, crop); - buffer->setViewport(x[i], y[i], w[i], h[i]); - auto frustum = Camera::frustum(false, 90.0f, 1.0f, position, m_directions[i], zNear, zFar); // Draw in the depth buffer from position of the light source RenderList culled; m_context->frustumCulling(frustum, components, culled); - m_context->drawRenderers(culled, CommandBuffer::SHADOWCAST); + + std::list groups; + filterAndGroup(culled, groups, Material::Shadowcast); + + if(!groups.empty()) { + buffer->setViewProjection(mat, crop); + buffer->setViewport(x[i], y[i], w[i], h[i]); + + for(auto &it : groups) { + buffer->drawMesh(it.mesh, it.subMesh, Material::Shadowcast, *it.instance); + it.instance->resetBatches(); + } + } } auto instance = light->material(); @@ -147,10 +154,10 @@ void ShadowMap::areaLightUpdate(AreaLight *light, std::list &compo } } -void ShadowMap::directLightUpdate(DirectLight *light, std::list &components) { +void ShadowMap::directLightUpdate(DirectLight *light, const RenderList &components) { const Camera *camera = m_context->currentCamera(); - CommandBuffer *buffer = m_context->buffer(); + float nearPlane = camera->nearPlane(); @@ -190,6 +197,7 @@ void ShadowMap::directLightUpdate(DirectLight *light, std::list &c Vector4 tiles[MAX_LODS]; Matrix4 matrix[MAX_LODS]; + CommandBuffer *buffer = m_context->buffer(); buffer->setRenderTarget(shadowTarget); for(int32_t lod = 0; lod < MAX_LODS; lod++) { @@ -223,11 +231,18 @@ void ShadowMap::directLightUpdate(DirectLight *light, std::list &c static_cast(w[lod]) / pageSize, static_cast(h[lod]) / pageSize); - buffer->setViewProjection(view, crop); - buffer->setViewport(x[lod], y[lod], w[lod], h[lod]); + std::list groups; + filterAndGroup(culled, groups, Material::Shadowcast); + if(!groups.empty()) { + buffer->setViewProjection(view, crop); + buffer->setViewport(x[lod], y[lod], w[lod], h[lod]); - // Draw in the depth buffer from position of the light source - m_context->drawRenderers(culled, CommandBuffer::SHADOWCAST); + // Draw in the depth buffer from position of the light source + for(auto &it : groups) { + buffer->drawMesh(it.mesh, it.subMesh, Material::Shadowcast, *it.instance); + it.instance->resetBatches(); + } + } } auto instance = light->material(); @@ -247,7 +262,7 @@ void ShadowMap::directLightUpdate(DirectLight *light, std::list &c } } -void ShadowMap::pointLightUpdate(PointLight *light, std::list &components) { +void ShadowMap::pointLightUpdate(PointLight *light, const RenderList &components) { CommandBuffer *buffer = m_context->buffer(); Transform *t = light->transform(); @@ -258,8 +273,7 @@ void ShadowMap::pointLightUpdate(PointLight *light, std::list &com float zFar = light->attenuationRadius(); Matrix4 crop(Matrix4::perspective(90.0f, 1.0f, zNear, zFar)); - Matrix4 wt(t->worldTransform()); - Vector3 position(wt[12], wt[13], wt[14]); + Vector3 position(t->worldTransform().position()); Matrix4 wp; wp.translate(position); @@ -280,14 +294,22 @@ void ShadowMap::pointLightUpdate(PointLight *light, std::list &com static_cast(w[i]) / pageSize, static_cast(h[i]) / pageSize); - buffer->setViewProjection(mat, crop); - buffer->setViewport(x[i], y[i], w[i], h[i]); - RenderList culled; m_context->frustumCulling(Camera::frustum(false, 90.0f, 1.0f, position, m_directions[i], zNear, zFar), components, culled); - // Draw in the depth buffer from position of the light source - m_context->drawRenderers(culled, CommandBuffer::SHADOWCAST); + std::list groups; + filterAndGroup(culled, groups, Material::Shadowcast); + + if(!groups.empty()) { + buffer->setViewProjection(mat, crop); + buffer->setViewport(x[i], y[i], w[i], h[i]); + + // Draw in the depth buffer from position of the light source + for(auto &it : groups) { + buffer->drawMesh(it.mesh, it.subMesh, Material::Shadowcast, *it.instance); + it.instance->resetBatches(); + } + } } auto instance = light->material(); @@ -301,7 +323,7 @@ void ShadowMap::pointLightUpdate(PointLight *light, std::list &com } } -void ShadowMap::spotLightUpdate(SpotLight *light, std::list &components) { +void ShadowMap::spotLightUpdate(SpotLight *light, const RenderList &components) { CommandBuffer *buffer = m_context->buffer(); Transform *t = light->transform(); @@ -309,7 +331,7 @@ void ShadowMap::spotLightUpdate(SpotLight *light, std::list &compo Matrix4 wt(t->worldTransform()); Matrix4 rot(wt.inverse()); - Vector3 position(wt[12], wt[13], wt[14]); + Vector3 position(wt.position()); float zNear = 0.1f; float zFar = light->attenuationDistance(); @@ -321,16 +343,24 @@ void ShadowMap::spotLightUpdate(SpotLight *light, std::list &compo int32_t h = 0; RenderTarget *shadowTarget = requestShadowTiles(light->uuid(), 1, &x, &y, &w, &h, 1); - buffer->setRenderTarget(shadowTarget); - - buffer->setViewProjection(rot, crop); - buffer->setViewport(x, y, w, h); - RenderList culled; m_context->frustumCulling(Camera::frustum(false, light->outerAngle() * 2.0f, 1.0f, position, q, zNear, zFar), components, culled); - // Draw in the depth buffer from position of the light source - m_context->drawRenderers(culled, CommandBuffer::SHADOWCAST); + std::list groups; + filterAndGroup(culled, groups, Material::Shadowcast); + + if(!groups.empty()) { + buffer->setRenderTarget(shadowTarget); + + buffer->setViewProjection(rot, crop); + buffer->setViewport(x, y, w, h); + + // Draw in the depth buffer from position of the light source + for(auto &it : groups) { + buffer->drawMesh(it.mesh, it.subMesh, Material::Shadowcast, *it.instance); + it.instance->resetBatches(); + } + } auto instance = light->material(); if(instance) { diff --git a/engine/src/pipelinetasks/tonemap.cpp b/engine/src/pipelinetasks/tonemap.cpp index 638d049b8..01ece4e94 100644 --- a/engine/src/pipelinetasks/tonemap.cpp +++ b/engine/src/pipelinetasks/tonemap.cpp @@ -89,7 +89,7 @@ void Tonemap::exec() { buffer->beginDebugMarker(gTonemap); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_resultMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_resultMaterial); buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/translucent.cpp b/engine/src/pipelinetasks/translucent.cpp index 0e0a03134..7f1a85374 100644 --- a/engine/src/pipelinetasks/translucent.cpp +++ b/engine/src/pipelinetasks/translucent.cpp @@ -2,7 +2,10 @@ #include "resources/rendertarget.h" -#include "pipelinecontext.h" +#include "components/renderable.h" +#include "components/transform.h" +#include "components/camera.h" + #include "commandbuffer.h" Translucent::Translucent() : @@ -19,13 +22,18 @@ Translucent::Translucent() : void Translucent::exec() { CommandBuffer *buffer = m_context->buffer(); - buffer->beginDebugMarker("TranslucentPass"); + if(!m_translucent.empty()) { + buffer->beginDebugMarker("TranslucentPass"); - buffer->setRenderTarget(m_translucentPass); + buffer->setRenderTarget(m_translucentPass); - m_context->drawRenderers(m_context->culledComponents(), CommandBuffer::TRANSLUCENT); + for(auto &it : m_translucent) { + buffer->drawMesh(it.mesh, it.subMesh, Material::Translucent, *it.instance); + it.instance->resetBatches(); + } - buffer->endDebugMarker(); + buffer->endDebugMarker(); + } } void Translucent::setInput(int index, Texture *texture) { @@ -40,3 +48,24 @@ void Translucent::setInput(int index, Texture *texture) { default: break; } } + +void Translucent::analyze(World *world) { + RenderList translucent; + + filterByLayer(m_context->culledRenderables(), translucent, Material::Translucent); + + Vector3 cameraWP(Camera::current()->transform()->worldPosition()); + + translucent.sort([cameraWP](const Renderable *left, const Renderable *right) { + int p1 = left->priority(); + int p2 = right->priority(); + if(p1 == p2) { + return cameraWP.dot(left->transform()->worldPosition()) < cameraWP.dot(right->transform()->worldPosition()); + } + return p1 < p2; + }); + + m_translucent.clear(); + + filterAndGroup(translucent, m_translucent, 0); +} diff --git a/engine/src/resources/material.cpp b/engine/src/resources/material.cpp index c0a24408f..3af415522 100644 --- a/engine/src/resources/material.cpp +++ b/engine/src/resources/material.cpp @@ -350,7 +350,6 @@ ByteArray &MaterialInstance::rawUniformBuffer() { return m_uniformBuffer; } - /*! Batches a material \a instance to draw using GPU instancing. */ @@ -365,7 +364,6 @@ void MaterialInstance::batch(MaterialInstance &instance) { m_batchesCount += instance.m_instanceCount; } - /*! Rests batch buffer. */ @@ -389,6 +387,7 @@ Material::Material() : m_uniformSize(0), m_lightModel(Unlit), m_materialType(Surface), + m_layers(0), m_doubleSided(true), m_wireframe(false) { @@ -449,6 +448,12 @@ bool Material::wireframe() const { void Material::setWireframe(bool wireframe) { m_wireframe = wireframe; } +/*! + Returns layers that supported by this material. +*/ +int Material::layers() const { + return m_layers; +} /*! \internal */ @@ -479,6 +484,12 @@ void Material::loadUserData(const VariantMap &data) { if(it != data.end()) { loadStencilState((*it).second.value()); } + + if(m_blendState.enabled) { + m_layers |= Material::Translucent; + } else { + m_layers |= Material::Default; + } } { m_textures.clear(); @@ -549,7 +560,6 @@ void Material::loadBlendState(const VariantList &data) { m_blendState.sourceColorBlendMode = (*i).toInt(); ++i; m_blendState.enabled = (*i).toBool(); - } /*! \internal diff --git a/engine/tests/tst_actor.h b/engine/tests/tst_actor.h index 299c17d26..eb76717ba 100644 --- a/engine/tests/tst_actor.h +++ b/engine/tests/tst_actor.h @@ -54,10 +54,6 @@ TEST_F(ActorTest, Basic_properties) { ASSERT_TRUE(actor.isEnabled()); actor.setEnabled(false); ASSERT_FALSE(actor.isEnabled()); - - ASSERT_TRUE(actor.layers() == (CommandBuffer::DEFAULT | CommandBuffer::RAYCAST | CommandBuffer::SHADOWCAST| CommandBuffer::TRANSLUCENT)); - actor.setLayers(CommandBuffer::UI); - ASSERT_TRUE(actor.layers() == CommandBuffer::UI); } TEST_F(ActorTest, Transform_hierarchy) { diff --git a/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.cpp b/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.cpp index 852436415..ea1157b99 100644 --- a/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.cpp +++ b/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.cpp @@ -39,7 +39,7 @@ void LinksRender::draw(CommandBuffer &buffer) { m_material->setTransform(rectTransform()); if(m_linksMesh && !m_linksMesh->vertices().empty()) { - buffer.drawMesh(m_linksMesh, 0, CommandBuffer::UI, *m_material); + buffer.drawMesh(m_linksMesh, 0, Material::Translucent, *m_material); } if(m_creationMesh && m_portWidget) { RectTransform *parentTransform = static_cast(static_cast(actor()->parent())->transform()); @@ -106,7 +106,7 @@ void LinksRender::draw(CommandBuffer &buffer) { m_creationMesh->recalcBounds(); } - buffer.drawMesh(m_creationMesh, 0, CommandBuffer::UI, *m_material); + buffer.drawMesh(m_creationMesh, 0, Material::Translucent, *m_material); } } diff --git a/modules/editor/shadertools/converter/shadergraph.cpp b/modules/editor/shadertools/converter/shadergraph.cpp index 72ec52860..5cd57994f 100644 --- a/modules/editor/shadertools/converter/shadergraph.cpp +++ b/modules/editor/shadertools/converter/shadergraph.cpp @@ -703,7 +703,7 @@ void ShaderGraph::updatePreviews(CommandBuffer &buffer) { } } buffer.setRenderTarget(it.second.target); - buffer.drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::TRANSLUCENT, *it.second.instance); + buffer.drawMesh(PipelineContext::defaultPlane(), 0, Material::Translucent, *it.second.instance); } } } diff --git a/modules/editor/shadertools/editor/materialedit.cpp b/modules/editor/shadertools/editor/materialedit.cpp index 125c53eee..76bf0f43d 100644 --- a/modules/editor/shadertools/editor/materialedit.cpp +++ b/modules/editor/shadertools/editor/materialedit.cpp @@ -212,7 +212,7 @@ void MaterialEdit::onGraphUpdated() { MeshRender *mesh = static_cast(m_mesh->component(gMeshRender)); if(mesh) { - MaterialInstance *instance = mesh->materialInstance(); + MaterialInstance *instance = mesh->materialInstance(0); m_material->initInstance(instance); } } diff --git a/modules/editor/texturetools/converter/textureconverter.cpp b/modules/editor/texturetools/converter/textureconverter.cpp index 46f1c428a..fca5fcfb7 100644 --- a/modules/editor/texturetools/converter/textureconverter.cpp +++ b/modules/editor/texturetools/converter/textureconverter.cpp @@ -489,7 +489,7 @@ Actor *TextureConverter::createActor(const AssetConverterSettings *settings, con MeshRender *render = actor->getComponent(); render->setMesh(Engine::loadResource(".embedded/sphere.fbx/Sphere001")); render->setMaterial(Engine::loadResource(".embedded/cubemap.shader")); - render->materialInstance()->setTexture("mainTexture", texture); + render->materialInstance(0)->setTexture("mainTexture", texture); return actor; } diff --git a/modules/editor/texturetools/editor/spriteedit.cpp b/modules/editor/texturetools/editor/spriteedit.cpp index fb14166d9..c2fae645a 100644 --- a/modules/editor/texturetools/editor/spriteedit.cpp +++ b/modules/editor/texturetools/editor/spriteedit.cpp @@ -119,7 +119,7 @@ void SpriteEdit::loadAsset(AssetConverterSettings *settings) { renderTransform->setPosition(size * 0.5f); Vector2 scale(texture->width() / 20.0f, texture->height() / 20.0f); - m_checker->materialInstance()->setVector2("scale", &scale); + m_checker->materialInstance(0)->setVector2("scale", &scale); Transform *checkerTransform = m_checker->transform(); checkerTransform->setScale(size); diff --git a/modules/network/src/objects/webrequest.cpp b/modules/network/src/objects/webrequest.cpp index f30ec5428..f962f1de3 100644 --- a/modules/network/src/objects/webrequest.cpp +++ b/modules/network/src/objects/webrequest.cpp @@ -125,8 +125,7 @@ void WebRequest::send() { if(m_socket->connect(NetworkAddress(host, port))) { // Prepare HTTP request m_state = State::SendingHeader; - ByteArray data; - std::copy(headerData.toStdString().begin(), headerData.toStdString().end(), std::back_inserter(data)); + ByteArray data(headerData.toStdString().begin(), headerData.toStdString().end()); if(m_socket->write(data) == headerData.size()) { m_content.clear(); diff --git a/modules/renders/rendergl/includes/resources/materialgl.h b/modules/renders/rendergl/includes/resources/materialgl.h index eecb5c89b..dde76281f 100644 --- a/modules/renders/rendergl/includes/resources/materialgl.h +++ b/modules/renders/rendergl/includes/resources/materialgl.h @@ -31,11 +31,11 @@ class MaterialInstanceGL : public MaterialInstance { static void setStencilState(const Material::StencilState &state); private: - Material::BlendState m_blendState; + Material::BlendState m_glBlendState; - Material::DepthState m_depthState; + Material::DepthState m_glDepthState; - Material::StencilState m_stencilState; + Material::StencilState m_glStencilState; uint32_t m_instanceBuffer; uint32_t m_globalBuffer; @@ -58,9 +58,6 @@ class MaterialGL : public Material { FragmentDefault, FragmentVisibility, FragmentLast, - - GeometryDefault, - GeometryLast }; typedef std::unordered_map ObjectMap; diff --git a/modules/renders/rendergl/src/resources/materialgl.cpp b/modules/renders/rendergl/src/resources/materialgl.cpp index b37302e7a..085a0ea85 100644 --- a/modules/renders/rendergl/src/resources/materialgl.cpp +++ b/modules/renders/rendergl/src/resources/materialgl.cpp @@ -29,9 +29,7 @@ void MaterialGL::loadUserData(const VariantMap &data) { {"Static", VertexStatic}, {"Skinned", VertexSkinned}, - {"Particle", VertexParticle}, - - {"Geometry", GeometryDefault} + {"Particle", VertexParticle} }; for(auto &pair : pairs) { @@ -40,6 +38,13 @@ void MaterialGL::loadUserData(const VariantMap &data) { auto fields = (*it).second.toList(); m_shaderSources[pair.second] = fields.front().toString(); // Shader data + + if(pair.second == FragmentVisibility) { + m_layers |= Material::Visibility; + if(m_layers & Default) { + m_layers |= Material::Shadowcast; + } + } } } @@ -63,12 +68,6 @@ uint32_t MaterialGL::getProgram(uint16_t type, int32_t &global, int32_t &local) m_programs.clear(); - uint32_t geometry = 0; - auto itg = m_shaderSources.find(GeometryDefault); - if(itg != m_shaderSources.end()) { - buildShader(itg->first, itg->second); - } - for(uint16_t v = Static; v < VertexLast; v++) { auto itv = m_shaderSources.find(v); if(itv != m_shaderSources.end()) { @@ -79,9 +78,6 @@ uint32_t MaterialGL::getProgram(uint16_t type, int32_t &global, int32_t &local) uint32_t fragment = buildShader(itf->first, itf->second); std::vector shaders = {vertex, fragment}; - if(geometry > 0) { - shaders.push_back(geometry); - } uint32_t program = buildProgram(shaders, v); m_programs[v * f] = program; @@ -131,12 +127,6 @@ uint32_t MaterialGL::buildShader(uint16_t type, const TString &src) { t = GL_FRAGMENT_SHADER; } else if(type >= VertexStatic && type < VertexLast) { t = GL_VERTEX_SHADER; - } else if(type >= GeometryDefault && type < GeometryLast) { -#ifndef THUNDER_MOBILE - t = GL_GEOMETRY_SHADER; -#else - return 0; -#endif } uint32_t shader = glCreateShader(t); @@ -303,35 +293,35 @@ MaterialInstanceGL::MaterialInstanceGL(Material *material) : m_globalBuffer(0) { MaterialGL *m = static_cast(material); - m_blendState = m->m_blendState; + m_glBlendState = m->m_blendState; // Blending - m_blendState.colorOperation = convertBlendMode(m_blendState.colorOperation); - m_blendState.alphaOperation = convertBlendMode(m_blendState.alphaOperation); + m_glBlendState.colorOperation = convertBlendMode(m_glBlendState.colorOperation); + m_glBlendState.alphaOperation = convertBlendMode(m_glBlendState.alphaOperation); - m_blendState.sourceColorBlendMode = convertBlendFactor(m_blendState.sourceColorBlendMode); - m_blendState.sourceAlphaBlendMode = convertBlendFactor(m_blendState.sourceAlphaBlendMode); + m_glBlendState.sourceColorBlendMode = convertBlendFactor(m_glBlendState.sourceColorBlendMode); + m_glBlendState.sourceAlphaBlendMode = convertBlendFactor(m_glBlendState.sourceAlphaBlendMode); - m_blendState.destinationColorBlendMode = convertBlendFactor(m_blendState.destinationColorBlendMode); - m_blendState.destinationAlphaBlendMode = convertBlendFactor(m_blendState.destinationAlphaBlendMode); + m_glBlendState.destinationColorBlendMode = convertBlendFactor(m_glBlendState.destinationColorBlendMode); + m_glBlendState.destinationAlphaBlendMode = convertBlendFactor(m_glBlendState.destinationAlphaBlendMode); // Depth - m_depthState = m->m_depthState; - m_depthState.compareFunction = 0x0200 | m_depthState.compareFunction; + m_glDepthState = m->m_depthState; + m_glDepthState.compareFunction = 0x0200 | m_glDepthState.compareFunction; // Stencil - m_stencilState = m->m_stencilState; - m_stencilState.compareFunctionBack = 0x0200 | m_stencilState.compareFunctionBack; - m_stencilState.compareFunctionFront = 0x0200 | m_stencilState.compareFunctionFront; + m_glStencilState = m->m_stencilState; + m_glStencilState.compareFunctionBack = 0x0200 | m_glStencilState.compareFunctionBack; + m_glStencilState.compareFunctionFront = 0x0200 | m_glStencilState.compareFunctionFront; - m_stencilState.failOperationBack = convertAction(m_stencilState.failOperationBack); - m_stencilState.failOperationFront = convertAction(m_stencilState.failOperationFront); + m_glStencilState.failOperationBack = convertAction(m_glStencilState.failOperationBack); + m_glStencilState.failOperationFront = convertAction(m_glStencilState.failOperationFront); - m_stencilState.zFailOperationBack = convertAction(m_stencilState.zFailOperationBack); - m_stencilState.zFailOperationFront = convertAction(m_stencilState.zFailOperationFront); + m_glStencilState.zFailOperationBack = convertAction(m_glStencilState.zFailOperationBack); + m_glStencilState.zFailOperationFront = convertAction(m_glStencilState.zFailOperationFront); - m_stencilState.passOperationBack = convertAction(m_stencilState.passOperationBack); - m_stencilState.passOperationFront = convertAction(m_stencilState.passOperationFront); + m_glStencilState.passOperationBack = convertAction(m_glStencilState.passOperationBack); + m_glStencilState.passOperationFront = convertAction(m_glStencilState.passOperationFront); } @@ -347,15 +337,8 @@ uint32_t MaterialInstanceGL::drawsCount() const { } bool MaterialInstanceGL::bind(CommandBufferGL *buffer, uint32_t layer, uint32_t index, const Global &global) { - if((layer & CommandBuffer::DEFAULT || layer & CommandBuffer::SHADOWCAST) && m_blendState.enabled) { - return false; - } - if(layer & CommandBuffer::TRANSLUCENT && !m_blendState.enabled) { - return false; - } - uint16_t type = MaterialGL::FragmentDefault; - if((layer & CommandBuffer::RAYCAST) || (layer & CommandBuffer::SHADOWCAST)) { + if((layer & Material::Visibility) || (layer & Material::Shadowcast)) { type = MaterialGL::FragmentVisibility; } @@ -470,9 +453,9 @@ bool MaterialInstanceGL::bind(CommandBufferGL *buffer, uint32_t layer, uint32_t Material::RasterState rasterState; rasterState.cullingMode = GL_BACK; - if(layer & CommandBuffer::SHADOWCAST) { + if(layer & Material::Shadowcast) { rasterState.cullingMode = GL_FRONT; - } else if(!material->doubleSided() && !(layer & CommandBuffer::RAYCAST)) { + } else if(!material->doubleSided() && !(layer & Material::Visibility)) { if(materialType != Material::LightFunction) { rasterState.cullingMode = GL_BACK; } @@ -482,8 +465,8 @@ bool MaterialInstanceGL::bind(CommandBufferGL *buffer, uint32_t layer, uint32_t setRasterState(rasterState); - Material::BlendState blendState = m_blendState; - if(layer & CommandBuffer::RAYCAST) { + Material::BlendState blendState = m_glBlendState; + if(layer & Material::Visibility) { blendState.sourceColorBlendMode = GL_ONE; blendState.sourceAlphaBlendMode = GL_ONE; @@ -493,9 +476,9 @@ bool MaterialInstanceGL::bind(CommandBufferGL *buffer, uint32_t layer, uint32_t setBlendState(blendState); - setDepthState(m_depthState); + setDepthState(m_glDepthState); - setStencilState(m_stencilState); + setStencilState(m_glStencilState); return true; } diff --git a/modules/renders/rendervk/src/resources/materialvk.cpp b/modules/renders/rendervk/src/resources/materialvk.cpp index 348e07c9a..07685c3f2 100644 --- a/modules/renders/rendervk/src/resources/materialvk.cpp +++ b/modules/renders/rendervk/src/resources/materialvk.cpp @@ -151,15 +151,8 @@ VkDescriptorSetLayout MaterialVk::globalDescriptorSetLayout() const { } bool MaterialVk::bind(VkCommandBuffer buffer, RenderTargetVk *target, uint32_t layer, uint16_t vertex) { - if((layer & CommandBuffer::DEFAULT || layer & CommandBuffer::SHADOWCAST) && m_blendState.enabled) { - return false; - } - if(layer & CommandBuffer::TRANSLUCENT && !m_blendState.enabled) { - return false; - } - uint16_t type = FragmentDefault; - if((layer & CommandBuffer::RAYCAST) || (layer & CommandBuffer::SHADOWCAST)) { + if((layer & Material::Visibility) || (layer & Material::Shadowcast)) { type = FragmentVisibility; } diff --git a/modules/uikit/includes/uisystem.h b/modules/uikit/includes/uisystem.h index 6a4efb1a5..a143a7a6d 100644 --- a/modules/uikit/includes/uisystem.h +++ b/modules/uikit/includes/uisystem.h @@ -16,8 +16,6 @@ class UiSystem : public System { int threadPolicy() const override; - Object *instantiateObject(const MetaObject *meta, const TString &name, Object *parent) override; - void addWidget(Widget *widget); void removeWidget(Widget *widget); diff --git a/modules/uikit/src/components/frame.cpp b/modules/uikit/src/components/frame.cpp index 15890923b..9447ef61c 100644 --- a/modules/uikit/src/components/frame.cpp +++ b/modules/uikit/src/components/frame.cpp @@ -75,7 +75,7 @@ void Frame::draw(CommandBuffer &buffer) { m_material->setTransform(m * s); - buffer.drawMesh(m_mesh, 0, CommandBuffer::UI, *m_material); + buffer.drawMesh(m_mesh, 0, Material::Translucent, *m_material); } } /*! diff --git a/modules/uikit/src/components/image.cpp b/modules/uikit/src/components/image.cpp index d25a75251..27a2ff72b 100644 --- a/modules/uikit/src/components/image.cpp +++ b/modules/uikit/src/components/image.cpp @@ -64,7 +64,7 @@ void Image::draw(CommandBuffer &buffer) { MaterialInstance &isntance = (m_customMaterial) ? *m_customMaterial : *m_material; isntance.setTransform(mat); - buffer.drawMesh(m_mesh, 0, CommandBuffer::UI, isntance); + buffer.drawMesh(m_mesh, 0, Material::Translucent, isntance); } } } diff --git a/modules/uikit/src/components/label.cpp b/modules/uikit/src/components/label.cpp index b22d78536..106308bcf 100644 --- a/modules/uikit/src/components/label.cpp +++ b/modules/uikit/src/components/label.cpp @@ -77,7 +77,7 @@ void Label::draw(CommandBuffer &buffer) { m_dirty = false; } - buffer.drawMesh(m_mesh, 0, CommandBuffer::UI, *m_material); + buffer.drawMesh(m_mesh, 0, Material::Translucent, *m_material); } } /*! diff --git a/modules/uikit/src/uisystem.cpp b/modules/uikit/src/uisystem.cpp index 4904b3f95..55ea11870 100644 --- a/modules/uikit/src/uisystem.cpp +++ b/modules/uikit/src/uisystem.cpp @@ -106,15 +106,6 @@ int UiSystem::threadPolicy() const { return Main; } -Object *UiSystem::instantiateObject(const MetaObject *meta, const TString &name, Object *parent) { - Object *result = ObjectSystem::instantiateObject(meta, name, parent); - Widget *widget = dynamic_cast(result); - if(widget) { - widget->actor()->setLayers(CommandBuffer::UI | CommandBuffer::RAYCAST); - } - return result; -} - void UiSystem::addWidget(Widget *widget) { m_uiComponents.push_back(widget); } diff --git a/thirdparty/next/inc/math/matrix4.h b/thirdparty/next/inc/math/matrix4.h index c17731c57..d8bf33f88 100644 --- a/thirdparty/next/inc/math/matrix4.h +++ b/thirdparty/next/inc/math/matrix4.h @@ -60,6 +60,7 @@ class NEXT_LIBRARY_EXPORT Matrix4 { void direction(const Vector3 &direction, const Vector3 &up); Vector3 euler(); + Vector3 position() const; void zero(); void identity(); diff --git a/thirdparty/next/src/math/matrix4.cpp b/thirdparty/next/src/math/matrix4.cpp index 1366ca609..4b60cf337 100644 --- a/thirdparty/next/src/math/matrix4.cpp +++ b/thirdparty/next/src/math/matrix4.cpp @@ -348,6 +348,12 @@ void Matrix4::translate(const Vector3 &vector) { Vector3 Matrix4::euler() { return rotation().euler(); } +/*! + Returns position component of the matrix. +*/ +Vector3 Matrix4::position() const { + return Vector3(mat[12], mat[13], mat[14]); +} /*! Constructs a matrix that reflects the coordinate system about the \a plane. */ diff --git a/worldeditor/src/screens/contentbrowser/contentbrowser.cpp b/worldeditor/src/screens/contentbrowser/contentbrowser.cpp index 6458358db..7e623a11a 100644 --- a/worldeditor/src/screens/contentbrowser/contentbrowser.cpp +++ b/worldeditor/src/screens/contentbrowser/contentbrowser.cpp @@ -512,7 +512,7 @@ void ContentBrowser::on_contentList_clicked(const QModelIndex &index) { TString source = ContentTree::instance()->path(origin).toStdString(); TString path(source); if(!source.contains(".embedded/")) { - path = TString(ProjectSettings::instance()->contentPath().toStdString()) + "/" + source; + path = ProjectSettings::instance()->contentPath() + "/" + source; } m_settings = AssetManager::instance()->fetchSettings(path); @@ -534,7 +534,7 @@ void ContentBrowser::importAsset() { const QModelIndex origin = m_listProxy->mapToSource(ui->contentList->rootIndex()); - TString target = TString(ProjectSettings::instance()->contentPath().toStdString()) + "/" + ContentTree::instance()->path(origin).toStdString(); + TString target = ProjectSettings::instance()->contentPath() + "/" + ContentTree::instance()->path(origin).toStdString(); foreach(auto &it, files) { AssetManager::instance()->import(it.toStdString(), target); diff --git a/worldeditor/src/screens/contentbrowser/contenttree.cpp b/worldeditor/src/screens/contentbrowser/contenttree.cpp index 41a54565d..b2cb4c98d 100644 --- a/worldeditor/src/screens/contentbrowser/contenttree.cpp +++ b/worldeditor/src/screens/contentbrowser/contenttree.cpp @@ -113,12 +113,12 @@ void ContentTree::onRendered(const TString &uuid) { AssetManager *asset = AssetManager::instance(); - AssetConverterSettings *settings = asset->fetchSettings(asset->guidToPath(uuid.toStdString())); + AssetConverterSettings *settings = asset->fetchSettings(asset->guidToPath(uuid)); if(settings) { - settings->resetIcon(uuid.toStdString()); + settings->resetIcon(uuid); } - QFileInfo info(asset->guidToPath(uuid.toStdString()).data()); + QFileInfo info(asset->guidToPath(uuid).data()); QString source = info.absoluteFilePath().contains(dir.absolutePath()) ? dir.relativeFilePath(info.absoluteFilePath()) : (QString(".embedded/") + info.fileName()); diff --git a/worldeditor/src/screens/scenecomposer/objectcontroller.cpp b/worldeditor/src/screens/scenecomposer/objectcontroller.cpp index 4266c88a2..989d916fe 100644 --- a/worldeditor/src/screens/scenecomposer/objectcontroller.cpp +++ b/worldeditor/src/screens/scenecomposer/objectcontroller.cpp @@ -79,7 +79,19 @@ class ViewportRaycast : public PipelineTask { buffer->setRenderTarget(m_resultTarget); if(!m_controller->isPickingBlocked() && !m_controller->isPickingOverlaped()) { - m_context->drawRenderers(m_context->culledComponents(), CommandBuffer::RAYCAST, Actor::Selectable); + RenderList filtered; + for(auto it : m_context->culledRenderables()) { + if(it && it->actor()->flags() & Actor::Selectable) { + filtered.push_back(it); + } + } + + std::list groups; + filterAndGroup(filtered, groups, Material::Visibility); + for(auto &it : groups) { + buffer->drawMesh(it.mesh, it.subMesh, Material::Visibility, *it.instance); + it.instance->resetBatches(); + } Camera *activeCamera = m_controller->activeCamera(); @@ -105,7 +117,7 @@ class ViewportRaycast : public PipelineTask { for(auto it : m_dragList) { it->update(); - m_context->culledComponents().push_back(it); + m_context->culledRenderables().push_back(it); } buffer->endDebugMarker(); From 872d4e51c767e450e271a9d251003becd7b58e7c Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Mon, 4 Aug 2025 21:40:00 +0300 Subject: [PATCH 2/4] update --- .../renders/rendermt/src/resources/materialmt.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/modules/renders/rendermt/src/resources/materialmt.cpp b/modules/renders/rendermt/src/resources/materialmt.cpp index b2513e879..a4f45e597 100644 --- a/modules/renders/rendermt/src/resources/materialmt.cpp +++ b/modules/renders/rendermt/src/resources/materialmt.cpp @@ -12,9 +12,9 @@ #include namespace { -const char *gGlobal("g"); -const char *gLocal("instance"); -const char *gUniform("uni"); + const char *gGlobal("g"); + const char *gLocal("instance"); + const char *gUniform("uni"); } enum ShaderType { @@ -202,15 +202,8 @@ MTL::RenderPipelineState *MaterialMt::getPipeline(uint16_t vertex, uint16_t frag } bool MaterialMt::bind(MTL::RenderCommandEncoder *encoder, RenderTargetMt *target, uint32_t layer, uint16_t vertex) { - if((layer & CommandBuffer::DEFAULT || layer & CommandBuffer::SHADOWCAST) && m_blendState.enabled) { - return false; - } - if(layer & CommandBuffer::TRANSLUCENT && !m_blendState.enabled) { - return false; - } - uint16_t type = FragmentDefault; - if((layer & CommandBuffer::RAYCAST) || (layer & CommandBuffer::SHADOWCAST)) { + if((layer & Material::Visibility) || (layer & Material::Shadowcast)) { type = FragmentVisibility; } From b314cc9f568b190ac72f79bafbff8505c9f57fb3 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Tue, 5 Aug 2025 18:21:11 +0300 Subject: [PATCH 3/4] update --- engine/includes/components/meshrender.h | 2 - engine/includes/components/renderable.h | 2 - engine/includes/components/spriterender.h | 4 +- engine/includes/components/tilemaprender.h | 5 +- .../editor/viewport/tasks/debugrender.h | 2 +- .../editor/viewport/tasks/gizmorender.h | 4 +- .../editor/viewport/tasks/outlinerender.h | 7 +- engine/includes/pipelinetask.h | 9 +- engine/includes/pipelinetasks/gbuffer.h | 2 +- engine/includes/pipelinetasks/translucent.h | 2 +- engine/includes/resources/material.h | 28 +-- engine/src/components/meshrender.cpp | 6 - engine/src/components/renderable.cpp | 7 - engine/src/components/spriterender.cpp | 20 +-- engine/src/components/tilemaprender.cpp | 30 ++-- engine/src/pipelinecontext.cpp | 2 +- engine/src/pipelinetask.cpp | 67 ++++--- engine/src/pipelinetasks/ambientocclusion.cpp | 4 +- engine/src/pipelinetasks/antialiasing.cpp | 2 +- engine/src/pipelinetasks/bloom.cpp | 4 +- engine/src/pipelinetasks/depthoffield.cpp | 2 +- engine/src/pipelinetasks/downsample.cpp | 2 +- engine/src/pipelinetasks/gbuffer.cpp | 10 +- engine/src/pipelinetasks/indirect.cpp | 2 +- engine/src/pipelinetasks/reflections.cpp | 2 +- engine/src/pipelinetasks/shadowmap.cpp | 37 ++-- engine/src/pipelinetasks/tonemap.cpp | 2 +- engine/src/pipelinetasks/translucent.cpp | 22 +-- engine/src/resources/material.cpp | 164 +++++------------- .../editor/texturetools/editor/spriteedit.cpp | 1 + .../rendergl/src/resources/materialgl.cpp | 4 +- .../rendermt/src/resources/materialmt.cpp | 2 +- .../rendervk/src/resources/materialvk.cpp | 2 +- .../scenecomposer/objectcontroller.cpp | 6 +- 34 files changed, 185 insertions(+), 282 deletions(-) diff --git a/engine/includes/components/meshrender.h b/engine/includes/components/meshrender.h index f3f8203f7..74dd293dd 100644 --- a/engine/includes/components/meshrender.h +++ b/engine/includes/components/meshrender.h @@ -34,8 +34,6 @@ class ENGINE_EXPORT MeshRender : public Renderable { Mesh *meshToDraw(int instance) const override; - void composeComponent() override; - void setProperty(const char *name, const Variant &value) override; void drawGizmosSelected() override; diff --git a/engine/includes/components/renderable.h b/engine/includes/components/renderable.h index 2b011672c..bd7d3b811 100644 --- a/engine/includes/components/renderable.h +++ b/engine/includes/components/renderable.h @@ -32,8 +32,6 @@ class ENGINE_EXPORT Renderable : public NativeBehaviour { int32_t materialsCount() const; MaterialInstance *materialInstance(int index) const; - virtual int priority() const; - protected: virtual Mesh *meshToDraw(int instance) const; diff --git a/engine/includes/components/spriterender.h b/engine/includes/components/spriterender.h index cb57205bc..c5a1aa24e 100644 --- a/engine/includes/components/spriterender.h +++ b/engine/includes/components/spriterender.h @@ -74,8 +74,6 @@ class ENGINE_EXPORT SpriteRender : public Renderable { void composeComponent() override; - int priority() const override; - void composeMesh(bool resetSize = false); static bool composeSliced(Mesh *mesh, Vector2 &size, Vector3 &delta, float scale); @@ -101,7 +99,7 @@ class ENGINE_EXPORT SpriteRender : public Renderable { int m_drawMode; - int m_layer; + int m_priority; }; diff --git a/engine/includes/components/tilemaprender.h b/engine/includes/components/tilemaprender.h index 62c23a47e..d34ac130a 100644 --- a/engine/includes/components/tilemaprender.h +++ b/engine/includes/components/tilemaprender.h @@ -40,13 +40,10 @@ class ENGINE_EXPORT TileMapRender : public Renderable { void composeComponent() override; - int priority() const override; - private: TileMap *m_tileMap; - int m_layer; - + int m_priority; }; #endif // TILEMAPRENDER_H diff --git a/engine/includes/editor/viewport/tasks/debugrender.h b/engine/includes/editor/viewport/tasks/debugrender.h index 44532998e..df2af29d6 100644 --- a/engine/includes/editor/viewport/tasks/debugrender.h +++ b/engine/includes/editor/viewport/tasks/debugrender.h @@ -59,7 +59,7 @@ class DebugRender : public PipelineTask { } it.second->setTransform(m); - buffer->drawMesh(m_mesh, 0, Material::Default, *it.second); + buffer->drawMesh(m_mesh, 0, Material::Opaque, *it.second); i++; } diff --git a/engine/includes/editor/viewport/tasks/gizmorender.h b/engine/includes/editor/viewport/tasks/gizmorender.h index 313fa0d17..69a0d9912 100644 --- a/engine/includes/editor/viewport/tasks/gizmorender.h +++ b/engine/includes/editor/viewport/tasks/gizmorender.h @@ -126,10 +126,10 @@ class GizmoRender : public PipelineTask { buffer->setViewport(m_width-gNaviCubeSize, m_height-gNaviCubeSize, gNaviCubeSize, gNaviCubeSize); buffer->setViewProjection(m_camera->viewMatrix(), m_camera->projectionMatrix()); - buffer->drawMesh(PipelineContext::defaultCube(), 0, Material::Default, *m_cubeMaterial); + buffer->drawMesh(PipelineContext::defaultCube(), 0, Material::Opaque, *m_cubeMaterial); if(m_side != -1) { - buffer->drawMesh(m_solidCube, m_side, Material::Default, *m_solidMaterial); + buffer->drawMesh(m_solidCube, m_side, Material::Opaque, *m_solidMaterial); } buffer->setViewport(0, 0, m_width, m_height); diff --git a/engine/includes/editor/viewport/tasks/outlinerender.h b/engine/includes/editor/viewport/tasks/outlinerender.h index ec04bd0b6..252c2303d 100644 --- a/engine/includes/editor/viewport/tasks/outlinerender.h +++ b/engine/includes/editor/viewport/tasks/outlinerender.h @@ -94,7 +94,7 @@ class Outline : public PipelineTask { } buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_combineMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Opaque, *m_combineMaterial); buffer->endDebugMarker(); } @@ -118,13 +118,14 @@ class Outline : public PipelineTask { } } - filterAndGroup(outline, m_outline, Material::Visibility); + m_outline.clear(); + filterByLayer(outline, m_outline, Material::Visibility); } protected: Vector4 m_color; - std::list m_outline; + GroupList m_outline; Texture *m_outlineMap; Texture *m_outlineDepth; diff --git a/engine/includes/pipelinetask.h b/engine/includes/pipelinetask.h index dc56e3666..68586626e 100644 --- a/engine/includes/pipelinetask.h +++ b/engine/includes/pipelinetask.h @@ -40,11 +40,16 @@ class ENGINE_EXPORT PipelineTask : public Object { Mesh *mesh = nullptr; uint32_t subMesh = 0; + + uint32_t hash = 0; + + ByteArray buffer; }; + typedef std::list GroupList; - void filterByLayer(const RenderList &in, RenderList &out, int layer) const; + void filterByLayer(const RenderList &in, GroupList &out, int layer) const; - void filterAndGroup(const RenderList &in, std::list &out, int layer); + void group(const GroupList &in, GroupList &out) const; protected: std::vector m_inputs; diff --git a/engine/includes/pipelinetasks/gbuffer.h b/engine/includes/pipelinetasks/gbuffer.h index eb9974009..19178b881 100644 --- a/engine/includes/pipelinetasks/gbuffer.h +++ b/engine/includes/pipelinetasks/gbuffer.h @@ -17,7 +17,7 @@ class GBuffer : public PipelineTask { void analyze(World *world) override; private: - std::list m_opaque; + GroupList m_opaque; RenderTarget *m_gbuffer; diff --git a/engine/includes/pipelinetasks/translucent.h b/engine/includes/pipelinetasks/translucent.h index 1750d6181..2be15779f 100644 --- a/engine/includes/pipelinetasks/translucent.h +++ b/engine/includes/pipelinetasks/translucent.h @@ -19,7 +19,7 @@ class Translucent : public PipelineTask { void setInput(int index, Texture *texture) override; private: - std::list m_translucent; + GroupList m_translucent; RenderTarget *m_translucentPass; diff --git a/engine/includes/resources/material.h b/engine/includes/resources/material.h index 1d95ebcee..6cd0fc40d 100644 --- a/engine/includes/resources/material.h +++ b/engine/includes/resources/material.h @@ -32,7 +32,7 @@ class ENGINE_EXPORT Material : public Resource { public: enum Layer { - Default = (1<<0), + Opaque = (1<<0), Translucent = (1<<1), Visibility = (1<<2), Shadowcast = (1<<3) @@ -203,6 +203,9 @@ class ENGINE_EXPORT Material : public Resource { bool wireframe() const; void setWireframe(bool wireframe); + int proprity() const; + void setPriority(int proprity); + int layers() const; virtual MaterialInstance *createInstance(SurfaceType type = SurfaceType::Static); @@ -247,12 +250,14 @@ class ENGINE_EXPORT Material : public Resource { uint32_t m_uniformSize; + uint32_t m_layers; + + uint32_t m_priority; + int32_t m_lightModel; int32_t m_materialType; - int32_t m_layers; - bool m_doubleSided; bool m_wireframe; @@ -285,24 +290,20 @@ class ENGINE_EXPORT MaterialInstance { void setTexture(const TString &name, Texture *texture); - Transform *transform(); void setTransform(Transform *transform); - void setTransform(const Matrix4 &transform); - uint32_t paramCount() const; - TString paramName(uint32_t index) const; - Variant paramValue(uint32_t index) const; + int32_t priority() const; + void setPriority(int32_t priority); uint16_t surfaceType() const; void setSurfaceType(uint16_t type); ByteArray &rawUniformBuffer(); - void batch(MaterialInstance &instance); - void resetBatches(); + void setInstanceBuffer(ByteArray *groups); - int hash() const; + uint32_t hash() const; protected: void setBufferValue(const TString &name, const void *value); @@ -315,10 +316,10 @@ class ENGINE_EXPORT MaterialInstance { friend class Material; std::unordered_map m_textureOverride; - std::map m_paramOverride; ByteArray m_uniformBuffer; - ByteArray m_batchBuffer; + + ByteArray *m_batchBuffer; Material *m_material; @@ -329,6 +330,7 @@ class ENGINE_EXPORT MaterialInstance { uint32_t m_hash; uint32_t m_transformHash; + uint32_t m_priority; uint16_t m_surfaceType; diff --git a/engine/src/components/meshrender.cpp b/engine/src/components/meshrender.cpp index 7f8844ad7..25b5f8060 100644 --- a/engine/src/components/meshrender.cpp +++ b/engine/src/components/meshrender.cpp @@ -112,12 +112,6 @@ void MeshRender::setMaterials(VariantList materials) { /*! \internal */ -void MeshRender::composeComponent() { - setMesh(PipelineContext::defaultCube()); -} -/*! - \internal -*/ void MeshRender::setProperty(const char *name, const Variant &value) { Renderable::setProperty(name, value); } diff --git a/engine/src/components/renderable.cpp b/engine/src/components/renderable.cpp index fa388d758..d3c12c5e8 100644 --- a/engine/src/components/renderable.cpp +++ b/engine/src/components/renderable.cpp @@ -56,13 +56,6 @@ Mesh *Renderable::meshToDraw(int instance) const { uint32_t Renderable::subMesh(int instance) const { return instance; } -/*! - Returns the prority value used to sort renadarble components before drawing. - Lower values are rendered first and higher are rendered last. -*/ -int Renderable::priority() const { - return 0; -} /*! Returns a first instantiated Material assigned to this Renderable. */ diff --git a/engine/src/components/spriterender.cpp b/engine/src/components/spriterender.cpp index dce9be018..1e0e80881 100644 --- a/engine/src/components/spriterender.cpp +++ b/engine/src/components/spriterender.cpp @@ -41,7 +41,7 @@ SpriteRender::SpriteRender() : m_customMesh(nullptr), m_hash(0), m_drawMode(Simple), - m_layer(0) { + m_priority(0) { } @@ -189,16 +189,20 @@ void SpriteRender::setDrawMode(int mode) { composeMesh(); } /*! - Returns the order layer for the sprite. + Returns the redering layer for the sprite. */ int SpriteRender::layer() const { - return m_layer; + return m_priority; } /*! - Sets the order \a layer for the sprite. + Sets the redering \a layer for the sprite. */ void SpriteRender::setLayer(int layer) { - m_layer = layer; + m_priority = layer; + + for(auto it : m_materials) { + it->setPriority(m_priority); + } } /*! \internal @@ -419,12 +423,6 @@ void SpriteRender::composeComponent() { /*! \internal */ -int SpriteRender::priority() const { - return m_layer; -} -/*! - \internal -*/ void SpriteRender::composeMesh(bool resetSize) { if(m_sheet) { Mesh *mesh = SpriteRender::composeMesh(m_sheet, m_hash, m_size, m_drawMode, resetSize); diff --git a/engine/src/components/tilemaprender.cpp b/engine/src/components/tilemaprender.cpp index b68112c43..a69dd2fa8 100644 --- a/engine/src/components/tilemaprender.cpp +++ b/engine/src/components/tilemaprender.cpp @@ -9,11 +9,11 @@ #include "resources/mesh.h" namespace { - const char *gTileMap = "TileMap"; - const char *gMaterial = "Material"; - const char *gColor = "mainColor"; - const char *gTexture = "mainTexture"; - const char *gDefaultSprite = ".embedded/DefaultSprite.shader"; + const char *gTileMap("TileMap"); + const char *gMaterial("Material"); + const char *gColor("mainColor"); + const char *gTexture("mainTexture"); + const char *gDefaultSprite(".embedded/DefaultSprite.shader"); } /*! @@ -27,7 +27,7 @@ namespace { TileMapRender::TileMapRender() : m_tileMap(nullptr), - m_layer(0) { + m_priority(0) { } @@ -108,16 +108,20 @@ void TileMapRender::setMaterial(Material *material) { } /*! - Returns the order layer for the tile map. + Returns the redering priority for the tile map. */ int TileMapRender::layer() const { - return m_layer; + return m_priority; } /*! - Sets the order \a layer for the tile map. + Sets the redering \a layer for the tile map. */ void TileMapRender::setLayer(int layer) { - m_layer = layer; + m_priority = layer; + + for(auto it : m_materials) { + it->setPriority(m_priority); + } } /*! \internal @@ -137,9 +141,3 @@ void TileMapRender::setMaterialsList(const std::list &materials) { void TileMapRender::composeComponent() { setMaterial(Engine::loadResource(gDefaultSprite)); } -/*! - \internal -*/ -int TileMapRender::priority() const { - return m_layer; -} diff --git a/engine/src/pipelinecontext.cpp b/engine/src/pipelinecontext.cpp index 1c3ffe238..baee026b7 100644 --- a/engine/src/pipelinecontext.cpp +++ b/engine/src/pipelinecontext.cpp @@ -96,7 +96,7 @@ void PipelineContext::draw(Camera *camera) { // Finish m_buffer->setRenderTarget(m_defaultTarget); - m_buffer->drawMesh(defaultPlane(), 0, Material::Default, *m_finalMaterial); + m_buffer->drawMesh(defaultPlane(), 0, Material::Opaque, *m_finalMaterial); for(auto it : m_postObservers) { (*it.first)(it.second); diff --git a/engine/src/pipelinetask.cpp b/engine/src/pipelinetask.cpp index 7f8a9729a..ae44e4556 100644 --- a/engine/src/pipelinetask.cpp +++ b/engine/src/pipelinetask.cpp @@ -124,52 +124,51 @@ bool PipelineTask::isEnabled() const { /*! Filters \a out an \a in renderable components by it's material \a layer. */ -void PipelineTask::filterByLayer(const RenderList &in, RenderList &out, int layer) const { +void PipelineTask::filterByLayer(const RenderList &in, GroupList &out, int layer) const { for(auto it : in) { for(int i = 0; i < it->materialsCount(); i++) { MaterialInstance *instance = it->materialInstance(i); if(instance && instance->material()->layers() & layer) { - if(instance->transform() == nullptr) { - instance->setTransform(it->transform()); - } + Mesh *mesh = it->meshToDraw(i); + if(mesh) { + it->meshToDraw(i); + + uint32_t hash = instance->hash(); + Mathf::hashCombine(hash, mesh->uuid()); - out.push_back(it); + out.push_back({instance, mesh, it->subMesh(i), hash}); + } } } } -} -void PipelineTask::filterAndGroup(const RenderList &in, std::list &out, int layer) { - uint32_t lastHash = 0; + out.sort([](const Group &left, const Group &right) { + int p1 = left.instance->priority(); + int p2 = right.instance->priority(); + if(p1 == p2) { + return left.hash < right.hash; + } + return p1 < p2; + }); +} +/*! + Groups elements from \a in list into \a out rendering instances. +*/ +void PipelineTask::group(const GroupList &in, GroupList &out) const { Group last; - for(auto it : in) { - for(int i = 0; i < it->materialsCount(); i++) { - MaterialInstance *instance = it->materialInstance(i); - if(instance && (layer == 0 || instance->material()->layers() & layer)) { - if(instance->transform() == nullptr) { - instance->setTransform(it->transform()); - } - - Mesh *mesh = it->meshToDraw(i); - if(mesh) { - uint32_t hash = instance->hash(); - Mathf::hashCombine(hash, mesh->uuid()); - - if(lastHash != hash || (last.instance != nullptr && last.instance->material() != instance->material())) { - if(last.instance != nullptr) { - out.push_back(last); - } - - lastHash = hash; - last.mesh = mesh; - last.instance = instance; - last.subMesh = it->subMesh(i); - } else if(last.instance != nullptr) { - last.instance->batch(*instance); - } - } + for(auto &it : in) { + if(last.hash != it.hash || (last.instance != nullptr && last.instance->material() != it.instance->material())) { + if(last.instance != nullptr) { + out.push_back(last); } + + last = it; + auto &buffer = it.instance->rawUniformBuffer(); + last.buffer.insert(last.buffer.begin(), buffer.begin(), buffer.end()); + } else { + auto &buffer = it.instance->rawUniformBuffer(); + last.buffer.insert(last.buffer.end(), buffer.begin(), buffer.end()); } } diff --git a/engine/src/pipelinetasks/ambientocclusion.cpp b/engine/src/pipelinetasks/ambientocclusion.cpp index 785d68897..a5b2ae092 100644 --- a/engine/src/pipelinetasks/ambientocclusion.cpp +++ b/engine/src/pipelinetasks/ambientocclusion.cpp @@ -165,14 +165,14 @@ void AmbientOcclusion::exec() { buffer->setViewport(0, 0, m_aoTexture->width(), m_aoTexture->height()); buffer->setRenderTarget(m_aoTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_occlusion); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Opaque, *m_occlusion); } if(m_blur) { buffer->setViewport(0, 0, m_blurTexture->width(), m_blurTexture->height()); buffer->setRenderTarget(m_blurTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_blur); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Opaque, *m_blur); } buffer->endDebugMarker(); diff --git a/engine/src/pipelinetasks/antialiasing.cpp b/engine/src/pipelinetasks/antialiasing.cpp index dd344c82b..b9afb5198 100644 --- a/engine/src/pipelinetasks/antialiasing.cpp +++ b/engine/src/pipelinetasks/antialiasing.cpp @@ -46,7 +46,7 @@ void AntiAliasing::exec() { buffer->beginDebugMarker("AntiAliasing"); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_resultMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Opaque, *m_resultMaterial); buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/bloom.cpp b/engine/src/pipelinetasks/bloom.cpp index 1ce9e6f59..5ab4a0db5 100644 --- a/engine/src/pipelinetasks/bloom.cpp +++ b/engine/src/pipelinetasks/bloom.cpp @@ -118,10 +118,10 @@ void Bloom::exec() { for(uint8_t i = 0; i < BLOOM_PASSES; i++) { buffer->setRenderTarget(m_blurTempTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_bloomPasses[i].blurMaterialH); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Opaque, *m_bloomPasses[i].blurMaterialH); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_bloomPasses[i].blurMaterialV); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Opaque, *m_bloomPasses[i].blurMaterialV); } buffer->endDebugMarker(); diff --git a/engine/src/pipelinetasks/depthoffield.cpp b/engine/src/pipelinetasks/depthoffield.cpp index bd3179a7e..6f490da04 100644 --- a/engine/src/pipelinetasks/depthoffield.cpp +++ b/engine/src/pipelinetasks/depthoffield.cpp @@ -140,7 +140,7 @@ void DepthOfField::exec() { buffer->beginDebugMarker("DepthOfField"); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_dofMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Opaque, *m_dofMaterial); buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/downsample.cpp b/engine/src/pipelinetasks/downsample.cpp index 0121f2bbf..861ad7042 100644 --- a/engine/src/pipelinetasks/downsample.cpp +++ b/engine/src/pipelinetasks/downsample.cpp @@ -68,7 +68,7 @@ void Downsample::exec() { buffer->setRenderTarget(m_downPasses[i].downTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_downPasses[i].downMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Opaque, *m_downPasses[i].downMaterial); } buffer->setViewport(0, 0, m_width, m_height); diff --git a/engine/src/pipelinetasks/gbuffer.cpp b/engine/src/pipelinetasks/gbuffer.cpp index 372970a20..2bc26cdc1 100644 --- a/engine/src/pipelinetasks/gbuffer.cpp +++ b/engine/src/pipelinetasks/gbuffer.cpp @@ -66,15 +66,17 @@ void GBuffer::exec() { buffer->setRenderTarget(m_gbuffer); for(auto &it : m_opaque) { - buffer->drawMesh(it.mesh, it.subMesh, Material::Default, *it.instance); - it.instance->resetBatches(); + it.instance->setInstanceBuffer(&it.buffer); + buffer->drawMesh(it.mesh, it.subMesh, Material::Opaque, *it.instance); } buffer->endDebugMarker(); } void GBuffer::analyze(World *world) { - m_opaque.clear(); + GroupList list; + filterByLayer(m_context->culledRenderables(), list, Material::Opaque); - filterAndGroup(m_context->culledRenderables(), m_opaque, Material::Default); + m_opaque.clear(); + group(list, m_opaque); } diff --git a/engine/src/pipelinetasks/indirect.cpp b/engine/src/pipelinetasks/indirect.cpp index 213bb1be7..9b1562619 100644 --- a/engine/src/pipelinetasks/indirect.cpp +++ b/engine/src/pipelinetasks/indirect.cpp @@ -92,7 +92,7 @@ void DeferredIndirect::exec() { buffer->beginDebugMarker("ReflectionIndirect"); if(m_iblMaterial) { buffer->setRenderTarget(m_iblTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_iblMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Opaque, *m_iblMaterial); } buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/reflections.cpp b/engine/src/pipelinetasks/reflections.cpp index 96cd203ec..62d097a43 100644 --- a/engine/src/pipelinetasks/reflections.cpp +++ b/engine/src/pipelinetasks/reflections.cpp @@ -46,7 +46,7 @@ void Reflections::exec() { buffer->beginDebugMarker("ScreenReflections"); buffer->setRenderTarget(m_sslrTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_sslrMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Opaque, *m_sslrMaterial); buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/shadowmap.cpp b/engine/src/pipelinetasks/shadowmap.cpp index ae1fae365..00f64b9ad 100644 --- a/engine/src/pipelinetasks/shadowmap.cpp +++ b/engine/src/pipelinetasks/shadowmap.cpp @@ -129,16 +129,19 @@ void ShadowMap::areaLightUpdate(AreaLight *light, const RenderList &components) RenderList culled; m_context->frustumCulling(frustum, components, culled); - std::list groups; - filterAndGroup(culled, groups, Material::Shadowcast); + GroupList list; + filterByLayer(culled, list, Material::Shadowcast); + GroupList groups; + group(list, groups); if(!groups.empty()) { buffer->setViewProjection(mat, crop); buffer->setViewport(x[i], y[i], w[i], h[i]); for(auto &it : groups) { + it.instance->setInstanceBuffer(&it.buffer); buffer->drawMesh(it.mesh, it.subMesh, Material::Shadowcast, *it.instance); - it.instance->resetBatches(); + it.instance->setInstanceBuffer(nullptr); } } } @@ -231,16 +234,20 @@ void ShadowMap::directLightUpdate(DirectLight *light, const RenderList &componen static_cast(w[lod]) / pageSize, static_cast(h[lod]) / pageSize); - std::list groups; - filterAndGroup(culled, groups, Material::Shadowcast); + GroupList list; + filterByLayer(culled, list, Material::Shadowcast); + GroupList groups; + group(list, groups); + if(!groups.empty()) { buffer->setViewProjection(view, crop); buffer->setViewport(x[lod], y[lod], w[lod], h[lod]); // Draw in the depth buffer from position of the light source for(auto &it : groups) { + it.instance->setInstanceBuffer(&it.buffer); buffer->drawMesh(it.mesh, it.subMesh, Material::Shadowcast, *it.instance); - it.instance->resetBatches(); + it.instance->setInstanceBuffer(nullptr); } } } @@ -297,8 +304,10 @@ void ShadowMap::pointLightUpdate(PointLight *light, const RenderList &components RenderList culled; m_context->frustumCulling(Camera::frustum(false, 90.0f, 1.0f, position, m_directions[i], zNear, zFar), components, culled); - std::list groups; - filterAndGroup(culled, groups, Material::Shadowcast); + GroupList list; + filterByLayer(culled, list, Material::Shadowcast); + GroupList groups; + group(list, groups); if(!groups.empty()) { buffer->setViewProjection(mat, crop); @@ -306,8 +315,9 @@ void ShadowMap::pointLightUpdate(PointLight *light, const RenderList &components // Draw in the depth buffer from position of the light source for(auto &it : groups) { + it.instance->setInstanceBuffer(&it.buffer); buffer->drawMesh(it.mesh, it.subMesh, Material::Shadowcast, *it.instance); - it.instance->resetBatches(); + it.instance->setInstanceBuffer(nullptr); } } } @@ -346,8 +356,10 @@ void ShadowMap::spotLightUpdate(SpotLight *light, const RenderList &components) RenderList culled; m_context->frustumCulling(Camera::frustum(false, light->outerAngle() * 2.0f, 1.0f, position, q, zNear, zFar), components, culled); - std::list groups; - filterAndGroup(culled, groups, Material::Shadowcast); + GroupList list; + filterByLayer(culled, list, Material::Shadowcast); + GroupList groups; + group(list, groups); if(!groups.empty()) { buffer->setRenderTarget(shadowTarget); @@ -357,8 +369,9 @@ void ShadowMap::spotLightUpdate(SpotLight *light, const RenderList &components) // Draw in the depth buffer from position of the light source for(auto &it : groups) { + it.instance->setInstanceBuffer(&it.buffer); buffer->drawMesh(it.mesh, it.subMesh, Material::Shadowcast, *it.instance); - it.instance->resetBatches(); + it.instance->setInstanceBuffer(nullptr); } } diff --git a/engine/src/pipelinetasks/tonemap.cpp b/engine/src/pipelinetasks/tonemap.cpp index 01ece4e94..79181d74d 100644 --- a/engine/src/pipelinetasks/tonemap.cpp +++ b/engine/src/pipelinetasks/tonemap.cpp @@ -89,7 +89,7 @@ void Tonemap::exec() { buffer->beginDebugMarker(gTonemap); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Default, *m_resultMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, Material::Opaque, *m_resultMaterial); buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/translucent.cpp b/engine/src/pipelinetasks/translucent.cpp index 7f1a85374..626933cf2 100644 --- a/engine/src/pipelinetasks/translucent.cpp +++ b/engine/src/pipelinetasks/translucent.cpp @@ -28,8 +28,9 @@ void Translucent::exec() { buffer->setRenderTarget(m_translucentPass); for(auto &it : m_translucent) { + it.instance->setInstanceBuffer(&it.buffer); buffer->drawMesh(it.mesh, it.subMesh, Material::Translucent, *it.instance); - it.instance->resetBatches(); + it.instance->setInstanceBuffer(nullptr); } buffer->endDebugMarker(); @@ -50,22 +51,9 @@ void Translucent::setInput(int index, Texture *texture) { } void Translucent::analyze(World *world) { - RenderList translucent; - - filterByLayer(m_context->culledRenderables(), translucent, Material::Translucent); - - Vector3 cameraWP(Camera::current()->transform()->worldPosition()); - - translucent.sort([cameraWP](const Renderable *left, const Renderable *right) { - int p1 = left->priority(); - int p2 = right->priority(); - if(p1 == p2) { - return cameraWP.dot(left->transform()->worldPosition()) < cameraWP.dot(right->transform()->worldPosition()); - } - return p1 < p2; - }); + GroupList list; + filterByLayer(m_context->culledRenderables(), list, Material::Translucent); m_translucent.clear(); - - filterAndGroup(translucent, m_translucent, 0); + group(list, m_translucent); } diff --git a/engine/src/resources/material.cpp b/engine/src/resources/material.cpp index 3af415522..d533329d6 100644 --- a/engine/src/resources/material.cpp +++ b/engine/src/resources/material.cpp @@ -27,11 +27,13 @@ namespace { MaterialInstance::MaterialInstance(Material *material) : m_material(material), + m_batchBuffer(nullptr), m_transform(nullptr), m_instanceCount(1), m_batchesCount(0), m_hash(material->uuid()), m_transformHash(0), + m_priority(0), m_surfaceType(0) { } @@ -103,16 +105,6 @@ uint32_t MaterialInstance::instanceSize() const { Parameter \a count a number of elements in the array. */ void MaterialInstance::setBool(const TString &name, const bool *value, int32_t count) { - if(count > 1) { - VariantList list; - for(int32_t i = 0; i < count; i++) { - list.push_back(value[i]); - } - m_paramOverride[name] = list; - } else { - m_paramOverride[name] = *value; - } - setBufferValue(name, value); } /*! @@ -122,16 +114,6 @@ void MaterialInstance::setBool(const TString &name, const bool *value, int32_t c Parameter \a count a number of elements in the array. */ void MaterialInstance::setInteger(const TString &name, const int32_t *value, int32_t count) { - if(count > 1) { - VariantList list; - for(int32_t i = 0; i < count; i++) { - list.push_back(value[i]); - } - m_paramOverride[name] = list; - } else { - m_paramOverride[name] = *value; - } - setBufferValue(name, value); } /*! @@ -141,16 +123,6 @@ void MaterialInstance::setInteger(const TString &name, const int32_t *value, int Parameter \a count a number of elements in the array. */ void MaterialInstance::setFloat(const TString &name, const float *value, int32_t count) { - if(count > 1) { - VariantList list; - for(int32_t i = 0; i < count; i++) { - list.push_back(value[i]); - } - m_paramOverride[name] = list; - } else { - m_paramOverride[name] = *value; - } - setBufferValue(name, value); } /*! @@ -160,16 +132,6 @@ void MaterialInstance::setFloat(const TString &name, const float *value, int32_t Parameter \a count a number of elements in the array. */ void MaterialInstance::setVector2(const TString &name, const Vector2 *value, int32_t count) { - if(count > 1) { - VariantList list; - for(int32_t i = 0; i < count; i++) { - list.push_back(value[i]); - } - m_paramOverride[name] = list; - } else { - m_paramOverride[name] = *value; - } - setBufferValue(name, value); } /*! @@ -179,16 +141,6 @@ void MaterialInstance::setVector2(const TString &name, const Vector2 *value, int Parameter \a count a number of elements in the array. */ void MaterialInstance::setVector3(const TString &name, const Vector3 *value, int32_t count) { - if(count > 1) { - VariantList list; - for(int32_t i = 0; i < count; i++) { - list.push_back(value[i]); - } - m_paramOverride[name] = list; - } else { - m_paramOverride[name] = *value; - } - setBufferValue(name, value); } /*! @@ -198,16 +150,6 @@ void MaterialInstance::setVector3(const TString &name, const Vector3 *value, int Parameter \a count a number of elements in the array. */ void MaterialInstance::setVector4(const TString &name, const Vector4 *value, int32_t count) { - if(count > 1) { - VariantList list; - for(int32_t i = 0; i < count; i++) { - list.push_back(value[i]); - } - m_paramOverride[name] = list; - } else { - m_paramOverride[name] = *value; - } - setBufferValue(name, value); } /*! @@ -217,24 +159,8 @@ void MaterialInstance::setVector4(const TString &name, const Vector4 *value, int Parameter \a count a number of elements in the array. */ void MaterialInstance::setMatrix4(const TString &name, const Matrix4 *value, int32_t count) { - if(count > 1) { - VariantList list; - for(int32_t i = 0; i < count; i++) { - list.push_back(value[i]); - } - m_paramOverride[name] = list; - } else { - m_paramOverride[name] = *value; - } - setBufferValue(name, value); } -/*! - Returns the a transform component. -*/ -Transform *MaterialInstance::transform() { - return m_transform; -} /*! Sets the \a transform component to track it. */ @@ -287,34 +213,6 @@ void MaterialInstance::setTexture(const TString &name, Texture *texture) { } } } -/*! - Gets the total count of parameters in the material. -*/ -uint32_t MaterialInstance::paramCount() const { - return m_material->m_uniforms.size(); -} -/*! - Gets the name of a parameter by \a index. -*/ -TString MaterialInstance::paramName(uint32_t index) const { - if(index < m_material->m_uniforms.size()) { - return m_material->m_uniforms[index].name; - } - return std::string(); -} -/*! - Gets the overridden or default value of a parameter by \a index. -*/ -Variant MaterialInstance::paramValue(uint32_t index) const { - if(index < m_material->m_uniforms.size()) { - auto it = m_paramOverride.find(m_material->m_uniforms[index].name); - if(it != m_paramOverride.end()) { - return it->second; - } - return m_material->m_uniforms[index].defaultValue; - } - return Variant(); -} /*! Gets the surface type associated with the material instance. */ @@ -351,31 +249,34 @@ ByteArray &MaterialInstance::rawUniformBuffer() { return m_uniformBuffer; } /*! - Batches a material \a instance to draw using GPU instancing. + Rests batch buffer. */ -void MaterialInstance::batch(MaterialInstance &instance) { - if(m_batchBuffer.empty()) { - ByteArray &buffer = rawUniformBuffer(); - m_batchBuffer.insert(m_batchBuffer.begin(), buffer.begin(), buffer.end()); +void MaterialInstance::setInstanceBuffer(ByteArray *groups) { + m_batchBuffer = groups; + if(m_batchBuffer) { + m_batchesCount = m_batchBuffer->size() / m_material->m_uniformSize; + } else { + m_batchesCount = 0; } - - ByteArray &buffer = instance.rawUniformBuffer(); - m_batchBuffer.insert(m_batchBuffer.end(), buffer.begin(), buffer.end()); - - m_batchesCount += instance.m_instanceCount; } /*! - Rests batch buffer. + \internal */ -void MaterialInstance::resetBatches() { - m_batchBuffer.clear(); - m_batchesCount = 0; +uint32_t MaterialInstance::hash() const { + return static_cast(m_hash); } /*! - \internal + Returns a meterial instance priority used for sorting of rendering queue. + Calculated as Material::priority + priority */ -int MaterialInstance::hash() const { - return static_cast(m_hash); +int32_t MaterialInstance::priority() const { + return m_material->m_priority + m_priority; +} +/*! + Sets the instance \a priority. +*/ +void MaterialInstance::setPriority(int32_t priority) { + m_priority = priority; } /*! \class Material @@ -385,9 +286,10 @@ int MaterialInstance::hash() const { Material::Material() : m_uniformSize(0), + m_layers(0), + m_priority(0), m_lightModel(Unlit), m_materialType(Surface), - m_layers(0), m_doubleSided(true), m_wireframe(false) { @@ -454,6 +356,20 @@ void Material::setWireframe(bool wireframe) { int Material::layers() const { return m_layers; } +/*! + Returns a rendering priority for the material. + This parameter is used alpha rendering sorting +*/ +int Material::proprity() const { + return m_priority; +} +/*! + Sets a \a rendering priority for the material. + This parameter is used alpha rendering sorting +*/ +void Material::setPriority(int proprity) { + m_priority = proprity; +} /*! \internal */ @@ -487,8 +403,10 @@ void Material::loadUserData(const VariantMap &data) { if(m_blendState.enabled) { m_layers |= Material::Translucent; + m_priority = 3000; } else { - m_layers |= Material::Default; + m_layers |= Material::Opaque; + m_priority = 2000; } } { diff --git a/modules/editor/texturetools/editor/spriteedit.cpp b/modules/editor/texturetools/editor/spriteedit.cpp index c2fae645a..ac3bcbfe3 100644 --- a/modules/editor/texturetools/editor/spriteedit.cpp +++ b/modules/editor/texturetools/editor/spriteedit.cpp @@ -53,6 +53,7 @@ SpriteEdit::SpriteEdit() : Actor *object = Engine::composeActor(gSpriteRender, gSpriteRender, m_scene); m_render = object->getComponent(); + m_render->setMaterial(Engine::loadResource(".embedded/DefaultSprite.shader")); m_render->setLayer(2); object = Engine::composeActor(gSpriteRender, "CheckerBoard", m_scene); diff --git a/modules/renders/rendergl/src/resources/materialgl.cpp b/modules/renders/rendergl/src/resources/materialgl.cpp index 085a0ea85..876e4bd02 100644 --- a/modules/renders/rendergl/src/resources/materialgl.cpp +++ b/modules/renders/rendergl/src/resources/materialgl.cpp @@ -41,7 +41,7 @@ void MaterialGL::loadUserData(const VariantMap &data) { if(pair.second == FragmentVisibility) { m_layers |= Material::Visibility; - if(m_layers & Default) { + if(m_layers & Opaque) { m_layers |= Material::Shadowcast; } } @@ -378,7 +378,7 @@ bool MaterialInstanceGL::bind(CommandBufferGL *buffer, uint32_t layer, uint32_t uint32_t offset = index * gMaxUBO; - ByteArray &gpuBuffer = m_batchBuffer.empty() ? rawUniformBuffer() : m_batchBuffer; + ByteArray &gpuBuffer = m_batchBuffer ? *m_batchBuffer : rawUniformBuffer(); int gpuBufferSize = MIN(gpuBuffer.size() - offset, gMaxUBO); #ifdef THUNDER_MOBILE diff --git a/modules/renders/rendermt/src/resources/materialmt.cpp b/modules/renders/rendermt/src/resources/materialmt.cpp index a4f45e597..eb59e1d18 100644 --- a/modules/renders/rendermt/src/resources/materialmt.cpp +++ b/modules/renders/rendermt/src/resources/materialmt.cpp @@ -398,7 +398,7 @@ bool MaterialInstanceMt::bind(CommandBufferMt &buffer, uint32_t layer, const Glo // Instance buffer { - ByteArray &localBuffer = m_batchBuffer.empty() ? rawUniformBuffer() : m_batchBuffer; + ByteArray &localBuffer = m_batchBuffer ? *m_batchBuffer : rawUniformBuffer(); if(m_instanceBuffer == nullptr || m_instanceBuffer->length() < localBuffer.size()) { if(m_instanceBuffer) { diff --git a/modules/renders/rendervk/src/resources/materialvk.cpp b/modules/renders/rendervk/src/resources/materialvk.cpp index 07685c3f2..666b8e399 100644 --- a/modules/renders/rendervk/src/resources/materialvk.cpp +++ b/modules/renders/rendervk/src/resources/materialvk.cpp @@ -482,7 +482,7 @@ bool MaterialInstanceVk::bind(CommandBufferVk &buffer, uint32_t layer, const Glo if(materialVk->bind(cmd, buffer.currentRenderTarget(), layer, surfaceType())) { VkDeviceSize globalSize = sizeof(global); - ByteArray &localBuffer = m_batchBuffer.empty() ? rawUniformBuffer() : m_batchBuffer; + ByteArray &localBuffer = m_batchBuffer ? *m_batchBuffer : rawUniformBuffer(); VkDevice device = WrapperVk::device(); diff --git a/worldeditor/src/screens/scenecomposer/objectcontroller.cpp b/worldeditor/src/screens/scenecomposer/objectcontroller.cpp index 989d916fe..96bc1fb19 100644 --- a/worldeditor/src/screens/scenecomposer/objectcontroller.cpp +++ b/worldeditor/src/screens/scenecomposer/objectcontroller.cpp @@ -86,11 +86,11 @@ class ViewportRaycast : public PipelineTask { } } - std::list groups; - filterAndGroup(filtered, groups, Material::Visibility); + GroupList groups; + filterByLayer(filtered, groups, Material::Visibility); + for(auto &it : groups) { buffer->drawMesh(it.mesh, it.subMesh, Material::Visibility, *it.instance); - it.instance->resetBatches(); } Camera *activeCamera = m_controller->activeCamera(); From 2f0c09e95a34ff7d7d0f33d2223eeca8a3ece835 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Tue, 5 Aug 2025 20:10:27 +0300 Subject: [PATCH 4/4] update --- engine/includes/resources/material.h | 2 +- engine/src/resources/material.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/includes/resources/material.h b/engine/includes/resources/material.h index 6cd0fc40d..c227ca7d2 100644 --- a/engine/includes/resources/material.h +++ b/engine/includes/resources/material.h @@ -301,7 +301,7 @@ class ENGINE_EXPORT MaterialInstance { ByteArray &rawUniformBuffer(); - void setInstanceBuffer(ByteArray *groups); + void setInstanceBuffer(ByteArray *buffer); uint32_t hash() const; diff --git a/engine/src/resources/material.cpp b/engine/src/resources/material.cpp index d533329d6..84b338466 100644 --- a/engine/src/resources/material.cpp +++ b/engine/src/resources/material.cpp @@ -249,10 +249,10 @@ ByteArray &MaterialInstance::rawUniformBuffer() { return m_uniformBuffer; } /*! - Rests batch buffer. + Sets instances \a buffer. */ -void MaterialInstance::setInstanceBuffer(ByteArray *groups) { - m_batchBuffer = groups; +void MaterialInstance::setInstanceBuffer(ByteArray *buffer) { + m_batchBuffer = buffer; if(m_batchBuffer) { m_batchesCount = m_batchBuffer->size() / m_material->m_uniformSize; } else {