Graphics: Add GraphicalMesh and Model classes

This commit is contained in:
Jérôme Leclercq 2021-01-27 16:45:00 +01:00
parent a1e0ae3f38
commit a9e9ef2524
7 changed files with 300 additions and 66 deletions

View File

@ -23,6 +23,7 @@ int main()
Nz::RenderWindow window;
Nz::MeshParams meshParams;
meshParams.storage = Nz::DataStorage_Software;
meshParams.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, 90.f, 180.f)) * Nz::Matrix4f::Scale(Nz::Vector3f(0.002f));
meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ_Normal_UV);
@ -42,16 +43,7 @@ int main()
return __LINE__;
}
Nz::StaticMesh* drfreakMesh = static_cast<Nz::StaticMesh*>(drfreak->GetSubMesh(0));
const Nz::VertexBuffer* drfreakVB = drfreakMesh->GetVertexBuffer();
const Nz::IndexBuffer* drfreakIB = drfreakMesh->GetIndexBuffer();
// Index buffer
std::cout << "Index count: " << drfreakIB->GetIndexCount() << std::endl;
// Vertex buffer
std::cout << "Vertex count: " << drfreakVB->GetVertexCount() << std::endl;
std::shared_ptr<Nz::GraphicalMesh> gfxMesh = std::make_shared<Nz::GraphicalMesh>(drfreak);
// Texture
Nz::ImageRef drfreakImage = Nz::Image::LoadFromFile("resources/Spaceship/Texture/diffuse.png");
@ -101,16 +93,20 @@ int main()
std::shared_ptr<Nz::TextureSampler> textureSampler = device->InstantiateTextureSampler({});
Nz::Material material(Nz::BasicMaterial::GetSettings());
material.EnableDepthBuffer(true);
std::shared_ptr<Nz::Material> material = std::make_shared<Nz::Material>(Nz::BasicMaterial::GetSettings());
material->EnableDepthBuffer(true);
Nz::BasicMaterial basicMat(material);
Nz::BasicMaterial basicMat(*material);
basicMat.EnableAlphaTest(false);
basicMat.SetAlphaMap(alphaTexture);
basicMat.SetAlphaSampler(textureSampler);
basicMat.SetDiffuseMap(texture);
basicMat.SetDiffuseSampler(textureSampler);
Nz::Model model(std::move(gfxMesh));
for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i)
model.SetMaterial(i, material);
Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets();
Nz::PredefinedViewerData viewerUboOffsets = Nz::PredefinedViewerData::GetOffsets();
const Nz::BasicMaterial::UniformOffsets& materialSettingOffsets = Nz::BasicMaterial::GetOffsets();
@ -126,29 +122,11 @@ int main()
Nz::AccessByOffset<float&>(materialSettings.data(), materialSettingOffsets.alphaThreshold) = 0.5f;
Nz::AccessByOffset<Nz::Vector4f&>(materialSettings.data(), materialSettingOffsets.diffuseColor) = Nz::Vector4f(1.f, 1.f, 1.f, 1.f);
std::shared_ptr<Nz::RenderPipelineLayout> renderPipelineLayout = material.GetSettings()->GetRenderPipelineLayout();
std::shared_ptr<Nz::AbstractBuffer> matSettingUBO = device->InstantiateBuffer(Nz::BufferType_Uniform);
if (!matSettingUBO->Initialize(materialSettings.size(), Nz::BufferUsage_DeviceLocal | Nz::BufferUsage_Dynamic))
{
NazaraError("Failed to create mat setting UBO");
return __LINE__;
}
matSettingUBO->Fill(materialSettings.data(), 0, materialSettings.size());
std::vector<Nz::RenderPipelineInfo::VertexBufferData> vertexBuffers = {
{
0,
drfreakVB->GetVertexDeclaration()
}
};
std::vector<std::uint8_t> instanceDataBuffer(instanceUboOffsets.totalSize);
Nz::ModelInstance modelInstance(material.GetSettings());
Nz::ModelInstance modelInstance(material->GetSettings());
{
material.UpdateShaderBinding(modelInstance.GetShaderBinding());
material->UpdateShaderBinding(modelInstance.GetShaderBinding());
Nz::AccessByOffset<Nz::Matrix4f&>(instanceDataBuffer.data(), instanceUboOffsets.worldMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right());
@ -156,9 +134,9 @@ int main()
instanceDataUBO->Fill(instanceDataBuffer.data(), 0, instanceDataBuffer.size());
}
Nz::ModelInstance modelInstance2(material.GetSettings());
Nz::ModelInstance modelInstance2(material->GetSettings());
{
material.UpdateShaderBinding(modelInstance2.GetShaderBinding());
material->UpdateShaderBinding(modelInstance2.GetShaderBinding());
Nz::AccessByOffset<Nz::Matrix4f&>(instanceDataBuffer.data(), instanceUboOffsets.worldMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right() * 3.f);
@ -168,31 +146,9 @@ int main()
std::shared_ptr<Nz::AbstractBuffer> viewerDataUBO = Nz::Graphics::Instance()->GetViewerDataUBO();
std::shared_ptr<Nz::RenderPipeline> pipeline = material.GetPipeline()->GetRenderPipeline(vertexBuffers);
Nz::RenderDevice* renderDevice = window.GetRenderDevice().get();
Nz::RenderWindowImpl* windowImpl = window.GetImpl();
std::shared_ptr<Nz::CommandPool> commandPool = windowImpl->CreateCommandPool(Nz::QueueType::Graphics);
Nz::RenderBuffer* renderBufferIB = static_cast<Nz::RenderBuffer*>(drfreakIB->GetBuffer()->GetImpl());
Nz::RenderBuffer* renderBufferVB = static_cast<Nz::RenderBuffer*>(drfreakVB->GetBuffer()->GetImpl());
if (!renderBufferIB->Synchronize(renderDevice))
{
NazaraError("Failed to synchronize render buffer");
return __LINE__;
}
if (!renderBufferVB->Synchronize(renderDevice))
{
NazaraError("Failed to synchronize render buffer");
return __LINE__;
}
Nz::AbstractBuffer* indexBufferImpl = renderBufferIB->GetHardwareBuffer(renderDevice);
Nz::AbstractBuffer* vertexBufferImpl = renderBufferVB->GetHardwareBuffer(renderDevice);
Nz::CommandBufferPtr drawCommandBuffer;
auto RebuildCommandBuffer = [&]
{
@ -214,17 +170,19 @@ int main()
builder.SetScissor(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) });
builder.SetViewport(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) });
builder.BindIndexBuffer(indexBufferImpl);
builder.BindPipeline(*pipeline);
builder.BindVertexBuffer(0, vertexBufferImpl);
for (Nz::ModelInstance& modelInstance : { std::ref(modelInstance), std::ref(modelInstance2) })
{
builder.BindShaderBinding(modelInstance.GetShaderBinding());
builder.BindShaderBinding(modelInstance.GetShaderBinding());
for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i)
{
builder.BindIndexBuffer(model.GetIndexBuffer(i).get());
builder.BindVertexBuffer(0, model.GetVertexBuffer(i).get());
builder.BindPipeline(*model.GetRenderPipeline(i));
builder.DrawIndexed(drfreakIB->GetIndexCount());
builder.BindShaderBinding(modelInstance2.GetShaderBinding());
builder.DrawIndexed(drfreakIB->GetIndexCount());
builder.DrawIndexed(model.GetIndexCount(i));
}
}
}
builder.EndRenderPass();
}

View File

@ -0,0 +1,50 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_GRAPHICALMESH_HPP
#define NAZARA_GRAPHICALMESH_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <memory>
namespace Nz
{
class NAZARA_GRAPHICS_API GraphicalMesh
{
public:
GraphicalMesh(const Mesh* mesh);
GraphicalMesh(const GraphicalMesh&) = delete;
GraphicalMesh(GraphicalMesh&&) noexcept = default;
~GraphicalMesh() = default;
inline const std::shared_ptr<AbstractBuffer>& GetIndexBuffer(std::size_t subMesh) const;
inline std::size_t GetIndexCount(std::size_t subMesh) const;
inline const std::shared_ptr<AbstractBuffer>& GetVertexBuffer(std::size_t subMesh) const;
inline const VertexDeclarationConstRef& GetVertexDeclaration(std::size_t subMesh) const;
inline std::size_t GetSubMeshCount() const;
GraphicalMesh& operator=(const GraphicalMesh&) = delete;
GraphicalMesh& operator=(GraphicalMesh&&) noexcept = default;
private:
struct GraphicalSubMesh
{
std::shared_ptr<AbstractBuffer> indexBuffer;
std::shared_ptr<AbstractBuffer> vertexBuffer;
std::size_t indexCount;
VertexDeclarationConstRef vertexDeclaration;
};
std::vector<GraphicalSubMesh> m_subMeshes;
};
}
#include <Nazara/Graphics/GraphicalMesh.inl>
#endif // NAZARA_GRAPHICALMESH_HPP

View File

@ -0,0 +1,41 @@
// Copyright (C) 2017 Jérôme Leclercq
// 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/GraphicalMesh.hpp>
#include <cassert>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
inline const std::shared_ptr<AbstractBuffer>& GraphicalMesh::GetIndexBuffer(std::size_t subMesh) const
{
assert(subMesh < m_subMeshes.size());
return m_subMeshes[subMesh].indexBuffer;
}
inline std::size_t GraphicalMesh::GetIndexCount(std::size_t subMesh) const
{
assert(subMesh < m_subMeshes.size());
return m_subMeshes[subMesh].indexCount;
}
inline const std::shared_ptr<AbstractBuffer>& GraphicalMesh::GetVertexBuffer(std::size_t subMesh) const
{
assert(subMesh < m_subMeshes.size());
return m_subMeshes[subMesh].vertexBuffer;
}
inline const VertexDeclarationConstRef& GraphicalMesh::GetVertexDeclaration(std::size_t subMesh) const
{
assert(subMesh < m_subMeshes.size());
return m_subMeshes[subMesh].vertexDeclaration;
}
inline std::size_t GraphicalMesh::GetSubMeshCount() const
{
return m_subMeshes.size();
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@ -0,0 +1,55 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_MODEL_HPP
#define NAZARA_MODEL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Renderer/RenderPipeline.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <memory>
namespace Nz
{
class GraphicalMesh;
class Material;
class NAZARA_GRAPHICS_API Model
{
public:
Model(std::shared_ptr<GraphicalMesh> graphicalMesh);
Model(const Model&) = delete;
Model(Model&&) noexcept = default;
~Model() = default;
const std::shared_ptr<AbstractBuffer>& GetIndexBuffer(std::size_t subMeshIndex) const;
std::size_t GetIndexCount(std::size_t subMeshIndex) const;
const std::shared_ptr<RenderPipeline>& GetRenderPipeline(std::size_t subMeshIndex) const;
const std::shared_ptr<AbstractBuffer>& GetVertexBuffer(std::size_t subMeshIndex) const;
inline std::size_t GetSubMeshCount() const;
inline void SetMaterial(std::size_t subMeshIndex, std::shared_ptr<Material> material);
Model& operator=(const Model&) = delete;
Model& operator=(Model&&) noexcept = default;
private:
struct SubMeshData
{
std::shared_ptr<Material> material;
std::vector<RenderPipelineInfo::VertexBufferData> vertexBufferData;
};
std::shared_ptr<GraphicalMesh> m_graphicalMesh;
std::vector<SubMeshData> m_subMeshes;
};
}
#include <Nazara/Graphics/Model.inl>
#endif

View File

@ -0,0 +1,23 @@
// Copyright (C) 2017 Jérôme Leclercq
// 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/Model.hpp>
#include <cassert>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
inline std::size_t Model::GetSubMeshCount() const
{
return m_subMeshes.size();
}
inline void Model::SetMaterial(std::size_t subMeshIndex, std::shared_ptr<Material> material)
{
assert(subMeshIndex < m_subMeshes.size());
m_subMeshes[subMeshIndex].material = std::move(material);
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@ -0,0 +1,56 @@
// Copyright (C) 2017 Jérôme Leclercq
// 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/GraphicalMesh.hpp>
#include <Nazara/Graphics/Graphics.hpp>
#include <Nazara/Utility/SoftwareBuffer.hpp>
#include <Nazara/Utility/StaticMesh.hpp>
#include <cassert>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
GraphicalMesh::GraphicalMesh(const Mesh* mesh)
{
assert(mesh->GetAnimationType() == AnimationType_Static);
RenderDevice& renderDevice = Graphics::Instance()->GetRenderDevice();
m_subMeshes.reserve(mesh->GetSubMeshCount());
for (std::size_t i = 0; i < mesh->GetSubMeshCount(); ++i)
{
const SubMesh* subMesh = mesh->GetSubMesh(i);
const StaticMesh* staticMesh = static_cast<const StaticMesh*>(subMesh);
const IndexBuffer* indexBuffer = staticMesh->GetIndexBuffer();
const VertexBuffer* vertexBuffer = staticMesh->GetVertexBuffer();
assert(indexBuffer->GetBuffer()->GetStorage() == DataStorage_Software);
const SoftwareBuffer* indexBufferContent = static_cast<const SoftwareBuffer*>(indexBuffer->GetBuffer()->GetImpl());
assert(vertexBuffer->GetBuffer()->GetStorage() == DataStorage_Software);
const SoftwareBuffer* vertexBufferContent = static_cast<const SoftwareBuffer*>(vertexBuffer->GetBuffer()->GetImpl());
auto& submeshData = m_subMeshes.emplace_back();
submeshData.indexBuffer = renderDevice.InstantiateBuffer(BufferType_Index);
if (!submeshData.indexBuffer->Initialize(indexBuffer->GetStride() * indexBuffer->GetIndexCount(), BufferUsage_DeviceLocal))
throw std::runtime_error("failed to create index buffer");
if (!submeshData.indexBuffer->Fill(indexBufferContent->GetData() + indexBuffer->GetStartOffset(), 0, indexBuffer->GetEndOffset() - indexBuffer->GetStartOffset()))
throw std::runtime_error("failed to fill index buffer");
submeshData.indexCount = indexBuffer->GetIndexCount();
submeshData.vertexBuffer = renderDevice.InstantiateBuffer(BufferType_Vertex);
if (!submeshData.vertexBuffer->Initialize(vertexBuffer->GetStride() * vertexBuffer->GetVertexCount(), BufferUsage_DeviceLocal))
throw std::runtime_error("failed to create vertex buffer");
if (!submeshData.vertexBuffer->Fill(vertexBufferContent->GetData() + vertexBuffer->GetStartOffset(), 0, vertexBuffer->GetEndOffset() - vertexBuffer->GetStartOffset()))
throw std::runtime_error("failed to fill vertex buffer");
submeshData.vertexDeclaration = vertexBuffer->GetVertexDeclaration();
}
}
}

View File

@ -0,0 +1,51 @@
// Copyright (C) 2017 Jérôme Leclercq
// 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/Model.hpp>
#include <Nazara/Graphics/GraphicalMesh.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
inline Model::Model(std::shared_ptr<GraphicalMesh> graphicalMesh) :
m_graphicalMesh(std::move(graphicalMesh))
{
m_subMeshes.reserve(m_graphicalMesh->GetSubMeshCount());
for (std::size_t i = 0; i < m_graphicalMesh->GetSubMeshCount(); ++i)
{
auto& subMeshData = m_subMeshes.emplace_back();
//subMeshData.material = DefaultMaterial; //< TODO
subMeshData.vertexBufferData = {
{
0,
m_graphicalMesh->GetVertexDeclaration(i)
}
};
}
}
const std::shared_ptr<AbstractBuffer>& Model::GetIndexBuffer(std::size_t subMeshIndex) const
{
return m_graphicalMesh->GetIndexBuffer(subMeshIndex);
}
std::size_t Model::GetIndexCount(std::size_t subMeshIndex) const
{
return m_graphicalMesh->GetIndexCount(subMeshIndex);
}
const std::shared_ptr<RenderPipeline>& Model::GetRenderPipeline(std::size_t subMeshIndex) const
{
assert(subMeshIndex < m_subMeshes.size());
const auto& subMeshData = m_subMeshes[subMeshIndex];
return subMeshData.material->GetPipeline()->GetRenderPipeline(subMeshData.vertexBufferData);
}
const std::shared_ptr<AbstractBuffer>& Model::GetVertexBuffer(std::size_t subMeshIndex) const
{
return m_graphicalMesh->GetVertexBuffer(subMeshIndex);
}
}