From e2ae1687acabb042883a29eae8ac4f7fd468217d Mon Sep 17 00:00:00 2001 From: ohyzha Date: Mon, 26 Aug 2024 17:42:43 +0300 Subject: [PATCH] rework label drawable and text drawable's API --- .../ExampleApps/LabelDrawableExampleApp.cpp | 12 +- examples/ExampleApps/TextExampleApp.cpp | 6 +- examples/ExampleSources/msdf_atlas_packed.png | Bin 1036200 -> 1036208 bytes examples/ExampleSources/sdf_atlas_packed.png | Bin 646499 -> 646507 bytes openVulkanoCpp/Scene/AtlasData.hpp | 63 ++++++++++ openVulkanoCpp/Scene/AtlasMetadata.hpp | 28 ----- openVulkanoCpp/Scene/FontAtlasGenerator.cpp | 66 +++++----- openVulkanoCpp/Scene/FontAtlasGenerator.hpp | 12 +- openVulkanoCpp/Scene/IFontAtlasGenerator.hpp | 7 +- .../Scene/Prefabs/LabelDrawable.cpp | 119 ++++++------------ .../Scene/Prefabs/LabelDrawable.hpp | 8 +- openVulkanoCpp/Scene/TextDrawable.cpp | 42 +------ openVulkanoCpp/Scene/TextDrawable.hpp | 14 +-- 13 files changed, 160 insertions(+), 217 deletions(-) create mode 100644 openVulkanoCpp/Scene/AtlasData.hpp delete mode 100644 openVulkanoCpp/Scene/AtlasMetadata.hpp diff --git a/examples/ExampleApps/LabelDrawableExampleApp.cpp b/examples/ExampleApps/LabelDrawableExampleApp.cpp index d718b77..21dffe2 100644 --- a/examples/ExampleApps/LabelDrawableExampleApp.cpp +++ b/examples/ExampleApps/LabelDrawableExampleApp.cpp @@ -61,11 +61,7 @@ namespace OpenVulkano m_nodesPool.resize(N); m_drawablesPool.reserve(N); - static TextDrawable textDrawable(sdfMetadataInfo); - auto& sh = TextDrawable::GetSdfDefaultShader(); - sh.depthWrite = false; - sh.depthCompareOp = CompareOp::LESS_OR_EQUAL; - textDrawable.SetShader(&sh); + TextDrawable textDrawable(sdfMetadataInfo); const std::vector texts = { "Hello", "1", "XYZ" }; BillboardControlBlock billboardSettings; LabelDrawableSettings labelSettings; @@ -75,14 +71,14 @@ namespace OpenVulkano //labelSettings.hasRoundedCorners = (i % 2 == 0 ? 1 : 0); labelSettings.hasArrow = (i % 2 == 0 ? 1 : 0); bool isBillboard = (i % 2 == 0 ? 1 : 0); - LabelDrawable& label = m_drawablesPool.emplace_back(labelSettings, isBillboard); + LabelDrawable& label = m_drawablesPool.emplace_back(textDrawable.GetAtlasData(), labelSettings, isBillboard); label.SetBillboardSettings(billboardSettings); - label.AddText(&textDrawable, texts[i]); + label.AddText(texts[i]); if (i == 2) { for (int j = 0; j < 3; j++) { - label.AddText(&textDrawable, "Additional text" + std::to_string(j)); + label.AddText("Additional text" + std::to_string(j)); } } m_scene.GetRoot()->AddChild(&m_nodesPool[i]); diff --git a/examples/ExampleApps/TextExampleApp.cpp b/examples/ExampleApps/TextExampleApp.cpp index 386211c..4a97377 100644 --- a/examples/ExampleApps/TextExampleApp.cpp +++ b/examples/ExampleApps/TextExampleApp.cpp @@ -74,6 +74,8 @@ namespace OpenVulkano msdf_atlas::Charset charset = SdfFontAtlasGenerator::LoadAllGlyphs(fontPath); m_atlasGenerator.GenerateAtlas(fontPath, charset); m_msdfAtlasGenerator.GenerateAtlas(fontPath, charset); + m_atlasGenerator.SaveAtlasMetadataInfo("sdf_atlas.png"); + m_msdfAtlasGenerator.SaveAtlasMetadataInfo("msdf_atlas"); #else auto sdfMetadataInfo = resourceLoader.GetResource("sdf_atlas_packed.png"); auto msdfMetadataInfo = resourceLoader.GetResource("msdf_atlas_packed.png"); @@ -86,12 +88,12 @@ namespace OpenVulkano #if defined(MSDFGEN_AVAILABLE) && defined(CREATE_NEW_ATLAS) if (i < texts.size()) { - t = new TextDrawable(&m_atlasGenerator, texts[textIdx].second); + t = new TextDrawable(m_atlasGenerator.GetAtlasData(), texts[textIdx].second); t->SetShader(&TextDrawable::GetSdfDefaultShader()); } else { - t = new TextDrawable(&m_msdfAtlasGenerator, texts[textIdx].second); + t = new TextDrawable(m_msdfAtlasGenerator.GetAtlasData(), texts[textIdx].second); t->SetShader(&TextDrawable::GetMsdfDefaultShader()); } #else diff --git a/examples/ExampleSources/msdf_atlas_packed.png b/examples/ExampleSources/msdf_atlas_packed.png index ac883d945e78e115243ec138238ff26ea05b1026..c9baf4d184961acd00e99b94ba63318cc913a83b 100644 GIT binary patch delta 74 zcmZ26-+se<`-T?A7N!>F7M2#)7Pc1l7LFFq7OocV7M>Q~Eqrq`-T?A7N!>F7M2#)7Pc1l7LFFq7OocV7M>Q~EqrqF7M2#)7Pc1lEgX^VY-hn>`bBq+yy*q*9Bl2U-8r_OcIWJw N$|Eq1kpToiBmi%G7Qz4k delta 53 zcmaF8Oa1XK^@bM47N!>F7M2#)7Pc1lEgX^V)05pf3feEab8Nrp&e=DWhhrKe0| +#include + +namespace OpenVulkano::Scene +{ + struct GlyphInfo + { + //GlyphGeometry geometry; + //GlyphBox glyphBox; + Math::Vector3f_SIMD xyz[4] = {}; + Math::Vector2f_SIMD uv[4] = {}; + double advance = 0; + }; + + class FontAtlasType + { + public: + enum Type : int16_t + { + SDF = 0, + MSDF, + UNKNOWN + }; + static constexpr std::string_view DEFAULT_FG_SHADERS[] = { "Shader/text", "Shader/msdfText" }; + + public: + FontAtlasType(Type type) : m_type(type) {} + Type GetType() const { return m_type; } + const std::string_view& GetDefaultFragmentShader() const + { + return DEFAULT_FG_SHADERS[static_cast(m_type)]; + } + private: + Type m_type; + }; + + struct AtlasMetadata + { + // vertical difference between baselines + double lineHeight = 0; + int16_t atlasType = FontAtlasType::UNKNOWN; + }; + + struct AtlasData + { + std::map glyphs; + AtlasMetadata meta; + std::unique_ptr img; + Texture texture; + }; + +} \ No newline at end of file diff --git a/openVulkanoCpp/Scene/AtlasMetadata.hpp b/openVulkanoCpp/Scene/AtlasMetadata.hpp deleted file mode 100644 index 99f6e7f..0000000 --- a/openVulkanoCpp/Scene/AtlasMetadata.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include "Math/Math.hpp" - -namespace OpenVulkano::Scene -{ - struct GlyphInfo - { - //GlyphGeometry geometry; - //GlyphBox glyphBox; - Math::Vector3f_SIMD xyz[4] = {}; - Math::Vector2f_SIMD uv[4] = {}; - double advance = 0; - }; - - struct AtlasMetadata - { - // vertical difference between baselines - double lineHeight = 0; - }; - -} \ No newline at end of file diff --git a/openVulkanoCpp/Scene/FontAtlasGenerator.cpp b/openVulkanoCpp/Scene/FontAtlasGenerator.cpp index dc751b0..dd0bdb9 100644 --- a/openVulkanoCpp/Scene/FontAtlasGenerator.cpp +++ b/openVulkanoCpp/Scene/FontAtlasGenerator.cpp @@ -8,7 +8,7 @@ #include "FontAtlasGenerator.hpp" #include "Base/Logger.hpp" -#include "Scene/AtlasMetadata.hpp" +#include "Scene/AtlasData.hpp" #include #include #include @@ -120,7 +120,7 @@ namespace OpenVulkano::Scene void FontAtlasGenerator::SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile) const { - if (m_symbols.empty()) + if (m_atlasData->glyphs.empty()) { Logger::DATA->info("No glyphs loaded. Nothing to save."); return; @@ -134,9 +134,9 @@ namespace OpenVulkano::Scene SavePng(fileName); } std::fstream fs(fileName.c_str(), std::ios_base::out | std::ios_base::binary | (packedFlag ? std::ios_base::app : std::ios_base::trunc)); - fs.write(reinterpret_cast(&m_meta), sizeof(AtlasMetadata)); + fs.write(reinterpret_cast(&m_atlasData->meta), sizeof(AtlasMetadata)); uint64_t metadataBytes = sizeof(AtlasMetadata); - for (const auto& [key, val] : m_symbols) + for (const auto& [key, val]: m_atlasData->glyphs) { fs.write(reinterpret_cast(&key), sizeof(uint32_t)); fs.write(reinterpret_cast(&val), sizeof(GlyphInfo)); @@ -181,7 +181,8 @@ namespace OpenVulkano::Scene void FontAtlasGenerator::Generate(FreetypeHandle* ft, FontHandle* font, const Charset& chset, const std::optional& pngOutput) { - m_symbols.clear(); + m_atlasData.reset(new AtlasData); + std::vector glyphsGeometry; // FontGeometry is a helper class that loads a set of glyphs from a single font. FontGeometry fontGeometry(&glyphsGeometry); @@ -219,9 +220,12 @@ namespace OpenVulkano::Scene if constexpr (Channels == 3) { // store RGB as RGBA + m_atlasData->img = std::make_unique(); + m_atlasData->img->data = Array(width * height * 4); + m_atlasData->img->resolution = Math::Vector3ui(width, height, 1); + m_atlasData->img->dataFormat = OpenVulkano::DataFormat::R8G8B8A8_UNORM; const BitmapConstRef storage = generator.atlasStorage(); - msdfgen::Bitmap bitmap(width, height); - msdfgen::byte* data = static_cast(bitmap); + msdfgen::byte* data = static_cast(m_atlasData->img->data.Data()); for (size_t srcPos = 0, dstPos = 0; srcPos < width * height * 3; srcPos += 3, dstPos += 4) { data[dstPos] = storage.pixels[srcPos]; @@ -229,19 +233,23 @@ namespace OpenVulkano::Scene data[dstPos + 2] = storage.pixels[srcPos + 2]; data[dstPos + 3] = 255; } - m_atlasStorage = std::move(bitmap); } - else + else { - m_atlasStorage = generator.atlasStorage(); + m_atlasData->img = std::make_unique(); + m_atlasData->img->data = Array(width * height); + m_atlasData->img->resolution = Math::Vector3ui(width, height, 1); + m_atlasData->img->dataFormat = OpenVulkano::DataFormat::R8_UNORM; + const msdfgen::BitmapConstRef& storage = generator.atlasStorage(); + memcpy(m_atlasData->img->data.Data(), storage.pixels, width * height); } - m_atlasTex.resolution = Math::Vector3ui(m_atlasStorage.width(), m_atlasStorage.height(), 1); - m_atlasTex.textureBuffer = (msdfgen::byte*) m_atlasStorage; - m_atlasTex.format = (channelsCount == 1 ? OpenVulkano::DataFormat::R8_UNORM : OpenVulkano::DataFormat::R8G8B8A8_UNORM); - m_atlasTex.size = m_atlasStorage.width() * m_atlasStorage.height() * channelsCount; - - m_meta.lineHeight = fontGeometry.getMetrics().lineHeight; + m_atlasData->texture.resolution = m_atlasData->img->resolution; + m_atlasData->texture.textureBuffer = m_atlasData->img->data.Data(); + m_atlasData->texture.format = m_atlasData->img->dataFormat; + m_atlasData->texture.size = width * height * channelsCount; + m_atlasData->meta.lineHeight = fontGeometry.getMetrics().lineHeight; + m_atlasData->meta.atlasType = channelsCount == 1 ? FontAtlasType::SDF : FontAtlasType::MSDF; struct Bbox { @@ -250,7 +258,7 @@ namespace OpenVulkano::Scene for (const auto& glyph: glyphsGeometry) { - GlyphInfo& info = m_symbols[glyph.getCodepoint()]; + GlyphInfo& info = m_atlasData->glyphs[glyph.getCodepoint()]; const GlyphBox& glyphBox = generator.getLayout()[idx++]; Bbox glyphBaselineBbox, glyphAtlasBbox; @@ -269,26 +277,26 @@ namespace OpenVulkano::Scene info.xyz[0].x = bearingX; info.xyz[0].y = h - bearingY; info.xyz[0].z = 0; - info.uv[0].x = l / m_atlasTex.resolution.x; - info.uv[0].y = b / m_atlasTex.resolution.y; + info.uv[0].x = l / m_atlasData->texture.resolution.x; + info.uv[0].y = b / m_atlasData->texture.resolution.y; info.xyz[1].x = bearingX + w; info.xyz[1].y = h - bearingY; info.xyz[1].z = 0; - info.uv[1].x = r / m_atlasTex.resolution.x; - info.uv[1].y = b / m_atlasTex.resolution.y; + info.uv[1].x = r / m_atlasData->texture.resolution.x; + info.uv[1].y = b / m_atlasData->texture.resolution.y; info.xyz[2].x = bearingX + w; info.xyz[2].y = bearingY; //h - bearingY + h; info.xyz[2].z = 0; - info.uv[2].x = r / m_atlasTex.resolution.x; - info.uv[2].y = t / m_atlasTex.resolution.y; + info.uv[2].x = r / m_atlasData->texture.resolution.x; + info.uv[2].y = t / m_atlasData->texture.resolution.y; info.xyz[3].x = bearingX; info.xyz[3].y = bearingY; info.xyz[3].z = 0; - info.uv[3].x = l / m_atlasTex.resolution.x; - info.uv[3].y = t / m_atlasTex.resolution.y; + info.uv[3].x = l / m_atlasData->texture.resolution.x; + info.uv[3].y = t / m_atlasData->texture.resolution.y; info.advance = glyphBox.advance; } @@ -304,13 +312,13 @@ namespace OpenVulkano::Scene stbi_flip_vertically_on_write(1); if (std::filesystem::path(output).extension() == ".png") { - stbi_write_png(output.c_str(), m_atlasStorage.width(), m_atlasStorage.height(), channelsCount, - m_atlasStorage.operator const msdfgen::byte*(), channelsCount * m_atlasStorage.width()); + stbi_write_png(output.c_str(), m_atlasData->img->resolution.x, m_atlasData->img->resolution.y, + channelsCount, m_atlasData->img->data.Data(), channelsCount * m_atlasData->img->resolution.x); } else { - stbi_write_png((output + ".png").c_str(), m_atlasStorage.width(), m_atlasStorage.height(), channelsCount, - m_atlasStorage.operator const msdfgen::byte*(), channelsCount * m_atlasStorage.width()); + stbi_write_png((output + ".png").c_str(), m_atlasData->img->resolution.x, m_atlasData->img->resolution.y, + channelsCount, m_atlasData->img->data.Data(), channelsCount * m_atlasData->img->resolution.x); } } template class FontAtlasGenerator<1>; diff --git a/openVulkanoCpp/Scene/FontAtlasGenerator.hpp b/openVulkanoCpp/Scene/FontAtlasGenerator.hpp index c86b6ae..bac326c 100644 --- a/openVulkanoCpp/Scene/FontAtlasGenerator.hpp +++ b/openVulkanoCpp/Scene/FontAtlasGenerator.hpp @@ -8,7 +8,7 @@ #if __has_include("msdfgen.h") -#include "Scene/AtlasMetadata.hpp" +#include "Scene/AtlasData.hpp" #include "IFontAtlasGenerator.hpp" #include "Scene/Texture.hpp" #include @@ -41,7 +41,6 @@ namespace OpenVulkano::Scene msdf_atlas::BitmapAtlasStorage>; public: using Generator = std::conditional::type; - using AtlasData = std::conditional, msdfgen::Bitmap>::type; using Config = FontAtlasGeneratorConfig; static constexpr int channelsCount = (Channels == 1 ? 1 : 4); static msdf_atlas::Charset LoadAllGlyphs(const std::variant>& data); @@ -57,9 +56,7 @@ namespace OpenVulkano::Scene const std::optional& pngOutput = std::nullopt); void SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile = true) const override; void SetGeneratorConfig(const Config& config) { m_config = config; } - const Texture& GetAtlas() const override { return m_atlasTex; } - std::map& GetGlyphsInfo() override { return m_symbols; } - AtlasMetadata& GetAtlasMetadata() override { return m_meta; } + std::shared_ptr GetAtlasData() const { return m_atlasData; } Config& GetGeneratorConfig() { return m_config; } private: void InitFreetypeFromFile(msdfgen::FreetypeHandle*& ft, msdfgen::FontHandle*& font, const std::string& file); @@ -70,11 +67,8 @@ namespace OpenVulkano::Scene void SavePng(const std::string& output) const; private: - Texture m_atlasTex; - AtlasMetadata m_meta; Config m_config; - std::map m_symbols; - AtlasData m_atlasStorage; + std::shared_ptr m_atlasData; }; using SdfFontAtlasGenerator = FontAtlasGenerator<1>; using MsdfFontAtlasGenerator = FontAtlasGenerator<3>; diff --git a/openVulkanoCpp/Scene/IFontAtlasGenerator.hpp b/openVulkanoCpp/Scene/IFontAtlasGenerator.hpp index aeae92d..bd641c1 100644 --- a/openVulkanoCpp/Scene/IFontAtlasGenerator.hpp +++ b/openVulkanoCpp/Scene/IFontAtlasGenerator.hpp @@ -6,8 +6,7 @@ #pragma once -#include "Scene/AtlasMetadata.hpp" -#include "Scene/Texture.hpp" +#include "Scene/AtlasData.hpp" #include #include #include @@ -25,8 +24,6 @@ namespace OpenVulkano::Scene virtual void GenerateAtlas(const Array& fontData, int length, const std::set& charset, const std::optional& pngOutput = std::nullopt) = 0; virtual void SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile = true) const = 0; - virtual const Texture& GetAtlas() const = 0; - virtual std::map& GetGlyphsInfo() = 0; - virtual AtlasMetadata& GetAtlasMetadata() = 0; + virtual std::shared_ptr GetAtlasData() const = 0; }; } diff --git a/openVulkanoCpp/Scene/Prefabs/LabelDrawable.cpp b/openVulkanoCpp/Scene/Prefabs/LabelDrawable.cpp index abe1f86..5473c10 100644 --- a/openVulkanoCpp/Scene/Prefabs/LabelDrawable.cpp +++ b/openVulkanoCpp/Scene/Prefabs/LabelDrawable.cpp @@ -15,9 +15,15 @@ namespace OpenVulkano::Scene { using namespace Math; - LabelDrawable::LabelDrawable(const LabelDrawableSettings& settings, bool isBillboard) + LabelDrawable::LabelDrawable(const std::shared_ptr& atlasData, const LabelDrawableSettings& settings, + bool isBillboard) : Drawable(DrawEncoder::GetDrawEncoder(), DrawPhase::MAIN) { + if (atlasData->glyphs.empty() || !atlasData->texture.size) + { + throw std::runtime_error("Can't create label drawable. Either glyphs or texture is empty"); + } + m_atlasData = atlasData; m_isBillboard = isBillboard; SetLabelSettings(settings); SetupShaders(); @@ -34,40 +40,19 @@ namespace OpenVulkano::Scene m_labelData.arrowLength = settings.arrowLength; } - void LabelDrawable::AddText(TextDrawable* td, const std::string& text) + void LabelDrawable::AddText(const std::string& text, const TextConfig& config) { - if (!td || text.empty()) + if (text.empty()) { return; } - if (!td->GetShader()) - { - Logger::RENDER->error("Text drawable shader is null, cannot add text to label drawable\n"); - return; - } - TextDrawable& textDrawable = m_texts.emplace_back(td->GetConfig()); // do not render glyph's background + TextDrawable& textDrawable = m_texts.emplace_back(m_atlasData, config); textDrawable.GetConfig().backgroundColor.a = 0; - if (m_isBillboard) - { - textDrawable.SetShader(GetBillboardTextShader(td->GetShader())); - } - else - { - textDrawable.SetShader(td->GetShader()); - } - double lineHeight; - if (textDrawable.GetFontAtlasGenerator()) - { - textDrawable.SetFontAtlasGenerator(td->GetFontAtlasGenerator()); - lineHeight = td->GetFontAtlasGenerator()->GetAtlasMetadata().lineHeight; - } - else - { - textDrawable.SetAtlasData(td->GetAtlasData()); - lineHeight = td->GetAtlasData()->meta.lineHeight; - } + textDrawable.SetShader(&m_textShader); + double lineHeight = m_atlasData->meta.lineHeight; + textDrawable.GenerateText(text, m_position); RecalculateBbox(textDrawable.GetBoundingBox()); // update position for next text entry @@ -163,59 +148,6 @@ namespace OpenVulkano::Scene } } - // if we have want our label to be billboard, then we'll create new shader and set it's vertex shader to billboard.vert - // to avoid modifying input shader - Shader* LabelDrawable::GetBillboardTextShader(Shader* src) - { - auto GetFragmentShaderName = [](const Shader& shaderToCheck) -> std::optional - { - const auto& shaderPrograms = shaderToCheck.shaderPrograms; - auto pos = std::find_if(shaderPrograms.begin(), shaderPrograms.end(), - [](const ShaderProgram& program) - { return program.type == ShaderProgramType::FRAGMENT; }); - return pos != shaderPrograms.end() ? std::optional(pos->name) : std::nullopt; - }; - - std::optional inputFragmentName = GetFragmentShaderName(*src); - if (!inputFragmentName) - { - throw std::runtime_error("Shader doesn't have fragment program"); - } - - bool exists = false; - int shaderIdx = 0; - for (; shaderIdx < m_billboardTextShaders.size(); shaderIdx++) - { - std::optional name = GetFragmentShaderName(m_billboardTextShaders[shaderIdx]); - if (name.value() == inputFragmentName.value()) - { - exists = true; - break; - } - } - - if (!exists) - { - Shader& shader = m_billboardTextShaders.emplace_back(); - shaderIdx = m_billboardTextShaders.size() - 1; - shader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/billboard"); - shader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, inputFragmentName.value()); - shader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); - shader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING); - DescriptorSetLayoutBinding binding = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; - binding.stageFlags = ShaderProgramType::Type::VERTEX; - DescriptorSetLayoutBinding binding2 = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; - binding2.stageFlags = ShaderProgramType::FRAGMENT; - shader.AddDescriptorSetLayoutBinding(binding2, 3); - shader.AddDescriptorSetLayoutBinding(binding, 4); - shader.depthWrite = false; - shader.depthCompareOp = CompareOp::LESS_OR_EQUAL; - shader.alphaBlend = true; - shader.cullMode = CullMode::NONE; - } - return &m_billboardTextShaders[shaderIdx]; - } - void LabelDrawable::SetupShaders() { DescriptorSetLayoutBinding binding = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; @@ -237,6 +169,31 @@ namespace OpenVulkano::Scene m_backgroundShader.AddDescriptorSetLayoutBinding(binding, 5); m_backgroundShader.cullMode = CullMode::NONE; SetShader(&m_backgroundShader); + + FontAtlasType fontAtlasType(static_cast(m_atlasData->meta.atlasType)); + if (!m_isBillboard) + { + m_textShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/text"); + } + else + { + m_textShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/billboard"); + DescriptorSetLayoutBinding billboardUniformBinding = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; + billboardUniformBinding.stageFlags = ShaderProgramType::Type::VERTEX; + m_textShader.AddDescriptorSetLayoutBinding(billboardUniformBinding, 4); + } + + DescriptorSetLayoutBinding textUniformBinding = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; + textUniformBinding.stageFlags = ShaderProgramType::FRAGMENT; + m_textShader.AddDescriptorSetLayoutBinding(textUniformBinding, 3); + m_textShader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, + std::string(fontAtlasType.GetDefaultFragmentShader())); + m_textShader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); + m_textShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING, 2); + m_textShader.alphaBlend = true; + m_textShader.cullMode = CullMode::NONE; + m_textShader.depthWrite = false; + m_textShader.depthCompareOp = CompareOp::LESS_OR_EQUAL; } void LabelDrawable::SetupBuffers() diff --git a/openVulkanoCpp/Scene/Prefabs/LabelDrawable.hpp b/openVulkanoCpp/Scene/Prefabs/LabelDrawable.hpp index 7d2253c..40aa851 100644 --- a/openVulkanoCpp/Scene/Prefabs/LabelDrawable.hpp +++ b/openVulkanoCpp/Scene/Prefabs/LabelDrawable.hpp @@ -46,8 +46,9 @@ namespace OpenVulkano::Scene class LabelDrawable final : public Drawable { public: - LabelDrawable(const LabelDrawableSettings& settings = LabelDrawableSettings(), bool isBillboard = false); - void AddText(TextDrawable* td, const std::string& text); + LabelDrawable(const std::shared_ptr& atlasData, + const LabelDrawableSettings& settings = LabelDrawableSettings(), bool isBillboard = false); + void AddText(const std::string& text, const TextConfig& config = TextConfig()); void SetLabelSettings(const LabelDrawableSettings& settings); void SetBillboardSettings(const BillboardControlBlock& settings); void SetPosition(const Math::Vector3f& pos) { m_position = pos; } @@ -62,7 +63,6 @@ namespace OpenVulkano::Scene const Math::AABB& GetBoundingBox() const { return m_bbox; } private: void RecalculateBbox(const Math::AABB& other); - Shader* GetBillboardTextShader(Shader* src); void SetupShaders(); void SetupBuffers(); private: @@ -73,8 +73,10 @@ namespace OpenVulkano::Scene std::vector m_billboardTextShaders; // list over vector to prevent memory reallocation and crash std::list m_texts; + Shader m_textShader; LabelDrawableSettings m_settings; LabelUniformData m_labelData; + std::shared_ptr m_atlasData; BillboardControlBlock m_billboardSettings; Math::Vector3f m_position = { 0, 0, 0 }; Math::AABB m_bbox; diff --git a/openVulkanoCpp/Scene/TextDrawable.cpp b/openVulkanoCpp/Scene/TextDrawable.cpp index 190d807..d9fd170 100644 --- a/openVulkanoCpp/Scene/TextDrawable.cpp +++ b/openVulkanoCpp/Scene/TextDrawable.cpp @@ -139,23 +139,11 @@ namespace OpenVulkano::Scene throw std::runtime_error("Cannot initialize text drawable with empty atlas data"); } m_atlasData = atlasData; - m_material.texture = &atlasData->texture; m_cfg = config; m_uniBuffer.Init(sizeof(TextConfig), &m_cfg, 3); m_uniBuffer.binding.stageFlags = ShaderProgramType::FRAGMENT; } - TextDrawable::TextDrawable(IFontAtlasGenerator* fontAtlasGenerator, const TextConfig& config) - { - if (!fontAtlasGenerator) { throw std::runtime_error("FontAtlasGenerator is nullptr"); } - if (fontAtlasGenerator->GetGlyphsInfo().empty()) { throw std::runtime_error("Glyphs are not loaded"); } - m_fontAtlasGenerator = fontAtlasGenerator; - m_cfg = config; - m_material.texture = const_cast(&m_fontAtlasGenerator->GetAtlas()); - m_uniBuffer.Init(sizeof(TextConfig), &m_cfg, 3); - m_uniBuffer.binding.stageFlags = ShaderProgramType::FRAGMENT; - } - void TextDrawable::GenerateText(const std::string& text, const Math::Vector3f& pos) { if (text.empty()) @@ -180,26 +168,12 @@ namespace OpenVulkano::Scene size_t len = GetActualLength(); m_geometry.Close(); m_geometry.Init(len * 4, len * 6); - - // TODO: better implementation to decide what to use: data from atlas generator or data read from file - // we have msdf but loaded glyphs metadata from file before AtlasMetadata* meta; std::map* symbols; - if (m_fontAtlasGenerator) - { - // just in case if FontAtlasGenerator changed it's atlas - m_material.texture = const_cast(&m_fontAtlasGenerator->GetAtlas()); - symbols = &m_fontAtlasGenerator->GetGlyphsInfo(); - meta = &m_fontAtlasGenerator->GetAtlasMetadata(); - } - else - { - m_material.texture = &m_atlasData->texture; - symbols = &m_atlasData->glyphs; - meta = &m_atlasData->meta; - } + m_material.texture = &m_atlasData->texture; + symbols = &m_atlasData->glyphs; + meta = &m_atlasData->meta; - const Texture& atlasTex = *m_material.texture; double cursorX = pos.x; auto begin = text.begin(); auto end = text.end(); @@ -285,14 +259,4 @@ namespace OpenVulkano::Scene } m_atlasData = atlasData; } - - void TextDrawable::SetFontAtlasGenerator(IFontAtlasGenerator* fontAtlasGenerator) - { - if (!fontAtlasGenerator || fontAtlasGenerator->GetGlyphsInfo().empty()) - { - Logger::RENDER->error("FontAtlasGenerator is either nullptr or doesn't contain glyphs info"); - return; - } - m_fontAtlasGenerator = fontAtlasGenerator; - } } \ No newline at end of file diff --git a/openVulkanoCpp/Scene/TextDrawable.hpp b/openVulkanoCpp/Scene/TextDrawable.hpp index 3e898f0..2d50129 100644 --- a/openVulkanoCpp/Scene/TextDrawable.hpp +++ b/openVulkanoCpp/Scene/TextDrawable.hpp @@ -11,7 +11,7 @@ #include "Material.hpp" #include "Geometry.hpp" #include "UniformBuffer.hpp" -#include "AtlasMetadata.hpp" +#include "AtlasData.hpp" #include "Image/Image.hpp" #include #include @@ -33,14 +33,6 @@ namespace OpenVulkano::Scene //bool sdfMultiChannel = false; }; - struct AtlasData - { - std::map glyphs; - AtlasMetadata meta; - std::unique_ptr img; - Texture texture; - }; - class TextDrawable : public SimpleDrawable { public: @@ -52,7 +44,6 @@ namespace OpenVulkano::Scene TextDrawable(const std::string& atlasMetadataFile, Texture* atlasTex, const TextConfig& config = TextConfig()); TextDrawable(const Array& atlasMetadata, Texture* atlasTex, const TextConfig& config = TextConfig()); TextDrawable(const std::shared_ptr& atlasData, const TextConfig& config = TextConfig()); - TextDrawable(IFontAtlasGenerator* fontAtlasGenerator, const TextConfig& config = TextConfig()); void GenerateText(const std::string& text, const Math::Vector3f& pos = Math::Vector3f(0.f)); void SetConfig(const TextConfig& cfg) { m_cfg = cfg; } void SetShader(Shader* shader) { m_shader = shader; } @@ -61,15 +52,12 @@ namespace OpenVulkano::Scene TextConfig& GetConfig() { return m_cfg; } Shader* GetShader() { return m_shader; } std::shared_ptr GetAtlasData() { return m_atlasData; } - void SetFontAtlasGenerator(IFontAtlasGenerator* fontAtlasGenerator); - IFontAtlasGenerator* GetFontAtlasGenerator() { return m_fontAtlasGenerator; } private: Geometry m_geometry; Material m_material; UniformBuffer m_uniBuffer; std::shared_ptr m_atlasData; Math::AABB m_bbox; - IFontAtlasGenerator* m_fontAtlasGenerator = nullptr; Shader* m_shader = nullptr; TextConfig m_cfg; };