From f418ccabbc557f52e56fb36f17d570b95d92eb1f Mon Sep 17 00:00:00 2001 From: Alexandre Date: Sun, 13 Sep 2026 19:43:24 +0200 Subject: [PATCH] Added a depth image --- src/Common/Types.h | 2 + src/Engine/engine/engine.h | 453 ++++++++++++++++++++----------- src/Engine/engine/initializers.h | 27 ++ src/Engine/engine/loader.h | 117 ++++++-- src/Engine/engine/pipelines.h | 24 ++ 5 files changed, 447 insertions(+), 176 deletions(-) diff --git a/src/Common/Types.h b/src/Common/Types.h index e79ad2c..accc404 100644 --- a/src/Common/Types.h +++ b/src/Common/Types.h @@ -25,6 +25,8 @@ #include #include +#define GLM_ENABLE_EXPERIMENTAL +#include // Custom headers //#include "callbacks.h" diff --git a/src/Engine/engine/engine.h b/src/Engine/engine/engine.h index b7ae452..b2de7f8 100644 --- a/src/Engine/engine/engine.h +++ b/src/Engine/engine/engine.h @@ -3,7 +3,7 @@ // Normal header // Current progress -// 3 - Graphics Pipeline - Doing mesh buffers +// 3 - Graphics Pipeline - Doing depth image creation in swapchain init #include "descriptors.h" // Required for public interface custom allocator #include "Common/Types.h" @@ -14,6 +14,7 @@ #include #include "imgui.h" // For types #include "imgui_memory_editor.h" // For mem edit +#include "loader.h" // For MeshAsset struct FrameData { VkCommandPool _commandPool; @@ -83,6 +84,7 @@ class Engine { // Draw resources AllocatedImage _drawImage; + AllocatedImage _depthImage; // Depth testing VkExtent2D _drawExtent; // Descriptor Sets @@ -131,7 +133,7 @@ class Engine { // Model std::string _modelPath { "models/basicmesh.glb" }; - + std::vector> testMeshes; void parseConfig( int gpuIndex, @@ -152,6 +154,11 @@ class Engine { // Public functions (for CLI args) void getAvailableGPU(); + // Meshes + GPUMeshBuffers uploadMesh( + std::span indices, + std::span vertices + ); private: using enum LogModule; @@ -183,12 +190,6 @@ class Engine { const AllocatedBuffer& buffer ); - // Meshes - GPUMeshBuffers uploadMesh( - std::span indices, - std::span vertices - ); - // Random functions void createSwapchain( uint32_t width, @@ -442,6 +443,12 @@ void Engine::draw() { VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); + vkutil::transitionImage( + cmd, + _depthImage.image, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL + ); drawGeometry(cmd); @@ -647,8 +654,6 @@ void Engine::initVulkan() { if(_gpuIndex < 0) { // No overwrite, use VKB - - // Use vkBootstrap to select the GPU vkb::PhysicalDeviceSelector selector { vkbInst }; vkb::PhysicalDevice physicalDevice = selector @@ -728,7 +733,7 @@ void Engine::initVulkan() { _graphicsQueueFamily = queueFamily.value(); - // 3. Créer le device logique + // Create logical device float queuePriority = 1.0f; VkDeviceQueueCreateInfo queueCreateInfo{}; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; @@ -743,13 +748,14 @@ void Engine::initVulkan() { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; - VkDeviceCreateInfo deviceCreateInfo{}; - deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - deviceCreateInfo.pNext = &features13; - deviceCreateInfo.queueCreateInfoCount = 1; - deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; - deviceCreateInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); - deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data(); + VkDeviceCreateInfo deviceCreateInfo{ + .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, + .pNext = &features13, + .queueCreateInfoCount = 1, + .pQueueCreateInfos = &queueCreateInfo, + .enabledExtensionCount = static_cast(deviceExtensions.size()), + .ppEnabledExtensionNames = deviceExtensions.data() + }; if (vkCreateDevice(_choosenGPU, &deviceCreateInfo, nullptr, &_device) != VK_SUCCESS) { throw std::runtime_error("[Engine:Error] Failed to create Vulkan device !"); @@ -758,11 +764,12 @@ void Engine::initVulkan() { vkGetDeviceQueue(_device, _graphicsQueueFamily, 0, &_graphicsQueue); } - VmaAllocatorCreateInfo allocatorInfo = {}; - allocatorInfo.physicalDevice = _choosenGPU; - allocatorInfo.device = _device; - allocatorInfo.instance = _instance; - allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; + VmaAllocatorCreateInfo allocatorInfo = { + .flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT, + .physicalDevice = _choosenGPU, + .device = _device, + .instance = _instance + }; vmaCreateAllocator(&allocatorInfo, &_allocator); @@ -798,7 +805,6 @@ void Engine::initSwapchain() { }; // Hardcoding draw format to a 32 bit float - _drawImage.imageFormat = VK_FORMAT_R16G16B16A16_SFLOAT; _drawImage.imageExtent = drawImageExtent; @@ -850,8 +856,51 @@ void Engine::initSwapchain() { ) ); - // Add to deletion queues + // Depth image + _depthImage.imageFormat = VK_FORMAT_D32_SFLOAT; + _depthImage.imageExtent = drawImageExtent; + VkImageUsageFlags depthImageUsages {}; + depthImageUsages |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + VkImageCreateInfo dImgInfo { + vkinit::imageCreateInfo( + _depthImage.imageFormat, + depthImageUsages, + drawImageExtent + ) + }; + + // Allocate and create the image + vmaCreateImage( + _allocator, + &dImgInfo, + &rImgAllocInfo, + &_depthImage.image, + &_depthImage.allocation, + nullptr + ); + + // Build an image view for the draw image (used for rendering) + VkImageViewCreateInfo dViewInfo { + vkinit::imageViewCreateInfo( + _depthImage.imageFormat, + _depthImage.image, + VK_IMAGE_ASPECT_DEPTH_BIT + ) + }; + + VK_CHECK( + vkCreateImageView( + _device, + &dViewInfo, + nullptr, + &_depthImage.imageView + ) + ); + + // Add to deletion queue _mainDeletionQueue.pushFunction([this]() { + // Draw image vkDestroyImageView( _device, _drawImage.imageView, @@ -862,6 +911,18 @@ void Engine::initSwapchain() { _drawImage.image, _drawImage.allocation ); + // Depth image + vkDestroyImageView( + _device, + _depthImage.imageView, + nullptr + ); + + vmaDestroyImage( + _allocator, + _depthImage.image, + _depthImage.allocation + ); }); #ifdef DEBUG @@ -1057,6 +1118,127 @@ void Engine::initDescriptors(){ #endif } +void Engine::initImgui() { + #ifdef DEBUG + fmt::println("[Engine:Init] Initializing ImGui..."); + #endif + // Oversized descriptor pool for IMGUI, from the official tutorial + // Ajust for optimization, or needs + + VkDescriptorPoolSize poolSizes[] = { + { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 }, + { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 }, + { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 } + }; + + VkDescriptorPoolCreateInfo poolInfo { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + .maxSets = 1000, + .poolSizeCount = (uint32_t)std::size(poolSizes), + .pPoolSizes = poolSizes + }; + + VkDescriptorPool imguiPool; + VK_CHECK( + vkCreateDescriptorPool( + _device, + &poolInfo, + nullptr, + &imguiPool + ); + ); + + // Init IMGUI + ImGui::CreateContext(); + + // Config + ImGuiIO& io = ImGui::GetIO(); + // Docking + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + // Viewports + io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; + + // Init backends + ImGui_ImplGlfw_InitForVulkan( + window, + true + ); + + ImGui_ImplVulkan_InitInfo initInfo { + .Instance = _instance, + .PhysicalDevice = _choosenGPU, + .Device = _device, + .Queue = _graphicsQueue, + .DescriptorPool = imguiPool, + .MinImageCount = 3, + .ImageCount = 3, + .PipelineInfoMain = { + .MSAASamples = VK_SAMPLE_COUNT_1_BIT, + .PipelineRenderingCreateInfo { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, + .colorAttachmentCount = 1, + .pColorAttachmentFormats = &_swapchainImageFormat + } + }, + .UseDynamicRendering = true + }; + + ImGui_ImplVulkan_Init(&initInfo); + + // Create a sampler for Viewport rendering + VkSamplerCreateInfo samplerInfo = {}; + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.anisotropyEnable = VK_FALSE; + samplerInfo.maxAnisotropy = 1.0f; + + VK_CHECK(vkCreateSampler(_device, &samplerInfo, nullptr, &_viewportSampler)); + + // Register the draw image as a texture for ImGui + _viewportTextureID = ImGui_ImplVulkan_AddTexture( + _viewportSampler, + _drawImage.imageView, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + ); + + _mainDeletionQueue.pushFunction([this, imguiPool]() { + ImGui_ImplVulkan_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + vkDestroyDescriptorPool( + _device, + imguiPool, + nullptr + ); + vkDestroySampler( + _device, + _viewportSampler, + nullptr + ); + }); + #ifdef DEBUG + fmt::println("[Engine:Init] ImGui initialized !"); + #endif +} + +//================= +//=== Pipelines === +//================= + void Engine::initPipelines() { #ifdef DEBUG _logger.logRAM(ENGINE, EINIT, "Initializing pipelines..."); @@ -1290,7 +1472,8 @@ void Engine::initTrianglePipeline() { // Connect the image format we will draw into, from draw image pipelineBuilder.setColorAttachmentFormat(_drawImage.imageFormat); - pipelineBuilder.setDepthFormat(VK_FORMAT_UNDEFINED); + pipelineBuilder.setDepthFormat(_depthImage.imageFormat); // Why ? + // Because validation errors, now it's the same format // Finally build the pipeline _trianglePipeline = pipelineBuilder.buildPipeline(_device); @@ -1357,11 +1540,20 @@ void Engine::initMeshPipeline() { // No blending pipelineBuilder.disableBlending(); - pipelineBuilder.disableDepthtest(); + pipelineBuilder.enableDepthtest( + true, + VK_COMPARE_OP_GREATER_OR_EQUAL + /* + Greater or equal because + 0 is far and 1 is near, so + render the pixels if the current value (depth) + is greater than the value on the depth image + */ + ); // Connect the image format we will draw into, from draw image pipelineBuilder.setColorAttachmentFormat(_drawImage.imageFormat); - pipelineBuilder.setDepthFormat(VK_FORMAT_UNDEFINED); + pipelineBuilder.setDepthFormat(_depthImage.imageFormat); // Finally build the pipeline _meshPipeline = pipelineBuilder.buildPipeline(_device); @@ -1377,129 +1569,9 @@ void Engine::initMeshPipeline() { #ifdef DEBUG _logger.logRAM(ENGINE, EINIT, "Mesh pipeline initialized !"); - std::cout << "sizeof(GPUDrawPushConstants) = " << sizeof(GPUDrawPushConstants) << std::endl; - std::cout << "offsetof(GPUDrawPushConstants, worldMatrix) = " << offsetof(GPUDrawPushConstants, worldMatrix) << std::endl; - std::cout << "offsetof(GPUDrawPushConstants, vertexBuffer) = " << offsetof(GPUDrawPushConstants, vertexBuffer) << std::endl; #endif } -void Engine::initImgui() { - #ifdef DEBUG - fmt::println("[Engine:Init] Initializing ImGui..."); - #endif - // Oversized descriptor pool for IMGUI, from the official tutorial - // Ajust for optimization, or needs - - VkDescriptorPoolSize poolSizes[] = { - { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 }, - { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 }, - { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 }, - { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 } - }; - - VkDescriptorPoolCreateInfo poolInfo { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, - .maxSets = 1000, - .poolSizeCount = (uint32_t)std::size(poolSizes), - .pPoolSizes = poolSizes - }; - - VkDescriptorPool imguiPool; - VK_CHECK( - vkCreateDescriptorPool( - _device, - &poolInfo, - nullptr, - &imguiPool - ); - ); - - // Init IMGUI - ImGui::CreateContext(); - - // Config - ImGuiIO& io = ImGui::GetIO(); - // Docking - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; - // Viewports - io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; - - // Init backends - ImGui_ImplGlfw_InitForVulkan( - window, - true - ); - - ImGui_ImplVulkan_InitInfo initInfo { - .Instance = _instance, - .PhysicalDevice = _choosenGPU, - .Device = _device, - .Queue = _graphicsQueue, - .DescriptorPool = imguiPool, - .MinImageCount = 3, - .ImageCount = 3, - .PipelineInfoMain = { - .MSAASamples = VK_SAMPLE_COUNT_1_BIT, - .PipelineRenderingCreateInfo { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, - .colorAttachmentCount = 1, - .pColorAttachmentFormats = &_swapchainImageFormat - } - }, - .UseDynamicRendering = true - }; - - ImGui_ImplVulkan_Init(&initInfo); - - // Create a sampler for Viewport rendering - VkSamplerCreateInfo samplerInfo = {}; - samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.anisotropyEnable = VK_FALSE; - samplerInfo.maxAnisotropy = 1.0f; - - VK_CHECK(vkCreateSampler(_device, &samplerInfo, nullptr, &_viewportSampler)); - - // Register the draw image as a texture for ImGui - _viewportTextureID = ImGui_ImplVulkan_AddTexture( - _viewportSampler, - _drawImage.imageView, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL - ); - - _mainDeletionQueue.pushFunction([this, imguiPool]() { - ImGui_ImplVulkan_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - vkDestroyDescriptorPool( - _device, - imguiPool, - nullptr - ); - vkDestroySampler( - _device, - _viewportSampler, - nullptr - ); - }); - #ifdef DEBUG - fmt::println("[Engine:Init] ImGui initialized !"); - #endif -} - //==================================== //=== Allocation-related Functions === //==================================== @@ -1680,21 +1752,16 @@ void Engine::initDefaultData() { rectVertices ); - // Delete the rectangle data on engine shutdown + // Load the mesh + testMeshes = loadGltfMeshes(this, _modelPath).value(); + + // Delete the default data on engine shutdown _mainDeletionQueue.pushFunction([this](){ destroyBuffer(rectangle.indexBuffer); destroyBuffer(rectangle.vertexBuffer); }); #ifdef DEBUG _logger.logRAM(ENGINE, EINIT, "Default data created !"); - for (size_t i = 0; i < rectIndices.size(); i++) { - fmt::println( - "index[{}] = {} ({:#x})", - i, - rectIndices[i], - rectIndices[i] - ); - } #endif } @@ -1774,6 +1841,11 @@ void Engine::buildImgui() { } ImGui::End(); + // Depth image + // Todo + // But follows the same logic as viewport, + // but does not resize dynamicly + // Shader control if(ImGui::Begin("Background Shader control")) { ComputeEffect& selected = backgroundEffects[currentBackgroundEffect]; @@ -1910,9 +1982,29 @@ void Engine::drawGeometry( uint32_t width = _drawExtent.width; uint32_t height = _drawExtent.height; // Begin rendering - VkRenderingAttachmentInfo colorAttachment = vkinit::attachmentInfo(_drawImage.imageView, nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + // Some info structs + VkRenderingAttachmentInfo colorAttachment { + vkinit::attachmentInfo( + _drawImage.imageView, + nullptr, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + ) + }; + VkRenderingAttachmentInfo depthAttachement { + vkinit::depthAttachmentInfo( + _depthImage.imageView, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL + ) + }; + + VkRenderingInfo renderInfo { + vkinit::renderingInfo( + _drawExtent, + &colorAttachment, + &depthAttachement + ) + }; - VkRenderingInfo renderInfo = vkinit::renderingInfo(_drawExtent, &colorAttachment, nullptr); vkCmdBeginRendering(cmd, &renderInfo); vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, _trianglePipeline); @@ -1971,8 +2063,50 @@ void Engine::drawGeometry( VK_INDEX_TYPE_UINT32 ); + // Draw the rectangle vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0); + // Now the model + // Correct the matrix + glm::mat4 view = glm::translate(glm::vec3{ 0, 0, -5}); + // Camera projection + /* + glm::mat4 projection = glm::perspective( + glm::radians(70.0f), + (float)_drawExtent.width / (float)_drawExtent.height, + 10000.0f, + 0.1f + ); + */ + // Invert the Y direction + //projection[1][1] *= -1; + //pushConstants.worldMatrix = projection * view; + + pushConstants.vertexBuffer = testMeshes[2]->meshBuffers.vertexBufferAddress; + vkCmdPushConstants( + cmd, + _meshPipelineLayout, + VK_SHADER_STAGE_VERTEX_BIT, + 0, + sizeof(GPUDrawPushConstants), + &pushConstants + ); + vkCmdBindIndexBuffer( + cmd, + testMeshes[2]->meshBuffers.indexBuffer.buffer, + 0, + VK_INDEX_TYPE_UINT32 + ); + + vkCmdDrawIndexed( + cmd, + testMeshes[2]->surfaces[0].count, + 1, + testMeshes[2]->surfaces[0].startIndex, + 0, + 0 + ); + vkCmdEndRendering(cmd); } @@ -2187,6 +2321,7 @@ void Engine::resizeRenderImage(uint32_t width, uint32_t height) { #endif } +// CLI functions void Engine::getAvailableGPU() { // Creates a temporary Vulkan Instance // Largely copied from initVulkan function diff --git a/src/Engine/engine/initializers.h b/src/Engine/engine/initializers.h index e9462cb..28986a0 100644 --- a/src/Engine/engine/initializers.h +++ b/src/Engine/engine/initializers.h @@ -2,6 +2,7 @@ #define INITIALIZERS_H // Normal header #include "Common/Types.h" +#include "simdjson.h" #include namespace vkinit { @@ -64,6 +65,11 @@ namespace vkinit { VkImageLayout layout /*= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL*/ ); + VkRenderingAttachmentInfo depthAttachmentInfo( + VkImageView view, + VkImageLayout layout + ); + VkRenderingInfo renderingInfo( VkExtent2D renderExtent, VkRenderingAttachmentInfo* colorAttachment, @@ -289,6 +295,27 @@ namespace vkinit { return colorAttachment; } + VkRenderingAttachmentInfo depthAttachmentInfo( + VkImageView view, + VkImageLayout layout + ) { + VkRenderingAttachmentInfo depthAttachment { + .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + .pNext = nullptr, + .imageView = view, + .imageLayout = layout, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .clearValue = { + .depthStencil = { + .depth = 0.0f + } + } + }; + + return depthAttachment; + } + VkRenderingInfo renderingInfo( VkExtent2D renderExtent, VkRenderingAttachmentInfo* colorAttachment, diff --git a/src/Engine/engine/loader.h b/src/Engine/engine/loader.h index c354929..b14ce9f 100644 --- a/src/Engine/engine/loader.h +++ b/src/Engine/engine/loader.h @@ -37,11 +37,14 @@ class Engine; #include #include +constexpr bool OverrideColors = true; std::optional>> loadGltfMeshes( Engine* engine, std::filesystem::path filePath ) { + // Todo: + // Use util functions for attributes auto& logger = engine->_logger; // Uses the main logger logger.logAll(LogModule::ENGINE, LogLevel::EINFO, "Loading GLTF: {}", filePath.string()); @@ -86,27 +89,107 @@ std::optional>> loadGltfMeshes( In the official docs, it is stated we can get direct references to the Asset class, using pointers (->) For exemple with buffers: asset->buffers - - But the guide is using asset.meshes ? - We'll need to validate if it's a real class member - - Then, foreach meshes in the file, he creates a temporary mesh, - that he will fill with the model data. - - He assign the model name from the big chunk (we'll call it the Origin) - - He does some cleaning, to not merge meshes by error. - - And...uh..another loop. - - This time, it's using mesh.primitives, which is the iterator of the first loop. - It creates a new GeoSurface, foreach "primitives" ? - - */ + for(fastgltf::Mesh& mesh : gltf.meshes) { // Perhaps error ? + MeshAsset newmesh; + + newmesh.name = mesh.name; + + // Clear the arrays for memory optimizations + indices.clear(); + vertices.clear(); + + for(auto&& p : mesh.primitives) { // 100% Error, use pointers ig ? + GeoSurface newSurface; + newSurface.startIndex = (uint32_t)indices.size(); + newSurface.count = (uint32_t)gltf.accessors[p.indicesAccessor.value()].count; + + size_t initialVTX = vertices.size(); + + // -- Indices -- + { + fastgltf::Accessor& indexAccessor = gltf.accessors[p.indicesAccessor.value()]; + indices.reserve(indices.size() + indexAccessor.count); // Memory alloc ig ? + + fastgltf::iterateAccessor(gltf, indexAccessor, + [&](std::uint32_t idx) { + indices.push_back(idx + initialVTX); + } + ); + } + + // -- Vertex Positions -- + { + auto posIt = p.findAttribute("POSITION"); + if (posIt == p.attributes.end()) { + logger.logFatal(LogModule::ENGINE, "Primitive without POSITION attribute"); + return std::nullopt; + } + fastgltf::Accessor& posAccessor = gltf.accessors[posIt->accessorIndex]; + vertices.resize(vertices.size() + posAccessor.count); + + fastgltf::iterateAccessorWithIndex(gltf, posAccessor, + [&](glm::vec3 v, size_t index) { + Vertex newvtx; + newvtx.position = v; + newvtx.normal = { 1.0f, 0.0f, 0.0f }; + newvtx.color = glm::vec4(1.0f); + newvtx.uv_x = 0.0f; + newvtx.uv_y = 0.0f; + vertices[initialVTX + index] = newvtx; + } + ); + } + + // --- Normals --- + if (auto normals = p.findAttribute("NORMAL"); normals != p.attributes.end()) { + fastgltf::iterateAccessorWithIndex(gltf, gltf.accessors[normals->accessorIndex], + [&](glm::vec3 v, size_t index) { + vertices[initialVTX + index].normal = v; + } + ); + } + + // --- UVs --- + if (auto uv = p.findAttribute("TEXCOORD_0"); uv != p.attributes.end()) { + fastgltf::iterateAccessorWithIndex(gltf, gltf.accessors[uv->accessorIndex], + [&](glm::vec2 v, size_t index) { + vertices[initialVTX + index].uv_x = v.x; + vertices[initialVTX + index].uv_y = v.y; + } + ); + } + + // --- Vertex Colors --- + if (auto colors = p.findAttribute("COLOR_0"); colors != p.attributes.end()) { + fastgltf::iterateAccessorWithIndex(gltf, gltf.accessors[colors->accessorIndex], + [&](glm::vec4 v, size_t index) { + vertices[initialVTX + index].color = v; + } + ); + } + + newmesh.surfaces.push_back(newSurface); + } + + // Display vertex normals + if (OverrideColors) { + for (Vertex& vtx : vertices) { + vtx.color = glm::vec4(vtx.normal, 1.0f); + } + } + newmesh.meshBuffers = engine->uploadMesh(indices, vertices); + meshes.emplace_back(std::make_shared(std::move(newmesh))); + } // Debug things + #ifdef DEBUG + if(fastgltf::validate(load.get()) != fastgltf::Error::None) { + logger.logFatal(LogModule::ENGINE, "gltf file is not up to spec !"); + } + #endif + return meshes; } diff --git a/src/Engine/engine/pipelines.h b/src/Engine/engine/pipelines.h index e588075..6617cd9 100644 --- a/src/Engine/engine/pipelines.h +++ b/src/Engine/engine/pipelines.h @@ -1,3 +1,8 @@ +/* + Todo: + Create a temporary struct, to have the correct structure + then copy it to the class member +*/ #ifndef PIPELINES_H #define PIPELINES_H // Normal header @@ -69,6 +74,10 @@ class PipelineBuilder { ); void disableDepthtest(); + void enableDepthtest( + bool depthWriteEnable, + VkCompareOp op + ); }; #endif @@ -358,5 +367,20 @@ void PipelineBuilder::disableDepthtest() { _depthStencil.maxDepthBounds = 1.0f; } +void PipelineBuilder::enableDepthtest( + bool depthWriteEnable, + VkCompareOp op +) { + _depthStencil.depthTestEnable = VK_TRUE; + _depthStencil.depthWriteEnable = depthWriteEnable; + _depthStencil.depthCompareOp = op; + _depthStencil.depthBoundsTestEnable = VK_FALSE; + _depthStencil.stencilTestEnable = VK_FALSE; + _depthStencil.front = {}; + _depthStencil.back = {}; + _depthStencil.minDepthBounds = 0.0f; + _depthStencil.maxDepthBounds = 1.0f; +} + #endif #endif