2022-04-15 11:19:30 +02:00
|
|
|
#include "TextPass.h"
|
2024-06-09 12:20:04 +02:00
|
|
|
#include "Graphics/Command.h"
|
2024-04-15 13:48:34 +02:00
|
|
|
#include "Graphics/Enums.h"
|
2022-04-15 11:19:30 +02:00
|
|
|
#include "Graphics/Graphics.h"
|
2023-10-26 18:37:29 +02:00
|
|
|
#include "Graphics/RenderTarget.h"
|
2024-06-09 12:20:04 +02:00
|
|
|
#include "RenderGraph.h"
|
|
|
|
|
|
2022-04-15 11:19:30 +02:00
|
|
|
|
|
|
|
|
using namespace Seele;
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
TextPass::TextPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {}
|
2022-04-15 11:19:30 +02:00
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
TextPass::~TextPass() {}
|
2022-04-15 11:19:30 +02:00
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
void TextPass::beginFrame(const Component::Camera& cam) {
|
2023-11-05 10:36:01 +01:00
|
|
|
RenderPass::beginFrame(cam);
|
2024-06-09 12:20:04 +02:00
|
|
|
for (TextRender& render : texts) {
|
2022-11-15 12:19:11 +01: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;
|
2024-06-09 12:20:04 +02:00
|
|
|
for (uint32 c : render.text) {
|
2022-11-15 12:19:11 +01:00
|
|
|
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;
|
2024-06-09 12:20:04 +02:00
|
|
|
|
2022-04-17 09:10:20 +02:00
|
|
|
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),
|
2022-11-15 12:19:11 +01:00
|
|
|
.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{
|
2024-06-09 12:20:04 +02:00
|
|
|
.sourceData =
|
|
|
|
|
{
|
|
|
|
|
.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
|
|
|
|
2022-11-15 12:19:11 +01:00
|
|
|
res.textureArraySet = fd.textureArraySet;
|
2022-04-15 11:19:30 +02:00
|
|
|
|
2022-11-15 12:19:11 +01: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();
|
2024-06-09 12:20:04 +02:00
|
|
|
// co_return;
|
2022-04-15 11:19:30 +02:00
|
|
|
}
|
|
|
|
|
|
2024-06-09 12:20:04 +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;
|
2024-06-09 12:20:04 +02:00
|
|
|
for (const auto& [fontAsset, res] : textResources) {
|
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);
|
2024-06-09 12:20:04 +02:00
|
|
|
for (const auto& resource : res) {
|
2022-04-18 18:08:38 +02:00
|
|
|
command->bindDescriptor({generalSet, resource.textureArraySet});
|
2024-06-09 12:20:04 +02:00
|
|
|
// 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);
|
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();
|
2024-06-09 12:20:04 +02:00
|
|
|
// co_return;
|
2022-04-15 11:19:30 +02:00
|
|
|
}
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
void TextPass::endFrame() {
|
|
|
|
|
// co_return;
|
2022-04-15 11:19:30 +02:00
|
|
|
}
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
void TextPass::publishOutputs() {}
|
2022-04-15 11:19:30 +02:00
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
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");
|
2024-06-09 12:20:04 +02:00
|
|
|
|
2024-04-26 19:32:38 +02:00
|
|
|
ShaderCreateInfo createInfo = {
|
|
|
|
|
.name = "TextVertex",
|
|
|
|
|
.mainModule = "TextPass",
|
|
|
|
|
.entryPoint = "vertexMain",
|
|
|
|
|
};
|
2022-04-15 11:19:30 +02:00
|
|
|
vertexShader = graphics->createVertexShader(createInfo);
|
|
|
|
|
|
|
|
|
|
createInfo.name = "TextFragment";
|
2024-06-09 12:20:04 +02:00
|
|
|
createInfo.entryPoint = "fragmentMain";
|
2022-04-15 11:19:30 +02:00
|
|
|
fragmentShader = graphics->createFragmentShader(createInfo);
|
2024-04-19 18:23:36 +02:00
|
|
|
generalLayout = graphics->createDescriptorLayout("pRender");
|
2024-06-09 12:20:04 +02:00
|
|
|
generalLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
|
|
|
.binding = 0,
|
|
|
|
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
|
|
|
});
|
|
|
|
|
generalLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
|
|
|
.binding = 1,
|
|
|
|
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
|
|
|
|
});
|
2022-04-15 23:45:44 +02:00
|
|
|
generalLayout->create();
|
2022-04-15 11:19:30 +02:00
|
|
|
|
2024-04-19 18:23:36 +02:00
|
|
|
textureArrayLayout = graphics->createDescriptorLayout("pGlyphTextures");
|
2024-06-09 12:20:04 +02:00
|
|
|
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,
|
|
|
|
|
});
|
2022-04-15 11:19:30 +02:00
|
|
|
textureArrayLayout->create();
|
|
|
|
|
|
|
|
|
|
projectionBuffer = graphics->createUniformBuffer({
|
2024-06-09 12:20:04 +02:00
|
|
|
.sourceData =
|
|
|
|
|
{
|
|
|
|
|
.size = sizeof(Matrix4),
|
|
|
|
|
.data = nullptr,
|
|
|
|
|
},
|
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();
|
2024-06-09 12:20:04 +02:00
|
|
|
|
2024-04-19 18:23:36 +02:00
|
|
|
pipelineLayout = graphics->createPipelineLayout();
|
|
|
|
|
pipelineLayout->addDescriptorLayout(generalLayout);
|
|
|
|
|
pipelineLayout->addDescriptorLayout(textureArrayLayout);
|
2024-06-09 12:20:04 +02:00
|
|
|
pipelineLayout->addPushConstants(
|
|
|
|
|
{.stageFlags = Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, .offset = 0, .size = sizeof(TextData)});
|
2022-04-15 11:19:30 +02:00
|
|
|
pipelineLayout->create();
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{.colorAttachments = {renderTarget}, .depthAttachment = depthAttachment};
|
2024-01-31 09:49:53 +01:00
|
|
|
renderPass = graphics->createRenderPass(std::move(layout), {}, viewport);
|
2024-06-09 12:20:04 +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;
|
2024-04-19 18:23:36 +02:00
|
|
|
pipelineInfo.pipelineLayout = 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;
|
2024-06-09 12:20:04 +02:00
|
|
|
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;
|
2022-04-15 23:45:44 +02:00
|
|
|
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
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
TextPass::FontData& TextPass::getFontData(PFontAsset font) {
|
|
|
|
|
if (fontData.exists(font)) {
|
2022-04-15 11:19:30 +02:00
|
|
|
return fontData[font];
|
2024-06-09 12:20:04 +02:00
|
|
|
}
|
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;
|
2024-06-20 21:57:26 +02:00
|
|
|
Array<Gfx::PTexture2D> textures;
|
2022-04-17 09:10:20 +02:00
|
|
|
glyphData.reserve(fontGlyphs.size());
|
2024-06-09 12:20:04 +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;
|
2024-06-09 12:20:04 +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];
|
|
|
|
|
}
|