Refactoring basic text rendering

This commit is contained in:
Dynamitos
2025-01-08 19:15:12 +01:00
parent eef78e8aa5
commit e487867f96
70 changed files with 608 additions and 1133 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ void Seele::addDebugVertex(DebugVertex vert) { gDebugVertices.add(vert); }
void Seele::addDebugVertices(Array<DebugVertex> verts) { gDebugVertices.addAll(verts); }
BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
//waterRenderer = new WaterRenderer(graphics, scene, viewParamsLayout);
basePassLayout = graphics->createPipelineLayout("BasePassLayout");
@@ -78,6 +78,7 @@ class BasePass : public RenderPass {
} skyboxData;
Gfx::OUniformBuffer skyboxBuffer;
Component::Skybox skybox;
PScene scene;
};
DEFINE_REF(BasePass)
} // namespace Seele
@@ -17,8 +17,6 @@ target_sources(Engine
RenderPass.cpp
TerrainRenderer.h
TerrainRenderer.cpp
TextPass.h
TextPass.cpp
UIPass.h
UIPass.cpp
VisibilityPass.h
@@ -38,6 +36,5 @@ target_sources(Engine
RenderGraphResources.h
RenderPass.h
TerrainRenderer.h
TextPass.h
UIPass.h
VisibilityPass.h)
@@ -3,7 +3,7 @@
using namespace Seele;
CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
depthPrepassLayout = graphics->createPipelineLayout("CachedDepthLayout");
depthPrepassLayout->addDescriptorLayout(viewParamsLayout);
depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{
@@ -25,6 +25,7 @@ class CachedDepthPass : public RenderPass {
Gfx::OTimestampQuery timestamps;
Gfx::PShaderBuffer cullingBuffer;
PScene scene;
};
DEFINE_REF(CachedDepthPass)
} // namespace Seele
@@ -4,7 +4,7 @@
using namespace Seele;
DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
depthAttachmentLayout = graphics->createDescriptorLayout("pDepthAttachment");
depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 0,
@@ -44,6 +44,7 @@ class DepthCullingPass : public RenderPass {
Gfx::PComputePipeline depthReduceLevel;
Gfx::PShaderBuffer cullingBuffer;
PScene scene;
};
DEFINE_REF(DepthCullingPass)
} // namespace Seele
@@ -8,7 +8,7 @@
using namespace Seele;
LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {}
LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {}
LightCullingPass::~LightCullingPass() {}
@@ -58,6 +58,8 @@ class LightCullingPass : public RenderPass {
Gfx::PComputePipeline cullingEnabledPipeline;
Gfx::OPipelineStatisticsQuery query;
Gfx::PTimestampQuery timestamps;
PScene scene;
};
DEFINE_REF(LightCullingPass)
} // namespace Seele
@@ -14,7 +14,7 @@ struct SampleParams {
uint32 samplesPerPixel;
};
RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
paramsLayout = graphics->createDescriptorLayout("pRayTracingParams");
paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 0,
@@ -25,5 +25,6 @@ class RayTracingPass : public RenderPass {
Gfx::OMissShader miss;
Gfx::PRayTracingPipeline pipeline;
Gfx::OTopLevelAS tlas;
PScene scene;
};
} // namespace Seele
@@ -2,7 +2,7 @@
using namespace Seele;
RenderPass::RenderPass(Gfx::PGraphics graphics, PScene scene) : graphics(graphics), scene(scene) {
RenderPass::RenderPass(Gfx::PGraphics graphics) : graphics(graphics) {
viewParamsLayout = graphics->createDescriptorLayout("pViewParams");
viewParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 0,
+1 -2
View File
@@ -14,7 +14,7 @@ DECLARE_NAME_REF(Gfx, Graphics)
DECLARE_NAME_REF(Gfx, RenderPass)
class RenderPass {
public:
RenderPass(Gfx::PGraphics graphics, PScene scene);
RenderPass(Gfx::PGraphics graphics);
RenderPass(RenderPass&&) = default;
RenderPass& operator=(RenderPass&&) = default;
virtual ~RenderPass();
@@ -71,7 +71,6 @@ class RenderPass {
Gfx::ORenderPass renderPass;
Gfx::PGraphics graphics;
Gfx::PViewport viewport;
PScene scene;
};
DEFINE_REF(RenderPass)
template <typename RP>
-202
View File
@@ -1,202 +0,0 @@
#include "TextPass.h"
#include "Graphics/Command.h"
#include "Graphics/Enums.h"
#include "Graphics/Graphics.h"
#include "Graphics/RenderTarget.h"
#include "RenderGraph.h"
using namespace Seele;
TextPass::TextPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {}
TextPass::~TextPass() {}
void TextPass::beginFrame(const Component::Camera& cam) {
RenderPass::beginFrame(cam);
for (TextRender& render : texts) {
FontData& fd = getFontData(render.font);
TextResources& res = textResources[render.font].add();
Array<GlyphInstanceData> instanceData;
float x = render.position.x;
float y = render.position.y;
for (uint32 c : render.text) {
const GlyphData& glyph = fd.glyphDataSet[fd.characterToGlyphIndex[c]];
Vector2 bearing = glyph.bearing;
Vector2 size = glyph.size;
float xpos = x + bearing.x * render.scale;
float ypos = y - (size.y - bearing.y) * render.scale;
float w = size.x * render.scale;
float h = size.y * render.scale;
instanceData.add(GlyphInstanceData{
.position = Vector2(xpos, ypos),
.widthHeight = Vector2(w, h),
.glyphIndex = fd.characterToGlyphIndex[c],
});
x += (glyph.advance >> 6) * render.scale;
}
res.instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = static_cast<uint32>(instanceData.size() * sizeof(GlyphInstanceData)),
.data = reinterpret_cast<uint8*>(instanceData.data()),
},
.numElements = instanceData.size(),
});
res.textureArraySet = fd.textureArraySet;
res.textData = {
.textColor = render.textColor,
.scale = render.scale,
};
}
auto proj = viewport->getProjectionMatrix();
projectionBuffer->updateContents(0, sizeof(Matrix4), &proj);
generalSet->updateBuffer(1, 0, projectionBuffer);
generalSet->writeChanges();
// co_return;
}
void TextPass::render() {
graphics->beginRenderPass(renderPass);
Array<Gfx::ORenderCommand> commands;
for (const auto& [fontAsset, res] : textResources) {
Gfx::ORenderCommand command = graphics->createRenderCommand("TextPassCommand");
command->setViewport(viewport);
command->bindPipeline(pipeline);
for (const auto& resource : res) {
command->bindDescriptor({generalSet, resource.textureArraySet});
// command->bindVertexBuffer({resource.vertexBuffer});
command->pushConstants(Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(TextData),
&resource.textData);
// command->draw(4, static_cast<uint32>(resource.vertexBuffer->getNumVertices()), 0, 0);
}
commands.add(std::move(command));
}
graphics->executeCommands(std::move(commands));
graphics->endRenderPass();
textResources.clear();
// co_return;
}
void TextPass::endFrame() {
// co_return;
}
void TextPass::publishOutputs() {}
void TextPass::createRenderPass() {
renderTarget = resources->requestRenderTarget("UIPASS_COLOR");
depthAttachment = resources->requestRenderTarget("UIPASS_DEPTH");
ShaderCompilationInfo createInfo = {
.name = "TextVertex",
.modules = {"TextPass"},
.entryPoints = {{"vertexMain", "TextPass"}, {"fragmentMain", "TextFragment"}},
};
graphics->beginShaderCompilation(createInfo);
vertexShader = graphics->createVertexShader({0});
fragmentShader = graphics->createFragmentShader({1});
generalLayout = graphics->createDescriptorLayout("pRender");
generalLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 0,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.uniformLength = sizeof(Matrix4),
});
generalLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 1,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
});
generalLayout->create();
textureArrayLayout = graphics->createDescriptorLayout("pGlyphTextures");
textureArrayLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 0,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.textureType = Gfx::SE_IMAGE_VIEW_TYPE_2D_ARRAY,
.descriptorCount = 256,
.bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT,
});
textureArrayLayout->create();
projectionBuffer = graphics->createUniformBuffer({
.sourceData =
{
.size = sizeof(Matrix4),
.data = nullptr,
},
});
glyphSampler = graphics->createSampler({
.magFilter = Gfx::SE_FILTER_LINEAR,
.minFilter = Gfx::SE_FILTER_LINEAR,
.addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
});
generalSet = generalLayout->allocateDescriptorSet();
generalSet->updateBuffer(0, 0, projectionBuffer);
generalSet->updateSampler(1, 0, glyphSampler);
generalSet->writeChanges();
pipelineLayout = graphics->createPipelineLayout();
pipelineLayout->addDescriptorLayout(generalLayout);
pipelineLayout->addDescriptorLayout(textureArrayLayout);
pipelineLayout->addPushConstants(
{.stageFlags = Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, .offset = 0, .size = sizeof(TextData)});
pipelineLayout->create();
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{.colorAttachments = {renderTarget}, .depthAttachment = depthAttachment};
renderPass = graphics->createRenderPass(std::move(layout), {}, viewport);
Gfx::LegacyPipelineCreateInfo pipelineInfo;
pipelineInfo.vertexShader = vertexShader;
pipelineInfo.fragmentShader = fragmentShader;
pipelineInfo.renderPass = renderPass;
pipelineInfo.pipelineLayout = pipelineLayout;
pipelineInfo.rasterizationState.cullMode = Gfx::SE_CULL_MODE_NONE;
pipelineInfo.colorBlend.attachmentCount = 1;
pipelineInfo.colorBlend.blendAttachments[0].blendEnable = true;
pipelineInfo.colorBlend.blendAttachments[0].colorWriteMask =
Gfx::SE_COLOR_COMPONENT_R_BIT | Gfx::SE_COLOR_COMPONENT_G_BIT | Gfx::SE_COLOR_COMPONENT_B_BIT | Gfx::SE_COLOR_COMPONENT_A_BIT;
pipelineInfo.colorBlend.blendAttachments[0].srcColorBlendFactor = Gfx::SE_BLEND_FACTOR_SRC_ALPHA;
pipelineInfo.colorBlend.blendAttachments[0].dstColorBlendFactor = Gfx::SE_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
pipelineInfo.colorBlend.blendAttachments[0].alphaBlendOp = Gfx::SE_BLEND_OP_ADD;
pipelineInfo.colorBlend.blendAttachments[0].srcAlphaBlendFactor = Gfx::SE_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
pipelineInfo.colorBlend.blendAttachments[0].dstAlphaBlendFactor = Gfx::SE_BLEND_FACTOR_ZERO;
pipelineInfo.colorBlend.blendAttachments[0].alphaBlendOp = Gfx::SE_BLEND_OP_ADD;
pipelineInfo.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
}
TextPass::FontData& TextPass::getFontData(PFontAsset font) {
if (fontData.exists(font)) {
return fontData[font];
}
const auto& fontGlyphs = font->getGlyphData();
FontData& fd = fontData[font];
Array<GlyphData> glyphData;
Array<Gfx::PTexture2D> textures;
glyphData.reserve(fontGlyphs.size());
for (const auto& [key, value] : fontGlyphs) {
fd.characterToGlyphIndex[key] = static_cast<uint32>(glyphData.size());
GlyphData& gd = glyphData.add();
gd.bearing = value.bearing;
gd.size = value.size;
gd.advance = value.advance;
textures.add(font->getTexture(value.textureIndex));
}
fd.glyphDataSet = glyphData;
textureArrayLayout->reset();
fd.textureArraySet = textureArrayLayout->allocateDescriptorSet();
for (uint32 i = 0; i < textures.size(); ++i) {
fd.textureArraySet->updateTexture(0, i, textures[i]);
}
fd.textureArraySet->writeChanges();
return fontData[font];
}
-78
View File
@@ -1,78 +0,0 @@
#pragma once
#include "Asset/FontAsset.h"
#include "Graphics/Shader.h"
#include "RenderPass.h"
#include "UI/RenderHierarchy.h"
namespace Seele {
DECLARE_NAME_REF(Gfx, Texture2D)
DECLARE_NAME_REF(Gfx, ShaderBuffer)
struct TextRender {
std::string text;
PFontAsset font;
Vector4 textColor;
Vector2 position;
float scale;
};
class TextPass : public RenderPass {
public:
TextPass(Gfx::PGraphics graphics, PScene scene);
TextPass(TextPass&&) = default;
TextPass& operator=(TextPass&&) = default;
virtual ~TextPass();
virtual void beginFrame(const Component::Camera& cam) override;
virtual void render() override;
virtual void endFrame() override;
virtual void publishOutputs() override;
virtual void createRenderPass() override;
private:
struct GlyphData {
Vector2 bearing;
Vector2 size;
uint32 advance;
};
struct GlyphInstanceData {
Vector2 position;
Vector2 widthHeight;
uint32 glyphIndex;
};
struct TextData {
Vector4 textColor;
float scale;
};
struct FontData {
Gfx::PDescriptorSet textureArraySet;
Array<GlyphData> glyphDataSet;
Map<uint32, uint32> characterToGlyphIndex;
};
FontData& getFontData(PFontAsset font);
Map<PFontAsset, FontData> fontData;
struct TextResources {
Gfx::PShaderBuffer instanceBuffer;
Gfx::PDescriptorSet textureArraySet;
TextData textData;
};
Map<PFontAsset, Array<TextResources>> textResources;
Gfx::RenderTargetAttachment renderTarget;
Gfx::RenderTargetAttachment depthAttachment;
Gfx::ODescriptorLayout generalLayout;
Gfx::ODescriptorLayout textureArrayLayout;
Gfx::PDescriptorSet generalSet;
Gfx::OUniformBuffer projectionBuffer;
Gfx::OSampler glyphSampler;
Gfx::OVertexShader vertexShader;
Gfx::OFragmentShader fragmentShader;
Gfx::OPipelineLayout pipelineLayout;
Gfx::PGraphicsPipeline pipeline;
Array<TextRender> texts;
};
DEFINE_REF(TextPass);
} // namespace Seele
+137 -118
View File
@@ -1,4 +1,5 @@
#include "UIPass.h"
#include "Asset/AssetRegistry.h"
#include "Graphics/Command.h"
#include "Graphics/Enums.h"
#include "Graphics/Graphics.h"
@@ -7,53 +8,100 @@
using namespace Seele;
UIPass::UIPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {}
UIPass::UIPass(Gfx::PGraphics graphics, UI::PSystem system) : RenderPass(graphics) {
glyphInstanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{.name = "GlyphInstanceBuffer"});
textDescriptorLayout = graphics->createDescriptorLayout("pText");
textDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 0,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
textDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 1,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
});
textDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 2,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.descriptorCount = 1024,
});
textPipelineLayout = graphics->createPipelineLayout("TextPipeline");
textPipelineLayout->addDescriptorLayout(viewParamsLayout);
textPipelineLayout->addDescriptorLayout(textDescriptorLayout);
uiPipelineLayout = graphics->createPipelineLayout("UIPipeline");
uiPipelineLayout->addDescriptorLayout(viewParamsLayout);
// todo:
texts.add(TextRender{
.text = "TestText123",
.font = AssetRegistry::findFont("", "arial"),
.fontSize = 12,
.position = Vector2(0, 100),
});
}
UIPass::~UIPass() {}
void UIPass::beginFrame(const Component::Camera& cam) {
RenderPass::beginFrame(cam);
VertexBufferCreateInfo info = {
.sourceData =
{
.size = (uint32)(sizeof(UI::RenderElementStyle) * renderElements.size()),
.data = (uint8*)renderElements.data(),
},
.vertexSize = sizeof(UI::RenderElementStyle),
.numVertices = (uint32)renderElements.size(),
};
elementBuffer = graphics->createVertexBuffer(info);
uint32 numTextures = static_cast<uint32>(usedTextures.size());
numTexturesBuffer->updateContents(0, sizeof(uint32), &numTextures);
descriptorSet->updateBuffer(2, 0, numTexturesBuffer);
for (uint32 i = 0; i < usedTextures.size(); ++i) {
descriptorSet->updateTexture(3, i, usedTextures[i]);
glyphs.clear();
usedTextures.clear();
for (TextRender& render : texts) {
TextResources& res = textResources[render.font].add();
float x = render.position.x * viewport->getContentScaleX();
float y = (viewport->getHeight() - render.position.y) * viewport->getContentScaleY();
for (uint32 c : render.text) {
const FontAsset::Glyph& glyph = render.font->getGlyphData(c);
Vector2 bearing = Vector2(glyph.bearing) * viewport->getContentScaleX();
Vector2 size = Vector2(glyph.size) * viewport->getContentScaleY();
float xpos = x + glyph.bearing.x;
float ypos = y + (size.y - bearing.y);
float w = size.x;
float h = size.y;
glyphs.add(GlyphInstanceData{
.x = xpos,
.y = ypos,
.width = w,
.height = h,
.glyphIndex = (uint32)usedTextures.size(),
});
usedTextures.add(glyph.texture);
x += glyph.advance >> 6;
}
}
descriptorSet->writeChanges();
// co_return;
glyphInstanceBuffer->rotateBuffer(sizeof(GlyphInstanceData) * glyphs.size());
glyphInstanceBuffer->updateContents(0, sizeof(GlyphInstanceData) * glyphs.size(), glyphs.data());
glyphInstanceBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT);
textDescriptorLayout->reset();
textDescriptorSet = textDescriptorLayout->allocateDescriptorSet();
textDescriptorSet->updateBuffer(0, 0, glyphInstanceBuffer);
textDescriptorSet->updateSampler(1, 0, glyphSampler);
for (uint32 i = 0; i < usedTextures.size(); ++i) {
textDescriptorSet->updateTexture(2, i, usedTextures[i]);
}
textDescriptorSet->writeChanges();
}
void UIPass::render() {
graphics->beginRenderPass(renderPass);
Gfx::ORenderCommand command = graphics->createRenderCommand("UIPassCommand");
command->setViewport(viewport);
command->bindPipeline(pipeline);
command->bindVertexBuffer({elementBuffer});
command->bindDescriptor(descriptorSet);
command->draw(4, static_cast<uint32>(renderElements.size()), 0, 0);
Array<Gfx::ORenderCommand> commands;
Gfx::ORenderCommand command = graphics->createRenderCommand("TextPassCommand");
command->setViewport(viewport);
command->bindPipeline(textPipeline);
command->bindDescriptor({viewParamsSet, textDescriptorSet});
command->draw(4, glyphs.size(), 0, 0);
commands.add(std::move(command));
graphics->executeCommands(std::move(commands));
graphics->endRenderPass();
// co_return;
}
void UIPass::endFrame() {
// co_return;
}
void UIPass::endFrame() {}
void UIPass::publishOutputs() {
void UIPass::publishOutputs() {}
void UIPass::createRenderPass() {
TextureCreateInfo depthBufferInfo = {
.format = Gfx::SE_FORMAT_D32_SFLOAT,
.width = viewport->getWidth(),
@@ -65,98 +113,69 @@ void UIPass::publishOutputs() {
depthAttachment =
Gfx::RenderTargetAttachment(depthBuffer, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
resources->registerRenderPassOutput("UIPASS_DEPTH", depthAttachment);
depthAttachment.clear.depthStencil.depth = 0;
TextureCreateInfo colorBufferInfo = {
.format = Gfx::SE_FORMAT_R16G16B16A16_SFLOAT,
.width = viewport->getWidth(),
.height = viewport->getHeight(),
.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
colorAttachment = Gfx::RenderTargetAttachment(viewport, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
colorAttachment.clear.color = {{1.0f, 1.0f, 1.0f, 1.0f}};
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
.colorAttachments = {colorAttachment},
.depthAttachment = depthAttachment,
};
colorBuffer = graphics->createTexture2D(colorBufferInfo);
renderTarget = Gfx::RenderTargetAttachment(colorBuffer, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR,
Gfx::SE_ATTACHMENT_STORE_OP_STORE);
renderTarget.clear.color = {{0.0f, 0.0f, 0.0f, 1.0f}};
resources->registerRenderPassOutput("UIPASS_COLOR", renderTarget);
}
renderPass = graphics->createRenderPass(std::move(layout), {}, viewport, "TextPass");
void UIPass::createRenderPass() {
ShaderCompilationInfo createInfo = {
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "TextVertex",
.modules = {"TextPass"},
.entryPoints = {{"vertexMain", "TextPass"}, {"fragmentMain", "TextPass"}},
.rootSignature = textPipelineLayout,
});
textPipelineLayout->create();
textVertexShader = graphics->createVertexShader({0});
textFragmentShader = graphics->createFragmentShader({1});
glyphSampler = graphics->createSampler({
.magFilter = Gfx::SE_FILTER_LINEAR,
.minFilter = Gfx::SE_FILTER_LINEAR,
.addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
});
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
.vertexShader = textVertexShader,
.fragmentShader = textFragmentShader,
.renderPass = renderPass,
.pipelineLayout = textPipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_NONE,
},
.colorBlend =
{
.attachmentCount = 1,
.blendAttachments = {{
.blendEnable = true,
.srcColorBlendFactor = Gfx::SE_BLEND_FACTOR_SRC_ALPHA,
.dstColorBlendFactor = Gfx::SE_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
.srcAlphaBlendFactor = Gfx::SE_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
.dstAlphaBlendFactor = Gfx::SE_BLEND_FACTOR_ZERO,
.alphaBlendOp = Gfx::SE_BLEND_OP_ADD,
.colorWriteMask = Gfx::SE_COLOR_COMPONENT_R_BIT | Gfx::SE_COLOR_COMPONENT_G_BIT | Gfx::SE_COLOR_COMPONENT_B_BIT |
Gfx::SE_COLOR_COMPONENT_A_BIT,
}},
},
};
textPipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "UIVertex",
.modules = {"UIPass"},
.entryPoints =
{
{"vertexMain", "UIPass"},
{"fragmentMain", "UIFragment"},
},
};
graphics->beginShaderCompilation(createInfo);
vertexShader = graphics->createVertexShader({0});
fragmentShader = graphics->createFragmentShader({1});
descriptorLayout = graphics->createDescriptorLayout("pParams");
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 0,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.uniformLength = sizeof(Matrix4),
.entryPoints = {{"vertexMain", "UIPass"}, {"fragmentMain", "UIPass"}},
.rootSignature = uiPipelineLayout,
});
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 1,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
});
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 2,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.uniformLength = sizeof(uint32)
});
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 3,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.textureType = Gfx::SE_IMAGE_VIEW_TYPE_2D_ARRAY,
.descriptorCount = 256,
.bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT | Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT,
});
descriptorLayout->create();
Matrix4 projectionMatrix = glm::ortho(0, 1, 1, 0);
Gfx::OUniformBuffer uniformBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{
.sourceData =
{
.size = sizeof(Matrix4),
.data = (uint8*)&projectionMatrix,
},
});
Gfx::OSampler backgroundSampler = graphics->createSampler({});
numTexturesBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{
.sourceData =
{
.size = sizeof(uint32),
.data = nullptr,
},
});
descriptorSet = descriptorLayout->allocateDescriptorSet();
descriptorSet->updateBuffer(0, 0, uniformBuffer);
descriptorSet->updateSampler(1, 0, backgroundSampler);
descriptorSet->writeChanges();
pipelineLayout = graphics->createPipelineLayout();
pipelineLayout->addDescriptorLayout(descriptorLayout);
pipelineLayout->create();
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{.colorAttachments = {renderTarget}, .depthAttachment = depthAttachment};
renderPass = graphics->createRenderPass(std::move(layout), {}, viewport);
Gfx::LegacyPipelineCreateInfo pipelineInfo;
pipelineInfo.vertexShader = vertexShader;
pipelineInfo.fragmentShader = fragmentShader;
pipelineInfo.renderPass = renderPass;
pipelineInfo.pipelineLayout = pipelineLayout;
pipelineInfo.rasterizationState.cullMode = Gfx::SE_CULL_MODE_NONE;
pipelineInfo.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
uiVertexShader = graphics->createVertexShader({0});
uiFragmentShader = graphics->createFragmentShader({1});
}
+52 -14
View File
@@ -1,15 +1,22 @@
#pragma once
#include "Graphics/Shader.h"
#include "RenderPass.h"
#include "UI/RenderHierarchy.h"
#include "Asset/FontAsset.h"
#include "UI/System.h"
namespace Seele {
DECLARE_NAME_REF(Gfx, Texture2D)
DECLARE_NAME_REF(Gfx, RenderTargetAttachment)
struct TextRender {
std::string text;
PFontAsset font;
uint32 fontSize;
Vector4 textColor;
Vector2 position;
};
class UIPass : public RenderPass {
public:
UIPass(Gfx::PGraphics graphics, PScene scene);
UIPass(Gfx::PGraphics graphics, UI::PSystem system);
UIPass(UIPass&&) = default;
UIPass& operator=(UIPass&&) = default;
virtual ~UIPass();
@@ -20,23 +27,54 @@ class UIPass : public RenderPass {
virtual void createRenderPass() override;
private:
Gfx::RenderTargetAttachment renderTarget;
Gfx::OTexture2D colorBuffer;
struct GlyphData {
Vector2 bearing;
Vector2 size;
uint32 advance;
};
struct GlyphInstanceData {
float x;
float y;
float width;
float height;
uint32 glyphIndex;
};
struct TextData {
Vector4 textColor;
float scale;
};
struct TextResources {
Gfx::PShaderBuffer instanceBuffer;
Gfx::PDescriptorSet textureArraySet;
TextData textData;
};
Map<PFontAsset, Array<TextResources>> textResources;
Gfx::RenderTargetAttachment colorAttachment;
Gfx::RenderTargetAttachment depthAttachment;
Gfx::OTexture2D depthBuffer;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::PDescriptorSet descriptorSet;
Gfx::ODescriptorLayout textDescriptorLayout;
Gfx::PDescriptorSet textDescriptorSet;
Gfx::OUniformBuffer numTexturesBuffer;
Gfx::OVertexBuffer elementBuffer;
Gfx::OVertexShader textVertexShader;
Gfx::OFragmentShader textFragmentShader;
Gfx::OPipelineLayout textPipelineLayout;
Gfx::PGraphicsPipeline textPipeline;
Gfx::OVertexShader vertexShader;
Gfx::OFragmentShader fragmentShader;
Gfx::PGraphicsPipeline pipeline;
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout uiDescriptorLayout;
Gfx::PDescriptorSet uiDescriptorSet;
Array<UI::RenderElementStyle> renderElements;
Gfx::OVertexShader uiVertexShader;
Gfx::OFragmentShader uiFragmentShader;
Gfx::OPipelineLayout uiPipelineLayout;
Gfx::PGraphicsPipeline uiPipeline;
Array<TextRender> texts;
Array<GlyphInstanceData> glyphs;
Gfx::OShaderBuffer glyphInstanceBuffer;
Gfx::OSampler glyphSampler;
Array<Gfx::PTexture2D> usedTextures;
};
DEFINE_REF(UIPass);
@@ -3,7 +3,7 @@
using namespace Seele;
VisibilityPass::VisibilityPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {}
VisibilityPass::VisibilityPass(Gfx::PGraphics graphics) : RenderPass(graphics) {}
VisibilityPass::~VisibilityPass() {}
@@ -5,7 +5,7 @@
namespace Seele {
class VisibilityPass : public RenderPass {
public:
VisibilityPass(Gfx::PGraphics graphics, PScene scene);
VisibilityPass(Gfx::PGraphics graphics);
VisibilityPass(VisibilityPass&&) = default;
VisibilityPass& operator=(VisibilityPass&&) = default;
virtual ~VisibilityPass();