feat: add 2D rendering pipeline
This commit is contained in:
@@ -38,6 +38,7 @@ set(SRC_FILES
|
|||||||
"src/Graphics/Managers/FrameManager.cpp"
|
"src/Graphics/Managers/FrameManager.cpp"
|
||||||
"src/Graphics/Managers/ImageManager.cpp"
|
"src/Graphics/Managers/ImageManager.cpp"
|
||||||
"src/Graphics/Managers/LineRenderingManager.cpp"
|
"src/Graphics/Managers/LineRenderingManager.cpp"
|
||||||
|
"src/Graphics/Managers/QuadRenderingManager.cpp"
|
||||||
|
|
||||||
"src/Graphics/Resources/GPUImage.cpp"
|
"src/Graphics/Resources/GPUImage.cpp"
|
||||||
"src/Graphics/Resources/NBuffer.cpp"
|
"src/Graphics/Resources/NBuffer.cpp"
|
||||||
@@ -45,6 +46,7 @@ set(SRC_FILES
|
|||||||
|
|
||||||
"src/Graphics/Pipelines/MeshPipeline.cpp"
|
"src/Graphics/Pipelines/MeshPipeline.cpp"
|
||||||
"src/Graphics/Pipelines/LineRenderingPass.cpp"
|
"src/Graphics/Pipelines/LineRenderingPass.cpp"
|
||||||
|
"src/Graphics/Pipelines/QuadRendererPass.cpp"
|
||||||
"src/Graphics/Pipelines/SkyboxPipeline.cpp"
|
"src/Graphics/Pipelines/SkyboxPipeline.cpp"
|
||||||
"src/Graphics/Pipelines/SkinningPipeline.cpp"
|
"src/Graphics/Pipelines/SkinningPipeline.cpp"
|
||||||
"src/Graphics/Pipelines/ImguiPass.cpp"
|
"src/Graphics/Pipelines/ImguiPass.cpp"
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#version 460
|
||||||
|
#extension GL_GOOGLE_include_directive : require
|
||||||
|
#extension GL_EXT_nonuniform_qualifier : enable
|
||||||
|
|
||||||
|
#include "bindless.glsl"
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 inUV;
|
||||||
|
layout(location = 1) in vec4 inColor;
|
||||||
|
layout(location = 2) flat in uint inTexId;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 outFragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 texColor = sampleTexture2DLinear(inTexId, inUV);
|
||||||
|
outFragColor = texColor * inColor;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#version 460
|
||||||
|
#extension GL_GOOGLE_include_directive : require
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 inPosition;
|
||||||
|
layout(location = 1) in vec2 inUV;
|
||||||
|
layout(location = 2) in vec4 inColor;
|
||||||
|
layout(location = 3) in uint inTexId;
|
||||||
|
|
||||||
|
layout(location = 0) out vec2 outUV;
|
||||||
|
layout(location = 1) out vec4 outColor;
|
||||||
|
layout(location = 2) flat out uint outTexId;
|
||||||
|
|
||||||
|
layout(push_constant) uniform QuadPushConstants {
|
||||||
|
mat4 viewProjection;
|
||||||
|
} pcs;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = pcs.viewProjection * vec4(inPosition, 0.0, 1.0);
|
||||||
|
outUV = inUV;
|
||||||
|
outColor = inColor;
|
||||||
|
outTexId = inTexId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#ifndef DESTRUM_QUADRENDERINGMANAGER_H
|
||||||
|
#define DESTRUM_QUADRENDERINGMANAGER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include <destrum/Graphics/ids.h>
|
||||||
|
#include <destrum/Singleton.h>
|
||||||
|
|
||||||
|
struct QuadSubmission {
|
||||||
|
glm::vec2 position;
|
||||||
|
glm::vec2 size;
|
||||||
|
float rotation;
|
||||||
|
glm::vec4 color;
|
||||||
|
ImageID textureId;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuadRenderingManager final : public Singleton<QuadRenderingManager> {
|
||||||
|
public:
|
||||||
|
friend class Singleton<QuadRenderingManager>;
|
||||||
|
|
||||||
|
void SubmitQuad(
|
||||||
|
const glm::vec2& position,
|
||||||
|
const glm::vec2& size,
|
||||||
|
const glm::vec4& color = glm::vec4{1.0f},
|
||||||
|
ImageID textureId = NULL_IMAGE_ID);
|
||||||
|
|
||||||
|
void SubmitQuad(
|
||||||
|
const glm::vec2& position,
|
||||||
|
const glm::vec2& size,
|
||||||
|
float rotation,
|
||||||
|
const glm::vec4& color = glm::vec4{1.0f},
|
||||||
|
ImageID textureId = NULL_IMAGE_ID);
|
||||||
|
|
||||||
|
[[nodiscard]] const std::vector<QuadSubmission>& GetQuads() const { return quads; }
|
||||||
|
void ClearQuads();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QuadRenderingManager() = default;
|
||||||
|
|
||||||
|
std::vector<QuadSubmission> quads;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DESTRUM_QUADRENDERINGMANAGER_H
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#ifndef DESTRUM_QUADRENDERERPASS_H
|
||||||
|
#define DESTRUM_QUADRENDERERPASS_H
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
#include <destrum/Graphics/Resources/Buffer.h>
|
||||||
|
|
||||||
|
|
||||||
|
class GfxDevice;
|
||||||
|
class Pipeline;
|
||||||
|
struct GPUImage;
|
||||||
|
class RenderResources;
|
||||||
|
|
||||||
|
class QuadRendererPass final {
|
||||||
|
public:
|
||||||
|
void init(GfxDevice& gfxDevice, RenderResources& resources, VkFormat drawImageFormat);
|
||||||
|
void draw(
|
||||||
|
VkCommandBuffer cmd,
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
RenderResources& resources,
|
||||||
|
const GPUImage& target,
|
||||||
|
const glm::mat4& projection);
|
||||||
|
void cleanup(GfxDevice& gfxDevice);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct QuadVertex {
|
||||||
|
glm::vec2 position;
|
||||||
|
glm::vec2 uv;
|
||||||
|
glm::vec4 color;
|
||||||
|
std::uint32_t textureId;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ensureCapacity(GfxDevice& gfxDevice, std::size_t requiredQuads);
|
||||||
|
|
||||||
|
VkPipelineLayout pipelineLayout{VK_NULL_HANDLE};
|
||||||
|
std::unique_ptr<Pipeline> pipeline;
|
||||||
|
GPUBuffer vertexBuffer{};
|
||||||
|
GPUBuffer indexBuffer{};
|
||||||
|
std::size_t quadCapacity{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DESTRUM_QUADRENDERERPASS_H
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
#ifndef RENDERER_H
|
#ifndef RENDERER_H
|
||||||
#define RENDERER_H
|
#define RENDERER_H
|
||||||
|
|
||||||
|
#include <glm/mat4x4.hpp>
|
||||||
#include <glm/vec3.hpp>
|
#include <glm/vec3.hpp>
|
||||||
|
|
||||||
#include <destrum/Graphics/Camera.h>
|
#include <destrum/Graphics/Camera.h>
|
||||||
#include <destrum/Graphics/Pipelines/LineRenderingPass.h>
|
#include <destrum/Graphics/Pipelines/LineRenderingPass.h>
|
||||||
#include <destrum/Graphics/Pipelines/MeshPipeline.h>
|
#include <destrum/Graphics/Pipelines/MeshPipeline.h>
|
||||||
|
#include <destrum/Graphics/Pipelines/QuadRendererPass.h>
|
||||||
#include <destrum/Graphics/ids.h>
|
#include <destrum/Graphics/ids.h>
|
||||||
#include <destrum/Graphics/MeshDrawCommand.h>
|
#include <destrum/Graphics/MeshDrawCommand.h>
|
||||||
#include <destrum/Graphics/Resources/NBuffer.h>
|
#include <destrum/Graphics/Resources/NBuffer.h>
|
||||||
@@ -69,6 +71,11 @@ public:
|
|||||||
return resources;
|
return resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawQuads(
|
||||||
|
VkCommandBuffer cmd,
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
const glm::mat4& projection);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createDrawImage(GfxDevice& gfxDevice, const glm::ivec2& drawImageSize, bool firstCreate);
|
void createDrawImage(GfxDevice& gfxDevice, const glm::ivec2& drawImageSize, bool firstCreate);
|
||||||
|
|
||||||
@@ -113,6 +120,7 @@ private:
|
|||||||
std::unique_ptr<MeshPipeline> meshPipeline;
|
std::unique_ptr<MeshPipeline> meshPipeline;
|
||||||
std::unique_ptr<SkyboxPipeline> skyboxPipeline;
|
std::unique_ptr<SkyboxPipeline> skyboxPipeline;
|
||||||
std::unique_ptr<LineRenderingPass> lineRenderingPass;
|
std::unique_ptr<LineRenderingPass> lineRenderingPass;
|
||||||
|
std::unique_ptr<QuadRendererPass> quadRendererPass;
|
||||||
|
|
||||||
std::unique_ptr<SkinningPipeline> skinningPipeline;
|
std::unique_ptr<SkinningPipeline> skinningPipeline;
|
||||||
bool initialized{false};
|
bool initialized{false};
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#include <destrum/Graphics/Managers/QuadRenderingManager.h>
|
||||||
|
|
||||||
|
void QuadRenderingManager::SubmitQuad(
|
||||||
|
const glm::vec2& position,
|
||||||
|
const glm::vec2& size,
|
||||||
|
const glm::vec4& color,
|
||||||
|
ImageID textureId)
|
||||||
|
{
|
||||||
|
SubmitQuad(position, size, 0.0f, color, textureId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuadRenderingManager::SubmitQuad(
|
||||||
|
const glm::vec2& position,
|
||||||
|
const glm::vec2& size,
|
||||||
|
float rotation,
|
||||||
|
const glm::vec4& color,
|
||||||
|
ImageID textureId)
|
||||||
|
{
|
||||||
|
quads.push_back(QuadSubmission{
|
||||||
|
.position = position,
|
||||||
|
.size = size,
|
||||||
|
.rotation = rotation,
|
||||||
|
.color = color,
|
||||||
|
.textureId = textureId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuadRenderingManager::ClearQuads()
|
||||||
|
{
|
||||||
|
quads.clear();
|
||||||
|
}
|
||||||
@@ -0,0 +1,334 @@
|
|||||||
|
#include <destrum/Graphics/Pipelines/QuadRendererPass.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
#include <limits>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
|
#include <destrum/FS/AssetFS.h>
|
||||||
|
#include <destrum/Graphics/GfxDevice.h>
|
||||||
|
#include <destrum/Graphics/GPUImage.h>
|
||||||
|
#include <destrum/Graphics/Pipeline.h>
|
||||||
|
#include <destrum/Graphics/RenderResources.h>
|
||||||
|
#include <destrum/Graphics/Util.h>
|
||||||
|
#include <destrum/Graphics/Managers/QuadRenderingManager.h>
|
||||||
|
|
||||||
|
#include "volk.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr std::size_t InitialQuadCapacity = 256;
|
||||||
|
constexpr std::size_t VerticesPerQuad = 4;
|
||||||
|
constexpr std::size_t IndicesPerQuad = 6;
|
||||||
|
|
||||||
|
glm::vec2 rotatePoint(const glm::vec2& point, float cosA, float sinA) {
|
||||||
|
return glm::vec2{
|
||||||
|
point.x * cosA - point.y * sinA,
|
||||||
|
point.x * sinA + point.y * cosA,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuadRendererPass::init(GfxDevice& gfxDevice, RenderResources& resources, VkFormat drawImageFormat)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
const std::size_t vertexBytes = InitialQuadCapacity * VerticesPerQuad * sizeof(QuadVertex);
|
||||||
|
vertexBuffer = gfxDevice.createBuffer(
|
||||||
|
vertexBytes,
|
||||||
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||||
|
VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
|
||||||
|
|
||||||
|
const std::size_t indexBytes = InitialQuadCapacity * IndicesPerQuad * sizeof(std::uint32_t);
|
||||||
|
indexBuffer = gfxDevice.createBuffer(
|
||||||
|
indexBytes,
|
||||||
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||||
|
VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
|
||||||
|
|
||||||
|
quadCapacity = InitialQuadCapacity;
|
||||||
|
|
||||||
|
const auto vertexShader =
|
||||||
|
AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/quad.vert");
|
||||||
|
const auto fragmentShader =
|
||||||
|
AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/quad.frag");
|
||||||
|
|
||||||
|
const auto pushConstantRange = VkPushConstantRange{
|
||||||
|
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
.offset = 0,
|
||||||
|
.size = sizeof(glm::mat4),
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto layouts = std::array{
|
||||||
|
resources.getBindlessDescSetLayout()
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto pipelineLayoutInfo = VkPipelineLayoutCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
|
.setLayoutCount = static_cast<std::uint32_t>(layouts.size()),
|
||||||
|
.pSetLayouts = layouts.data(),
|
||||||
|
.pushConstantRangeCount = 1,
|
||||||
|
.pPushConstantRanges = &pushConstantRange,
|
||||||
|
};
|
||||||
|
|
||||||
|
VK_CHECK(vkCreatePipelineLayout(
|
||||||
|
gfxDevice.getDevice(),
|
||||||
|
&pipelineLayoutInfo,
|
||||||
|
nullptr,
|
||||||
|
&pipelineLayout));
|
||||||
|
|
||||||
|
PipelineConfigInfo pipelineConfig{};
|
||||||
|
Pipeline::DefaultPipelineConfigInfo(pipelineConfig);
|
||||||
|
pipelineConfig.name = "Quad Rendering Pipeline";
|
||||||
|
pipelineConfig.pipelineLayout = pipelineLayout;
|
||||||
|
pipelineConfig.inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
pipelineConfig.rasterizationInfo.cullMode = VK_CULL_MODE_NONE;
|
||||||
|
pipelineConfig.depthStencilInfo.depthTestEnable = VK_FALSE;
|
||||||
|
pipelineConfig.depthStencilInfo.depthWriteEnable = VK_FALSE;
|
||||||
|
pipelineConfig.depthStencilInfo.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||||
|
pipelineConfig.colorAttachments = {drawImageFormat};
|
||||||
|
pipelineConfig.depthAttachment = VK_FORMAT_UNDEFINED;
|
||||||
|
|
||||||
|
pipelineConfig.vertexBindingDescriptions = {
|
||||||
|
VkVertexInputBindingDescription{
|
||||||
|
.binding = 0,
|
||||||
|
.stride = sizeof(QuadVertex),
|
||||||
|
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pipelineConfig.vertexAttributeDescriptions = {
|
||||||
|
VkVertexInputAttributeDescription{
|
||||||
|
.location = 0,
|
||||||
|
.binding = 0,
|
||||||
|
.format = VK_FORMAT_R32G32_SFLOAT,
|
||||||
|
.offset = offsetof(QuadVertex, position),
|
||||||
|
},
|
||||||
|
VkVertexInputAttributeDescription{
|
||||||
|
.location = 1,
|
||||||
|
.binding = 0,
|
||||||
|
.format = VK_FORMAT_R32G32_SFLOAT,
|
||||||
|
.offset = offsetof(QuadVertex, uv),
|
||||||
|
},
|
||||||
|
VkVertexInputAttributeDescription{
|
||||||
|
.location = 2,
|
||||||
|
.binding = 0,
|
||||||
|
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
|
.offset = offsetof(QuadVertex, color),
|
||||||
|
},
|
||||||
|
VkVertexInputAttributeDescription{
|
||||||
|
.location = 3,
|
||||||
|
.binding = 0,
|
||||||
|
.format = VK_FORMAT_R32_UINT,
|
||||||
|
.offset = offsetof(QuadVertex, textureId),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pipelineConfig.colorBlendAttachment.blendEnable = VK_TRUE;
|
||||||
|
pipelineConfig.colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||||
|
pipelineConfig.colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||||
|
pipelineConfig.colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
|
||||||
|
pipelineConfig.colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||||
|
pipelineConfig.colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||||
|
pipelineConfig.colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||||
|
|
||||||
|
pipeline = std::make_unique<Pipeline>(
|
||||||
|
gfxDevice,
|
||||||
|
vertexShader.string(),
|
||||||
|
fragmentShader.string(),
|
||||||
|
pipelineConfig);
|
||||||
|
} catch (...) {
|
||||||
|
cleanup(gfxDevice);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuadRendererPass::draw(
|
||||||
|
VkCommandBuffer cmd,
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
RenderResources& resources,
|
||||||
|
const GPUImage& target,
|
||||||
|
const glm::mat4& projection)
|
||||||
|
{
|
||||||
|
auto& quadManager = QuadRenderingManager::GetInstance();
|
||||||
|
const auto& quads = quadManager.GetQuads();
|
||||||
|
if (!pipeline || quads.empty()) {
|
||||||
|
quadManager.ClearQuads();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::size_t numQuads = quads.size();
|
||||||
|
if (numQuads > std::numeric_limits<std::size_t>::max() / VerticesPerQuad) {
|
||||||
|
throw std::overflow_error("Too many quads submitted for rendering");
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::size_t numVertices = numQuads * VerticesPerQuad;
|
||||||
|
const std::size_t numIndices = numQuads * IndicesPerQuad;
|
||||||
|
|
||||||
|
if (numVertices > std::numeric_limits<std::uint32_t>::max()) {
|
||||||
|
throw std::overflow_error("Too many quad vertices submitted for rendering");
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureCapacity(gfxDevice, numQuads);
|
||||||
|
|
||||||
|
const ImageID whiteTextureId = resources.getWhiteTextureID();
|
||||||
|
|
||||||
|
auto* vertexMapped = reinterpret_cast<std::uint8_t*>(vertexBuffer.info.pMappedData);
|
||||||
|
auto* indexMapped = reinterpret_cast<std::uint8_t*>(indexBuffer.info.pMappedData);
|
||||||
|
|
||||||
|
constexpr std::array<glm::vec2, 4> localCorners = {{
|
||||||
|
glm::vec2{-0.5f, -0.5f},
|
||||||
|
glm::vec2{ 0.5f, -0.5f},
|
||||||
|
glm::vec2{ 0.5f, 0.5f},
|
||||||
|
glm::vec2{-0.5f, 0.5f},
|
||||||
|
}};
|
||||||
|
|
||||||
|
constexpr std::array<glm::vec2, 4> uvs = {{
|
||||||
|
glm::vec2{0.0f, 1.0f},
|
||||||
|
glm::vec2{1.0f, 1.0f},
|
||||||
|
glm::vec2{1.0f, 0.0f},
|
||||||
|
glm::vec2{0.0f, 0.0f},
|
||||||
|
}};
|
||||||
|
|
||||||
|
auto* vertWrite = reinterpret_cast<QuadVertex*>(vertexMapped);
|
||||||
|
auto* idxWrite = reinterpret_cast<std::uint32_t*>(indexMapped);
|
||||||
|
std::uint32_t vertexBase = 0;
|
||||||
|
|
||||||
|
for (const auto& quad : quads) {
|
||||||
|
const float cosA = std::cos(quad.rotation);
|
||||||
|
const float sinA = std::sin(quad.rotation);
|
||||||
|
const glm::vec2 halfSize = quad.size * 0.5f;
|
||||||
|
const ImageID texId = (quad.textureId == NULL_IMAGE_ID) ? whiteTextureId : quad.textureId;
|
||||||
|
|
||||||
|
for (std::size_t v = 0; v < VerticesPerQuad; ++v) {
|
||||||
|
glm::vec2 localPos = localCorners[v] * halfSize;
|
||||||
|
glm::vec2 rotatedPos = rotatePoint(localPos, cosA, sinA);
|
||||||
|
glm::vec2 worldPos = quad.position + rotatedPos;
|
||||||
|
|
||||||
|
vertWrite[vertexBase + v] = QuadVertex{
|
||||||
|
.position = worldPos,
|
||||||
|
.uv = uvs[v],
|
||||||
|
.color = quad.color,
|
||||||
|
.textureId = static_cast<std::uint32_t>(texId),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::uint32_t idxOffset = vertexBase / 4 * 6;
|
||||||
|
idxWrite[idxOffset + 0] = vertexBase + 0;
|
||||||
|
idxWrite[idxOffset + 1] = vertexBase + 1;
|
||||||
|
idxWrite[idxOffset + 2] = vertexBase + 2;
|
||||||
|
idxWrite[idxOffset + 3] = vertexBase + 0;
|
||||||
|
idxWrite[idxOffset + 4] = vertexBase + 2;
|
||||||
|
idxWrite[idxOffset + 5] = vertexBase + 3;
|
||||||
|
vertexBase += VerticesPerQuad;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& memMgr = gfxDevice.getMemoryManager();
|
||||||
|
memMgr.flushAllocation(vertexBuffer, 0, numVertices * sizeof(QuadVertex));
|
||||||
|
memMgr.flushAllocation(indexBuffer, 0, numIndices * sizeof(std::uint32_t));
|
||||||
|
|
||||||
|
auto renderInfo = vkutil::createRenderingInfo({
|
||||||
|
.renderExtent = target.getExtent2D(),
|
||||||
|
.colorImageView = target.imageView,
|
||||||
|
});
|
||||||
|
|
||||||
|
vkCmdBeginRendering(cmd, &renderInfo.renderingInfo);
|
||||||
|
|
||||||
|
pipeline->bind(cmd);
|
||||||
|
resources.bindBindlessDescSet(cmd, pipelineLayout);
|
||||||
|
|
||||||
|
const auto viewport = VkViewport{
|
||||||
|
.x = 0.0f,
|
||||||
|
.y = 0.0f,
|
||||||
|
.width = static_cast<float>(target.extent.width),
|
||||||
|
.height = static_cast<float>(target.extent.height),
|
||||||
|
.minDepth = 0.0f,
|
||||||
|
.maxDepth = 1.0f,
|
||||||
|
};
|
||||||
|
vkCmdSetViewport(cmd, 0, 1, &viewport);
|
||||||
|
|
||||||
|
const auto scissor = VkRect2D{
|
||||||
|
.offset = {},
|
||||||
|
.extent = target.getExtent2D(),
|
||||||
|
};
|
||||||
|
vkCmdSetScissor(cmd, 0, 1, &scissor);
|
||||||
|
vkCmdSetPolygonModeEXT(cmd, VK_POLYGON_MODE_FILL);
|
||||||
|
|
||||||
|
vkCmdPushConstants(
|
||||||
|
cmd,
|
||||||
|
pipelineLayout,
|
||||||
|
VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
0,
|
||||||
|
sizeof(glm::mat4),
|
||||||
|
&projection);
|
||||||
|
|
||||||
|
const VkBuffer vertexBufferHandle = vertexBuffer.buffer;
|
||||||
|
const VkDeviceSize vertexBufferOffset = 0;
|
||||||
|
vkCmdBindVertexBuffers(cmd, 0, 1, &vertexBufferHandle, &vertexBufferOffset);
|
||||||
|
|
||||||
|
const VkBuffer indexBufferHandle = indexBuffer.buffer;
|
||||||
|
vkCmdBindIndexBuffer(cmd, indexBufferHandle, 0, VK_INDEX_TYPE_UINT32);
|
||||||
|
|
||||||
|
vkCmdDrawIndexed(cmd, static_cast<std::uint32_t>(numIndices), 1, 0, 0, 0);
|
||||||
|
|
||||||
|
vkCmdEndRendering(cmd);
|
||||||
|
quadManager.ClearQuads();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuadRendererPass::cleanup(GfxDevice& gfxDevice)
|
||||||
|
{
|
||||||
|
pipeline.reset();
|
||||||
|
|
||||||
|
if (pipelineLayout != VK_NULL_HANDLE && gfxDevice.getDevice() != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyPipelineLayout(gfxDevice.getDevice(), pipelineLayout, nullptr);
|
||||||
|
}
|
||||||
|
pipelineLayout = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
if (vertexBuffer.buffer != VK_NULL_HANDLE) {
|
||||||
|
gfxDevice.destroyBuffer(vertexBuffer);
|
||||||
|
}
|
||||||
|
if (indexBuffer.buffer != VK_NULL_HANDLE) {
|
||||||
|
gfxDevice.destroyBuffer(indexBuffer);
|
||||||
|
}
|
||||||
|
quadCapacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuadRendererPass::ensureCapacity(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
std::size_t requiredQuads)
|
||||||
|
{
|
||||||
|
if (requiredQuads <= quadCapacity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t newCapacity = std::max(quadCapacity, InitialQuadCapacity);
|
||||||
|
while (newCapacity < requiredQuads) {
|
||||||
|
if (newCapacity > std::numeric_limits<std::size_t>::max() / 2) {
|
||||||
|
newCapacity = requiredQuads;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
newCapacity *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfxDevice.waitIdle();
|
||||||
|
|
||||||
|
if (vertexBuffer.buffer != VK_NULL_HANDLE) {
|
||||||
|
gfxDevice.destroyBuffer(vertexBuffer);
|
||||||
|
}
|
||||||
|
vertexBuffer = gfxDevice.createBuffer(
|
||||||
|
newCapacity * VerticesPerQuad * sizeof(QuadVertex),
|
||||||
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||||
|
VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
|
||||||
|
|
||||||
|
if (indexBuffer.buffer != VK_NULL_HANDLE) {
|
||||||
|
gfxDevice.destroyBuffer(indexBuffer);
|
||||||
|
}
|
||||||
|
indexBuffer = gfxDevice.createBuffer(
|
||||||
|
newCapacity * IndicesPerQuad * sizeof(std::uint32_t),
|
||||||
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||||
|
VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
|
||||||
|
|
||||||
|
quadCapacity = newCapacity;
|
||||||
|
}
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
#include <destrum/Graphics/Renderer.h>
|
#include <destrum/Graphics/Renderer.h>
|
||||||
|
|
||||||
#include <destrum/Graphics/Managers/LineRenderingManager.h>
|
#include <destrum/Graphics/Managers/LineRenderingManager.h>
|
||||||
|
#include <destrum/Graphics/Managers/QuadRenderingManager.h>
|
||||||
#include <destrum/Graphics/Util.h>
|
#include <destrum/Graphics/Util.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#include "volk.h"
|
#include "volk.h"
|
||||||
#include "destrum/Util/GameState.h"
|
#include "destrum/Util/GameState.h"
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
@@ -31,7 +34,7 @@ void GameRenderer::init(GfxDevice& gfxDevice, RenderResources& _resources, glm::
|
|||||||
meshPipeline = std::make_unique<MeshPipeline>();
|
meshPipeline = std::make_unique<MeshPipeline>();
|
||||||
meshPipeline->init(gfxDevice, _resources, drawImageFormat, depthImageFormat);
|
meshPipeline->init(gfxDevice, _resources, drawImageFormat, depthImageFormat);
|
||||||
|
|
||||||
skyboxPipeline = std::make_unique<SkyboxPipeline>();
|
skyboxPipeline = std::make_unique<SkyboxPipeline>();
|
||||||
skyboxPipeline->init(gfxDevice, _resources, drawImageFormat, depthImageFormat);
|
skyboxPipeline->init(gfxDevice, _resources, drawImageFormat, depthImageFormat);
|
||||||
|
|
||||||
skinningPipeline = std::make_unique<SkinningPipeline>();
|
skinningPipeline = std::make_unique<SkinningPipeline>();
|
||||||
@@ -40,6 +43,9 @@ void GameRenderer::init(GfxDevice& gfxDevice, RenderResources& _resources, glm::
|
|||||||
lineRenderingPass = std::make_unique<LineRenderingPass>();
|
lineRenderingPass = std::make_unique<LineRenderingPass>();
|
||||||
lineRenderingPass->init(gfxDevice, drawImageFormat);
|
lineRenderingPass->init(gfxDevice, drawImageFormat);
|
||||||
|
|
||||||
|
quadRendererPass = std::make_unique<QuadRendererPass>();
|
||||||
|
quadRendererPass->init(gfxDevice, _resources, drawImageFormat);
|
||||||
|
|
||||||
GameState::GetInstance().SetRenderer(this);
|
GameState::GetInstance().SetRenderer(this);
|
||||||
initialized = true;
|
initialized = true;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@@ -53,6 +59,7 @@ void GameRenderer::beginDrawing(GfxDevice& gfxDevice)
|
|||||||
flushMaterialUpdates(gfxDevice);
|
flushMaterialUpdates(gfxDevice);
|
||||||
meshDrawCommands.clear();
|
meshDrawCommands.clear();
|
||||||
skinningPipeline->beginDrawing(gfxDevice.getCurrentFrameIndex());
|
skinningPipeline->beginDrawing(gfxDevice.getCurrentFrameIndex());
|
||||||
|
QuadRenderingManager::GetInstance().ClearQuads();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::endDrawing()
|
void GameRenderer::endDrawing()
|
||||||
@@ -209,7 +216,30 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
|||||||
camera,
|
camera,
|
||||||
LineRenderingManager::GetInstance());
|
LineRenderingManager::GetInstance());
|
||||||
}
|
}
|
||||||
// vkutil::cmdEndLabel(cmd);
|
|
||||||
|
{
|
||||||
|
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "QuadRendererPass::draw");
|
||||||
|
|
||||||
|
quadRendererPass->draw(
|
||||||
|
cmd,
|
||||||
|
gfxDevice,
|
||||||
|
*resources,
|
||||||
|
drawImage,
|
||||||
|
glm::ortho(0.0f,
|
||||||
|
static_cast<float>(drawImage.extent.width),
|
||||||
|
static_cast<float>(drawImage.extent.height),
|
||||||
|
0.0f, -1.0f, 1.0f));
|
||||||
|
}
|
||||||
|
// vkutil::cmdEndLabel(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameRenderer::drawQuads(
|
||||||
|
VkCommandBuffer cmd,
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
const glm::mat4& projection)
|
||||||
|
{
|
||||||
|
const auto& drawImage = resources->getImage(drawImageId);
|
||||||
|
quadRendererPass->draw(cmd, gfxDevice, *resources, drawImage, projection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::cleanup(GfxDevice& gfxDevice)
|
void GameRenderer::cleanup(GfxDevice& gfxDevice)
|
||||||
@@ -220,12 +250,15 @@ void GameRenderer::cleanup(GfxDevice& gfxDevice)
|
|||||||
vkDeviceWaitIdle(device);
|
vkDeviceWaitIdle(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skinningPipeline)
|
if (skinningPipeline)
|
||||||
skinningPipeline->cleanup(gfxDevice);
|
skinningPipeline->cleanup(gfxDevice);
|
||||||
|
|
||||||
if (lineRenderingPass)
|
if (lineRenderingPass)
|
||||||
lineRenderingPass->cleanup(gfxDevice);
|
lineRenderingPass->cleanup(gfxDevice);
|
||||||
|
|
||||||
|
if (quadRendererPass)
|
||||||
|
quadRendererPass->cleanup(gfxDevice);
|
||||||
|
|
||||||
if (skyboxPipeline)
|
if (skyboxPipeline)
|
||||||
skyboxPipeline->cleanup(device);
|
skyboxPipeline->cleanup(device);
|
||||||
|
|
||||||
@@ -247,6 +280,7 @@ void GameRenderer::cleanup(GfxDevice& gfxDevice)
|
|||||||
skyboxPipeline.reset();
|
skyboxPipeline.reset();
|
||||||
skinningPipeline.reset();
|
skinningPipeline.reset();
|
||||||
lineRenderingPass.reset();
|
lineRenderingPass.reset();
|
||||||
|
quadRendererPass.reset();
|
||||||
pendingMaterialUploads.clear();
|
pendingMaterialUploads.clear();
|
||||||
meshDrawCommands.clear();
|
meshDrawCommands.clear();
|
||||||
sortedMeshDrawCommands.clear();
|
sortedMeshDrawCommands.clear();
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ private:
|
|||||||
MeshID sphereMesh;
|
MeshID sphereMesh;
|
||||||
MaterialID sphereMaterial;
|
MaterialID sphereMaterial;
|
||||||
|
|
||||||
|
ImageID texID;
|
||||||
|
|
||||||
std::unique_ptr<CubeMap> skyboxCubemap;
|
std::unique_ptr<CubeMap> skyboxCubemap;
|
||||||
|
|
||||||
GameObject* capybara = nullptr;
|
GameObject* capybara = nullptr;
|
||||||
@@ -42,6 +44,8 @@ private:
|
|||||||
char newSceneName[128]{"EmptyScene"};
|
char newSceneName[128]{"EmptyScene"};
|
||||||
std::string sceneStatus;
|
std::string sceneStatus;
|
||||||
bool renderBoxColliders{false};
|
bool renderBoxColliders{false};
|
||||||
|
bool renderQuads{true};
|
||||||
|
bool renderDebugLines{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //LIGHTKEEPER_H
|
#endif //LIGHTKEEPER_H
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#include "Lightkeeper.h"
|
#include "Lightkeeper.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
#include <destrum/FS/AssetFS.h>
|
#include <destrum/FS/AssetFS.h>
|
||||||
#include <destrum/Assets/AssetManager.h>
|
#include <destrum/Assets/AssetManager.h>
|
||||||
#include <destrum/Graphics/Managers/LineRenderingManager.h>
|
#include <destrum/Graphics/Managers/LineRenderingManager.h>
|
||||||
|
#include <destrum/Graphics/Managers/QuadRenderingManager.h>
|
||||||
#include "glm/gtx/transform.hpp"
|
#include "glm/gtx/transform.hpp"
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
#include <destrum/Components/Physics/Rigidbody.h>
|
#include <destrum/Components/Physics/Rigidbody.h>
|
||||||
@@ -444,6 +446,8 @@ void LightKeeper::customInit()
|
|||||||
triggerObj->AddComponent<TriggerLoggerComponent>();
|
triggerObj->AddComponent<TriggerLoggerComponent>();
|
||||||
triggerObj->GetTransform().SetWorldPosition({0.0f, 0.0f, 0.0f});
|
triggerObj->GetTransform().SetWorldPosition({0.0f, 0.0f, 0.0f});
|
||||||
|
|
||||||
|
const auto texPath = AssetFS::GetInstance().GetFullPath("engine://textures/kobe.png");
|
||||||
|
texID = resources.loadImageFromFile(gfxDevice, texPath);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,6 +491,7 @@ void LightKeeper::customUpdate(float dt)
|
|||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightKeeper::drawDebugMenuBar()
|
void LightKeeper::drawDebugMenuBar()
|
||||||
@@ -526,6 +531,8 @@ void LightKeeper::drawDebugMenuBar()
|
|||||||
|
|
||||||
if (ImGui::BeginMenu("Render")) {
|
if (ImGui::BeginMenu("Render")) {
|
||||||
ImGui::MenuItem("Box Colliders", nullptr, &renderBoxColliders);
|
ImGui::MenuItem("Box Colliders", nullptr, &renderBoxColliders);
|
||||||
|
ImGui::MenuItem("2D Quads", nullptr, &renderQuads);
|
||||||
|
ImGui::MenuItem("Debug Lines", nullptr, &renderDebugLines);
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -660,6 +667,10 @@ void LightKeeper::customDraw()
|
|||||||
renderer.beginDrawing(gfxDevice);
|
renderer.beginDrawing(gfxDevice);
|
||||||
submitBoxColliderDebugLines();
|
submitBoxColliderDebugLines();
|
||||||
|
|
||||||
|
QuadRenderingManager::GetInstance().SubmitQuad(
|
||||||
|
glm::vec2{100.0f, 100.0f}, glm::vec2{200.0f, 200.0f}, 0.0f,
|
||||||
|
glm::vec4{1.0f}, texID);
|
||||||
|
|
||||||
const RenderContext ctx{
|
const RenderContext ctx{
|
||||||
.renderer = renderer,
|
.renderer = renderer,
|
||||||
.camera = camera,
|
.camera = camera,
|
||||||
|
|||||||
Reference in New Issue
Block a user