1
Fork 0
mirror of https://github.com/redstrate/Novus.git synced 2025-05-14 20:47:46 +00:00

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.
This commit is contained in:
Joshua Goins 2025-05-13 16:41:52 -04:00
parent 66808619f3
commit fc327ba8b5
7 changed files with 145 additions and 6 deletions

View file

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

View file

@ -0,0 +1,26 @@
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <vulkan/vulkan.h>
#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;
};

View file

@ -1,5 +1,9 @@
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
// 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<SimpleRenderer *>(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<VkPipelineShaderStageCreateInfo, 2> 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<SimpleRenderer *>(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();

View file

@ -0,0 +1,80 @@
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "primitives.h"
#include "rendermanager.h"
#include <complex>
#include <glm/glm.hpp>
#include <glm/gtc/constants.hpp>
#include <glm/vec3.hpp>
Sphere Primitives::sphere;
void Primitives::Initialize(RenderManager *renderer)
{
// sphere
{
std::vector<glm::vec3> vertices;
std::vector<unsigned int> 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<float>(x) / static_cast<float>(xResolution);
float ySegment = static_cast<float>(y) / static_cast<float>(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<uint32_t>(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);
}

View file

@ -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();
}
}

View file

@ -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 = {};

View file

@ -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<uint64_t>(m_framebuffer), "simple renderer framebuffer");
}
void SimpleRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene &scene, const std::vector<DrawObject> &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<uint64_t>(m_renderPass), "simple renderer renderpass");
}
void SimpleRenderer::initPipeline()