diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp index 503d18936..d28511846 100644 --- a/examples/GraphicsTest/main.cpp +++ b/examples/GraphicsTest/main.cpp @@ -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(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 gfxMesh = std::make_shared(drfreak); // Texture Nz::ImageRef drfreakImage = Nz::Image::LoadFromFile("resources/Spaceship/Texture/diffuse.png"); @@ -101,16 +93,20 @@ int main() std::shared_ptr textureSampler = device->InstantiateTextureSampler({}); - Nz::Material material(Nz::BasicMaterial::GetSettings()); - material.EnableDepthBuffer(true); + std::shared_ptr material = std::make_shared(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(materialSettings.data(), materialSettingOffsets.alphaThreshold) = 0.5f; Nz::AccessByOffset(materialSettings.data(), materialSettingOffsets.diffuseColor) = Nz::Vector4f(1.f, 1.f, 1.f, 1.f); - std::shared_ptr renderPipelineLayout = material.GetSettings()->GetRenderPipelineLayout(); - - std::shared_ptr 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 vertexBuffers = { - { - 0, - drfreakVB->GetVertexDeclaration() - } - }; - std::vector instanceDataBuffer(instanceUboOffsets.totalSize); - Nz::ModelInstance modelInstance(material.GetSettings()); + Nz::ModelInstance modelInstance(material->GetSettings()); { - material.UpdateShaderBinding(modelInstance.GetShaderBinding()); + material->UpdateShaderBinding(modelInstance.GetShaderBinding()); Nz::AccessByOffset(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(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 viewerDataUBO = Nz::Graphics::Instance()->GetViewerDataUBO(); - std::shared_ptr pipeline = material.GetPipeline()->GetRenderPipeline(vertexBuffers); - - Nz::RenderDevice* renderDevice = window.GetRenderDevice().get(); - Nz::RenderWindowImpl* windowImpl = window.GetImpl(); std::shared_ptr commandPool = windowImpl->CreateCommandPool(Nz::QueueType::Graphics); - Nz::RenderBuffer* renderBufferIB = static_cast(drfreakIB->GetBuffer()->GetImpl()); - Nz::RenderBuffer* renderBufferVB = static_cast(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(); } diff --git a/include/Nazara/Graphics/GraphicalMesh.hpp b/include/Nazara/Graphics/GraphicalMesh.hpp new file mode 100644 index 000000000..cc68dcf95 --- /dev/null +++ b/include/Nazara/Graphics/GraphicalMesh.hpp @@ -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 +#include +#include +#include +#include + +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& GetIndexBuffer(std::size_t subMesh) const; + inline std::size_t GetIndexCount(std::size_t subMesh) const; + inline const std::shared_ptr& 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 indexBuffer; + std::shared_ptr vertexBuffer; + std::size_t indexCount; + VertexDeclarationConstRef vertexDeclaration; + }; + + std::vector m_subMeshes; + }; +} + +#include + +#endif // NAZARA_GRAPHICALMESH_HPP diff --git a/include/Nazara/Graphics/GraphicalMesh.inl b/include/Nazara/Graphics/GraphicalMesh.inl new file mode 100644 index 000000000..f00facb56 --- /dev/null +++ b/include/Nazara/Graphics/GraphicalMesh.inl @@ -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 +#include +#include + +namespace Nz +{ + inline const std::shared_ptr& 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& 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 diff --git a/include/Nazara/Graphics/Model.hpp b/include/Nazara/Graphics/Model.hpp new file mode 100644 index 000000000..47f9a1697 --- /dev/null +++ b/include/Nazara/Graphics/Model.hpp @@ -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 +#include +#include +#include +#include +#include + +namespace Nz +{ + class GraphicalMesh; + class Material; + + class NAZARA_GRAPHICS_API Model + { + public: + Model(std::shared_ptr graphicalMesh); + Model(const Model&) = delete; + Model(Model&&) noexcept = default; + ~Model() = default; + + const std::shared_ptr& GetIndexBuffer(std::size_t subMeshIndex) const; + std::size_t GetIndexCount(std::size_t subMeshIndex) const; + const std::shared_ptr& GetRenderPipeline(std::size_t subMeshIndex) const; + const std::shared_ptr& GetVertexBuffer(std::size_t subMeshIndex) const; + inline std::size_t GetSubMeshCount() const; + + inline void SetMaterial(std::size_t subMeshIndex, std::shared_ptr material); + + Model& operator=(const Model&) = delete; + Model& operator=(Model&&) noexcept = default; + + private: + struct SubMeshData + { + std::shared_ptr material; + std::vector vertexBufferData; + }; + + std::shared_ptr m_graphicalMesh; + std::vector m_subMeshes; + }; +} + +#include + +#endif diff --git a/include/Nazara/Graphics/Model.inl b/include/Nazara/Graphics/Model.inl new file mode 100644 index 000000000..de31598dc --- /dev/null +++ b/include/Nazara/Graphics/Model.inl @@ -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 +#include +#include + +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) + { + assert(subMeshIndex < m_subMeshes.size()); + m_subMeshes[subMeshIndex].material = std::move(material); + } +} + +#include diff --git a/src/Nazara/Graphics/GraphicalMesh.cpp b/src/Nazara/Graphics/GraphicalMesh.cpp new file mode 100644 index 000000000..a3042155c --- /dev/null +++ b/src/Nazara/Graphics/GraphicalMesh.cpp @@ -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 +#include +#include +#include +#include +#include + +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(subMesh); + + const IndexBuffer* indexBuffer = staticMesh->GetIndexBuffer(); + const VertexBuffer* vertexBuffer = staticMesh->GetVertexBuffer(); + + assert(indexBuffer->GetBuffer()->GetStorage() == DataStorage_Software); + const SoftwareBuffer* indexBufferContent = static_cast(indexBuffer->GetBuffer()->GetImpl()); + + assert(vertexBuffer->GetBuffer()->GetStorage() == DataStorage_Software); + const SoftwareBuffer* vertexBufferContent = static_cast(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(); + } + } +} diff --git a/src/Nazara/Graphics/Model.cpp b/src/Nazara/Graphics/Model.cpp new file mode 100644 index 000000000..aff54d805 --- /dev/null +++ b/src/Nazara/Graphics/Model.cpp @@ -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 +#include +#include +#include + +namespace Nz +{ + inline Model::Model(std::shared_ptr 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& 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& 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& Model::GetVertexBuffer(std::size_t subMeshIndex) const + { + return m_graphicalMesh->GetVertexBuffer(subMeshIndex); + } + +}