refactor code and support utf8 strings rendering

This commit is contained in:
ohyzha
2024-08-02 23:08:24 +03:00
parent 875ad80337
commit 9589b4d39f
11 changed files with 70 additions and 30 deletions

View File

@@ -8,7 +8,7 @@
#include "Scene/Scene.hpp" #include "Scene/Scene.hpp"
#include "Scene/Shader/Shader.hpp" #include "Scene/Shader/Shader.hpp"
#include "Scene/Geometry.hpp" #include "Scene/Geometry.hpp"
#include "Scene/Text.hpp" #include "Scene/TextDrawable.hpp"
#include "Scene/GeometryFactory.hpp" #include "Scene/GeometryFactory.hpp"
#include "Scene/Material.hpp" #include "Scene/Material.hpp"
#include "Scene/Vertex.hpp" #include "Scene/Vertex.hpp"
@@ -55,13 +55,13 @@ namespace OpenVulkano
static std::vector<std::pair<std::string, TextConfig>> texts; static std::vector<std::pair<std::string, TextConfig>> texts;
texts.push_back(std::make_pair("ABab?.^{}_cdFGETG123)(", TextConfig())); texts.push_back(std::make_pair("ABab?.^{}_cdFGETG123)(", TextConfig()));
texts.push_back(std::make_pair("Hello, World!", TextConfig())); texts.push_back(std::make_pair("Hello, World!", TextConfig()));
texts.push_back(std::make_pair("\u0410\u0411\u0412\u041F", TextConfig()));
texts[0].second.applyBorder = true; texts[0].second.applyBorder = true;
texts[1].second.backgroundColor.a = 1; texts[1].second.backgroundColor.a = 1;
const int N = texts.size(); const int N = texts.size();
std::string fontPath;
auto& resourceLoader = ResourceLoader::GetInstance(); auto& resourceLoader = ResourceLoader::GetInstance();
resourceLoader.GetResource("Roboto-Regular.ttf", fontPath); const std::string fontPath = resourceLoader.GetResourcePath("Roboto-Regular.ttf");
const std::string atlasPath = (fs::path(fontPath).parent_path() / "roboto-regular-atlas.png").string(); const std::string atlasPath = (fs::path(fontPath).parent_path() / "roboto-regular-atlas.png").string();
m_nodesPool.resize(N); m_nodesPool.resize(N);
@@ -81,11 +81,17 @@ namespace OpenVulkano
m_shader.alphaBlend = true; m_shader.alphaBlend = true;
m_shader.cullMode = CullMode::NONE; m_shader.cullMode = CullMode::NONE;
m_atlasGenerator.GenerateAtlas(fontPath, atlasPath); Charset charset = Charset::ASCII;
for (unicode_t c = 0x0410; c <= 0x041F; c++)
{
// some unicode values
charset.add(c);
}
m_atlasGenerator.GenerateAtlas(fontPath, atlasPath, charset);
for (int i = 0; i < texts.size(); i++) for (int i = 0; i < texts.size(); i++)
{ {
Text* t = new Text(); TextDrawable* t = new TextDrawable();
t->SetFontAtlasGenerator(&m_atlasGenerator); t->SetFontAtlasGenerator(&m_atlasGenerator);
t->SetConfig(texts[i].second); t->SetConfig(texts[i].second);
t->SetUniformBuffer(&m_uniBuffers[i]); t->SetUniformBuffer(&m_uniBuffers[i]);
@@ -93,15 +99,14 @@ namespace OpenVulkano
t->GenerateText(texts[i].first); t->GenerateText(texts[i].first);
m_drawablesPool[i] = t; m_drawablesPool[i] = t;
m_nodesPool[i].Init(); m_nodesPool[i].Init();
m_nodesPool[i].SetMatrix( m_nodesPool[i].SetMatrix(Math::Utils::translate(glm::mat4x4(1.f), Vector3f(-5, 2 - i * 2, 0)));
Math::Utils::translate(glm::mat4x4(1.f), Vector3f(-3 + std::rand() % 3, -2 + std::rand() % 4, 2)));
m_nodesPool[i].AddDrawable(m_drawablesPool[i]); m_nodesPool[i].AddDrawable(m_drawablesPool[i]);
m_scene.GetRoot()->AddChild(&m_nodesPool[i]); m_scene.GetRoot()->AddChild(&m_nodesPool[i]);
} }
GetGraphicsAppManager()->GetRenderer()->SetScene(&m_scene); GetGraphicsAppManager()->GetRenderer()->SetScene(&m_scene);
m_camController.Init(&m_cam); m_camController.Init(&m_cam);
m_camController.SetDefaultKeybindings(); m_camController.SetDefaultKeybindings();
m_camController.SetPosition({ 0, 0, 5 }); m_camController.SetPosition({ 0, 0, 10 });
m_camController.SetBoostFactor(5); m_camController.SetBoostFactor(5);
std::shared_ptr<OpenVulkano::Scene::UI::PerformanceInfo> m_perfInfo = std::shared_ptr<OpenVulkano::Scene::UI::PerformanceInfo> m_perfInfo =

View File

@@ -40,9 +40,13 @@ namespace OpenVulkano
} }
} }
Array<char> ResourceLoaderAppDirLinux::GetResource(const std::string& resourceName, std::string& resourcePath) std::string ResourceLoaderAppDirLinux::GetResourcePath(const std::string& resourceName)
{ {
resourcePath = GetAppDir() + resourceName; return GetAppDir() + resourceName;
return Utils::ReadFile(resourcePath, true); }
Array<char> ResourceLoaderAppDirLinux::GetResource(const std::string& resourceName)
{
return Utils::ReadFile(resourceName, true);
} }
} }

View File

@@ -13,6 +13,7 @@ namespace OpenVulkano
class ResourceLoaderAppDirLinux final : public ResourceLoader class ResourceLoaderAppDirLinux final : public ResourceLoader
{ {
public: public:
Array<char> GetResource(const std::string& resourceName, std::string& resourcePath) override; std::string GetResourcePath(const std::string& resourceName) override;
Array<char> GetResource(const std::string& resourceName) override;
}; };
} }

View File

@@ -15,13 +15,13 @@ namespace OpenVulkano
std::vector<std::unique_ptr<ResourceLoader>> m_loaders; std::vector<std::unique_ptr<ResourceLoader>> m_loaders;
public: public:
Array<char> GetResource(const std::string& resourceName, std::string& resourcePath) override Array<char> GetResource(const std::string& resourceName) override
{ {
for(auto& loader : m_loaders) for(auto& loader : m_loaders)
{ {
try try
{ {
auto res = loader->GetResource(resourceName, resourcePath); auto res = loader->GetResource(resourceName);
if (!res.Empty()) return res; if (!res.Empty()) return res;
} }
catch (const std::exception& e) catch (const std::exception& e)
@@ -54,6 +54,30 @@ namespace OpenVulkano
} }
return false; return false;
} }
std::string GetResourcePath(const std::string& resourceName) override
{
try
{
for (auto& loader: m_loaders)
{
auto res = loader->GetResourcePath(resourceName);
if (!res.empty())
{
return res;
}
}
}
catch (const std::exception& e)
{
Logger::FILESYS->error("Error trying to get resource path for '{}'! Error: {}", resourceName, e.what());
}
catch (...)
{
Logger::FILESYS->error("Unknown error trying to get resource path for '{}'!", resourceName);
}
return "";
}
}; };
ResourceLoader& ResourceLoader::GetInstance() ResourceLoader& ResourceLoader::GetInstance()

View File

@@ -15,7 +15,9 @@ namespace OpenVulkano
public: public:
virtual ~ResourceLoader() = default; virtual ~ResourceLoader() = default;
virtual Array<char> GetResource(const std::string& resourceName, std::string& resourcePath) = 0; virtual Array<char> GetResource(const std::string& resourceName) = 0;
virtual std::string GetResourcePath(const std::string& resourceName) { return ""; }
static ResourceLoader& GetInstance(); static ResourceLoader& GetInstance();

View File

@@ -90,12 +90,11 @@ namespace OpenVulkano
return Array<char>(buffer); return Array<char>(buffer);
} }
Array<char> WebResourceLoader::GetResource(const std::string& resourceName, std::string& resourcePath) Array<char> WebResourceLoader::GetResource(const std::string& resourceName)
{ {
if (IsUrl(resourceName)) if (IsUrl(resourceName))
{ {
std::filesystem::path cacheFilePath = GetCacheFilePath(resourceName); std::filesystem::path cacheFilePath = GetCacheFilePath(resourceName);
resourcePath = resourceName;
if (std::filesystem::exists(cacheFilePath)) { return Utils::ReadFile(cacheFilePath.string()); } if (std::filesystem::exists(cacheFilePath)) { return Utils::ReadFile(cacheFilePath.string()); }
else { return DownloadResource(resourceName); } else { return DownloadResource(resourceName); }
} }

View File

@@ -24,6 +24,6 @@ namespace OpenVulkano
WebResourceLoader(); WebResourceLoader();
~WebResourceLoader(); ~WebResourceLoader();
Array<char> GetResource(const std::string& resourceName, std::string& resourcePath) override; Array<char> GetResource(const std::string& resourceName) override;
}; };
} }

View File

@@ -38,9 +38,13 @@ namespace OpenVulkano
} }
} }
Array<char> ResourceLoaderAppDirWindows::GetResource(const std::string& resourceName, std::string& resourcePath) std::string ResourceLoaderAppDirWindows::GetResourcePath(const std::string& resourceName)
{ {
resourcePath = GetAppDir() + resourceName; return GetAppDir() + resourceName;
return Utils::ReadFile(resourcePath); }
Array<char> ResourceLoaderAppDirWindows::GetResource(const std::string& resourceName)
{
return Utils::ReadFile(resourceName);
} }
} }

View File

@@ -13,6 +13,7 @@ namespace OpenVulkano
class ResourceLoaderAppDirWindows final : public ResourceLoader class ResourceLoaderAppDirWindows final : public ResourceLoader
{ {
public: public:
Array<char> GetResource(const std::string& resourceName, std::string& resourcePath) override; std::string GetResourcePath(const std::string& resourceName) override;
Array<char> GetResource(const std::string& resourceName) override;
}; };
} }

View File

@@ -59,18 +59,17 @@ namespace OpenVulkano::Scene
m_generator.generate(glyphsGeometry.data(), glyphsGeometry.size()); m_generator.generate(glyphsGeometry.data(), glyphsGeometry.size());
int idx = 0; int idx = 0;
BitmapConstRef<byte, 1> storage = m_generator.atlasStorage(); const BitmapConstRef<byte, 1>& storage = m_generator.atlasStorage();
m_atlasTex.resolution = Math::Vector3ui(storage.width, storage.height, 1);
m_atlasTex.textureBuffer = (msdfgen::byte*) storage.pixels;
m_atlasTex.format = OpenVulkano::DataFormat::R8_UNORM;
m_atlasTex.size = storage.width * storage.height * 1; // 1 channel
for (const auto& glyph: glyphsGeometry) for (const auto& glyph: glyphsGeometry)
{ {
unicode_t c = static_cast<char8_t>(glyph.getCodepoint());
GlyphInfo info; GlyphInfo info;
info.texture.resolution = Math::Vector3ui(storage.width, storage.height, 1);
info.texture.textureBuffer = (msdfgen::byte*)storage.pixels;
info.texture.format = OpenVulkano::DataFormat::R8_UNORM;
info.texture.size = storage.width * storage.height * 1; // 1 channel
info.geometry = glyph; info.geometry = glyph;
info.glyphBox = m_generator.getLayout()[idx++]; info.glyphBox = m_generator.getLayout()[idx++];
m_symbols[c] = std::move(info); m_symbols[glyph.getCodepoint()] = std::move(info);
} }
savePng(m_generator.atlasStorage(), outputFile.c_str()); savePng(m_generator.atlasStorage(), outputFile.c_str());
destroyFont(font); destroyFont(font);

View File

@@ -23,18 +23,19 @@ namespace OpenVulkano::Scene
{ {
GlyphGeometry geometry; GlyphGeometry geometry;
GlyphBox glyphBox; GlyphBox glyphBox;
Texture texture;
}; };
class FontAtlasGenerator class FontAtlasGenerator
{ {
public: public:
void GenerateAtlas(const std::string& fontFile, const std::string& outputFile, const Charset& = Charset::ASCII); void GenerateAtlas(const std::string& fontFile, const std::string& outputFile, const Charset& = Charset::ASCII);
const Texture& GetAtlas() const { return m_atlasTex; }
std::map<unicode_t, GlyphInfo>& GetAtlasInfo() { return m_symbols; } std::map<unicode_t, GlyphInfo>& GetAtlasInfo() { return m_symbols; }
private: private:
std::pair<FreetypeHandle*, FontHandle*> GetHandlers(const std::string& fontFile); std::pair<FreetypeHandle*, FontHandle*> GetHandlers(const std::string& fontFile);
private: private:
ImmediateAtlasGenerator<float, 1, sdfGenerator, BitmapAtlasStorage<msdfgen::byte, 1>> m_generator; ImmediateAtlasGenerator<float, 1, sdfGenerator, BitmapAtlasStorage<msdfgen::byte, 1>> m_generator;
Texture m_atlasTex;
std::map<unicode_t, GlyphInfo> m_symbols; std::map<unicode_t, GlyphInfo> m_symbols;
std::string m_loadedFont; std::string m_loadedFont;
}; };