From cefbd1b4f7c564f58d956532bd9a57576eb00f7d Mon Sep 17 00:00:00 2001 From: Ivan Belyavtsev Date: Thu, 27 Mar 2025 16:54:32 +0300 Subject: [PATCH] Partially added matrices --- shaders/shader.vert | 6 +- src/main.cpp | 415 +++++++++++++++++++++++++++++++++----------- 2 files changed, 321 insertions(+), 100 deletions(-) diff --git a/shaders/shader.vert b/shaders/shader.vert index 6ab16da..026661c 100644 --- a/shaders/shader.vert +++ b/shaders/shader.vert @@ -4,6 +4,10 @@ layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inNormal; layout(location = 2) in vec2 inUV; +layout(binding = 0) uniform UniformBufferObject { + mat4 model; +} ubo; + layout(location = 0) out vec3 fragColor; vec2 positions[3] = vec2[]( @@ -19,6 +23,6 @@ vec3 colors[3] = vec3[] ( ); void main() { - gl_Position = vec4(inPosition, 1.0); + gl_Position = ubo.model * vec4(inPosition, 1.0); fragColor = inNormal; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 72b4d00..ea19f96 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "tiny_gltf.h" using namespace tinygltf; @@ -28,6 +29,11 @@ struct Vertex { glm::vec2 uv; }; +struct UniformBufferObject { + glm::mat4 model; + //glm::mat4 view; + //glm::mat4 proj; +}; VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, @@ -149,14 +155,19 @@ private: const std::vector validationLayers = { "VK_LAYER_KHRONOS_validation" }; - std::vector vertices; - std::vector indices; - VkBuffer vertexBuffer; - VkDeviceMemory vertexBufferMemory; - VkBuffer indexBuffer; - VkDeviceMemory indexBufferMemory; + std::vector> vertices; + std::vector> indices; + std::vector worldMatrices; + std::vector vertexBuffer; + std::vector vertexBufferMemory; + std::vector indexBuffer; + std::vector indexBufferMemory; Model model; + std::vector uniformBuffers; + std::vector uniformBuffersMemory; + std::vector uniformBuffersMapped; + #ifdef NDEBUG const bool enableValidationLayers = false; @@ -179,6 +190,9 @@ private: VkExtent2D swapChainExtent = {}; std::vector swapChainImageViews; VkRenderPass renderPass = VK_NULL_HANDLE; + VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE; + VkDescriptorPool descriptorPool = VK_NULL_HANDLE; + std::vector descriptorSets; VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; VkPipeline graphicsPipeline = VK_NULL_HANDLE; std::vector swapChainFramebuffers; @@ -216,12 +230,16 @@ private: createSurface(); pickPhysicalDevice(); createLogicalDevice(); - loadModel(); // Äîëæåí áûòü âûçâàí ïåðåä createVertexBuffer() + loadModel(); // ������ ���� ������ ����� createVertexBuffer() createVertexBuffer(); createIndexBuffer(); + createUniformBuffers(); createSwapChain(); createImageViews(); createRenderPass(); + createDescriptorSetLayout(); + createDescriptorPool(); + createDescriptorSets(); createGraphicsPipeline(); createFramebuffers(); createCommandPool(); @@ -250,12 +268,82 @@ private: return true; } private: + void processNodes(const std::vector &nodes, glm::mat4x4 globalTransform){ + for (const auto& node_id : nodes) { + auto node = model.nodes[node_id]; + + glm::mat4x4 localTransform; + if (node.translation.size() == 3) { + localTransform = glm::translate(localTransform, glm::vec3(glm::make_vec3(node.translation.data()))); + } + if (node.rotation.size() == 4) { + glm::quat q = glm::make_quat(node.rotation.data()); + localTransform *= glm::mat4(q); + } + if (node.scale.size() == 3) { + localTransform = glm::scale(localTransform, glm::vec3(glm::make_vec3(node.scale.data()))); + } + if (node.matrix.size() == 16) { + localTransform = glm::make_mat4x4(node.matrix.data()); + }; + + auto transform = globalTransform*localTransform; + + if (node.mesh > -1) { + loadMesh(model.meshes[node.mesh]); + worldMatrices.push_back(transform); + } + + processNodes(node.children, transform); + } + }; + + void loadMesh(const Mesh& mesh) { + std::cout << "Load mesh\n"; + std::vector vb; + std::vector ib; + for (const auto& primitive : mesh.primitives) { + // ������� + const auto& positionAccessor = model.accessors[primitive.attributes.at("POSITION")]; + const auto& positionView = model.bufferViews[positionAccessor.bufferView]; + const auto& positionBuffer = model.buffers[positionView.buffer]; + const float* positions = reinterpret_cast(&positionBuffer.data[positionView.byteOffset + positionAccessor.byteOffset]); + + // ������� (���� ����) + const auto& normalAccessor = model.accessors[primitive.attributes.at("NORMAL")]; + const auto& normalView = model.bufferViews[normalAccessor.bufferView]; + const auto& normalBuffer = model.buffers[normalView.buffer]; + const float* normals = reinterpret_cast(&normalBuffer.data[normalView.byteOffset + normalAccessor.byteOffset]); + + // ������� + const auto& indexAccessor = model.accessors[primitive.indices]; + const auto& indexView = model.bufferViews[indexAccessor.bufferView]; + const auto& indexBuffer = model.buffers[indexView.buffer]; + const uint16_t* indicesSrc = reinterpret_cast(&indexBuffer.data[indexView.byteOffset + indexAccessor.byteOffset]); + + // ���������� �������� + for (size_t i = 0; i < positionAccessor.count; i++) { + Vertex vertex{}; + vertex.pos = glm::vec3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]); + vertex.normal = glm::vec3(normals[i * 3], normals[i * 3 + 1], normals[i * 3 + 2]); + vb.push_back(vertex); + } + + for (size_t i = 0; i < indexAccessor.count; i++) { + ib.push_back(indicesSrc[i]); + } + } + + vertices.push_back(vb); + indices.push_back(ib); + } + void loadModel() { TinyGLTF loader; std::string err; std::string warn; - bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, "C:/Users/emil2/OneDrive/Desktop/Coding/Study/CGDG/vulkan_tweaking/models/Models/BrainStem/glTF/BrainStem.gltf"); + bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, "models/Models/BrainStem/glTF/BrainStem.gltf"); if (!warn.empty()) { std::cout << "GLTF warning: " << warn << std::endl; @@ -269,40 +357,8 @@ private: throw std::runtime_error("Failed to load GLTF: " + err); } - // Ïîëó÷åíèå äàííûõ âåðøèí è èíäåêñîâ - for (const auto& mesh : model.meshes) { - for (const auto& primitive : mesh.primitives) { - // Âåðøèíû - const auto& positionAccessor = model.accessors[primitive.attributes.at("POSITION")]; - const auto& positionView = model.bufferViews[positionAccessor.bufferView]; - const auto& positionBuffer = model.buffers[positionView.buffer]; - const float* positions = reinterpret_cast(&positionBuffer.data[positionView.byteOffset + positionAccessor.byteOffset]); + processNodes(model.scenes[0].nodes, glm::mat4x4{}); - // Íîðìàëè (åñëè åñòü) - const auto& normalAccessor = model.accessors[primitive.attributes.at("NORMAL")]; - const auto& normalView = model.bufferViews[normalAccessor.bufferView]; - const auto& normalBuffer = model.buffers[normalView.buffer]; - const float* normals = reinterpret_cast(&normalBuffer.data[normalView.byteOffset + normalAccessor.byteOffset]); - - // Èíäåêñû - const auto& indexAccessor = model.accessors[primitive.indices]; - const auto& indexView = model.bufferViews[indexAccessor.bufferView]; - const auto& indexBuffer = model.buffers[indexView.buffer]; - const uint16_t* indicesSrc = reinterpret_cast(&indexBuffer.data[indexView.byteOffset + indexAccessor.byteOffset]); - - // Çàïîëíåíèå âåêòîðîâ - for (size_t i = 0; i < positionAccessor.count; i++) { - Vertex vertex{}; - vertex.pos = glm::vec3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]); - vertex.normal = glm::vec3(normals[i * 3], normals[i * 3 + 1], normals[i * 3 + 2]); - vertices.push_back(vertex); - } - - for (size_t i = 0; i < indexAccessor.count; i++) { - indices.push_back(indicesSrc[i]); - } - } - } std::cout << "Loaded " << vertices.size() << " vertices, " << indices.size() << " indices" << std::endl; } @@ -311,37 +367,45 @@ private: throw std::runtime_error("No vertices loaded!"); } - VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size(); - VkBufferCreateInfo bufferInfo{}; - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.size = sizeof(vertices[0]) * vertices.size(); - bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + vertexBuffer.resize(vertices.size()); + vertexBufferMemory.resize(vertices.size()); - // Óáðàòü this->, òàê êàê device óæå ÷ëåí êëàññà - if (vkCreateBuffer(device, &bufferInfo, nullptr, &vertexBuffer) != VK_SUCCESS) { - throw std::runtime_error("failed to create vertex buffer!"); + for (size_t i = 0; i < vertices.size(); i++) + { + auto vb = vertices[i]; + std::cout << "Vertex buffer: " << vb.size() << "\n"; + VkDeviceSize bufferSize = sizeof(Vertex) * vb.size(); + VkBufferCreateInfo bufferInfo{}; + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferInfo.size = bufferSize; + bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + // ������ this->, ��� ��� device ��� ���� ������ + if (vkCreateBuffer(device, &bufferInfo, nullptr, &vertexBuffer[i]) != VK_SUCCESS) { + throw std::runtime_error("failed to create vertex buffer!"); + } + + VkMemoryRequirements memRequirements; + vkGetBufferMemoryRequirements(device, vertexBuffer[i], &memRequirements); + + VkMemoryAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocInfo.allocationSize = memRequirements.size; + allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + if (vkAllocateMemory(device, &allocInfo, nullptr, &vertexBufferMemory[i]) != VK_SUCCESS) { + throw std::runtime_error("failed to allocate vertex buffer memory!"); + } + + vkBindBufferMemory(device, vertexBuffer[i], vertexBufferMemory[i], 0); + + void* data; + vkMapMemory(device, vertexBufferMemory[i], 0, bufferInfo.size, 0, &data); + memcpy(data, vb.data(), bufferInfo.size); + vkUnmapMemory(device, vertexBufferMemory[i]); } - - VkMemoryRequirements memRequirements; - vkGetBufferMemoryRequirements(device, vertexBuffer, &memRequirements); - - VkMemoryAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memRequirements.size; - allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - - if (vkAllocateMemory(device, &allocInfo, nullptr, &vertexBufferMemory) != VK_SUCCESS) { - throw std::runtime_error("failed to allocate vertex buffer memory!"); - } - - vkBindBufferMemory(device, vertexBuffer, vertexBufferMemory, 0); - - void* data; - vkMapMemory(device, vertexBufferMemory, 0, bufferInfo.size, 0, &data); - memcpy(data, vertices.data(), bufferInfo.size); - vkUnmapMemory(device, vertexBufferMemory); } uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) { VkPhysicalDeviceMemoryProperties memProperties; @@ -614,36 +678,133 @@ private: throw std::runtime_error("No indices loaded!"); } - VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size(); + indexBuffer.resize(indices.size()); + indexBufferMemory.resize(indices.size()); + + for (size_t i=0; i layouts(indices.size(), descriptorSetLayout); + VkDescriptorSetAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocInfo.descriptorPool = descriptorPool; + allocInfo.descriptorSetCount = indices.size(); + allocInfo.pSetLayouts = layouts.data(); + + descriptorSets.resize(indices.size()); + if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) { + throw std::runtime_error("failed to allocate descriptor sets!"); } - vkBindBufferMemory(device, indexBuffer, indexBufferMemory, 0); + for (size_t i = 0; i < indices.size(); i++) { + VkDescriptorBufferInfo bufferInfo{}; + bufferInfo.buffer = uniformBuffers[i]; + bufferInfo.offset = 0; + bufferInfo.range = sizeof(UniformBufferObject); - void* data; - vkMapMemory(device, indexBufferMemory, 0, bufferInfo.size, 0, &data); - memcpy(data, indices.data(), bufferInfo.size); - vkUnmapMemory(device, indexBufferMemory); + VkWriteDescriptorSet descriptorWrite{}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = descriptorSets[i]; + descriptorWrite.dstBinding = 0; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pBufferInfo = &bufferInfo; + + vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); + } } void createSwapChain() { @@ -768,6 +929,24 @@ private: } } + void createDescriptorSetLayout() { + VkDescriptorSetLayoutBinding uboLayoutBinding{}; + uboLayoutBinding.binding = 0; + uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + uboLayoutBinding.descriptorCount = 1; + uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + uboLayoutBinding.pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutCreateInfo layoutInfo{}; + layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layoutInfo.bindingCount = 1; + layoutInfo.pBindings = &uboLayoutBinding; + + if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) { + throw std::runtime_error("failed to create descriptor set layout!"); + } + } + void createGraphicsPipeline() { auto vertShaderCode = readFile("shaders/vert.spv"); auto fragShaderCode = readFile("shaders/frag.spv"); @@ -838,7 +1017,7 @@ private: rasterizerState.polygonMode = VK_POLYGON_MODE_FILL; rasterizerState.lineWidth = 1.0f; rasterizerState.cullMode = VK_CULL_MODE_BACK_BIT; - rasterizerState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; // Èñïðàâëåíî íà ïðàâèëüíîå íàïðàâëåíèå + rasterizerState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; // ���������� �� ���������� ����������� rasterizerState.depthBiasEnable = VK_FALSE; VkPipelineMultisampleStateCreateInfo multisamplingState{}; @@ -871,7 +1050,8 @@ private: VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutInfo.setLayoutCount = 0; + pipelineLayoutInfo.setLayoutCount = 1; + pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout; pipelineLayoutInfo.pushConstantRangeCount = 0; if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) { @@ -882,7 +1062,7 @@ private: pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; pipelineInfo.stageCount = shaderStages.size(); pipelineInfo.pStages = shaderStages.data(); - pipelineInfo.pVertexInputState = &vertexInputInfo; // Èñïðàâëåííûé vertex input + pipelineInfo.pVertexInputState = &vertexInputInfo; // ������������ vertex input pipelineInfo.pInputAssemblyState = &inputAssemblyState; pipelineInfo.pViewportState = &viewportState; pipelineInfo.pRasterizationState = &rasterizerState; @@ -1002,11 +1182,15 @@ private: vkCmdSetScissor(commandBuffer, 0, 1, &scissor); // TODO: Add VertexBUffer binding - VkDeviceSize offsets[] = {0}; - vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer, offsets); - vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT32); + for (size_t i=0; i