138 lines
4.3 KiB
C++
138 lines
4.3 KiB
C++
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
|
// This file is part of the "Nazara Engine - Graphics module"
|
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
|
|
#include <Nazara/Graphics/Algorithm.hpp>
|
|
#include <Nazara/Graphics/MaterialPass.hpp>
|
|
#include <Nazara/Graphics/Debug.hpp>
|
|
|
|
namespace Nz
|
|
{
|
|
inline RenderSubmesh::RenderSubmesh(int renderLayer, std::shared_ptr<MaterialInstance> materialInstance, MaterialPassFlags materialFlags, std::shared_ptr<RenderPipeline> renderPipeline, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::size_t indexCount, IndexType indexType, std::shared_ptr<RenderBuffer> indexBuffer, std::shared_ptr<RenderBuffer> vertexBuffer, const Recti& scissorBox) :
|
|
RenderElement(BasicRenderElement::Submesh),
|
|
m_indexBuffer(std::move(indexBuffer)),
|
|
m_vertexBuffer(std::move(vertexBuffer)),
|
|
m_materialInstance(std::move(materialInstance)),
|
|
m_renderPipeline(std::move(renderPipeline)),
|
|
m_indexCount(indexCount),
|
|
m_skeletonInstance(skeletonInstance),
|
|
m_worldInstance(worldInstance),
|
|
m_indexType(indexType),
|
|
m_materialFlags(materialFlags),
|
|
m_scissorBox(scissorBox),
|
|
m_renderLayer(renderLayer)
|
|
{
|
|
}
|
|
|
|
inline UInt64 RenderSubmesh::ComputeSortingScore(const Frustumf& frustum, const RenderQueueRegistry& registry) const
|
|
{
|
|
UInt64 layerIndex = registry.FetchLayerIndex(m_renderLayer);
|
|
|
|
if (m_materialFlags.Test(MaterialPassFlag::SortByDistance))
|
|
{
|
|
UInt64 matFlags = 1;
|
|
|
|
float distanceNear = frustum.GetPlane(FrustumPlane::Near).SignedDistance(m_worldInstance.GetWorldMatrix().GetTranslation());
|
|
UInt64 distance = DistanceAsSortKey(distanceNear);
|
|
|
|
// Transparent RQ index:
|
|
// - Layer (8bits)
|
|
// - Sorted by distance flag (1bit)
|
|
// - Distance to near plane (32bits) - could by reduced to 24 or even 16 if required
|
|
// - ?? (23bits)
|
|
|
|
return (layerIndex & 0xFF) << 56 |
|
|
(matFlags) << 55 |
|
|
(distance) << 23;
|
|
}
|
|
else
|
|
{
|
|
UInt64 elementType = GetElementType();
|
|
UInt64 materialInstanceIndex = registry.FetchMaterialInstanceIndex(m_materialInstance.get());
|
|
UInt64 pipelineIndex = registry.FetchPipelineIndex(m_renderPipeline.get());
|
|
UInt64 vertexBufferIndex = registry.FetchVertexBuffer(m_vertexBuffer.get());
|
|
|
|
UInt64 skeletonIndex = 0;
|
|
if (m_skeletonInstance)
|
|
skeletonIndex = registry.FetchSkeletonIndex(m_skeletonInstance->GetSkeleton().get());
|
|
|
|
UInt64 matFlags = 0;
|
|
|
|
// Opaque RQ index:
|
|
// - Layer (8bits)
|
|
// - Sorted by distance flag (1bit)
|
|
// - Element type (4bits)
|
|
// - Pipeline (16bits)
|
|
// - MaterialPass (16bits)
|
|
// - VertexBuffer (8bits)
|
|
// - Skeleton (8bits)
|
|
// - Unused (3bits)
|
|
|
|
return (layerIndex & 0xFF) << 56 |
|
|
(matFlags) << 55 |
|
|
(elementType & 0xF) << 51 |
|
|
(pipelineIndex & 0xFFFF) << 35 |
|
|
(materialInstanceIndex & 0xFFFF) << 19 |
|
|
(vertexBufferIndex & 0xFF) << 11 |
|
|
(skeletonIndex & 0xFF) << 3;
|
|
}
|
|
}
|
|
|
|
inline const RenderBuffer* RenderSubmesh::GetIndexBuffer() const
|
|
{
|
|
return m_indexBuffer.get();
|
|
}
|
|
|
|
inline std::size_t RenderSubmesh::GetIndexCount() const
|
|
{
|
|
return m_indexCount;
|
|
}
|
|
|
|
inline IndexType RenderSubmesh::GetIndexType() const
|
|
{
|
|
return m_indexType;
|
|
}
|
|
|
|
inline const MaterialInstance& RenderSubmesh::GetMaterialInstance() const
|
|
{
|
|
return *m_materialInstance;
|
|
}
|
|
|
|
inline const RenderPipeline* RenderSubmesh::GetRenderPipeline() const
|
|
{
|
|
return m_renderPipeline.get();
|
|
}
|
|
|
|
inline const Recti& RenderSubmesh::GetScissorBox() const
|
|
{
|
|
return m_scissorBox;
|
|
}
|
|
|
|
inline const SkeletonInstance* RenderSubmesh::GetSkeletonInstance() const
|
|
{
|
|
return m_skeletonInstance;
|
|
}
|
|
|
|
inline const RenderBuffer* RenderSubmesh::GetVertexBuffer() const
|
|
{
|
|
return m_vertexBuffer.get();
|
|
}
|
|
|
|
inline const WorldInstance& RenderSubmesh::GetWorldInstance() const
|
|
{
|
|
return m_worldInstance;
|
|
}
|
|
|
|
inline void RenderSubmesh::Register(RenderQueueRegistry& registry) const
|
|
{
|
|
registry.RegisterLayer(m_renderLayer);
|
|
registry.RegisterMaterialInstance(m_materialInstance.get());
|
|
registry.RegisterPipeline(m_renderPipeline.get());
|
|
registry.RegisterVertexBuffer(m_vertexBuffer.get());
|
|
if (m_skeletonInstance)
|
|
registry.RegisterSkeleton(m_skeletonInstance->GetSkeleton().get());
|
|
}
|
|
}
|
|
|
|
#include <Nazara/Graphics/DebugOff.hpp>
|