From cd2a6269add4868870ea977b92dc928b77398b9c Mon Sep 17 00:00:00 2001 From: snowapril Date: Sun, 29 Oct 2023 19:13:40 +0900 Subject: [PATCH 1/3] feat : add initial sdf global illumination pass class --- .../RenderPass/SDFGlobalIlluminationPass.hpp | 38 +++++++++++++++++++ Sources/VoxFlow/Editor/CMakeLists.txt | 2 + .../RenderPass/SDFGlobalIlluminationPass.cpp | 35 +++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 Includes/VoxFlow/Editor/RenderPass/SDFGlobalIlluminationPass.hpp create mode 100644 Sources/VoxFlow/Editor/RenderPass/SDFGlobalIlluminationPass.cpp diff --git a/Includes/VoxFlow/Editor/RenderPass/SDFGlobalIlluminationPass.hpp b/Includes/VoxFlow/Editor/RenderPass/SDFGlobalIlluminationPass.hpp new file mode 100644 index 00000000..052cccfb --- /dev/null +++ b/Includes/VoxFlow/Editor/RenderPass/SDFGlobalIlluminationPass.hpp @@ -0,0 +1,38 @@ +// Author : snowapril + +#ifndef VOXEL_FLOW_SDF_GLOBAL_ILLUMINATION_PASS_HPP +#define VOXEL_FLOW_SDF_GLOBAL_ILLUMINATION_PASS_HPP + +#include +#include +#include +#include + +namespace VoxFlow +{ +class RenderDevice; +class Buffer; +class LogicalDevice; + +namespace RenderGraph +{ +class FrameGraph; +} + +class SDFGlobalIlluminationPass : public SceneRenderPass +{ + public: + SDFGlobalIlluminationPass(LogicalDevice* logicalDevice); + ~SDFGlobalIlluminationPass() override; + + public: + bool initialize() override; + void updateRender(ResourceUploadContext* uploadContext) override; + void renderScene(RenderGraph::FrameGraph* frameGraph) override; + + protected: + LogicalDevice* _logicalDevice = nullptr; +}; +} // namespace VoxFlow + +#endif \ No newline at end of file diff --git a/Sources/VoxFlow/Editor/CMakeLists.txt b/Sources/VoxFlow/Editor/CMakeLists.txt index 57410f2b..d091e8f7 100644 --- a/Sources/VoxFlow/Editor/CMakeLists.txt +++ b/Sources/VoxFlow/Editor/CMakeLists.txt @@ -9,6 +9,7 @@ set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../) set(PUBLIC_HDRS ${PUBLIC_HDR_DIR}/VoxFlow/Editor/RenderPass/PostProcessPass.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Editor/RenderPass/SceneObjectPass.hpp + ${PUBLIC_HDR_DIR}/VoxFlow/Editor/RenderPass/SDFGlobalIlluminationPass.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Editor/VoxEditor.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Editor/VoxFlow.hpp ) @@ -17,6 +18,7 @@ set(PUBLIC_HDRS set(SRCS ${SRC_DIR}/Editor/RenderPass/PostProcessPass.cpp ${SRC_DIR}/Editor/RenderPass/SceneObjectPass.cpp + ${SRC_DIR}/Editor/RenderPass/SDFGlobalIlluminationPass.cpp ${SRC_DIR}/Editor/VoxEditor.cpp ${SRC_DIR}/Editor/VoxFlow.cpp ${SRC_DIR}/Editor/WinMain.cpp diff --git a/Sources/VoxFlow/Editor/RenderPass/SDFGlobalIlluminationPass.cpp b/Sources/VoxFlow/Editor/RenderPass/SDFGlobalIlluminationPass.cpp new file mode 100644 index 00000000..70a99d3f --- /dev/null +++ b/Sources/VoxFlow/Editor/RenderPass/SDFGlobalIlluminationPass.cpp @@ -0,0 +1,35 @@ +// Author : snowapril + +#include +#include +#include +#include +#include + +namespace VoxFlow +{ + +SDFGlobalIlluminationPass::SDFGlobalIlluminationPass(LogicalDevice* logicalDevice) : _logicalDevice(logicalDevice) +{ +} + +SDFGlobalIlluminationPass::~SDFGlobalIlluminationPass() +{ +} + +bool SDFGlobalIlluminationPass::initialize() +{ + return true; +} + +void SDFGlobalIlluminationPass::updateRender(ResourceUploadContext* uploadContext) +{ + (void)uploadContext; +} + +void SDFGlobalIlluminationPass::renderScene(RenderGraph::FrameGraph* frameGraph) +{ + (void)frameGraph; +} + +} // namespace VoxFlow \ No newline at end of file From c32abd42d2ee640428b6a24348e77658afffaec6 Mon Sep 17 00:00:00 2001 From: snowapril Date: Sat, 4 Nov 2023 15:57:48 +0900 Subject: [PATCH 2/3] feat : add initial gltf loader implementations --- CMakeLists.txt | 17 +- Dependencies/bootstrap.json | 6 +- .../VoxFlow/Core/Devices/LogicalDevice.hpp | 2 +- Includes/VoxFlow/Core/Devices/SwapChain.hpp | 2 +- .../Graphics/RenderPass/RenderPassParams.hpp | 2 +- Includes/VoxFlow/Core/Scene/Material.hpp | 14 + .../Core/Scene/PrimitiveBufferPool.hpp | 14 + Includes/VoxFlow/Core/Scene/SceneObject.hpp | 14 + .../VoxFlow/Core/Scene/SceneObjectLoader.hpp | 26 ++ Includes/VoxFlow/Core/Utils/MathUtils.hpp | 19 + .../VoxFlow/Core/Utils/RendererCommon.hpp | 4 +- Sources/VoxFlow/Core/CMakeLists.txt | 9 + Sources/VoxFlow/Core/Devices/Queue.cpp | 2 +- Sources/VoxFlow/Core/Devices/SwapChain.cpp | 3 +- .../Core/FrameGraph/FrameGraphPass.cpp | 2 +- .../DescriptorSetAllocatorPool.cpp | 2 +- Sources/VoxFlow/Core/Scene/Material.cpp | 7 + .../Core/Scene/PrimitiveBufferPool.cpp | 7 + Sources/VoxFlow/Core/Scene/SceneObject.cpp | 7 + .../VoxFlow/Core/Scene/SceneObjectLoader.cpp | 381 ++++++++++++++++++ 20 files changed, 510 insertions(+), 30 deletions(-) create mode 100644 Includes/VoxFlow/Core/Scene/Material.hpp create mode 100644 Includes/VoxFlow/Core/Scene/PrimitiveBufferPool.hpp create mode 100644 Includes/VoxFlow/Core/Scene/SceneObject.hpp create mode 100644 Includes/VoxFlow/Core/Scene/SceneObjectLoader.hpp create mode 100644 Includes/VoxFlow/Core/Utils/MathUtils.hpp create mode 100644 Sources/VoxFlow/Core/Scene/Material.cpp create mode 100644 Sources/VoxFlow/Core/Scene/PrimitiveBufferPool.cpp create mode 100644 Sources/VoxFlow/Core/Scene/SceneObject.cpp create mode 100644 Sources/VoxFlow/Core/Scene/SceneObjectLoader.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e23dea99..af5f7b6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,7 +75,7 @@ include_directories(Dependencies/src/vulkan/include) include_directories(Dependencies/src/vma/src) include_directories(Dependencies/src/glfw/include) include_directories(Dependencies/src/glm) -include_directories(Dependencies/src/assimp/include) +include_directories(Dependencies/src/tinygltf) include_directories(Dependencies/src/etc2comp/EtcLib/Etc) include_directories(Dependencies/src/etc2comp/EtcLib/EtcCodec) include_directories(Dependencies/src/glslang/glslang/Include) @@ -103,16 +103,6 @@ set(GLFW_BUILD_DOCS OFF CACHE BOOL "") set(GLFW_INSTALL OFF CACHE BOOL "") add_subdirectory(Dependencies/src/glfw) -set(ASSIMP_NO_EXPORT ON CACHE BOOL "") -set(ASSIMP_BUILD_DRACO OFF CACHE BOOL "") -set(ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE BOOL "") -set(ASSIMP_BUILD_TESTS OFF CACHE BOOL "") -set(ASSIMP_INSTALL_PDB OFF CACHE BOOL "") -set(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT OFF CACHE BOOL "") -set(ASSIMP_BUILD_OBJ_IMPORTER ON CACHE BOOL "") -set(ASSIMP_BUILD_GLTF_IMPORTER ON CACHE BOOL "") -add_subdirectory(Dependencies/src/assimp) - set(MESHOPT_BUILD_DEMO OFF CACHE BOOL "") set(MESHOPT_BUILD_TOOLS OFF CACHE BOOL "") set(MESHOPT_BUILD_SHARED_LIBS OFF CACHE BOOL "") @@ -153,15 +143,10 @@ add_subdirectory(Dependencies/src/backward-cpp) set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(TARGET glfw PROPERTY FOLDER "ThirdPartyLibraries") -set_property(TARGET assimp PROPERTY FOLDER "ThirdPartyLibraries") set_property(TARGET EtcLib PROPERTY FOLDER "ThirdPartyLibraries") set_property(TARGET EtcTool PROPERTY FOLDER "ThirdPartyLibraries") set_property(TARGET meshoptimizer PROPERTY FOLDER "ThirdPartyLibraries") set_property(TARGET volk PROPERTY FOLDER "ThirdPartyLibraries") -if(WIN32) - set_property(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs PROPERTY FOLDER "ThirdPartyLibraries") -endif() -set_property(TARGET uninstall PROPERTY FOLDER "ThirdPartyLibraries") set_property(TARGET glslang PROPERTY FOLDER "ThirdPartyLibraries/glslang") set_property(TARGET OGLCompiler PROPERTY FOLDER "ThirdPartyLibraries/glslang") set_property(TARGET OSDependent PROPERTY FOLDER "ThirdPartyLibraries/glslang") diff --git a/Dependencies/bootstrap.json b/Dependencies/bootstrap.json index dbb51bd4..47aa8860 100644 --- a/Dependencies/bootstrap.json +++ b/Dependencies/bootstrap.json @@ -64,11 +64,11 @@ } }, { - "name": "assimp", + "name": "tinygltf", "source": { "type": "git", - "url": "https://github.com/assimp/assimp.git", - "revision": "a9f82dbe0b8a658003f93c7b5108ee4521458a18" + "url": "https://github.com/syoyo/tinygltf.git", + "revision": "v2.8.18" } }, { diff --git a/Includes/VoxFlow/Core/Devices/LogicalDevice.hpp b/Includes/VoxFlow/Core/Devices/LogicalDevice.hpp index 155dc45d..c7cb4f39 100644 --- a/Includes/VoxFlow/Core/Devices/LogicalDevice.hpp +++ b/Includes/VoxFlow/Core/Devices/LogicalDevice.hpp @@ -8,8 +8,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/Includes/VoxFlow/Core/Devices/SwapChain.hpp b/Includes/VoxFlow/Core/Devices/SwapChain.hpp index f6b1e04b..b69c803f 100644 --- a/Includes/VoxFlow/Core/Devices/SwapChain.hpp +++ b/Includes/VoxFlow/Core/Devices/SwapChain.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include struct GLFWwindow; diff --git a/Includes/VoxFlow/Core/Graphics/RenderPass/RenderPassParams.hpp b/Includes/VoxFlow/Core/Graphics/RenderPass/RenderPassParams.hpp index fb532bcb..95cecf11 100644 --- a/Includes/VoxFlow/Core/Graphics/RenderPass/RenderPassParams.hpp +++ b/Includes/VoxFlow/Core/Graphics/RenderPass/RenderPassParams.hpp @@ -6,8 +6,8 @@ #include #include #include +#include #include -#include namespace VoxFlow { diff --git a/Includes/VoxFlow/Core/Scene/Material.hpp b/Includes/VoxFlow/Core/Scene/Material.hpp new file mode 100644 index 00000000..2856261d --- /dev/null +++ b/Includes/VoxFlow/Core/Scene/Material.hpp @@ -0,0 +1,14 @@ +// Author : snowapril + +#ifndef VOX_FLOW_MATERIAL_HPP +#define VOX_FLOW_MATERIAL_HPP + +namespace VoxFlow +{ +class Material +{ + public: +}; +} // namespace VoxFlow + +#endif // VOX_FLOW_MATERIAL_HPP \ No newline at end of file diff --git a/Includes/VoxFlow/Core/Scene/PrimitiveBufferPool.hpp b/Includes/VoxFlow/Core/Scene/PrimitiveBufferPool.hpp new file mode 100644 index 00000000..e0a57613 --- /dev/null +++ b/Includes/VoxFlow/Core/Scene/PrimitiveBufferPool.hpp @@ -0,0 +1,14 @@ +// Author : snowapril + +#ifndef VOX_FLOW_PRIMITIVE_BUFFER_POOL_HPP +#define VOX_FLOW_PRIMITIVE_BUFFER_POOL_HPP + +namespace VoxFlow +{ +class PrimitiveBufferPool +{ + public: +}; +} // namespace VoxFlow + +#endif // VOX_FLOW_PRIMITIVE_BUFFER_POOL_HPP \ No newline at end of file diff --git a/Includes/VoxFlow/Core/Scene/SceneObject.hpp b/Includes/VoxFlow/Core/Scene/SceneObject.hpp new file mode 100644 index 00000000..fad44b40 --- /dev/null +++ b/Includes/VoxFlow/Core/Scene/SceneObject.hpp @@ -0,0 +1,14 @@ +// Author : snowapril + +#ifndef VOX_FLOW_SCENE_OBJECT_HPP +#define VOX_FLOW_SCENE_OBJECT_HPP + +namespace VoxFlow +{ +class SceneObject +{ + public: +}; +} // namespace VoxFlow + +#endif // VOX_FLOW_SCENE_OBJECT_HPP \ No newline at end of file diff --git a/Includes/VoxFlow/Core/Scene/SceneObjectLoader.hpp b/Includes/VoxFlow/Core/Scene/SceneObjectLoader.hpp new file mode 100644 index 00000000..211e38ae --- /dev/null +++ b/Includes/VoxFlow/Core/Scene/SceneObjectLoader.hpp @@ -0,0 +1,26 @@ +// Author : snowapril + +#ifndef VOX_FLOW_SCENE_OBJECT_LOADER_HPP +#define VOX_FLOW_SCENE_OBJECT_LOADER_HPP + +#include +#include +#include + +namespace VoxFlow +{ +class SceneObject; +class ResourceUploadContext; + +class SceneObjectLoader +{ + public: + SceneObjectLoader(); + ~SceneObjectLoader(); + + public: + std::shared_ptr loadSceneObjectObj(const std::string& objPath, ResourceUploadContext* uploadContext); +}; +} // namespace VoxFlow + +#endif // VOX_FLOW_SCENE_OBJECT_LOADER_HPP \ No newline at end of file diff --git a/Includes/VoxFlow/Core/Utils/MathUtils.hpp b/Includes/VoxFlow/Core/Utils/MathUtils.hpp new file mode 100644 index 00000000..5b9cdf47 --- /dev/null +++ b/Includes/VoxFlow/Core/Utils/MathUtils.hpp @@ -0,0 +1,19 @@ +// Author : snowapril + +#ifndef VOXEL_FLOW_MATH_UTILS_HPP +#define VOXEL_FLOW_MATH_UTILS_HPP + +#define GLM_FORCE_RADIANS +#define GLM_FORCE_DEPTH_ZERO_TO_ONE +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include + +namespace VoxFlow +{ + +} + +#endif // VOXEL_FLOW_MATH_UTILS_HPP \ No newline at end of file diff --git a/Includes/VoxFlow/Core/Utils/RendererCommon.hpp b/Includes/VoxFlow/Core/Utils/RendererCommon.hpp index 4a6d5f6d..a02807b3 100644 --- a/Includes/VoxFlow/Core/Utils/RendererCommon.hpp +++ b/Includes/VoxFlow/Core/Utils/RendererCommon.hpp @@ -6,10 +6,8 @@ #include #include #include +#include #include -#include -#include -#include #include #include #include diff --git a/Sources/VoxFlow/Core/CMakeLists.txt b/Sources/VoxFlow/Core/CMakeLists.txt index ac70e238..b124a5af 100644 --- a/Sources/VoxFlow/Core/CMakeLists.txt +++ b/Sources/VoxFlow/Core/CMakeLists.txt @@ -71,6 +71,10 @@ set(PUBLIC_HDRS ${PUBLIC_HDR_DIR}/VoxFlow/Core/Resources/RenderResourceGarbageCollector.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Core/Resources/RenderResourceMemoryPool.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Core/Resources/StagingBufferContext.hpp + ${PUBLIC_HDR_DIR}/VoxFlow/Core/Scene/SceneObject.hpp + ${PUBLIC_HDR_DIR}/VoxFlow/Core/Scene/SceneObjectLoader.hpp + ${PUBLIC_HDR_DIR}/VoxFlow/Core/Scene/PrimitiveBufferPool.hpp + ${PUBLIC_HDR_DIR}/VoxFlow/Core/Scene/Material.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Core/Utils/BitwiseOperators.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Core/Utils/ChromeTracer.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Core/Utils/DebugUtil.hpp @@ -78,6 +82,7 @@ set(PUBLIC_HDRS ${PUBLIC_HDR_DIR}/VoxFlow/Core/Utils/DecisionMaker.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Core/Utils/DeviceInputSubscriber.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Core/Utils/Logger.hpp + ${PUBLIC_HDR_DIR}/VoxFlow/Core/Utils/MathUtils.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Core/Utils/Thread.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Core/Utils/MemoryAllocator.hpp ${PUBLIC_HDR_DIR}/VoxFlow/Core/Utils/NonCopyable.hpp @@ -139,6 +144,10 @@ set(SRCS ${SRC_DIR}/Core/Resources/RenderResourceMemoryPool.cpp ${SRC_DIR}/Core/Resources/StagingBufferContext.cpp ${SRC_DIR}/Core/Resources/StagingBuffer.cpp + ${SRC_DIR}/Core/Scene/SceneObject.cpp + ${SRC_DIR}/Core/Scene/SceneObjectLoader.cpp + ${SRC_DIR}/Core/Scene/PrimitiveBufferPool.cpp + ${SRC_DIR}/Core/Scene/Material.cpp ${SRC_DIR}/Core/Utils/ChromeTracer.cpp ${SRC_DIR}/Core/Utils/DecisionMaker.cpp ${SRC_DIR}/Core/Utils/DeviceInputSubscriber.cpp diff --git a/Sources/VoxFlow/Core/Devices/Queue.cpp b/Sources/VoxFlow/Core/Devices/Queue.cpp index 869a06dc..b83ae35e 100644 --- a/Sources/VoxFlow/Core/Devices/Queue.cpp +++ b/Sources/VoxFlow/Core/Devices/Queue.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include namespace VoxFlow { diff --git a/Sources/VoxFlow/Core/Devices/SwapChain.cpp b/Sources/VoxFlow/Core/Devices/SwapChain.cpp index e579c14d..41709849 100644 --- a/Sources/VoxFlow/Core/Devices/SwapChain.cpp +++ b/Sources/VoxFlow/Core/Devices/SwapChain.cpp @@ -7,9 +7,8 @@ #include #include #include - #include -#include +#include namespace VoxFlow { diff --git a/Sources/VoxFlow/Core/FrameGraph/FrameGraphPass.cpp b/Sources/VoxFlow/Core/FrameGraph/FrameGraphPass.cpp index 66caecc6..78e83e19 100644 --- a/Sources/VoxFlow/Core/FrameGraph/FrameGraphPass.cpp +++ b/Sources/VoxFlow/Core/FrameGraph/FrameGraphPass.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include namespace VoxFlow { diff --git a/Sources/VoxFlow/Core/Graphics/Descriptors/DescriptorSetAllocatorPool.cpp b/Sources/VoxFlow/Core/Graphics/Descriptors/DescriptorSetAllocatorPool.cpp index 15361457..b404d556 100644 --- a/Sources/VoxFlow/Core/Graphics/Descriptors/DescriptorSetAllocatorPool.cpp +++ b/Sources/VoxFlow/Core/Graphics/Descriptors/DescriptorSetAllocatorPool.cpp @@ -5,8 +5,8 @@ #include #include #include +#include #include -#include namespace VoxFlow { diff --git a/Sources/VoxFlow/Core/Scene/Material.cpp b/Sources/VoxFlow/Core/Scene/Material.cpp new file mode 100644 index 00000000..c5e2f066 --- /dev/null +++ b/Sources/VoxFlow/Core/Scene/Material.cpp @@ -0,0 +1,7 @@ +// Author : snowapril + +#include + +namespace VoxFlow +{ +} // namespace VoxFlow \ No newline at end of file diff --git a/Sources/VoxFlow/Core/Scene/PrimitiveBufferPool.cpp b/Sources/VoxFlow/Core/Scene/PrimitiveBufferPool.cpp new file mode 100644 index 00000000..60ab37ad --- /dev/null +++ b/Sources/VoxFlow/Core/Scene/PrimitiveBufferPool.cpp @@ -0,0 +1,7 @@ +// Author : snowapril + +#include + +namespace VoxFlow +{ +} // namespace VoxFlow \ No newline at end of file diff --git a/Sources/VoxFlow/Core/Scene/SceneObject.cpp b/Sources/VoxFlow/Core/Scene/SceneObject.cpp new file mode 100644 index 00000000..001c620c --- /dev/null +++ b/Sources/VoxFlow/Core/Scene/SceneObject.cpp @@ -0,0 +1,7 @@ +// Author : snowapril + +#include + +namespace VoxFlow +{ +} // namespace VoxFlow \ No newline at end of file diff --git a/Sources/VoxFlow/Core/Scene/SceneObjectLoader.cpp b/Sources/VoxFlow/Core/Scene/SceneObjectLoader.cpp new file mode 100644 index 00000000..1ec7de9f --- /dev/null +++ b/Sources/VoxFlow/Core/Scene/SceneObjectLoader.cpp @@ -0,0 +1,381 @@ +// Author : snowapril + +#include + +#define TINYGLTF_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include + +#include +#include + +namespace VoxFlow +{ +// Initial codes from https://github.com/SaschaWillems/Vulkan/blob/master/examples/gltfloading/gltfloading.cpp +// Contains everything required to render a glTF model in Vulkan +// This class is heavily simplified (compared to glTF's feature set) but retains the basic glTF structure +class VulkanglTFModel +{ + public: + // The vertex layout for the samples' model + struct Vertex + { + glm::vec3 pos; + glm::vec3 normal; + glm::vec2 uv; + glm::vec3 color; + }; + + // The following structures roughly represent the glTF scene structure + // To keep things simple, they only contain those properties that are required for this sample + struct Node; + + // A primitive contains the data for a single draw call + struct Primitive + { + uint32_t firstIndex; + uint32_t indexCount; + int32_t materialIndex; + }; + + // Contains the node's (optional) geometry and can be made up of an arbitrary number of primitives + struct Mesh + { + std::vector primitives; + }; + + // A node represents an object in the glTF scene graph + struct Node + { + Node* parent; + std::vector children; + Mesh mesh; + glm::mat4 matrix; + ~Node() + { + for (auto& child : children) + { + delete child; + } + } + }; + + // A glTF material stores information in e.g. the texture that is attached to it and colors + struct Material + { + glm::vec4 baseColorFactor = glm::vec4(1.0f); + uint32_t baseColorTextureIndex; + }; + + // Contains the texture for a single glTF image + // Images may be reused by texture objects and are as such separated + struct Image + { + vks::Texture2D texture; + // We also store (and create) a descriptor set that's used to access this texture from the fragment shader + VkDescriptorSet descriptorSet; + }; + + // A glTF texture stores a reference to the image and a sampler + // In this sample, we are only interested in the image + struct Texture + { + int32_t imageIndex; + }; + + /* + Model data + */ + std::vector images; + std::vector textures; + std::vector materials; + std::vector nodes; + + ~VulkanglTFModel() + { + for (auto node : nodes) + { + delete node; + } + } + + /* + glTF loading functions + + The following functions take a glTF input model loaded via tinyglTF and convert all required data into our own structure + */ + + void loadImages(tinygltf::Model& input) + { + // Images can be stored inside the glTF (which is the case for the sample model), so instead of directly + // loading them from disk, we fetch them from the glTF loader and upload the buffers + images.resize(input.images.size()); + for (size_t i = 0; i < input.images.size(); i++) + { + tinygltf::Image& glTFImage = input.images[i]; + // Get the image data from the glTF loader + unsigned char* buffer = nullptr; + VkDeviceSize bufferSize = 0; + bool deleteBuffer = false; + // We convert RGB-only images to RGBA, as most devices don't support RGB-formats in Vulkan + if (glTFImage.component == 3) + { + bufferSize = glTFImage.width * glTFImage.height * 4; + buffer = new unsigned char[bufferSize]; + unsigned char* rgba = buffer; + unsigned char* rgb = &glTFImage.image[0]; + for (size_t i = 0; i < glTFImage.width * glTFImage.height; ++i) + { + memcpy(rgba, rgb, sizeof(unsigned char) * 3); + rgba += 4; + rgb += 3; + } + deleteBuffer = true; + } + else + { + buffer = &glTFImage.image[0]; + bufferSize = glTFImage.image.size(); + } + // Load texture from image buffer + images[i].texture.fromBuffer(buffer, bufferSize, VK_FORMAT_R8G8B8A8_UNORM, glTFImage.width, glTFImage.height, vulkanDevice, copyQueue); + if (deleteBuffer) + { + delete[] buffer; + } + } + } + + void loadTextures(tinygltf::Model& input) + { + textures.resize(input.textures.size()); + for (size_t i = 0; i < input.textures.size(); i++) + { + textures[i].imageIndex = input.textures[i].source; + } + } + + void loadMaterials(tinygltf::Model& input) + { + materials.resize(input.materials.size()); + for (size_t i = 0; i < input.materials.size(); i++) + { + // We only read the most basic properties required for our sample + tinygltf::Material glTFMaterial = input.materials[i]; + // Get the base color factor + if (glTFMaterial.values.find("baseColorFactor") != glTFMaterial.values.end()) + { + materials[i].baseColorFactor = glm::make_vec4(glTFMaterial.values["baseColorFactor"].ColorFactor().data()); + } + // Get base color texture index + if (glTFMaterial.values.find("baseColorTexture") != glTFMaterial.values.end()) + { + materials[i].baseColorTextureIndex = glTFMaterial.values["baseColorTexture"].TextureIndex(); + } + } + } + + void loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, std::vector& indexBuffer, + std::vector& vertexBuffer) + { + VulkanglTFModel::Node* node = new VulkanglTFModel::Node{}; + node->matrix = glm::mat4(1.0f); + node->parent = parent; + + // Get the local node matrix + // It's either made up from translation, rotation, scale or a 4x4 matrix + if (inputNode.translation.size() == 3) + { + node->matrix = glm::translate(node->matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); + } + if (inputNode.rotation.size() == 4) + { + glm::quat q = glm::make_quat(inputNode.rotation.data()); + node->matrix *= glm::mat4(q); + } + if (inputNode.scale.size() == 3) + { + node->matrix = glm::scale(node->matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); + } + if (inputNode.matrix.size() == 16) + { + node->matrix = glm::make_mat4x4(inputNode.matrix.data()); + }; + + // Load node's children + if (inputNode.children.size() > 0) + { + for (size_t i = 0; i < inputNode.children.size(); i++) + { + loadNode(input.nodes[inputNode.children[i]], input, node, indexBuffer, vertexBuffer); + } + } + + // If the node contains mesh data, we load vertices and indices from the buffers + // In glTF this is done via accessors and buffer views + if (inputNode.mesh > -1) + { + const tinygltf::Mesh mesh = input.meshes[inputNode.mesh]; + // Iterate through all primitives of this node's mesh + for (size_t i = 0; i < mesh.primitives.size(); i++) + { + const tinygltf::Primitive& glTFPrimitive = mesh.primitives[i]; + uint32_t firstIndex = static_cast(indexBuffer.size()); + uint32_t vertexStart = static_cast(vertexBuffer.size()); + uint32_t indexCount = 0; + // Vertices + { + const float* positionBuffer = nullptr; + const float* normalsBuffer = nullptr; + const float* texCoordsBuffer = nullptr; + size_t vertexCount = 0; + + // Get buffer data for vertex positions + if (glTFPrimitive.attributes.find("POSITION") != glTFPrimitive.attributes.end()) + { + const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("POSITION")->second]; + const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; + positionBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); + vertexCount = accessor.count; + } + // Get buffer data for vertex normals + if (glTFPrimitive.attributes.find("NORMAL") != glTFPrimitive.attributes.end()) + { + const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("NORMAL")->second]; + const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; + normalsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); + } + // Get buffer data for vertex texture coordinates + // glTF supports multiple sets, we only load the first one + if (glTFPrimitive.attributes.find("TEXCOORD_0") != glTFPrimitive.attributes.end()) + { + const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("TEXCOORD_0")->second]; + const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView]; + texCoordsBuffer = reinterpret_cast(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); + } + + // Append data to model's vertex buffer + for (size_t v = 0; v < vertexCount; v++) + { + Vertex vert{}; + vert.pos = glm::vec4(glm::make_vec3(&positionBuffer[v * 3]), 1.0f); + vert.normal = glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f))); + vert.uv = texCoordsBuffer ? glm::make_vec2(&texCoordsBuffer[v * 2]) : glm::vec3(0.0f); + vert.color = glm::vec3(1.0f); + vertexBuffer.push_back(vert); + } + } + // Indices + { + const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.indices]; + const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView]; + const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer]; + + indexCount += static_cast(accessor.count); + + // glTF supports different component types of indices + switch (accessor.componentType) + { + case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: { + const uint32_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); + for (size_t index = 0; index < accessor.count; index++) + { + indexBuffer.push_back(buf[index] + vertexStart); + } + break; + } + case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: { + const uint16_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); + for (size_t index = 0; index < accessor.count; index++) + { + indexBuffer.push_back(buf[index] + vertexStart); + } + break; + } + case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: { + const uint8_t* buf = reinterpret_cast(&buffer.data[accessor.byteOffset + bufferView.byteOffset]); + for (size_t index = 0; index < accessor.count; index++) + { + indexBuffer.push_back(buf[index] + vertexStart); + } + break; + } + default: + std::cerr << "Index component type " << accessor.componentType << " not supported!" << std::endl; + return; + } + } + Primitive primitive{}; + primitive.firstIndex = firstIndex; + primitive.indexCount = indexCount; + primitive.materialIndex = glTFPrimitive.material; + node->mesh.primitives.push_back(primitive); + } + } + + if (parent) + { + parent->children.push_back(node); + } + else + { + nodes.push_back(node); + } + } + + /* + glTF rendering functions + */ + + // Draw a single node including child nodes (if present) + void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node* node) + { + if (node->mesh.primitives.size() > 0) + { + // Pass the node's matrix via push constants + // Traverse the node hierarchy to the top-most parent to get the final matrix of the current node + glm::mat4 nodeMatrix = node->matrix; + VulkanglTFModel::Node* currentParent = node->parent; + while (currentParent) + { + nodeMatrix = currentParent->matrix * nodeMatrix; + currentParent = currentParent->parent; + } + // Pass the final matrix to the vertex shader using push constants + vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); + for (VulkanglTFModel::Primitive& primitive : node->mesh.primitives) + { + if (primitive.indexCount > 0) + { + // Get the texture index for this primitive + VulkanglTFModel::Texture texture = textures[materials[primitive.materialIndex].baseColorTextureIndex]; + // Bind the descriptor for the current primitive's texture + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &images[texture.imageIndex].descriptorSet, 0, + nullptr); + vkCmdDrawIndexed(commandBuffer, primitive.indexCount, 1, primitive.firstIndex, 0, 0); + } + } + } + for (auto& child : node->children) + { + drawNode(commandBuffer, pipelineLayout, child); + } + } + + // Draw the glTF scene starting at the top-level-nodes + void draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout) + { + // All vertices and indices are stored in single buffers, so we only need to bind once + VkDeviceSize offsets[1] = { 0 }; + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertices.buffer, offsets); + vkCmdBindIndexBuffer(commandBuffer, indices.buffer, 0, VK_INDEX_TYPE_UINT32); + // Render all nodes at top-level + for (auto& node : nodes) + { + drawNode(commandBuffer, pipelineLayout, node); + } + } +}; + +} // namespace VoxFlow \ No newline at end of file From 3e69b2e19ba402fa979408c43e62c3bca166403e Mon Sep 17 00:00:00 2001 From: snowapril Date: Sun, 5 Nov 2023 17:42:22 +0900 Subject: [PATCH 3/3] backup --- .../VoxFlow/Core/Scene/SceneObjectLoader.hpp | 2 +- Includes/VoxFlow/Core/Utils/Logger.hpp | 54 ++++++++++++----- .../VoxFlow/Core/Scene/SceneObjectLoader.cpp | 58 ++++++++++++++----- 3 files changed, 86 insertions(+), 28 deletions(-) diff --git a/Includes/VoxFlow/Core/Scene/SceneObjectLoader.hpp b/Includes/VoxFlow/Core/Scene/SceneObjectLoader.hpp index 211e38ae..da53be52 100644 --- a/Includes/VoxFlow/Core/Scene/SceneObjectLoader.hpp +++ b/Includes/VoxFlow/Core/Scene/SceneObjectLoader.hpp @@ -19,7 +19,7 @@ class SceneObjectLoader ~SceneObjectLoader(); public: - std::shared_ptr loadSceneObjectObj(const std::string& objPath, ResourceUploadContext* uploadContext); + std::shared_ptr loadSceneObjectGltf(const std::string& objPath, ResourceUploadContext* uploadContext); }; } // namespace VoxFlow diff --git a/Includes/VoxFlow/Core/Utils/Logger.hpp b/Includes/VoxFlow/Core/Utils/Logger.hpp index d39baf44..c58dc804 100644 --- a/Includes/VoxFlow/Core/Utils/Logger.hpp +++ b/Includes/VoxFlow/Core/Utils/Logger.hpp @@ -22,23 +22,51 @@ namespace VoxFlow } \ } while (false) -template -void voxAssertImpl(bool expr, const char* fmt, Args... args) -{ - do - { - if (!static_cast(expr)) - { - spdlog::error("{} at {}:{}.", fmt, args..., __FILE__, __LINE__); - DebugUtil::DebugBreak(); - } +#define VOX_ASSERT(expr, msg, ...) \ + do \ + { \ + if (!static_cast(expr)) \ + { \ + spdlog::error("{} at {}:{}.", fmt, args..., __FILE__, __LINE__); \ + DebugUtil::DebugBreak(); \ + } \ + } while (false); +#define VOX_ASSERT_RETURN_VOID(expr, msg, ...) \ + do \ + { \ + if (!static_cast(expr)) \ + { \ + spdlog::error("{} at {}:{}.", fmt, args..., __FILE__, __LINE__); \ + DebugUtil::DebugBreak(); \ + return; \ + } \ + } while (false); +#define VOX_ASSERT_RETURN_BOOL(expr, msg, ...) \ + do \ + { \ + if (!static_cast(expr)) \ + { \ + spdlog::error("{} at {}:{}.", fmt, args..., __FILE__, __LINE__); \ + DebugUtil::DebugBreak(); \ + return false; \ + } \ + } while (false); +#define VOX_ASSERT_RETURN_NULL(expr, msg, ...) \ + do \ + { \ + if (!static_cast(expr)) \ + { \ + spdlog::error("{} at {}:{}.", fmt, args..., __FILE__, __LINE__); \ + DebugUtil::DebugBreak(); \ + return nullptr; \ + } \ } while (false); -} - -#define VOX_ASSERT(expr, msg, ...) voxAssertImpl(expr, msg, ##__VA_ARGS__) // #else // #define VK_ASSERT(x) // #define VOX_ASSERT(x, msg, ...) +// #define VOX_ASSERT_RETURN_VOID(expr, msg, ...) +// #define VOX_ASSERT_RETURN_BOOL(expr, msg, ...) +// #define VOX_ASSERT_RETURN_NULL(expr, msg, ...) // #endif } // namespace VoxFlow diff --git a/Sources/VoxFlow/Core/Scene/SceneObjectLoader.cpp b/Sources/VoxFlow/Core/Scene/SceneObjectLoader.cpp index 1ec7de9f..212ac36e 100644 --- a/Sources/VoxFlow/Core/Scene/SceneObjectLoader.cpp +++ b/Sources/VoxFlow/Core/Scene/SceneObjectLoader.cpp @@ -1,6 +1,10 @@ // Author : snowapril #include +#include +#include +#include +#include #define TINYGLTF_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION @@ -72,23 +76,16 @@ class VulkanglTFModel // Images may be reused by texture objects and are as such separated struct Image { - vks::Texture2D texture; + Texture* texture; // We also store (and create) a descriptor set that's used to access this texture from the fragment shader VkDescriptorSet descriptorSet; }; - // A glTF texture stores a reference to the image and a sampler - // In this sample, we are only interested in the image - struct Texture - { - int32_t imageIndex; - }; - /* Model data */ std::vector images; - std::vector textures; + std::vector textures; std::vector materials; std::vector nodes; @@ -106,7 +103,7 @@ class VulkanglTFModel The following functions take a glTF input model loaded via tinyglTF and convert all required data into our own structure */ - void loadImages(tinygltf::Model& input) + void loadImages(tinygltf::Model& input, ResourceUploadContext* uploadContext) { // Images can be stored inside the glTF (which is the case for the sample model), so instead of directly // loading them from disk, we fetch them from the glTF loader and upload the buffers @@ -138,7 +135,11 @@ class VulkanglTFModel buffer = &glTFImage.image[0]; bufferSize = glTFImage.image.size(); } - // Load texture from image buffer + + + images[i].texture = new Texture(glTFImage.name, ) + uploadContext->addPendingUpload(UploadPhase::PreRender, images[i].texture, UploadData{ ._data = buffer, ._size = bufferSize, ._dstOffset = 0 }); + images[i].texture.fromBuffer(buffer, bufferSize, VK_FORMAT_R8G8B8A8_UNORM, glTFImage.width, glTFImage.height, vulkanDevice, copyQueue); if (deleteBuffer) { @@ -152,7 +153,7 @@ class VulkanglTFModel textures.resize(input.textures.size()); for (size_t i = 0; i < input.textures.size(); i++) { - textures[i].imageIndex = input.textures[i].source; + textures[i] = input.textures[i].source; } } @@ -349,9 +350,9 @@ class VulkanglTFModel if (primitive.indexCount > 0) { // Get the texture index for this primitive - VulkanglTFModel::Texture texture = textures[materials[primitive.materialIndex].baseColorTextureIndex]; + int32_t texture = textures[materials[primitive.materialIndex].baseColorTextureIndex]; // Bind the descriptor for the current primitive's texture - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &images[texture.imageIndex].descriptorSet, 0, + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &images[texture].descriptorSet, 0, nullptr); vkCmdDrawIndexed(commandBuffer, primitive.indexCount, 1, primitive.firstIndex, 0, 0); } @@ -378,4 +379,33 @@ class VulkanglTFModel } }; +std::shared_ptr SceneObjectLoader::loadSceneObjectGltf(const std::string& objPath, ResourceUploadContext* uploadContext) +{ + tinygltf::Model glTFInput; + tinygltf::TinyGLTF gltfContext; + std::string error, warning; + +#if defined(__ANDROID__) + // On Android all assets are packed with the apk in a compressed form, so we need to open them using the asset manager + // We let tinygltf handle this, by passing the asset manager of our app + tinygltf::asset_manager = androidApp->activity->assetManager; +#endif + const bool fileLoaded = gltfContext.LoadASCIIFromFile(&glTFInput, &error, &warning, objPath); + VOX_ASSERT_RETURN_NULL(fileLoaded, "Failed to load gltf : {}", objPath); + + VulkanglTFModel glTFModel; + + glTFModel.loadImages(glTFInput); + glTFModel.loadMaterials(glTFInput); + glTFModel.loadTextures(glTFInput); + const tinygltf::Scene& scene = glTFInput.scenes[0]; + for (size_t i = 0; i < scene.nodes.size(); i++) + { + const tinygltf::Node node = glTFInput.nodes[scene.nodes[i]]; + glTFModel.loadNode(node, glTFInput, nullptr, indexBuffer, vertexBuffer); + } + + return nullptr; +} + } // namespace VoxFlow \ No newline at end of file