Added a depth image

This commit is contained in:
Alexandre 2026-09-13 19:43:24 +02:00
parent 86257df3e8
commit f418ccabbc
5 changed files with 447 additions and 176 deletions

View File

@ -25,6 +25,8 @@
#include <glm/mat4x4.hpp>
#include <glm/vec4.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/transform.hpp>
// Custom headers
//#include "callbacks.h"

View File

@ -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 <vulkan/vulkan_core.h>
#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<std::shared_ptr<MeshAsset>> testMeshes;
void parseConfig(
int gpuIndex,
@ -152,6 +154,11 @@ class Engine {
// Public functions (for CLI args)
void getAvailableGPU();
// Meshes
GPUMeshBuffers uploadMesh(
std::span<uint32_t> indices,
std::span<Vertex> vertices
);
private:
using enum LogModule;
@ -183,12 +190,6 @@ class Engine {
const AllocatedBuffer& buffer
);
// Meshes
GPUMeshBuffers uploadMesh(
std::span<uint32_t> indices,
std::span<Vertex> 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<uint32_t>(deviceExtensions.size());
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
VkDeviceCreateInfo deviceCreateInfo{
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = &features13,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &queueCreateInfo,
.enabledExtensionCount = static_cast<uint32_t>(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

View File

@ -2,6 +2,7 @@
#define INITIALIZERS_H
// Normal header
#include "Common/Types.h"
#include "simdjson.h"
#include <vulkan/vulkan_core.h>
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,

View File

@ -37,11 +37,14 @@ class Engine;
#include <fastgltf/glm_element_traits.hpp>
#include <fastgltf/tools.hpp>
constexpr bool OverrideColors = true;
std::optional<std::vector<std::shared_ptr<MeshAsset>>> 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<std::vector<std::shared_ptr<MeshAsset>>> 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<std::uint32_t>(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<glm::vec3>(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<glm::vec3>(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<glm::vec2>(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<glm::vec4>(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<MeshAsset>(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;
}

View File

@ -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