From 7b592a9506e9978c72e46214aaf66b8d2898bef0 Mon Sep 17 00:00:00 2001 From: Tobias Frisch <tfrisch@uni-koblenz.de> Date: Tue, 6 Jul 2021 14:56:05 +0200 Subject: [PATCH] [#56] Fixed graph dependency error and added basic graph optimization Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de> --- .../include/vkcv/material/Material.hpp | 2 + .../material/src/vkcv/material/Material.cpp | 4 + modules/scene/include/vkcv/scene/Mesh.hpp | 8 +- modules/scene/include/vkcv/scene/MeshPart.hpp | 8 +- modules/scene/include/vkcv/scene/Node.hpp | 19 +- modules/scene/include/vkcv/scene/Scene.hpp | 16 +- modules/scene/src/vkcv/scene/Mesh.cpp | 32 ++-- modules/scene/src/vkcv/scene/MeshPart.cpp | 171 ++---------------- modules/scene/src/vkcv/scene/Node.cpp | 134 +++++++++++--- modules/scene/src/vkcv/scene/Scene.cpp | 163 ++++++++++++++++- 10 files changed, 334 insertions(+), 223 deletions(-) diff --git a/modules/material/include/vkcv/material/Material.hpp b/modules/material/include/vkcv/material/Material.hpp index a3b97823..9b54d998 100644 --- a/modules/material/include/vkcv/material/Material.hpp +++ b/modules/material/include/vkcv/material/Material.hpp @@ -41,6 +41,8 @@ namespace vkcv::material { [[nodiscard]] const DescriptorSetHandle& getDescriptorSet() const; + explicit operator bool() const; + bool operator!() const; static const std::vector<DescriptorBinding>& getDescriptorBindings(MaterialType type); diff --git a/modules/material/src/vkcv/material/Material.cpp b/modules/material/src/vkcv/material/Material.cpp index aaf2e130..409db0b9 100644 --- a/modules/material/src/vkcv/material/Material.cpp +++ b/modules/material/src/vkcv/material/Material.cpp @@ -15,6 +15,10 @@ namespace vkcv::material { return m_DescriptorSet; } + Material::operator bool() const { + return (m_Type != MaterialType::UNKNOWN); + } + bool Material::operator!() const { return (m_Type == MaterialType::UNKNOWN); } diff --git a/modules/scene/include/vkcv/scene/Mesh.hpp b/modules/scene/include/vkcv/scene/Mesh.hpp index 2d0a6bec..899e5e0c 100644 --- a/modules/scene/include/vkcv/scene/Mesh.hpp +++ b/modules/scene/include/vkcv/scene/Mesh.hpp @@ -14,13 +14,13 @@ namespace vkcv::scene { friend class Node; private: - Scene* m_scene; + Scene& m_scene; std::vector<MeshPart> m_parts; std::vector<DrawcallInfo> m_drawcalls; glm::mat4 m_transform; Bounds m_bounds; - explicit Mesh(Scene* scene); + explicit Mesh(Scene& scene); void load(const asset::Scene& scene, const asset::Mesh& mesh); @@ -35,8 +35,8 @@ namespace vkcv::scene { public: ~Mesh(); - Mesh(const Mesh& other); - Mesh(Mesh&& other) noexcept; + Mesh(const Mesh& other) = default; + Mesh(Mesh&& other) = default; Mesh& operator=(const Mesh& other); Mesh& operator=(Mesh&& other) noexcept; diff --git a/modules/scene/include/vkcv/scene/MeshPart.hpp b/modules/scene/include/vkcv/scene/MeshPart.hpp index 4b64d1d0..027c6f20 100644 --- a/modules/scene/include/vkcv/scene/MeshPart.hpp +++ b/modules/scene/include/vkcv/scene/MeshPart.hpp @@ -17,7 +17,7 @@ namespace vkcv::scene { friend class Mesh; private: - Scene* m_scene; + Scene& m_scene; BufferHandle m_vertices; std::vector<VertexBufferBinding> m_vertexBindings; BufferHandle m_indices; @@ -25,7 +25,7 @@ namespace vkcv::scene { Bounds m_bounds; size_t m_materialIndex; - explicit MeshPart(Scene* scene); + explicit MeshPart(Scene& scene); void load(const asset::Scene& scene, const asset::VertexGroup& vertexGroup, @@ -34,8 +34,8 @@ namespace vkcv::scene { public: ~MeshPart(); - MeshPart(const MeshPart& other); - MeshPart(MeshPart&& other) noexcept; + MeshPart(const MeshPart& other) = default; + MeshPart(MeshPart&& other) = default; MeshPart& operator=(const MeshPart& other); MeshPart& operator=(MeshPart&& other) noexcept; diff --git a/modules/scene/include/vkcv/scene/Node.hpp b/modules/scene/include/vkcv/scene/Node.hpp index 0323fa31..0772172d 100644 --- a/modules/scene/include/vkcv/scene/Node.hpp +++ b/modules/scene/include/vkcv/scene/Node.hpp @@ -15,13 +15,15 @@ namespace vkcv::scene { friend class Scene; private: - Scene* m_scene; + Scene& m_scene; std::vector<Mesh> m_meshes; std::vector<Node> m_nodes; Bounds m_bounds; - explicit Node(Scene* scene); + explicit Node(Scene& scene); + + void addMesh(const Mesh& mesh); void loadMesh(const asset::Scene& asset_scene, const asset::Mesh& asset_mesh); @@ -29,16 +31,23 @@ namespace vkcv::scene { std::vector<glm::mat4>& matrices, std::vector<DrawcallInfo>& drawcalls); + void splitMeshesToSubNodes(size_t maxMeshesPerNode); + [[nodiscard]] size_t getDrawcallCount() const; - Node& addNode(); + size_t addNode(); + + Node& getNode(size_t index); + + [[nodiscard]] + const Node& getNode(size_t index) const; public: ~Node(); - Node(const Node& other); - Node(Node&& other) noexcept; + Node(const Node& other) = default; + Node(Node&& other) = default; Node& operator=(const Node& other); Node& operator=(Node&& other) noexcept; diff --git a/modules/scene/include/vkcv/scene/Scene.hpp b/modules/scene/include/vkcv/scene/Scene.hpp index eb14e99f..d9104ab4 100644 --- a/modules/scene/include/vkcv/scene/Scene.hpp +++ b/modules/scene/include/vkcv/scene/Scene.hpp @@ -1,6 +1,7 @@ #pragma once #include <filesystem> +#include <mutex> #include <vkcv/Core.hpp> #include <vkcv/camera/Camera.hpp> @@ -26,6 +27,19 @@ namespace vkcv::scene { explicit Scene(Core* core); + size_t addNode(); + + Node& getNode(size_t index); + + const Node& getNode(size_t index) const; + + void increaseMaterialUsage(size_t index); + + void decreaseMaterialUsage(size_t index); + + void loadMaterial(size_t index, const asset::Scene& scene, + const asset::Material& material); + public: ~Scene(); @@ -35,8 +49,6 @@ namespace vkcv::scene { Scene& operator=(const Scene& other); Scene& operator=(Scene&& other) noexcept; - Node& addNode(); - size_t getMaterialCount() const; [[nodiscard]] diff --git a/modules/scene/src/vkcv/scene/Mesh.cpp b/modules/scene/src/vkcv/scene/Mesh.cpp index 683e660c..ff93029e 100644 --- a/modules/scene/src/vkcv/scene/Mesh.cpp +++ b/modules/scene/src/vkcv/scene/Mesh.cpp @@ -5,7 +5,7 @@ namespace vkcv::scene { - Mesh::Mesh(Scene* scene) : + Mesh::Mesh(Scene& scene) : m_scene(scene) {} static glm::mat4 arrayTo4x4Matrix(const std::array<float,16>& array){ @@ -56,27 +56,17 @@ namespace vkcv::scene { m_parts.clear(); } - Mesh::Mesh(const Mesh &other) : - m_scene(other.m_scene), - m_parts(other.m_parts), - m_drawcalls(other.m_drawcalls), - m_transform(other.m_transform), - m_bounds(other.m_bounds) {} - - Mesh::Mesh(Mesh &&other) noexcept : - m_scene(other.m_scene), - m_parts(other.m_parts), - m_drawcalls(other.m_drawcalls), - m_transform(other.m_transform), - m_bounds(other.m_bounds) {} - Mesh &Mesh::operator=(const Mesh &other) { if (&other == this) { return *this; } - m_scene = other.m_scene; - m_parts = std::vector<MeshPart>(other.m_parts); + m_parts.resize(other.m_parts.size(), MeshPart(m_scene)); + + for (size_t i = 0; i < m_parts.size(); i++) { + m_parts[i] = other.m_parts[i]; + } + m_drawcalls = std::vector<DrawcallInfo>(other.m_drawcalls); m_transform = other.m_transform; m_bounds = other.m_bounds; @@ -85,8 +75,12 @@ namespace vkcv::scene { } Mesh &Mesh::operator=(Mesh &&other) noexcept { - m_scene = other.m_scene; - m_parts = std::move(other.m_parts); + m_parts.resize(other.m_parts.size(), MeshPart(m_scene)); + + for (size_t i = 0; i < m_parts.size(); i++) { + m_parts[i] = std::move(other.m_parts[i]); + } + m_drawcalls = std::move(other.m_drawcalls); m_transform = other.m_transform; m_bounds = other.m_bounds; diff --git a/modules/scene/src/vkcv/scene/MeshPart.cpp b/modules/scene/src/vkcv/scene/MeshPart.cpp index acaa14e0..4bed429a 100644 --- a/modules/scene/src/vkcv/scene/MeshPart.cpp +++ b/modules/scene/src/vkcv/scene/MeshPart.cpp @@ -4,116 +4,19 @@ namespace vkcv::scene { - MeshPart::MeshPart(Scene* scene) : - m_scene(scene), - m_vertices(), - m_vertexBindings(), - m_indices(), - m_indexCount(0), - m_bounds(), - m_materialIndex(std::numeric_limits<size_t>::max()) {} - - static void loadImage(Core& core, const asset::Scene& asset_scene, - const asset::Texture& asset_texture, - const vk::Format& format, - ImageHandle& image, SamplerHandle& sampler) { - asset::Sampler* asset_sampler = nullptr; - - if ((asset_texture.sampler >= 0) && (asset_texture.sampler < asset_scene.samplers.size())) { - //asset_sampler = &(asset_scene.samplers[asset_texture.sampler]); // TODO - } - - Image img = core.createImage(format, asset_texture.w, asset_texture.h); - img.fill(asset_texture.data.data()); - image = img.getHandle(); - - if (asset_sampler) { - //sampler = core.createSampler(asset_sampler) // TODO - } else { - sampler = core.createSampler( - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - vkcv::SamplerAddressMode::REPEAT - ); - } - } - - static material::Material loadMaterial(Core& core, const asset::Scene& scene, - const asset::Material& material) { - ImageHandle diffuseImg; - SamplerHandle diffuseSmp; - - if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { - loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, - diffuseImg,diffuseSmp); - } - - ImageHandle normalImg; - SamplerHandle normalSmp; - - if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { - loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, - diffuseImg,diffuseSmp); - } - - ImageHandle metalRoughImg; - SamplerHandle metalRoughSmp; - - if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { - loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, - diffuseImg,diffuseSmp); - } - - ImageHandle occlusionImg; - SamplerHandle occlusionSmp; - - if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { - loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, - diffuseImg,diffuseSmp); - } - - ImageHandle emissionImg; - SamplerHandle emissionSmp; - - if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { - loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, - diffuseImg,diffuseSmp); - } - - const float colorFactors [4] = { - material.baseColorFactor.r, - material.baseColorFactor.g, - material.baseColorFactor.b, - material.baseColorFactor.a - }; - - const float emissionFactors[4] = { - material.emissiveFactor.r, - material.emissiveFactor.g, - material.emissiveFactor.b - }; - - return material::Material::createPBR( - core, - diffuseImg, diffuseSmp, - normalImg, normalSmp, - metalRoughImg, metalRoughSmp, - occlusionImg, occlusionSmp, - emissionImg, emissionSmp, - colorFactors, - material.normalScale, - material.metallicFactor, - material.roughnessFactor, - material.occlusionStrength, - emissionFactors - ); - } + MeshPart::MeshPart(Scene& scene) : + m_scene(scene), + m_vertices(), + m_vertexBindings(), + m_indices(), + m_indexCount(0), + m_bounds(), + m_materialIndex(std::numeric_limits<size_t>::max()) {} void MeshPart::load(const asset::Scene& scene, const asset::VertexGroup &vertexGroup, std::vector<DrawcallInfo>& drawcalls) { - Core& core = *(m_scene->m_core); + Core& core = *(m_scene.m_core); auto vertexBuffer = core.createBuffer<uint8_t>( BufferType::VERTEX, vertexGroup.vertexBuffer.data.size() @@ -156,11 +59,11 @@ namespace vkcv::scene { (vertexGroup.materialIndex < scene.materials.size())) { m_materialIndex = vertexGroup.materialIndex; - auto& material = m_scene->m_materials[m_materialIndex]; - - if (0 == material.m_usages++) { - material.m_data = loadMaterial(core, scene, scene.materials[vertexGroup.materialIndex]); + if (!getMaterial()) { + m_scene.loadMaterial(m_materialIndex, scene, scene.materials[vertexGroup.materialIndex]); } + + m_scene.increaseMaterialUsage(m_materialIndex); } else { m_materialIndex = std::numeric_limits<size_t>::max(); } @@ -177,39 +80,7 @@ namespace vkcv::scene { } MeshPart::~MeshPart() { - if ((m_scene->m_core) && (m_materialIndex < m_scene->m_materials.size())) { - auto& material = m_scene->m_materials[m_materialIndex]; - - if (material.m_usages > 0) { - material.m_usages--; - } - } - } - - MeshPart::MeshPart(const MeshPart &other) : - m_scene(other.m_scene), - m_vertices(other.m_vertices), - m_vertexBindings(other.m_vertexBindings), - m_indices(other.m_indices), - m_indexCount(other.m_indexCount), - m_bounds(other.m_bounds), - m_materialIndex(other.m_materialIndex) { - if (m_materialIndex < std::numeric_limits<size_t>::max()) { - auto& material = m_scene->m_materials[m_materialIndex]; - - material.m_usages++; - } - } - - MeshPart::MeshPart(MeshPart &&other) noexcept : - m_scene(other.m_scene), - m_vertices(other.m_vertices), - m_vertexBindings(other.m_vertexBindings), - m_indices(other.m_indices), - m_indexCount(other.m_indexCount), - m_bounds(other.m_bounds), - m_materialIndex(other.m_materialIndex) { - other.m_materialIndex = std::numeric_limits<size_t>::max(); + m_scene.decreaseMaterialUsage(m_materialIndex); } MeshPart &MeshPart::operator=(const MeshPart &other) { @@ -217,7 +88,6 @@ namespace vkcv::scene { return *this; } - m_scene = other.m_scene; m_vertices = other.m_vertices; m_vertexBindings = other.m_vertexBindings; m_indices = other.m_indices; @@ -229,7 +99,6 @@ namespace vkcv::scene { } MeshPart &MeshPart::operator=(MeshPart &&other) noexcept { - m_scene = other.m_scene; m_vertices = other.m_vertices; m_vertexBindings = other.m_vertexBindings; m_indices = other.m_indices; @@ -243,18 +112,12 @@ namespace vkcv::scene { } const material::Material & MeshPart::getMaterial() const { - static material::Material noMaterial; - - if (m_materialIndex < m_scene->m_materials.size()) { - return m_scene->m_materials[m_materialIndex].m_data; - } else { - return noMaterial; - } + return m_scene.getMaterial(m_materialIndex); } MeshPart::operator bool() const { return ( - (m_materialIndex < m_scene->m_materials.size()) && + (getMaterial()) && (m_vertices) && (m_indices) ); @@ -262,7 +125,7 @@ namespace vkcv::scene { bool MeshPart::operator!() const { return ( - (m_materialIndex >= m_scene->m_materials.size()) || + (!getMaterial()) || (!m_vertices) || (!m_indices) ); diff --git a/modules/scene/src/vkcv/scene/Node.cpp b/modules/scene/src/vkcv/scene/Node.cpp index ab65091c..906e00e8 100644 --- a/modules/scene/src/vkcv/scene/Node.cpp +++ b/modules/scene/src/vkcv/scene/Node.cpp @@ -1,10 +1,13 @@ #include "vkcv/scene/Node.hpp" +#include "vkcv/scene/Scene.hpp" #include "Frustum.hpp" +#include <algorithm> + namespace vkcv::scene { - Node::Node(Scene* scene) : + Node::Node(Scene& scene) : m_scene(scene), m_meshes(), m_nodes(), @@ -15,44 +18,47 @@ namespace vkcv::scene { m_meshes.clear(); } - Node::Node(const Node &other) : - m_scene(other.m_scene), - m_meshes(other.m_meshes), - m_nodes(other.m_nodes), - m_bounds(other.m_bounds) {} - - Node::Node(Node &&other) noexcept : - m_scene(other.m_scene), - m_meshes(other.m_meshes), - m_nodes(other.m_nodes), - m_bounds(other.m_bounds) {} - Node &Node::operator=(const Node &other) { if (&other == this) { return *this; } - m_scene = other.m_scene; - m_meshes = std::vector<Mesh>(other.m_meshes); - m_nodes = std::vector<Node>(other.m_nodes); + m_meshes.resize(other.m_meshes.size(), Mesh(m_scene)); + + for (size_t i = 0; i < m_meshes.size(); i++) { + m_meshes[i] = other.m_meshes[i]; + } + + m_nodes.resize(other.m_nodes.size(), Node(m_scene)); + + for (size_t i = 0; i < m_nodes.size(); i++) { + m_nodes[i] = other.m_nodes[i]; + } + m_bounds = other.m_bounds; return *this; } Node &Node::operator=(Node &&other) noexcept { - m_scene = other.m_scene; - m_meshes = std::move(other.m_meshes); - m_nodes = std::move(other.m_nodes); + m_meshes.resize(other.m_meshes.size(), Mesh(m_scene)); + + for (size_t i = 0; i < m_meshes.size(); i++) { + m_meshes[i] = std::move(other.m_meshes[i]); + } + + m_nodes.resize(other.m_nodes.size(), Node(m_scene)); + + for (size_t i = 0; i < m_nodes.size(); i++) { + m_nodes[i] = std::move(other.m_nodes[i]); + } + m_bounds = other.m_bounds; return *this; } - void Node::loadMesh(const asset::Scene &asset_scene, const asset::Mesh &asset_mesh) { - Mesh mesh (m_scene); - mesh.load(asset_scene, asset_mesh); - + void Node::addMesh(const Mesh& mesh) { if (m_meshes.empty()) { m_bounds = mesh.getBounds(); } else { @@ -63,10 +69,25 @@ namespace vkcv::scene { m_meshes.push_back(mesh); } - Node& Node::addNode() { - Node node (this->m_scene); + void Node::loadMesh(const asset::Scene &asset_scene, const asset::Mesh &asset_mesh) { + Mesh mesh (m_scene); + mesh.load(asset_scene, asset_mesh); + addMesh(mesh); + } + + size_t Node::addNode() { + const Node node (m_scene); + const size_t index = m_nodes.size(); m_nodes.push_back(node); - return m_nodes.back(); + return index; + } + + Node& Node::getNode(size_t index) { + return m_nodes[index]; + } + + const Node& Node::getNode(size_t index) const { + return m_nodes[index]; } void Node::recordDrawcalls(const glm::mat4& viewProjection, @@ -85,6 +106,67 @@ namespace vkcv::scene { } } + void Node::splitMeshesToSubNodes(size_t maxMeshesPerNode) { + if (m_meshes.size() <= maxMeshesPerNode) { + return; + } + + const auto split = m_bounds.getCenter(); + int axis = 0; + + const auto size = m_bounds.getSize(); + + if (size[1] > size[0]) { + if (size[2] > size[1]) { + axis = 2; + } else { + axis = 1; + } + } else + if (size[2] > size[0]) { + axis = 2; + } + + std::vector<size_t> left_meshes; + std::vector<size_t> right_meshes; + + for (size_t i = 0; i < m_meshes.size(); i++) { + const auto& bounds = m_meshes[i].getBounds(); + + if (bounds.getMax()[axis] <= split[axis]) { + left_meshes.push_back(i); + } else + if (bounds.getMin()[axis] >= split[axis]) { + right_meshes.push_back(i); + } + } + + if ((left_meshes.empty()) || (right_meshes.empty())) { + return; + } + + const size_t left = addNode(); + const size_t right = addNode(); + + for (size_t i : left_meshes) { + getNode(left).addMesh(m_meshes[i]); + } + + for (size_t i : right_meshes) { + getNode(right).addMesh(m_meshes[i]); + left_meshes.push_back(i); + } + + std::sort(left_meshes.begin(), left_meshes.end(), std::greater()); + + for (size_t i : left_meshes) { + m_meshes.erase(m_meshes.begin() + static_cast<long>(i)); + } + + getNode(left).splitMeshesToSubNodes(maxMeshesPerNode); + getNode(right).splitMeshesToSubNodes(maxMeshesPerNode); + } + size_t Node::getDrawcallCount() const { size_t count = 0; diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp index da0f7fb6..1a5f76e5 100644 --- a/modules/scene/src/vkcv/scene/Scene.cpp +++ b/modules/scene/src/vkcv/scene/Scene.cpp @@ -19,12 +19,24 @@ namespace vkcv::scene { Scene::Scene(const Scene &other) : m_core(other.m_core), m_materials(other.m_materials), - m_nodes(other.m_nodes) {} + m_nodes() { + m_nodes.resize(other.m_nodes.size(), Node(*this)); + + for (size_t i = 0; i < m_nodes.size(); i++) { + m_nodes[i] = other.m_nodes[i]; + } + } Scene::Scene(Scene &&other) noexcept : m_core(other.m_core), m_materials(other.m_materials), - m_nodes(other.m_nodes) {} + m_nodes() { + m_nodes.resize(other.m_nodes.size(), Node(*this)); + + for (size_t i = 0; i < m_nodes.size(); i++) { + m_nodes[i] = std::move(other.m_nodes[i]); + } + } Scene &Scene::operator=(const Scene &other) { if (&other == this) { @@ -33,7 +45,12 @@ namespace vkcv::scene { m_core = other.m_core; m_materials = std::vector<Material>(other.m_materials); - m_nodes = std::vector<Node>(other.m_nodes); + + m_nodes.resize(other.m_nodes.size(), Node(*this)); + + for (size_t i = 0; i < m_nodes.size(); i++) { + m_nodes[i] = other.m_nodes[i]; + } return *this; } @@ -41,15 +58,41 @@ namespace vkcv::scene { Scene &Scene::operator=(Scene &&other) noexcept { m_core = other.m_core; m_materials = std::move(other.m_materials); - m_nodes = std::move(other.m_nodes); + + m_nodes.resize(other.m_nodes.size(), Node(*this)); + + for (size_t i = 0; i < m_nodes.size(); i++) { + m_nodes[i] = std::move(other.m_nodes[i]); + } return *this; } - Node& Scene::addNode() { - Node node (this); + size_t Scene::addNode() { + const Node node (*this); + const size_t index = m_nodes.size(); m_nodes.push_back(node); - return m_nodes.back(); + return index; + } + + Node& Scene::getNode(size_t index) { + return m_nodes[index]; + } + + const Node& Scene::getNode(size_t index) const { + return m_nodes[index]; + } + + void Scene::increaseMaterialUsage(size_t index) { + if (index < m_materials.size()) { + m_materials[index].m_usages++; + } + } + + void Scene::decreaseMaterialUsage(size_t index) { + if ((index < m_materials.size()) && (m_materials[index].m_usages > 0)) { + m_materials[index].m_usages--; + } } size_t Scene::getMaterialCount() const { @@ -100,6 +143,107 @@ namespace vkcv::scene { return Scene(&core); } + static void loadImage(Core& core, const asset::Scene& asset_scene, + const asset::Texture& asset_texture, + const vk::Format& format, + ImageHandle& image, SamplerHandle& sampler) { + asset::Sampler* asset_sampler = nullptr; + + if ((asset_texture.sampler >= 0) && (asset_texture.sampler < asset_scene.samplers.size())) { + //asset_sampler = &(asset_scene.samplers[asset_texture.sampler]); // TODO + } + + Image img = core.createImage(format, asset_texture.w, asset_texture.h); + img.fill(asset_texture.data.data()); + image = img.getHandle(); + + if (asset_sampler) { + //sampler = core.createSampler(asset_sampler) // TODO + } else { + sampler = core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + } + } + + void Scene::loadMaterial(size_t index, const asset::Scene& scene, + const asset::Material& material) { + if (index >= m_materials.size()) { + return; + } + + ImageHandle diffuseImg; + SamplerHandle diffuseSmp; + + if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { + loadImage(*m_core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, + diffuseImg,diffuseSmp); + } + + ImageHandle normalImg; + SamplerHandle normalSmp; + + if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { + loadImage(*m_core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, + diffuseImg,diffuseSmp); + } + + ImageHandle metalRoughImg; + SamplerHandle metalRoughSmp; + + if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { + loadImage(*m_core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, + diffuseImg,diffuseSmp); + } + + ImageHandle occlusionImg; + SamplerHandle occlusionSmp; + + if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { + loadImage(*m_core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, + diffuseImg,diffuseSmp); + } + + ImageHandle emissionImg; + SamplerHandle emissionSmp; + + if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { + loadImage(*m_core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, + diffuseImg,diffuseSmp); + } + + const float colorFactors [4] = { + material.baseColorFactor.r, + material.baseColorFactor.g, + material.baseColorFactor.b, + material.baseColorFactor.a + }; + + const float emissionFactors[4] = { + material.emissiveFactor.r, + material.emissiveFactor.g, + material.emissiveFactor.b + }; + + m_materials[index].m_data = material::Material::createPBR( + *m_core, + diffuseImg, diffuseSmp, + normalImg, normalSmp, + metalRoughImg, metalRoughSmp, + occlusionImg, occlusionSmp, + emissionImg, emissionSmp, + colorFactors, + material.normalScale, + material.metallicFactor, + material.roughnessFactor, + material.occlusionStrength, + emissionFactors + ); + } + Scene Scene::load(Core& core, const std::filesystem::path &path) { asset::Scene asset_scene; @@ -116,12 +260,13 @@ namespace vkcv::scene { }); } - Node& node = scene.addNode(); + const size_t root = scene.addNode(); for (const auto& mesh : asset_scene.meshes) { - node.loadMesh(asset_scene, mesh); + scene.getNode(root).loadMesh(asset_scene, mesh); } + scene.getNode(root).splitMeshesToSubNodes(128); return scene; } -- GitLab