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;
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;

View File

@ -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

View File

@ -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

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 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);

View File

@ -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;

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 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;

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 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;

View File

@ -13,6 +13,7 @@
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Math/Box.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Math/Plane.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/MeshData.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>
@ -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 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> transparentModelData;
TransparentModelContainer depthSortedMeshes;
std::vector<TransparentModelData> depthSortedMeshData;
std::vector<const Drawable*> 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);

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)
{
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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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;