diff --git a/mdlviewer/src/mainwindow.cpp b/mdlviewer/src/mainwindow.cpp index 4b1f358..03e1ee0 100644 --- a/mdlviewer/src/mainwindow.cpp +++ b/mdlviewer/src/mainwindow.cpp @@ -82,13 +82,8 @@ MainWindow::MainWindow(GameData& data) : data(data) { vkWindow->setVulkanInstance(inst); auto widget = QWidget::createWindowContainer(vkWindow); - //widget->resize(640, 480); layout->addWidget(widget); - //vkWindow->show(); - - //auto surface = inst.surfaceForWindow(vkWindow); - //renderer->initSwapchain(surface); - - + data.extractFile("chara/equipment/e0000/model/c0201e0000_top.mdl", "top.mdl"); + renderer->addModel(parseMDL("top.mdl")); } \ No newline at end of file diff --git a/renderer/CMakeLists.txt b/renderer/CMakeLists.txt index 27fdd12..7a983be 100644 --- a/renderer/CMakeLists.txt +++ b/renderer/CMakeLists.txt @@ -2,4 +2,4 @@ find_package(Vulkan REQUIRED) add_library(renderer src/renderer.cpp) target_include_directories(renderer PUBLIC include) -target_link_libraries(renderer PUBLIC Vulkan::Vulkan fmt::fmt) \ No newline at end of file +target_link_libraries(renderer PUBLIC Vulkan::Vulkan fmt::fmt libxiv) \ No newline at end of file diff --git a/renderer/include/renderer.hpp b/renderer/include/renderer.hpp index 970c728..8b16d56 100644 --- a/renderer/include/renderer.hpp +++ b/renderer/include/renderer.hpp @@ -4,13 +4,22 @@ #include #include +#include "mdlparser.h"; + +struct RenderModel { + +}; + class Renderer { public: Renderer(); + void initPipeline(); void initSwapchain(VkSurfaceKHR surface, int width, int height); void resize(VkSurfaceKHR surface, int width, int height); + RenderModel addModel(const Model& model); + void render(); VkInstance instance = VK_NULL_HANDLE; @@ -28,4 +37,12 @@ public: std::array inFlightFences; std::array imageAvailableSemaphores, renderFinishedSemaphores; uint32_t currentFrame = 0; + + std::tuple createBuffer(size_t size, VkBufferUsageFlags usageFlags); + + uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); + + VkShaderModule createShaderModule(const uint32_t *code, const int length); + + VkShaderModule loadShaderFromDisk(const std::string_view path); }; \ No newline at end of file diff --git a/renderer/shaders/compile_shaders.sh b/renderer/shaders/compile_shaders.sh new file mode 100755 index 0000000..fd003a3 --- /dev/null +++ b/renderer/shaders/compile_shaders.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +glslc mesh.vert -o mesh.vert.spv && +glslc mesh.frag -o mesh.frag.spv \ No newline at end of file diff --git a/renderer/shaders/mesh.frag b/renderer/shaders/mesh.frag new file mode 100644 index 0000000..35a774d --- /dev/null +++ b/renderer/shaders/mesh.frag @@ -0,0 +1,7 @@ +#version 450 + +layout(location = 0) out vec4 outColor; + +void main() { + outColor = vec4(0.0, 1.0, 0.0, 1.0); +} diff --git a/renderer/shaders/mesh.frag.spv b/renderer/shaders/mesh.frag.spv new file mode 100644 index 0000000..47d2768 Binary files /dev/null and b/renderer/shaders/mesh.frag.spv differ diff --git a/renderer/shaders/mesh.vert b/renderer/shaders/mesh.vert new file mode 100644 index 0000000..b22c1b2 --- /dev/null +++ b/renderer/shaders/mesh.vert @@ -0,0 +1,7 @@ +#version 450 + +layout(location = 0) in vec3 inPosition; + +void main() { + gl_Position = vec4(inPosition, 1.0); +} diff --git a/renderer/shaders/mesh.vert.spv b/renderer/shaders/mesh.vert.spv new file mode 100644 index 0000000..b9cc072 Binary files /dev/null and b/renderer/shaders/mesh.vert.spv differ diff --git a/renderer/src/renderer.cpp b/renderer/src/renderer.cpp index f3ae8e3..a63f76a 100644 --- a/renderer/src/renderer.cpp +++ b/renderer/src/renderer.cpp @@ -5,6 +5,7 @@ #include #include #include +#include Renderer::Renderer() { VkApplicationInfo applicationInfo = {}; @@ -133,6 +134,8 @@ Renderer::Renderer() { vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool); + initPipeline(); + fmt::print("Initialized renderer!\n"); } @@ -412,4 +415,131 @@ void Renderer::render() { vkQueuePresentKHR(presentQueue, &presentInfo); currentFrame = (currentFrame + 1) % 3; +} + +std::tuple Renderer::createBuffer(size_t size, VkBufferUsageFlags usageFlags) { + vkDeviceWaitIdle(device); + + // create buffer + VkBufferCreateInfo bufferInfo = {}; + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferInfo.size = size; + bufferInfo.usage = usageFlags; + bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VkBuffer handle; + vkCreateBuffer(device, &bufferInfo, nullptr, &handle); + + // allocate memory + VkMemoryRequirements memRequirements; + vkGetBufferMemoryRequirements(device, handle, &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); + + VkDeviceMemory memory; + vkAllocateMemory(device, &allocInfo, nullptr, &memory); + + vkBindBufferMemory(device, handle, memory, 0); + + return {handle, memory}; +} + +uint32_t Renderer::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) { + VkPhysicalDeviceMemoryProperties memProperties; + vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties); + + for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) { + if ((typeFilter & (1 << i)) && + (memProperties.memoryTypes[i].propertyFlags & properties) == + properties) { + return i; + } + } + + return -1; +} + +RenderModel Renderer::addModel(const Model& model) { + RenderModel renderModel; + + size_t vertexSize = model.lods[0].parts[0].vertices.size() * sizeof(float) * 3; + auto [vertexBuffer, vertexMemory] = createBuffer(vertexSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + + size_t indexSize = model.lods[0].parts[0].indices.size() * sizeof(uint16_t); + auto [indexBuffer, indexMemory] = createBuffer(indexSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + + // copy vertex data + { + void* mapped_data = nullptr; + vkMapMemory(device, vertexMemory, 0, vertexSize, 0, &mapped_data); + + for(int i = 0; i < model.lods[0].parts[0].vertices.size(); i++) { + memcpy(mapped_data, model.lods[0].parts[0].vertices[i].position.data(), sizeof(float) * 3); + } + + VkMappedMemoryRange range = {}; + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.memory = vertexMemory; + range.size = vertexSize; + vkFlushMappedMemoryRanges(device, 1, &range); + + vkUnmapMemory(device, vertexMemory); + } + + // copy index data + { + void* mapped_data = nullptr; + vkMapMemory(device, indexMemory, 0, indexSize, 0, &mapped_data); + + memcpy(mapped_data, model.lods[0].parts[0].indices.data(), indexSize); + + VkMappedMemoryRange range = {}; + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.memory = indexMemory; + range.size = indexSize; + vkFlushMappedMemoryRanges(device, 1, &range); + + vkUnmapMemory(device, indexMemory); + } + + return renderModel; +} + +void Renderer::initPipeline() { + auto vertexModule = loadShaderFromDisk("mesh.vert.spv"); + auto fragmentModule = loadShaderFromDisk("mesh.frag.spv"); +} + +VkShaderModule Renderer::createShaderModule(const uint32_t* code, const int length) { + VkShaderModuleCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = length; + createInfo.pCode = reinterpret_cast(code); + + VkShaderModule shaderModule; + vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule); + + return shaderModule; +} + +VkShaderModule Renderer::loadShaderFromDisk(const std::string_view path) { + std::ifstream file(path.data(), std::ios::ate | std::ios::binary); + + if (!file.is_open()) { + throw std::runtime_error(fmt::format("failed to open shader file {}", path)); + } + + size_t fileSize = (size_t) file.tellg(); + std::vector buffer(fileSize); + + file.seekg(0); + file.read(buffer.data(), fileSize); + + return createShaderModule(reinterpret_cast(buffer.data()), fileSize); } \ No newline at end of file