Graphics/Material: Fix depth sorting flag handling for meshes

This commit is contained in:
Lynix 2017-04-22 17:13:51 +02:00
parent e3514db87f
commit 52a4a590e1
13 changed files with 122 additions and 83 deletions

View File

@ -44,7 +44,7 @@ namespace Ndk
const Nz::Frustumf& GetFrustum() const override; const Nz::Frustumf& GetFrustum() const override;
inline unsigned int GetLayer() const; inline unsigned int GetLayer() const;
const Nz::Matrix4f& GetProjectionMatrix() const override; const Nz::Matrix4f& GetProjectionMatrix() const override;
inline Nz::ProjectionType GetProjectionType() const; Nz::ProjectionType GetProjectionType() const override;
inline const Nz::Vector2f& GetSize() const; inline const Nz::Vector2f& GetSize() const;
const Nz::RenderTarget* GetTarget() const override; const Nz::RenderTarget* GetTarget() const override;
inline const Nz::Rectf& GetTargetRegion() const; inline const Nz::Rectf& GetTargetRegion() const;

View File

@ -117,16 +117,6 @@ namespace Ndk
return m_layer; 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 * \brief Gets the size of the camera
* \return Size of the camera * \return Size of the camera

View File

@ -93,6 +93,17 @@ namespace Ndk
return m_projectionMatrix; 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 * \brief Gets the target of the camera
* \return A constant reference to the render target of the camera * \return A constant reference to the render target of the camera

View File

@ -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 AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) = 0;
virtual void AddPointLight(const PointLight& light); virtual void AddPointLight(const PointLight& light);
virtual void AddSpotLight(const SpotLight& light); virtual void AddSpotLight(const SpotLight& light);
virtual void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, 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); virtual void Clear(bool fully = false);

View File

@ -33,6 +33,7 @@ namespace Nz
virtual Vector3f GetForward() const = 0; virtual Vector3f GetForward() const = 0;
virtual const Frustumf& GetFrustum() const = 0; virtual const Frustumf& GetFrustum() const = 0;
virtual const Matrix4f& GetProjectionMatrix() const = 0; virtual const Matrix4f& GetProjectionMatrix() const = 0;
virtual Nz::ProjectionType GetProjectionType() const = 0;
virtual const RenderTarget* GetTarget() const = 0; virtual const RenderTarget* GetTarget() const = 0;
virtual const Matrix4f& GetViewMatrix() const = 0; virtual const Matrix4f& GetViewMatrix() const = 0;
virtual const Recti& GetViewport() const = 0; virtual const Recti& GetViewport() const = 0;

View File

@ -37,7 +37,7 @@ namespace Nz
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override; void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
void AddDrawable(int renderOrder, const Drawable* drawable) override; void 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 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; void Clear(bool fully = false) override;

View File

@ -38,7 +38,7 @@ namespace Nz
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override; void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override;
void AddPointLight(const PointLight& light) override; void AddPointLight(const PointLight& light) override;
void AddSpotLight(const SpotLight& light) override; void AddSpotLight(const SpotLight& light) override;
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, 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: private:
inline bool IsMaterialSuitable(const Material* material) const; inline bool IsMaterialSuitable(const Material* material) const;

View File

@ -13,6 +13,7 @@
#include <Nazara/Graphics/Material.hpp> #include <Nazara/Graphics/Material.hpp>
#include <Nazara/Math/Box.hpp> #include <Nazara/Math/Box.hpp>
#include <Nazara/Math/Matrix4.hpp> #include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Math/Plane.hpp>
#include <Nazara/Utility/IndexBuffer.hpp> #include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/MeshData.hpp> #include <Nazara/Utility/MeshData.hpp>
#include <Nazara/Utility/VertexBuffer.hpp> #include <Nazara/Utility/VertexBuffer.hpp>
@ -41,7 +42,7 @@ namespace Nz
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override; void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
void AddDrawable(int renderOrder, const Drawable* drawable) override; void 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 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; void Clear(bool fully = false) override;
@ -156,7 +157,7 @@ namespace Nz
{ {
Matrix4f transformMatrix; Matrix4f transformMatrix;
MeshData meshData; MeshData meshData;
Spheref squaredBoundingSphere; Spheref obbSphere;
const Material* material; const Material* material;
}; };
@ -165,10 +166,11 @@ namespace Nz
struct Layer struct Layer
{ {
BillboardPipelineBatches billboards; BillboardPipelineBatches billboards;
SpritePipelineBatches basicSprites; SpritePipelineBatches opaqueSprites;
SpritePipelineBatches depthSortedSprites;
MeshPipelineBatches opaqueModels; MeshPipelineBatches opaqueModels;
TransparentModelContainer transparentModels; TransparentModelContainer depthSortedMeshes;
std::vector<TransparentModelData> transparentModelData; std::vector<TransparentModelData> depthSortedMeshData;
std::vector<const Drawable*> otherDrawables; std::vector<const Drawable*> otherDrawables;
unsigned int clearCount = 0; unsigned int clearCount = 0;
}; };
@ -179,6 +181,10 @@ namespace Nz
BillboardData* GetBillboardData(int renderOrder, const Material* material, unsigned int count); BillboardData* GetBillboardData(int renderOrder, const Material* material, unsigned int count);
Layer& GetLayer(int i); ///TODO: Inline 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 OnIndexBufferInvalidation(const IndexBuffer* indexBuffer);
void OnMaterialInvalidation(const Material* material); void OnMaterialInvalidation(const Material* material);
void OnTextureInvalidation(const Texture* texture); void OnTextureInvalidation(const Texture* texture);

View File

@ -191,8 +191,8 @@ namespace Nz
void DeferredRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) void DeferredRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix)
{ {
if (material->IsBlendingEnabled()) if (material->IsBlendingEnabled() || material->IsDepthSortingEnabled()) //< Fixme: Deferred Shading should be able to handle depth sorting
// One transparent material ? I don't like it, go see if I'm in the forward queue // Deferred Shading cannot handle blended objects, put them in the forward list
m_forwardQueue->AddMesh(renderOrder, material, meshData, meshAABB, transformMatrix); m_forwardQueue->AddMesh(renderOrder, material, meshData, meshAABB, transformMatrix);
else else
{ {
@ -254,7 +254,7 @@ namespace Nz
* \param overlay Texture of the sprites * \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); m_forwardQueue->AddSprites(renderOrder, material, vertices, spriteCount, overlay);
} }

View File

@ -351,7 +351,7 @@ namespace Nz
* \remark Produces a NazaraAssert if material is invalid * \remark Produces a NazaraAssert if material is invalid
*/ */
void DepthRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, 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"); NazaraAssert(material, "Invalid material");
NazaraUnused(renderOrder); NazaraUnused(renderOrder);

View File

@ -376,23 +376,23 @@ namespace Nz
{ {
NazaraAssert(material, "Invalid material"); NazaraAssert(material, "Invalid material");
if (material->IsBlendingEnabled()) if (material->IsDepthSortingEnabled())
{ {
Layer& currentLayer = GetLayer(renderOrder); Layer& currentLayer = GetLayer(renderOrder);
auto& transparentModels = currentLayer.transparentModels; auto& transparentMeshes = currentLayer.depthSortedMeshes;
auto& transparentModelData = currentLayer.transparentModelData; 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) // 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 = transparentModelData.size(); std::size_t index = transparentData.size();
transparentModelData.resize(index+1); transparentData.resize(index+1);
TransparentModelData& data = transparentModelData.back(); TransparentModelData& data = transparentData.back();
data.material = material; data.material = material;
data.meshData = meshData; data.meshData = meshData;
data.squaredBoundingSphere = Spheref(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius()); data.obbSphere = Spheref(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius());
data.transformMatrix = transformMatrix; data.transformMatrix = transformMatrix;
transparentModels.push_back(index); transparentMeshes.push_back(index);
} }
else else
{ {
@ -457,12 +457,12 @@ namespace Nz
* *
* \remark Produces a NazaraAssert if material is invalid * \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"); NazaraAssert(material, "Invalid material");
Layer& currentLayer = GetLayer(renderOrder); Layer& currentLayer = GetLayer(renderOrder);
SpritePipelineBatches& basicSprites = currentLayer.basicSprites; SpritePipelineBatches& basicSprites = currentLayer.opaqueSprites;
const MaterialPipeline* materialPipeline = material->GetPipeline(); const MaterialPipeline* materialPipeline = material->GetPipeline();
@ -545,7 +545,7 @@ namespace Nz
pipelineEntry.enabled = false; pipelineEntry.enabled = false;
} }
for (auto& pipelinePair : layer.basicSprites) for (auto& pipelinePair : layer.opaqueSprites)
{ {
auto& pipelineEntry = pipelinePair.second; auto& pipelineEntry = pipelinePair.second;
@ -597,8 +597,8 @@ namespace Nz
} }
layer.otherDrawables.clear(); layer.otherDrawables.clear();
layer.transparentModels.clear(); layer.depthSortedMeshes.clear();
layer.transparentModelData.clear(); layer.depthSortedMeshData.clear();
++it; ++it;
} }
} }
@ -613,44 +613,10 @@ namespace Nz
void ForwardRenderQueue::Sort(const AbstractViewer* viewer) void ForwardRenderQueue::Sort(const AbstractViewer* viewer)
{ {
Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near); if (viewer->GetProjectionType() == ProjectionType_Orthogonal)
Vector3f viewerPos = viewer->GetEyePosition(); SortForOrthographic(viewer);
Vector3f viewerNormal = viewer->GetForward(); else
SortForPerspective(viewer);
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);
});
}
}
}
}
} }
/*! /*!
@ -715,12 +681,75 @@ namespace Nz
return layer; 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 * \brief Handle the invalidation of an index buffer
* *
* \param indexBuffer Index buffer being invalidated * \param indexBuffer Index buffer being invalidated
*/ */
void ForwardRenderQueue::OnIndexBufferInvalidation(const IndexBuffer* indexBuffer) void ForwardRenderQueue::OnIndexBufferInvalidation(const IndexBuffer* indexBuffer)
{ {
for (auto& pair : layers) for (auto& pair : layers)
@ -757,7 +786,7 @@ namespace Nz
{ {
Layer& layer = pair.second; Layer& layer = pair.second;
for (auto& pipelineEntry : layer.basicSprites) for (auto& pipelineEntry : layer.opaqueSprites)
pipelineEntry.second.materialMap.erase(material); pipelineEntry.second.materialMap.erase(material);
for (auto& pipelineEntry : layer.billboards) for (auto& pipelineEntry : layer.billboards)
@ -779,7 +808,7 @@ namespace Nz
for (auto& pair : layers) for (auto& pair : layers)
{ {
Layer& layer = pair.second; Layer& layer = pair.second;
for (auto& pipelineEntry : layer.basicSprites) for (auto& pipelineEntry : layer.opaqueSprites)
{ {
for (auto& materialEntry : pipelineEntry.second.materialMap) for (auto& materialEntry : pipelineEntry.second.materialMap)
materialEntry.second.overlayMap.erase(texture); materialEntry.second.overlayMap.erase(texture);

View File

@ -101,7 +101,7 @@ namespace Nz
if (!layer.opaqueModels.empty()) if (!layer.opaqueModels.empty())
DrawOpaqueModels(sceneData, layer); DrawOpaqueModels(sceneData, layer);
if (!layer.transparentModels.empty()) if (!layer.depthSortedMeshes.empty())
DrawTransparentModels(sceneData, layer); DrawTransparentModels(sceneData, layer);
if (!layer.basicSprites.empty()) if (!layer.basicSprites.empty())
@ -796,9 +796,9 @@ namespace Nz
const ShaderUniforms* shaderUniforms = nullptr; const ShaderUniforms* shaderUniforms = nullptr;
unsigned int lightCount = 0; 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 // Material
const Material* material = modelData.material; const Material* material = modelData.material;
@ -865,8 +865,8 @@ namespace Nz
if (shaderUniforms->hasLightUniforms && lightCount < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS) if (shaderUniforms->hasLightUniforms && lightCount < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS)
{ {
// Compute the closest lights // Compute the closest lights
Vector3f position = matrix.GetTranslation() + modelData.squaredBoundingSphere.GetPosition(); Vector3f position = matrix.GetTranslation() + modelData.obbSphere.GetPosition();
float radius = modelData.squaredBoundingSphere.radius; float radius = modelData.obbSphere.radius;
ChooseLights(Spheref(position, radius), false); ChooseLights(Spheref(position, radius), false);
for (std::size_t i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) for (std::size_t i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)

View File

@ -197,6 +197,7 @@ namespace Nz
pipelineInfo.blending = true; pipelineInfo.blending = true;
pipelineInfo.depthWrite = false; pipelineInfo.depthWrite = false;
pipelineInfo.faceCulling = false; pipelineInfo.faceCulling = false;
pipelineInfo.depthSorting = true;
pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha; pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha;
pipelineInfo.srcBlend = BlendFunc_SrcAlpha; pipelineInfo.srcBlend = BlendFunc_SrcAlpha;
@ -207,6 +208,7 @@ namespace Nz
pipelineInfo.depthBuffer = true; pipelineInfo.depthBuffer = true;
pipelineInfo.depthWrite = false; pipelineInfo.depthWrite = false;
pipelineInfo.faceCulling = false; pipelineInfo.faceCulling = false;
pipelineInfo.depthSorting = true;
pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha; pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha;
pipelineInfo.srcBlend = BlendFunc_SrcAlpha; pipelineInfo.srcBlend = BlendFunc_SrcAlpha;