Files
Seele/src/Engine/Graphics/RenderPass/TextPass.cpp
T

214 lines
7.9 KiB
C++
Raw Normal View History

2022-04-15 11:19:30 +02:00
#include "TextPass.h"
#include "RenderGraph.h"
#include "Graphics/Graphics.h"
2023-10-26 18:37:29 +02:00
#include "Graphics/RenderTarget.h"
2023-11-15 17:42:57 +01:00
#include "Graphics/Command.h"
2022-04-15 11:19:30 +02:00
using namespace Seele;
2023-10-26 18:37:29 +02:00
TextPass::TextPass(Gfx::PGraphics graphics, PScene scene)
: RenderPass(graphics, scene)
2022-04-15 11:19:30 +02:00
{
}
TextPass::~TextPass()
{
}
2023-11-05 10:36:01 +01:00
void TextPass::beginFrame(const Component::Camera& cam)
2022-04-15 11:19:30 +02:00
{
2023-11-05 10:36:01 +01:00
RenderPass::beginFrame(cam);
2023-10-26 18:37:29 +02:00
for(TextRender& render : texts)
2022-04-15 11:19:30 +02:00
{
FontData& fd = getFontData(render.font);
TextResources& res = textResources[render.font].add();
2022-04-15 11:19:30 +02:00
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]];
2023-01-21 18:43:21 +01:00
Vector2 bearing = glyph.bearing;
Vector2 size = glyph.size;
2022-04-17 09:10:20 +02:00
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;
2022-04-15 11:19:30 +02:00
instanceData.add(GlyphInstanceData{
2023-01-21 18:43:21 +01:00
.position = Vector2(xpos, ypos),
.widthHeight = Vector2(w, h),
.glyphIndex = fd.characterToGlyphIndex[c],
2022-04-15 11:19:30 +02:00
});
2022-04-17 09:10:20 +02:00
x += (glyph.advance >> 6) * render.scale;
2022-04-15 11:19:30 +02:00
}
2023-11-15 17:42:57 +01:00
res.instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
2023-11-01 23:12:30 +01:00
.sourceData = {
2022-04-17 09:10:20 +02:00
.size = static_cast<uint32>(instanceData.size() * sizeof(GlyphInstanceData)),
.data = reinterpret_cast<uint8*>(instanceData.data()),
2023-11-15 17:42:57 +01:00
},
.numElements = instanceData.size(),
});
2022-04-15 11:19:30 +02:00
res.textureArraySet = fd.textureArraySet;
2022-04-15 11:19:30 +02:00
res.textData = {
2022-04-17 09:10:20 +02:00
.textColor = render.textColor,
.scale = render.scale,
};
2022-04-15 11:19:30 +02:00
}
2022-11-30 10:19:45 +01:00
auto proj = viewport->getProjectionMatrix();
2023-11-01 23:12:30 +01:00
DataSource projectionUpdate = {
2023-01-21 18:43:21 +01:00
.size = sizeof(Matrix4),
2022-11-30 10:19:45 +01:00
.data = (uint8*)&proj,
2022-11-17 16:47:42 +01:00
};
projectionBuffer->updateContents(projectionUpdate);
generalSet->updateBuffer(1, projectionBuffer);
generalSet->writeChanges();
2022-04-15 23:45:44 +02:00
//co_return;
2022-04-15 11:19:30 +02:00
}
2022-04-15 23:45:44 +02:00
void TextPass::render()
2022-04-15 11:19:30 +02:00
{
graphics->beginRenderPass(renderPass);
2024-04-11 12:38:42 +02:00
Array<Gfx::ORenderCommand> commands;
for(const auto& [fontAsset, res] : textResources)
2022-04-15 11:19:30 +02:00
{
2024-04-11 12:38:42 +02:00
Gfx::ORenderCommand command = graphics->createRenderCommand("TextPassCommand");
2022-04-15 11:19:30 +02:00
command->setViewport(viewport);
command->bindPipeline(pipeline);
for(const auto& resource : res)
2022-04-18 18:08:38 +02:00
{
command->bindDescriptor({generalSet, resource.textureArraySet});
2023-11-15 17:42:57 +01:00
//command->bindVertexBuffer({resource.vertexBuffer});
2022-04-18 18:08:38 +02:00
2023-11-09 22:15:51 +01:00
command->pushConstants(layoutRef, Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(TextData), &resource.textData);
2023-11-15 17:42:57 +01:00
//command->draw(4, static_cast<uint32>(resource.vertexBuffer->getNumVertices()), 0, 0);
2022-04-18 18:08:38 +02:00
}
2024-04-11 12:38:42 +02:00
commands.add(std::move(command));
2022-04-15 11:19:30 +02:00
}
2024-04-11 12:38:42 +02:00
graphics->executeCommands(std::move(commands));
2022-04-15 11:19:30 +02:00
graphics->endRenderPass();
2022-04-15 23:45:44 +02:00
textResources.clear();
//co_return;
2022-04-15 11:19:30 +02:00
}
2022-04-15 23:45:44 +02:00
void TextPass::endFrame()
2022-04-15 11:19:30 +02:00
{
2022-04-15 23:45:44 +02:00
//co_return;
2022-04-15 11:19:30 +02:00
}
void TextPass::publishOutputs()
{
}
void TextPass::createRenderPass()
{
2022-11-17 16:47:42 +01:00
renderTarget = resources->requestRenderTarget("UIPASS_COLOR");
2022-04-15 11:19:30 +02:00
depthAttachment = resources->requestRenderTarget("UIPASS_DEPTH");
2022-11-17 16:47:42 +01:00
2022-04-15 11:19:30 +02:00
ShaderCreateInfo createInfo;
createInfo.mainModule = "TextPass";
2022-04-15 11:19:30 +02:00
createInfo.defines["INDEX_VIEW_PARAMS"] = "0";
createInfo.name = "TextVertex";
createInfo.entryPoint = "vertexMain";
vertexShader = graphics->createVertexShader(createInfo);
createInfo.name = "TextFragment";
createInfo.entryPoint = "fragmentMain";
fragmentShader = graphics->createFragmentShader(createInfo);
2022-04-15 23:45:44 +02:00
generalLayout = graphics->createDescriptorLayout("TextGeneral");
generalLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
generalLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_SAMPLER);
generalLayout->create();
2022-04-15 11:19:30 +02:00
2022-04-15 23:45:44 +02:00
textureArrayLayout = graphics->createDescriptorLayout("TextTextureArray");
2022-04-17 09:10:20 +02:00
textureArrayLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 256, Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT);
2022-04-15 11:19:30 +02:00
textureArrayLayout->create();
projectionBuffer = graphics->createUniformBuffer({
2023-11-01 23:12:30 +01:00
.sourceData = {
2023-01-21 18:43:21 +01:00
.size = sizeof(Matrix4),
2022-11-17 16:47:42 +01:00
.data = nullptr,
2022-04-15 11:19:30 +02:00
},
2023-11-05 10:36:01 +01:00
.dynamic = true,
2022-04-15 11:19:30 +02:00
});
2023-11-15 17:42:57 +01:00
glyphSampler = graphics->createSampler({
2022-04-15 11:19:30 +02:00
.magFilter = Gfx::SE_FILTER_LINEAR,
.minFilter = Gfx::SE_FILTER_LINEAR,
.addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
2022-04-15 23:45:44 +02:00
.addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
2022-04-15 11:19:30 +02:00
});
2022-04-15 23:45:44 +02:00
generalSet = generalLayout->allocateDescriptorSet();
generalSet->updateBuffer(0, projectionBuffer);
generalSet->updateSampler(1, glyphSampler);
generalSet->writeChanges();
2023-11-09 22:15:51 +01:00
Gfx::OPipelineLayout pipelineLayout = graphics->createPipelineLayout();
layoutRef = pipelineLayout;
2022-04-15 23:45:44 +02:00
pipelineLayout->addDescriptorLayout(0, generalLayout);
2022-04-17 09:10:20 +02:00
pipelineLayout->addDescriptorLayout(1, textureArrayLayout);
2022-04-15 11:19:30 +02:00
pipelineLayout->addPushConstants({
2022-04-17 09:10:20 +02:00
.stageFlags = Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
2022-04-15 11:19:30 +02:00
.offset = 0,
2022-04-17 09:10:20 +02:00
.size = sizeof(TextData)});
2022-04-15 11:19:30 +02:00
pipelineLayout->create();
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
2023-12-10 22:27:59 +01:00
.colorAttachments = {renderTarget},
.depthAttachment = depthAttachment
};
renderPass = graphics->createRenderPass(std::move(layout), {}, viewport);
2022-04-15 11:19:30 +02:00
2023-10-26 18:37:29 +02:00
Gfx::LegacyPipelineCreateInfo pipelineInfo;
2022-04-15 11:19:30 +02:00
pipelineInfo.vertexShader = vertexShader;
pipelineInfo.fragmentShader = fragmentShader;
pipelineInfo.renderPass = renderPass;
2023-11-09 22:15:51 +01:00
pipelineInfo.pipelineLayout = std::move(pipelineLayout);
2022-04-15 11:19:30 +02:00
pipelineInfo.rasterizationState.cullMode = Gfx::SE_CULL_MODE_NONE;
2022-04-15 23:45:44 +02:00
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;
2022-04-15 11:19:30 +02:00
pipelineInfo.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
2023-11-09 22:15:51 +01:00
pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
2022-04-15 11:19:30 +02:00
}
TextPass::FontData& TextPass::getFontData(PFontAsset font)
{
if(fontData.exists(font))
{
return fontData[font];
2022-04-17 09:10:20 +02:00
}
const auto& fontGlyphs = font->getGlyphData();
2022-04-15 11:19:30 +02:00
FontData& fd = fontData[font];
2022-04-17 09:10:20 +02:00
Array<GlyphData> glyphData;
2022-04-15 23:45:44 +02:00
Array<Gfx::PTexture> textures;
2022-04-17 09:10:20 +02:00
glyphData.reserve(fontGlyphs.size());
2022-04-15 11:19:30 +02:00
for(const auto& [key, value] : fontGlyphs)
{
2022-04-17 09:10:20 +02:00
fd.characterToGlyphIndex[key] = static_cast<uint32>(glyphData.size());
GlyphData& gd = glyphData.add();
2022-04-15 11:19:30 +02:00
gd.bearing = value.bearing;
gd.size = value.size;
2022-04-17 09:10:20 +02:00
gd.advance = value.advance;
2023-11-07 16:55:13 +01:00
textures.add(font->getTexture(value.textureIndex));
2022-04-15 11:19:30 +02:00
}
2022-04-17 09:10:20 +02:00
fd.glyphDataSet = glyphData;
2022-04-15 23:45:44 +02:00
2023-11-05 10:36:01 +01:00
textureArrayLayout->reset();
2022-04-15 23:45:44 +02:00
fd.textureArraySet = textureArrayLayout->allocateDescriptorSet();
fd.textureArraySet->updateTextureArray(0, textures);
fd.textureArraySet->writeChanges();
2022-04-15 11:19:30 +02:00
return fontData[font];
}