From fc327ba8b5ef95e8776d77bd2efd51debc765125 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Tue, 13 May 2025 16:41:52 -0400 Subject: [PATCH] Fix the object pass, start rendering a sphere The sphere doesn't look correct (bad vertex stride) but that doesn't matter. I need to expose the object's transform in libphysis next, before we can start drawing. --- apps/mapeditor/CMakeLists.txt | 4 +- apps/mapeditor/include/primitives.h | 26 ++++++++++ apps/mapeditor/src/objectpass.cpp | 30 +++++++++-- apps/mapeditor/src/primitives.cpp | 80 +++++++++++++++++++++++++++++ parts/mdl/vulkanwindow.cpp | 2 +- renderer/src/rendermanager.cpp | 5 ++ renderer/src/simplerenderer.cpp | 4 +- 7 files changed, 145 insertions(+), 6 deletions(-) create mode 100644 apps/mapeditor/include/primitives.h create mode 100644 apps/mapeditor/src/primitives.cpp diff --git a/apps/mapeditor/CMakeLists.txt b/apps/mapeditor/CMakeLists.txt index 9bc312a..24967e4 100644 --- a/apps/mapeditor/CMakeLists.txt +++ b/apps/mapeditor/CMakeLists.txt @@ -11,6 +11,7 @@ target_sources(novus-mapeditor include/objectlistwidget.h include/appstate.h include/objectlistmodel.h + include/primitives.h src/main.cpp src/mainwindow.cpp @@ -19,7 +20,8 @@ target_sources(novus-mapeditor src/objectpass.cpp src/objectlistwidget.cpp src/appstate.cpp - src/objectlistmodel.cpp) + src/objectlistmodel.cpp + src/primitives.cpp) target_include_directories(novus-mapeditor PUBLIC include) diff --git a/apps/mapeditor/include/primitives.h b/apps/mapeditor/include/primitives.h new file mode 100644 index 0000000..7a3cebd --- /dev/null +++ b/apps/mapeditor/include/primitives.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2025 Joshua Goins +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include + +#include "buffer.h" + +class RenderManager; + +struct Sphere { + Buffer vertexBuffer, indexBuffer; + uint32_t indexCount; +}; + +class Primitives +{ +public: + static void Initialize(RenderManager *renderer); + static void Cleanup(RenderManager *renderer); + + static void DrawSphere(VkCommandBuffer commandBuffer); + + static Sphere sphere; +}; diff --git a/apps/mapeditor/src/objectpass.cpp b/apps/mapeditor/src/objectpass.cpp index 6fbfafe..ca4f798 100644 --- a/apps/mapeditor/src/objectpass.cpp +++ b/apps/mapeditor/src/objectpass.cpp @@ -1,5 +1,9 @@ +// SPDX-FileCopyrightText: 2025 Joshua Goins +// SPDX-License-Identifier: GPL-3.0-or-later + #include "objectpass.h" #include "device.h" +#include "primitives.h" #include "rendermanager.h" #include "simplerenderer.h" #include "swapchain.h" @@ -11,11 +15,23 @@ ObjectPass::ObjectPass(RenderManager *renderer) , m_device(m_renderer->device()) { createPipeline(); + + Primitives::Initialize(m_renderer); } void ObjectPass::render(VkCommandBuffer commandBuffer, Camera &camera) { if (auto renderer = dynamic_cast(m_renderer->renderer())) { + VkDebugUtilsLabelEXT labelExt{}; + labelExt.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; + labelExt.pLabelName = "Object Pass"; + m_renderer->device().beginDebugMarker(commandBuffer, labelExt); + + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_); + + Primitives::DrawSphere(commandBuffer); + + m_renderer->device().endDebugMarker(commandBuffer); } else { qWarning() << "Can't render object pass in non-simple renderer for now!!"; } @@ -77,8 +93,8 @@ void ObjectPass::createPipeline() VkPipelineShaderStageCreateInfo fragmentShaderStageInfo = {}; fragmentShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - fragmentShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; - fragmentShaderStageInfo.module = m_device.loadShaderFromDisk(":/shaders/debug.vert.spv"); + fragmentShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fragmentShaderStageInfo.module = m_device.loadShaderFromDisk(":/shaders/debug.frag.spv"); fragmentShaderStageInfo.pName = "main"; const std::array shaderStages = {vertexShaderStageInfo, fragmentShaderStageInfo}; @@ -132,7 +148,7 @@ void ObjectPass::createPipeline() dynamicState.pDynamicStates = dynamicStates.data(); VkPushConstantRange pushConstant = {}; - pushConstant.size = sizeof(glm::mat4); + pushConstant.size = sizeof(glm::mat4) * 2; pushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; VkPipelineLayoutCreateInfo pipelineLayoutInfo = {}; @@ -142,6 +158,13 @@ void ObjectPass::createPipeline() vkCreatePipelineLayout(m_device.device, &pipelineLayoutInfo, nullptr, &pipelineLayout_); + VkPipelineDepthStencilStateCreateInfo depthStencil = {}; + depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depthStencil.depthTestEnable = VK_TRUE; + depthStencil.depthWriteEnable = VK_TRUE; + depthStencil.depthCompareOp = VK_COMPARE_OP_LESS; + depthStencil.maxDepthBounds = 1.0f; + auto renderer = dynamic_cast(m_renderer->renderer()); VkGraphicsPipelineCreateInfo pipelineInfo = {}; @@ -155,6 +178,7 @@ void ObjectPass::createPipeline() pipelineInfo.pMultisampleState = &multisampling; pipelineInfo.pColorBlendState = &colorBlending; pipelineInfo.pDynamicState = &dynamicState; + pipelineInfo.pDepthStencilState = &depthStencil; pipelineInfo.layout = pipelineLayout_; pipelineInfo.renderPass = renderer->renderPass(); diff --git a/apps/mapeditor/src/primitives.cpp b/apps/mapeditor/src/primitives.cpp new file mode 100644 index 0000000..a0e9000 --- /dev/null +++ b/apps/mapeditor/src/primitives.cpp @@ -0,0 +1,80 @@ +// SPDX-FileCopyrightText: 2025 Joshua Goins +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "primitives.h" +#include "rendermanager.h" + +#include +#include +#include +#include + +Sphere Primitives::sphere; + +void Primitives::Initialize(RenderManager *renderer) +{ + // sphere + { + std::vector vertices; + std::vector indices; + + unsigned int xResolution = 64; + unsigned int yResolution = 64; + float PI = 3.14159265359f; + + for (unsigned int y = 0; y <= yResolution; ++y) { + for (unsigned int x = 0; x <= xResolution; ++x) { + float xSegment = static_cast(x) / static_cast(xResolution); + float ySegment = static_cast(y) / static_cast(yResolution); + + float xPos = glm::cos(xSegment * 2.0f * PI) * glm::sin(ySegment * PI); + float yPos = glm::cos(ySegment * PI); + float zPos = glm::sin(xSegment * 2.0f * PI) * glm::sin(ySegment * PI); + + vertices.push_back(glm::vec3(xPos, yPos, zPos)); + } + } + + bool oddRow = false; + for (unsigned int y = 0; y < yResolution; ++y) { + if (!oddRow) { + for (unsigned int x = 0; x <= xResolution; ++x) { + indices.push_back(y * (xResolution + 1) + x); + indices.push_back((y + 1) * (xResolution + 1) + x); + } + } else { + for (int x = xResolution; x >= 0; --x) { + indices.push_back((y + 1) * (xResolution + 1) + x); + indices.push_back(y * (xResolution + 1) + x); + } + } + oddRow = !oddRow; + } + sphere.indexCount = static_cast(indices.size()); + + // VERTICES + VkDeviceSize vertexSize = sizeof(glm::vec3) * vertices.size(); + sphere.vertexBuffer = renderer->device().createBuffer(vertexSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + renderer->device().copyToBuffer(sphere.vertexBuffer, vertices.data(), vertexSize); + + // INDICES + VkDeviceSize indexSize = sizeof(unsigned int) * indices.size(); + sphere.indexBuffer = renderer->device().createBuffer(indexSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + renderer->device().copyToBuffer(sphere.indexBuffer, indices.data(), indexSize); + } +} + +void Primitives::Cleanup(RenderManager *renderer) +{ + // TODO: stub +} + +void Primitives::DrawSphere(VkCommandBuffer commandBuffer) +{ + VkDeviceSize offsets[] = {0}; + + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &sphere.vertexBuffer.buffer, offsets); + vkCmdBindIndexBuffer(commandBuffer, sphere.indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); + + vkCmdDrawIndexed(commandBuffer, sphere.indexCount, 1, 0, 0, 0); +} diff --git a/parts/mdl/vulkanwindow.cpp b/parts/mdl/vulkanwindow.cpp index 9b1e773..846f5db 100644 --- a/parts/mdl/vulkanwindow.cpp +++ b/parts/mdl/vulkanwindow.cpp @@ -25,9 +25,9 @@ void VulkanWindow::exposeEvent(QExposeEvent *) auto surface = m_instance->surfaceForWindow(this); if (!m_renderer->initSwapchain(surface, width() * screen()->devicePixelRatio(), height() * screen()->devicePixelRatio())) { - Q_EMIT part->initializeRender(); m_initialized = false; } else { + Q_EMIT part->initializeRender(); render(); } } diff --git a/renderer/src/rendermanager.cpp b/renderer/src/rendermanager.cpp index 4de5982..8a3f458 100644 --- a/renderer/src/rendermanager.cpp +++ b/renderer/src/rendermanager.cpp @@ -84,6 +84,11 @@ RenderManager::RenderManager(GameData *data) if (strstr(extension.extensionName, "VK_EXT_debug_utils") != nullptr) { instanceExtensions.push_back(extension.extensionName); } + + // needed for VK_EXT_display_surface_counter + if (strstr(extension.extensionName, "VK_KHR_display") != nullptr) { + instanceExtensions.push_back(extension.extensionName); + } } VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = {}; diff --git a/renderer/src/simplerenderer.cpp b/renderer/src/simplerenderer.cpp index 9c76f01..0da5093 100644 --- a/renderer/src/simplerenderer.cpp +++ b/renderer/src/simplerenderer.cpp @@ -46,6 +46,7 @@ void SimpleRenderer::resize() framebufferInfo.layers = 1; vkCreateFramebuffer(m_device.device, &framebufferInfo, nullptr, &m_framebuffer); + m_device.nameObject(VK_OBJECT_TYPE_FRAMEBUFFER, reinterpret_cast(m_framebuffer), "simple renderer framebuffer"); } void SimpleRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene &scene, const std::vector &models) @@ -166,7 +167,7 @@ void SimpleRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene void SimpleRenderer::initRenderPass() { VkAttachmentDescription colorAttachment = {}; - colorAttachment.format = m_device.swapChain->surfaceFormat; + colorAttachment.format = VK_FORMAT_R8G8B8A8_UNORM; colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; @@ -220,6 +221,7 @@ void SimpleRenderer::initRenderPass() renderPassInfo.pDependencies = &dependency; vkCreateRenderPass(m_device.device, &renderPassInfo, nullptr, &m_renderPass); + m_device.nameObject(VK_OBJECT_TYPE_RENDER_PASS, reinterpret_cast(m_renderPass), "simple renderer renderpass"); } void SimpleRenderer::initPipeline()