From 52a4a590e1288226dea6f9ed5d8c36c8462f8c52 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 22 Apr 2017 17:13:51 +0200 Subject: [PATCH] Graphics/Material: Fix depth sorting flag handling for meshes --- .../NDK/Components/CameraComponent.hpp | 2 +- .../NDK/Components/CameraComponent.inl | 10 -- SDK/src/NDK/Components/CameraComponent.cpp | 11 ++ .../Nazara/Graphics/AbstractRenderQueue.hpp | 2 +- include/Nazara/Graphics/AbstractViewer.hpp | 1 + .../Nazara/Graphics/DeferredRenderQueue.hpp | 2 +- include/Nazara/Graphics/DepthRenderQueue.hpp | 2 +- .../Nazara/Graphics/ForwardRenderQueue.hpp | 16 +- src/Nazara/Graphics/DeferredRenderQueue.cpp | 6 +- src/Nazara/Graphics/DepthRenderQueue.cpp | 2 +- src/Nazara/Graphics/ForwardRenderQueue.cpp | 139 +++++++++++------- .../Graphics/ForwardRenderTechnique.cpp | 10 +- src/Nazara/Graphics/MaterialPipeline.cpp | 2 + 13 files changed, 122 insertions(+), 83 deletions(-) diff --git a/SDK/include/NDK/Components/CameraComponent.hpp b/SDK/include/NDK/Components/CameraComponent.hpp index 04859b1de..f4a29f2e4 100644 --- a/SDK/include/NDK/Components/CameraComponent.hpp +++ b/SDK/include/NDK/Components/CameraComponent.hpp @@ -44,7 +44,7 @@ namespace Ndk const Nz::Frustumf& GetFrustum() const override; inline unsigned int GetLayer() const; const Nz::Matrix4f& GetProjectionMatrix() const override; - inline Nz::ProjectionType GetProjectionType() const; + Nz::ProjectionType GetProjectionType() const override; inline const Nz::Vector2f& GetSize() const; const Nz::RenderTarget* GetTarget() const override; inline const Nz::Rectf& GetTargetRegion() const; diff --git a/SDK/include/NDK/Components/CameraComponent.inl b/SDK/include/NDK/Components/CameraComponent.inl index 33c63bfe3..1018f9f3d 100644 --- a/SDK/include/NDK/Components/CameraComponent.inl +++ b/SDK/include/NDK/Components/CameraComponent.inl @@ -117,16 +117,6 @@ namespace Ndk return m_layer; } - /*! - * \brief Gets the projection type of the camera - * \return Projection type of the camera - */ - - inline Nz::ProjectionType CameraComponent::GetProjectionType() const - { - return m_projectionType; - } - /*! * \brief Gets the size of the camera * \return Size of the camera diff --git a/SDK/src/NDK/Components/CameraComponent.cpp b/SDK/src/NDK/Components/CameraComponent.cpp index 13b6bdd2b..2441dd7a8 100644 --- a/SDK/src/NDK/Components/CameraComponent.cpp +++ b/SDK/src/NDK/Components/CameraComponent.cpp @@ -93,6 +93,17 @@ namespace Ndk return m_projectionMatrix; } + + /*! + * \brief Gets the projection type of the camera + * \return Projection type of the camera + */ + Nz::ProjectionType CameraComponent::GetProjectionType() const + { + return m_projectionType; + } + + /*! * \brief Gets the target of the camera * \return A constant reference to the render target of the camera diff --git a/include/Nazara/Graphics/AbstractRenderQueue.hpp b/include/Nazara/Graphics/AbstractRenderQueue.hpp index f0074cd50..0e3b94f2f 100644 --- a/include/Nazara/Graphics/AbstractRenderQueue.hpp +++ b/include/Nazara/Graphics/AbstractRenderQueue.hpp @@ -51,7 +51,7 @@ namespace Nz virtual void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) = 0; virtual void AddPointLight(const PointLight& light); virtual void AddSpotLight(const SpotLight& light); - virtual void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay = nullptr) = 0; + virtual void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay = nullptr) = 0; virtual void Clear(bool fully = false); diff --git a/include/Nazara/Graphics/AbstractViewer.hpp b/include/Nazara/Graphics/AbstractViewer.hpp index 9bef56373..21a62a890 100644 --- a/include/Nazara/Graphics/AbstractViewer.hpp +++ b/include/Nazara/Graphics/AbstractViewer.hpp @@ -33,6 +33,7 @@ namespace Nz virtual Vector3f GetForward() const = 0; virtual const Frustumf& GetFrustum() const = 0; virtual const Matrix4f& GetProjectionMatrix() const = 0; + virtual Nz::ProjectionType GetProjectionType() const = 0; virtual const RenderTarget* GetTarget() const = 0; virtual const Matrix4f& GetViewMatrix() const = 0; virtual const Recti& GetViewport() const = 0; diff --git a/include/Nazara/Graphics/DeferredRenderQueue.hpp b/include/Nazara/Graphics/DeferredRenderQueue.hpp index 982469873..5f9f7538e 100644 --- a/include/Nazara/Graphics/DeferredRenderQueue.hpp +++ b/include/Nazara/Graphics/DeferredRenderQueue.hpp @@ -37,7 +37,7 @@ namespace Nz void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr anglePtr, SparsePtr alphaPtr) override; void AddDrawable(int renderOrder, const Drawable* drawable) override; void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override; - void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay = nullptr) override; + void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay = nullptr) override; void Clear(bool fully = false) override; diff --git a/include/Nazara/Graphics/DepthRenderQueue.hpp b/include/Nazara/Graphics/DepthRenderQueue.hpp index ed7c9f3c3..871cefa66 100644 --- a/include/Nazara/Graphics/DepthRenderQueue.hpp +++ b/include/Nazara/Graphics/DepthRenderQueue.hpp @@ -38,7 +38,7 @@ namespace Nz void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override; void AddPointLight(const PointLight& light) override; void AddSpotLight(const SpotLight& light) override; - void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay = nullptr) override; + void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay = nullptr) override; private: inline bool IsMaterialSuitable(const Material* material) const; diff --git a/include/Nazara/Graphics/ForwardRenderQueue.hpp b/include/Nazara/Graphics/ForwardRenderQueue.hpp index 218fd312d..b081641c1 100644 --- a/include/Nazara/Graphics/ForwardRenderQueue.hpp +++ b/include/Nazara/Graphics/ForwardRenderQueue.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,7 @@ namespace Nz void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr positionPtr, SparsePtr sizePtr, SparsePtr anglePtr, SparsePtr alphaPtr) override; void AddDrawable(int renderOrder, const Drawable* drawable) override; void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override; - void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay = nullptr) override; + void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay = nullptr) override; void Clear(bool fully = false) override; @@ -156,7 +157,7 @@ namespace Nz { Matrix4f transformMatrix; MeshData meshData; - Spheref squaredBoundingSphere; + Spheref obbSphere; const Material* material; }; @@ -165,10 +166,11 @@ namespace Nz struct Layer { BillboardPipelineBatches billboards; - SpritePipelineBatches basicSprites; + SpritePipelineBatches opaqueSprites; + SpritePipelineBatches depthSortedSprites; MeshPipelineBatches opaqueModels; - TransparentModelContainer transparentModels; - std::vector transparentModelData; + TransparentModelContainer depthSortedMeshes; + std::vector depthSortedMeshData; std::vector otherDrawables; unsigned int clearCount = 0; }; @@ -179,6 +181,10 @@ namespace Nz BillboardData* GetBillboardData(int renderOrder, const Material* material, unsigned int count); Layer& GetLayer(int i); ///TODO: Inline + void SortBillboards(Layer& layer, const Planef& nearPlane); + void SortForOrthographic(const AbstractViewer* viewer); + void SortForPerspective(const AbstractViewer* viewer); + void OnIndexBufferInvalidation(const IndexBuffer* indexBuffer); void OnMaterialInvalidation(const Material* material); void OnTextureInvalidation(const Texture* texture); diff --git a/src/Nazara/Graphics/DeferredRenderQueue.cpp b/src/Nazara/Graphics/DeferredRenderQueue.cpp index 22ead6ec0..a0455fe11 100644 --- a/src/Nazara/Graphics/DeferredRenderQueue.cpp +++ b/src/Nazara/Graphics/DeferredRenderQueue.cpp @@ -191,8 +191,8 @@ namespace Nz void DeferredRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) { - if (material->IsBlendingEnabled()) - // One transparent material ? I don't like it, go see if I'm in the forward queue + if (material->IsBlendingEnabled() || material->IsDepthSortingEnabled()) //< Fixme: Deferred Shading should be able to handle depth sorting + // Deferred Shading cannot handle blended objects, put them in the forward list m_forwardQueue->AddMesh(renderOrder, material, meshData, meshAABB, transformMatrix); else { @@ -254,7 +254,7 @@ namespace Nz * \param overlay Texture of the sprites */ - void DeferredRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay) + void DeferredRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay) { m_forwardQueue->AddSprites(renderOrder, material, vertices, spriteCount, overlay); } diff --git a/src/Nazara/Graphics/DepthRenderQueue.cpp b/src/Nazara/Graphics/DepthRenderQueue.cpp index 46096e33f..a2acdf4bb 100644 --- a/src/Nazara/Graphics/DepthRenderQueue.cpp +++ b/src/Nazara/Graphics/DepthRenderQueue.cpp @@ -351,7 +351,7 @@ namespace Nz * \remark Produces a NazaraAssert if material is invalid */ - void DepthRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay) + void DepthRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay) { NazaraAssert(material, "Invalid material"); NazaraUnused(renderOrder); diff --git a/src/Nazara/Graphics/ForwardRenderQueue.cpp b/src/Nazara/Graphics/ForwardRenderQueue.cpp index 8eb70fe7e..c594157b9 100644 --- a/src/Nazara/Graphics/ForwardRenderQueue.cpp +++ b/src/Nazara/Graphics/ForwardRenderQueue.cpp @@ -376,23 +376,23 @@ namespace Nz { NazaraAssert(material, "Invalid material"); - if (material->IsBlendingEnabled()) + if (material->IsDepthSortingEnabled()) { Layer& currentLayer = GetLayer(renderOrder); - auto& transparentModels = currentLayer.transparentModels; - auto& transparentModelData = currentLayer.transparentModelData; + auto& transparentMeshes = currentLayer.depthSortedMeshes; + auto& transparentData = currentLayer.depthSortedMeshData; - // The material is transparent, we must draw this mesh using another way (after the rendering of opages objects while sorting them) - std::size_t index = transparentModelData.size(); - transparentModelData.resize(index+1); + // The material is marked for depth sorting, we must draw this mesh using another way (after the rendering of opaques objects while sorting them) + std::size_t index = transparentData.size(); + transparentData.resize(index+1); - TransparentModelData& data = transparentModelData.back(); + TransparentModelData& data = transparentData.back(); data.material = material; data.meshData = meshData; - data.squaredBoundingSphere = Spheref(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius()); + data.obbSphere = Spheref(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius()); data.transformMatrix = transformMatrix; - transparentModels.push_back(index); + transparentMeshes.push_back(index); } else { @@ -457,12 +457,12 @@ namespace Nz * * \remark Produces a NazaraAssert if material is invalid */ - void ForwardRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay) + void ForwardRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay) { NazaraAssert(material, "Invalid material"); Layer& currentLayer = GetLayer(renderOrder); - SpritePipelineBatches& basicSprites = currentLayer.basicSprites; + SpritePipelineBatches& basicSprites = currentLayer.opaqueSprites; const MaterialPipeline* materialPipeline = material->GetPipeline(); @@ -545,7 +545,7 @@ namespace Nz pipelineEntry.enabled = false; } - for (auto& pipelinePair : layer.basicSprites) + for (auto& pipelinePair : layer.opaqueSprites) { auto& pipelineEntry = pipelinePair.second; @@ -597,8 +597,8 @@ namespace Nz } layer.otherDrawables.clear(); - layer.transparentModels.clear(); - layer.transparentModelData.clear(); + layer.depthSortedMeshes.clear(); + layer.depthSortedMeshData.clear(); ++it; } } @@ -613,44 +613,10 @@ namespace Nz void ForwardRenderQueue::Sort(const AbstractViewer* viewer) { - Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near); - Vector3f viewerPos = viewer->GetEyePosition(); - Vector3f viewerNormal = viewer->GetForward(); - - for (auto& pair : layers) - { - Layer& layer = pair.second; - - std::sort(layer.transparentModels.begin(), layer.transparentModels.end(), [&layer, &nearPlane, &viewerNormal] (std::size_t index1, std::size_t index2) - { - const Spheref& sphere1 = layer.transparentModelData[index1].squaredBoundingSphere; - const Spheref& sphere2 = layer.transparentModelData[index2].squaredBoundingSphere; - - Vector3f position1 = sphere1.GetNegativeVertex(viewerNormal); - Vector3f position2 = sphere2.GetNegativeVertex(viewerNormal); - - return nearPlane.Distance(position1) > nearPlane.Distance(position2); - }); - - for (auto& pipelinePair : layer.billboards) - { - for (auto& matPair : pipelinePair.second.materialMap) - { - const Material* mat = matPair.first; - - if (mat->IsDepthSortingEnabled()) - { - BatchedBillboardEntry& entry = matPair.second; - auto& billboardVector = entry.billboards; - - std::sort(billboardVector.begin(), billboardVector.end(), [&viewerPos] (const BillboardData& data1, const BillboardData& data2) - { - return viewerPos.SquaredDistance(data1.center) > viewerPos.SquaredDistance(data2.center); - }); - } - } - } - } + if (viewer->GetProjectionType() == ProjectionType_Orthogonal) + SortForOrthographic(viewer); + else + SortForPerspective(viewer); } /*! @@ -715,12 +681,75 @@ namespace Nz return layer; } + void ForwardRenderQueue::SortBillboards(Layer& layer, const Planef& nearPlane) + { + for (auto& pipelinePair : layer.billboards) + { + for (auto& matPair : pipelinePair.second.materialMap) + { + const Material* mat = matPair.first; + + if (mat->IsDepthSortingEnabled()) + { + BatchedBillboardEntry& entry = matPair.second; + auto& billboardVector = entry.billboards; + + std::sort(billboardVector.begin(), billboardVector.end(), [&nearPlane] (const BillboardData& data1, const BillboardData& data2) + { + return nearPlane.Distance(data1.center) > nearPlane.Distance(data2.center); + }); + } + } + } + } + + void ForwardRenderQueue::SortForOrthographic(const AbstractViewer * viewer) + { + Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near); + Vector3f viewerPos = viewer->GetEyePosition(); + + for (auto& pair : layers) + { + Layer& layer = pair.second; + + std::sort(layer.depthSortedMeshes.begin(), layer.depthSortedMeshes.end(), [&layer, &nearPlane] (std::size_t index1, std::size_t index2) + { + const Spheref& sphere1 = layer.depthSortedMeshData[index1].obbSphere; + const Spheref& sphere2 = layer.depthSortedMeshData[index2].obbSphere; + + return nearPlane.Distance(sphere1.GetPosition()) > nearPlane.Distance(sphere2.GetPosition()); + }); + + SortBillboards(layer, nearPlane); + } + } + + void ForwardRenderQueue::SortForPerspective(const AbstractViewer* viewer) + { + Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near); + Vector3f viewerPos = viewer->GetEyePosition(); + + for (auto& pair : layers) + { + Layer& layer = pair.second; + + std::sort(layer.depthSortedMeshes.begin(), layer.depthSortedMeshes.end(), [&layer, &viewerPos] (std::size_t index1, std::size_t index2) + { + const Spheref& sphere1 = layer.depthSortedMeshData[index1].obbSphere; + const Spheref& sphere2 = layer.depthSortedMeshData[index2].obbSphere; + + return viewerPos.SquaredDistance(sphere1.GetPosition()) > viewerPos.SquaredDistance(sphere2.GetPosition()); + }); + + SortBillboards(layer, nearPlane); + } + } + /*! * \brief Handle the invalidation of an index buffer * * \param indexBuffer Index buffer being invalidated */ - void ForwardRenderQueue::OnIndexBufferInvalidation(const IndexBuffer* indexBuffer) { for (auto& pair : layers) @@ -757,7 +786,7 @@ namespace Nz { Layer& layer = pair.second; - for (auto& pipelineEntry : layer.basicSprites) + for (auto& pipelineEntry : layer.opaqueSprites) pipelineEntry.second.materialMap.erase(material); for (auto& pipelineEntry : layer.billboards) @@ -779,7 +808,7 @@ namespace Nz for (auto& pair : layers) { Layer& layer = pair.second; - for (auto& pipelineEntry : layer.basicSprites) + for (auto& pipelineEntry : layer.opaqueSprites) { for (auto& materialEntry : pipelineEntry.second.materialMap) materialEntry.second.overlayMap.erase(texture); diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp index 2f9319ca0..910e2bd1f 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -101,7 +101,7 @@ namespace Nz if (!layer.opaqueModels.empty()) DrawOpaqueModels(sceneData, layer); - if (!layer.transparentModels.empty()) + if (!layer.depthSortedMeshes.empty()) DrawTransparentModels(sceneData, layer); if (!layer.basicSprites.empty()) @@ -796,9 +796,9 @@ namespace Nz const ShaderUniforms* shaderUniforms = nullptr; unsigned int lightCount = 0; - for (unsigned int index : layer.transparentModels) + for (unsigned int index : layer.depthSortedMeshes) { - const ForwardRenderQueue::TransparentModelData& modelData = layer.transparentModelData[index]; + const ForwardRenderQueue::TransparentModelData& modelData = layer.depthSortedMeshData[index]; // Material const Material* material = modelData.material; @@ -865,8 +865,8 @@ namespace Nz if (shaderUniforms->hasLightUniforms && lightCount < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS) { // Compute the closest lights - Vector3f position = matrix.GetTranslation() + modelData.squaredBoundingSphere.GetPosition(); - float radius = modelData.squaredBoundingSphere.radius; + Vector3f position = matrix.GetTranslation() + modelData.obbSphere.GetPosition(); + float radius = modelData.obbSphere.radius; ChooseLights(Spheref(position, radius), false); for (std::size_t i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) diff --git a/src/Nazara/Graphics/MaterialPipeline.cpp b/src/Nazara/Graphics/MaterialPipeline.cpp index 761bc500f..e9a100ad2 100644 --- a/src/Nazara/Graphics/MaterialPipeline.cpp +++ b/src/Nazara/Graphics/MaterialPipeline.cpp @@ -197,6 +197,7 @@ namespace Nz pipelineInfo.blending = true; pipelineInfo.depthWrite = false; pipelineInfo.faceCulling = false; + pipelineInfo.depthSorting = true; pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha; pipelineInfo.srcBlend = BlendFunc_SrcAlpha; @@ -207,6 +208,7 @@ namespace Nz pipelineInfo.depthBuffer = true; pipelineInfo.depthWrite = false; pipelineInfo.faceCulling = false; + pipelineInfo.depthSorting = true; pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha; pipelineInfo.srcBlend = BlendFunc_SrcAlpha;