mirror of
https://github.com/redstrate/Novus.git
synced 2025-05-14 04:27:46 +00:00
Begin adding support for drawing additional objects in the renderer
This will be used in the map editor to draw where objects are. It doesn't draw anything yet, and can't until we get LGB support in libphysis.
This commit is contained in:
parent
442a13a612
commit
93bb7fec43
28 changed files with 304 additions and 5 deletions
|
@ -7,11 +7,13 @@ target_sources(novus-mapeditor
|
|||
include/mainwindow.h
|
||||
include/maplistwidget.h
|
||||
include/mapview.h
|
||||
include/objectpass.h
|
||||
|
||||
src/main.cpp
|
||||
src/mainwindow.cpp
|
||||
src/maplistwidget.cpp
|
||||
src/mapview.cpp)
|
||||
src/mapview.cpp
|
||||
src/objectpass.cpp)
|
||||
target_include_directories(novus-mapeditor
|
||||
PUBLIC
|
||||
include)
|
||||
|
|
26
apps/mapeditor/include/objectpass.h
Normal file
26
apps/mapeditor/include/objectpass.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include "pass.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
class RenderManager;
|
||||
class Device;
|
||||
|
||||
class ObjectPass : public RendererPass
|
||||
{
|
||||
public:
|
||||
ObjectPass(RenderManager *renderer);
|
||||
|
||||
void render(VkCommandBuffer commandBuffer, Camera &camera) override;
|
||||
|
||||
private:
|
||||
void createPipeline();
|
||||
|
||||
VkPipeline pipeline_ = nullptr;
|
||||
VkPipelineLayout pipelineLayout_ = nullptr;
|
||||
|
||||
RenderManager *m_renderer;
|
||||
Device &m_device;
|
||||
};
|
|
@ -7,6 +7,7 @@
|
|||
#include <QVBoxLayout>
|
||||
|
||||
#include "filecache.h"
|
||||
#include "objectpass.h"
|
||||
|
||||
MapView::MapView(GameData *data, FileCache &cache, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
|
@ -15,6 +16,9 @@ MapView::MapView(GameData *data, FileCache &cache, QWidget *parent)
|
|||
{
|
||||
mdlPart = new MDLPart(data, cache);
|
||||
mdlPart->enableFreemode();
|
||||
connect(mdlPart, &MDLPart::initializeRender, this, [this] {
|
||||
mdlPart->manager()->addPass(new ObjectPass(mdlPart->manager()));
|
||||
});
|
||||
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
|
162
apps/mapeditor/src/objectpass.cpp
Normal file
162
apps/mapeditor/src/objectpass.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
#include "objectpass.h"
|
||||
#include "device.h"
|
||||
#include "rendermanager.h"
|
||||
#include "simplerenderer.h"
|
||||
#include "swapchain.h"
|
||||
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
ObjectPass::ObjectPass(RenderManager *renderer)
|
||||
: m_renderer(renderer)
|
||||
, m_device(m_renderer->device())
|
||||
{
|
||||
createPipeline();
|
||||
}
|
||||
|
||||
void ObjectPass::render(VkCommandBuffer commandBuffer, Camera &camera)
|
||||
{
|
||||
if (auto renderer = dynamic_cast<SimpleRenderer *>(m_renderer->renderer())) {
|
||||
} else {
|
||||
qWarning() << "Can't render object pass in non-simple renderer for now!!";
|
||||
}
|
||||
|
||||
/*VkClearValue clearValue = {};
|
||||
clearValue.color = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
VkRenderPassBeginInfo renderPassInfo = {};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassInfo.renderPass = m_renderPass;
|
||||
renderPassInfo.framebuffer = target->sobelFramebuffers[target->currentResource];
|
||||
renderPassInfo.renderArea.extent = target->extent;
|
||||
renderPassInfo.clearValueCount = 1;
|
||||
renderPassInfo.pClearValues = &clearValue;
|
||||
|
||||
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
|
||||
|
||||
if(extraInfo != nullptr) {
|
||||
for (auto mesh: collection.meshes) {
|
||||
bool shouldRender = false;
|
||||
for (int i = 0; i < extraInfo->numSelectedEntities; i++) {
|
||||
if (extraInfo->selectedEntities[i] == mesh.entity)
|
||||
shouldRender = true;
|
||||
}
|
||||
|
||||
if (shouldRender) {
|
||||
glm::mat4 mvp;
|
||||
mvp = glm::perspective(glm::radians(collection.camera.camera->fov),
|
||||
(float) target->extent.width / target->extent.height,
|
||||
collection.camera.camera->near, collection.camera.camera->far);
|
||||
mvp *= glm::lookAt(collection.camera.transform->position, collection.camera.camera->target,
|
||||
glm::vec3(0, -1, 0));
|
||||
mvp = glm::translate(mvp, mesh.transform->position);
|
||||
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4),
|
||||
&mvp);
|
||||
|
||||
const VkDeviceSize offsets[] = {0};
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh.mesh->mesh->vertexBuffer, offsets);
|
||||
vkCmdBindIndexBuffer(commandBuffer, mesh.mesh->mesh->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
|
||||
vkCmdDrawIndexed(commandBuffer, mesh.mesh->mesh->indices.size(), 1, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vkCmdEndRenderPass(commandBuffer);*/
|
||||
}
|
||||
|
||||
void ObjectPass::createPipeline()
|
||||
{
|
||||
VkPipelineShaderStageCreateInfo vertexShaderStageInfo = {};
|
||||
vertexShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
vertexShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
vertexShaderStageInfo.module = m_device.loadShaderFromDisk(":/shaders/debug.vert.spv");
|
||||
vertexShaderStageInfo.pName = "main";
|
||||
|
||||
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.pName = "main";
|
||||
|
||||
const std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages = {vertexShaderStageInfo, fragmentShaderStageInfo};
|
||||
|
||||
VkVertexInputBindingDescription vertexBindingDescription = {};
|
||||
vertexBindingDescription.stride = sizeof(Vertex);
|
||||
|
||||
VkVertexInputAttributeDescription positionAttributeDescription = {};
|
||||
positionAttributeDescription.format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
|
||||
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
vertexInputInfo.vertexBindingDescriptionCount = 1;
|
||||
vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDescription;
|
||||
vertexInputInfo.vertexAttributeDescriptionCount = 1;
|
||||
vertexInputInfo.pVertexAttributeDescriptions = &positionAttributeDescription;
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
|
||||
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewportState = {};
|
||||
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||
viewportState.viewportCount = 1;
|
||||
viewportState.scissorCount = 1;
|
||||
|
||||
VkPipelineRasterizationStateCreateInfo rasterizer = {};
|
||||
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
|
||||
rasterizer.cullMode = VK_CULL_MODE_NONE;
|
||||
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
rasterizer.lineWidth = 1.0f;
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
||||
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
|
||||
VkPipelineColorBlendStateCreateInfo colorBlending = {};
|
||||
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||
colorBlending.attachmentCount = 1;
|
||||
colorBlending.pAttachments = &colorBlendAttachment;
|
||||
|
||||
const std::array<VkDynamicState, 2> dynamicStates = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
|
||||
|
||||
VkPipelineDynamicStateCreateInfo dynamicState = {};
|
||||
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||
dynamicState.dynamicStateCount = dynamicStates.size();
|
||||
dynamicState.pDynamicStates = dynamicStates.data();
|
||||
|
||||
VkPushConstantRange pushConstant = {};
|
||||
pushConstant.size = sizeof(glm::mat4);
|
||||
pushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
|
||||
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
||||
pipelineLayoutInfo.pPushConstantRanges = &pushConstant;
|
||||
|
||||
vkCreatePipelineLayout(m_device.device, &pipelineLayoutInfo, nullptr, &pipelineLayout_);
|
||||
|
||||
auto renderer = dynamic_cast<SimpleRenderer *>(m_renderer->renderer());
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineInfo = {};
|
||||
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||
pipelineInfo.stageCount = shaderStages.size();
|
||||
pipelineInfo.pStages = shaderStages.data();
|
||||
pipelineInfo.pVertexInputState = &vertexInputInfo;
|
||||
pipelineInfo.pInputAssemblyState = &inputAssembly;
|
||||
pipelineInfo.pViewportState = &viewportState;
|
||||
pipelineInfo.pRasterizationState = &rasterizer;
|
||||
pipelineInfo.pMultisampleState = &multisampling;
|
||||
pipelineInfo.pColorBlendState = &colorBlending;
|
||||
pipelineInfo.pDynamicState = &dynamicState;
|
||||
pipelineInfo.layout = pipelineLayout_;
|
||||
pipelineInfo.renderPass = renderer->renderPass();
|
||||
|
||||
vkCreateGraphicsPipelines(m_device.device, nullptr, 1, &pipelineInfo, nullptr, &pipeline_);
|
||||
}
|
|
@ -423,4 +423,9 @@ int MDLPart::numModels() const
|
|||
return models.size();
|
||||
}
|
||||
|
||||
RenderManager *MDLPart::manager() const
|
||||
{
|
||||
return renderer;
|
||||
}
|
||||
|
||||
#include "moc_mdlpart.cpp"
|
||||
|
|
|
@ -49,6 +49,8 @@ public:
|
|||
|
||||
int numModels() const;
|
||||
|
||||
RenderManager *manager() const;
|
||||
|
||||
physis_PBD pbd{};
|
||||
|
||||
bool enableRacialDeform = true;
|
||||
|
@ -56,6 +58,8 @@ public:
|
|||
Q_SIGNALS:
|
||||
void modelChanged();
|
||||
void skeletonChanged();
|
||||
// Called when a Vulkan context is available, and you can safely access RenderManager
|
||||
void initializeRender();
|
||||
|
||||
public Q_SLOTS:
|
||||
/// Clears all stored MDLs.
|
||||
|
|
|
@ -25,6 +25,7 @@ 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 {
|
||||
render();
|
||||
|
|
|
@ -22,6 +22,7 @@ target_sources(renderer
|
|||
include/simplerenderer.h
|
||||
include/swapchain.h
|
||||
include/texture.h
|
||||
include/pass.h
|
||||
|
||||
src/device.cpp
|
||||
src/gamerenderer.cpp
|
||||
|
@ -42,7 +43,9 @@ qt_add_resources(renderer
|
|||
shaders/mesh.vert.spv
|
||||
shaders/skinned.vert.spv
|
||||
shaders/blit.vert.spv
|
||||
shaders/blit.frag.spv)
|
||||
shaders/blit.frag.spv
|
||||
shaders/debug.vert.spv
|
||||
shaders/debug.frag.spv)
|
||||
target_include_directories(renderer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_link_libraries(renderer
|
||||
PUBLIC
|
||||
|
|
|
@ -18,6 +18,8 @@ struct DrawObject;
|
|||
struct Camera;
|
||||
struct Texture;
|
||||
struct Scene;
|
||||
class Pass;
|
||||
class Device;
|
||||
|
||||
/// Base class for all rendering implementations
|
||||
class BaseRenderer
|
||||
|
@ -33,4 +35,6 @@ public:
|
|||
|
||||
/// The final composite texture that is drawn into with render()
|
||||
virtual Texture &getCompositeTexture() = 0;
|
||||
|
||||
virtual Device &device() = 0;
|
||||
};
|
|
@ -35,6 +35,8 @@ public:
|
|||
|
||||
Texture &getCompositeTexture() override;
|
||||
|
||||
Device &device() override;
|
||||
|
||||
private:
|
||||
struct RequestedBinding {
|
||||
VkDescriptorType type;
|
||||
|
|
11
renderer/include/pass.h
Normal file
11
renderer/include/pass.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
class Camera;
|
||||
|
||||
class RendererPass
|
||||
{
|
||||
public:
|
||||
virtual void render(VkCommandBuffer commandBuffer, Camera &camera) = 0;
|
||||
};
|
|
@ -20,6 +20,7 @@
|
|||
class ImGuiPass;
|
||||
struct ImGuiContext;
|
||||
class BaseRenderer;
|
||||
class RendererPass;
|
||||
|
||||
/// Render 3D scenes made up of FFXIV game objects
|
||||
class RenderManager
|
||||
|
@ -49,6 +50,10 @@ public:
|
|||
|
||||
VkSampler defaultSampler();
|
||||
|
||||
void addPass(RendererPass *pass);
|
||||
|
||||
BaseRenderer *renderer();
|
||||
|
||||
private:
|
||||
void updateCamera(Camera &camera);
|
||||
void initBlitPipeline();
|
||||
|
@ -68,4 +73,5 @@ private:
|
|||
Device *m_device = nullptr;
|
||||
BaseRenderer *m_renderer = nullptr;
|
||||
GameData *m_data = nullptr;
|
||||
std::vector<RendererPass *> m_passes;
|
||||
};
|
|
@ -34,6 +34,11 @@ public:
|
|||
|
||||
Texture &getCompositeTexture() override;
|
||||
|
||||
Device &device() override;
|
||||
|
||||
VkFramebuffer framebuffer();
|
||||
VkRenderPass renderPass();
|
||||
|
||||
private:
|
||||
void initRenderPass();
|
||||
void initPipeline();
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -9,4 +9,6 @@ glslc imgui.vert -o imgui.vert.spv &&
|
|||
glslc imgui.frag -o imgui.frag.spv &&
|
||||
glslc dummy.frag -o dummy.frag.spv &&
|
||||
glslc blit.vert -o blit.vert.spv &&
|
||||
glslc blit.frag -o blit.frag.spv
|
||||
glslc blit.frag -o blit.frag.spv &&
|
||||
glslc debug.vert -o debug.vert.spv &&
|
||||
glslc debug.frag -o debug.frag.spv
|
10
renderer/shaders/debug.frag
Normal file
10
renderer/shaders/debug.frag
Normal file
|
@ -0,0 +1,10 @@
|
|||
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
#version 450
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = vec4(1, 0, 0, 1);
|
||||
}
|
BIN
renderer/shaders/debug.frag.spv
Normal file
BIN
renderer/shaders/debug.frag.spv
Normal file
Binary file not shown.
16
renderer/shaders/debug.vert
Normal file
16
renderer/shaders/debug.vert
Normal file
|
@ -0,0 +1,16 @@
|
|||
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 inPosition;
|
||||
|
||||
layout(std430, push_constant) uniform PushConstant {
|
||||
mat4 vp, model;
|
||||
};
|
||||
|
||||
void main() {
|
||||
vec4 bPos = model * vec4(inPosition, 1.0);
|
||||
|
||||
gl_Position = vp * bPos;
|
||||
}
|
BIN
renderer/shaders/debug.vert.spv
Normal file
BIN
renderer/shaders/debug.vert.spv
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1498,3 +1498,8 @@ void GameRenderer::bindDescriptorSets(VkCommandBuffer commandBuffer,
|
|||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipelineLayout, i, 1, &pipeline.cachedDescriptors[i], 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
Device &GameRenderer::device()
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "gamerenderer.h"
|
||||
#include "imgui.h"
|
||||
#include "imguipass.h"
|
||||
#include "pass.h"
|
||||
#include "simplerenderer.h"
|
||||
#include "swapchain.h"
|
||||
|
||||
|
@ -423,6 +424,13 @@ void RenderManager::render(const std::vector<DrawObject> &models)
|
|||
|
||||
m_renderer->render(commandBuffer, camera, scene, models);
|
||||
|
||||
// render extra passes
|
||||
for (const auto &pass : m_passes) {
|
||||
pass->render(commandBuffer, camera);
|
||||
}
|
||||
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
|
||||
VkRenderPassBeginInfo renderPassInfo = {};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassInfo.renderPass = m_renderPass;
|
||||
|
@ -708,3 +716,13 @@ void RenderManager::initBlitPipeline()
|
|||
|
||||
vkUpdateDescriptorSets(m_device->device, 1, &multiDescriptorWrite2, 0, nullptr);
|
||||
}
|
||||
|
||||
void RenderManager::addPass(RendererPass *pass)
|
||||
{
|
||||
m_passes.push_back(pass);
|
||||
}
|
||||
|
||||
BaseRenderer *RenderManager::renderer()
|
||||
{
|
||||
return m_renderer;
|
||||
}
|
||||
|
|
|
@ -161,8 +161,6 @@ void SimpleRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene
|
|||
vkCmdDrawIndexed(commandBuffer, part.numIndices, 1, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
}
|
||||
|
||||
void SimpleRenderer::initRenderPass()
|
||||
|
@ -569,3 +567,18 @@ Texture &SimpleRenderer::getCompositeTexture()
|
|||
{
|
||||
return m_compositeTexture;
|
||||
}
|
||||
|
||||
Device &SimpleRenderer::device()
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
|
||||
VkFramebuffer SimpleRenderer::framebuffer()
|
||||
{
|
||||
return m_framebuffer;
|
||||
}
|
||||
|
||||
VkRenderPass SimpleRenderer::renderPass()
|
||||
{
|
||||
return m_renderPass;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue