code refactoring
This commit is contained in:
@@ -24,7 +24,7 @@
|
|||||||
#include "Base/EngineConfiguration.hpp"
|
#include "Base/EngineConfiguration.hpp"
|
||||||
#include "Controller/FreeCamCameraController.hpp"
|
#include "Controller/FreeCamCameraController.hpp"
|
||||||
#include "Image/ImageLoaderPng.hpp"
|
#include "Image/ImageLoaderPng.hpp"
|
||||||
#include "Scene/FontAtlasGenerator.hpp"
|
#include "Scene/SdfFontAtlasGenerator.hpp"
|
||||||
#include "Scene/IFontAtlasGenerator.hpp"
|
#include "Scene/IFontAtlasGenerator.hpp"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#include "Base/EngineConfiguration.hpp"
|
#include "Base/EngineConfiguration.hpp"
|
||||||
#include "Controller/FreeCamCameraController.hpp"
|
#include "Controller/FreeCamCameraController.hpp"
|
||||||
#include "Image/ImageLoaderPng.hpp"
|
#include "Image/ImageLoaderPng.hpp"
|
||||||
#include "Scene/FontAtlasGenerator.hpp"
|
#include "Scene/SdfFontAtlasGenerator.hpp"
|
||||||
#include "Scene/IFontAtlasGenerator.hpp"
|
#include "Scene/IFontAtlasGenerator.hpp"
|
||||||
#include "Scene/BitmapFontAtlasGenerator.hpp"
|
#include "Scene/BitmapFontAtlasGenerator.hpp"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@@ -39,8 +39,8 @@ namespace OpenVulkano
|
|||||||
using namespace Math;
|
using namespace Math;
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
//#define CREATE_NEW_ATLAS 1
|
constexpr int CREATE_BITMAP_ATLAS = 0;
|
||||||
#define CREATE_BITMAP_ATLAS 0
|
constexpr int CREATE_NEW_ATLAS = 0;
|
||||||
|
|
||||||
class TextExampleAppImpl final : public TextExampleApp
|
class TextExampleAppImpl final : public TextExampleApp
|
||||||
{
|
{
|
||||||
@@ -71,14 +71,15 @@ namespace OpenVulkano
|
|||||||
m_nodesPool.resize(N * 3);
|
m_nodesPool.resize(N * 3);
|
||||||
m_drawablesPool.resize(N * 3);
|
m_drawablesPool.resize(N * 3);
|
||||||
|
|
||||||
#if CREATE_BITMAP_ATLAS
|
if constexpr (CREATE_BITMAP_ATLAS)
|
||||||
std::set<uint32_t> s = BitmapFontAtlasGenerator::LoadAllGlyphs(fontPath);
|
{
|
||||||
BitmapFontAtlasGenerator generator;
|
std::set<uint32_t> s = BitmapFontAtlasGenerator::LoadAllGlyphs(fontPath);
|
||||||
generator.GenerateAtlas(fontPath, s);
|
BitmapFontAtlasGenerator generator;
|
||||||
generator.SaveAtlasMetadataInfo("bitmap_atlas");
|
generator.GenerateAtlas(fontPath, s);
|
||||||
#endif
|
generator.SaveAtlasMetadataInfo("bitmap_atlas");
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(MSDFGEN_AVAILABLE) && defined(CREATE_NEW_ATLAS)
|
#if defined(MSDFGEN_AVAILABLE) && CREATE_NEW_ATLAS
|
||||||
std::set<uint32_t> s = SdfFontAtlasGenerator::LoadAllGlyphs(fontPath);
|
std::set<uint32_t> s = SdfFontAtlasGenerator::LoadAllGlyphs(fontPath);
|
||||||
msdf_atlas::Charset charset;
|
msdf_atlas::Charset charset;
|
||||||
for (uint32_t c : s)
|
for (uint32_t c : s)
|
||||||
@@ -99,7 +100,7 @@ namespace OpenVulkano
|
|||||||
{
|
{
|
||||||
int textIdx = i % texts.size();
|
int textIdx = i % texts.size();
|
||||||
TextDrawable* t = nullptr;
|
TextDrawable* t = nullptr;
|
||||||
#if defined(MSDFGEN_AVAILABLE) && defined(CREATE_NEW_ATLAS)
|
#if defined(MSDFGEN_AVAILABLE) && CREATE_NEW_ATLAS
|
||||||
if (i < texts.size())
|
if (i < texts.size())
|
||||||
{
|
{
|
||||||
t = new TextDrawable(m_atlasGenerator.GetAtlasData(), texts[textIdx].second);
|
t = new TextDrawable(m_atlasGenerator.GetAtlasData(), texts[textIdx].second);
|
||||||
@@ -180,7 +181,7 @@ namespace OpenVulkano
|
|||||||
PerspectiveCamera m_cam;
|
PerspectiveCamera m_cam;
|
||||||
OpenVulkano::FreeCamCameraController m_camController;
|
OpenVulkano::FreeCamCameraController m_camController;
|
||||||
#ifdef MSDFGEN_AVAILABLE
|
#ifdef MSDFGEN_AVAILABLE
|
||||||
SdfFontAtlasGenerator m_atlasGenerator;
|
SdfFontAtlasGeneratorT m_atlasGenerator;
|
||||||
MsdfFontAtlasGenerator m_msdfAtlasGenerator;
|
MsdfFontAtlasGenerator m_msdfAtlasGenerator;
|
||||||
#endif
|
#endif
|
||||||
std::vector<SimpleDrawable*> m_drawablesPool;
|
std::vector<SimpleDrawable*> m_drawablesPool;
|
||||||
|
|||||||
@@ -31,17 +31,15 @@ namespace OpenVulkano::Scene
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_atlasData.reset(new AtlasData);
|
m_atlasData = std::make_shared<AtlasData>();
|
||||||
const std::string sourceName = (std::holds_alternative<std::string>(source) ? std::get<0>(source) : "Binary array");
|
|
||||||
const auto& [lib, face] = FontAtlasGeneratorBase::InitFreetype(source);
|
const auto& [lib, face] = FontAtlasGeneratorBase::InitFreetype(source);
|
||||||
FT_FaceRec* pFace = face.get();
|
|
||||||
|
|
||||||
// TODO: add flexibility to set your own size
|
// TODO: add flexibility to set your own size
|
||||||
const Math::Vector2ui cellSize = { 24, 24 };
|
const Math::Vector2ui cellSize = { 24, 24 };
|
||||||
// set pixel width/height lower than glyph size above, otherwise some glyphs will be cropped or some overlapping will be present
|
// set pixel width/height lower than glyph size above, otherwise some glyphs will be cropped or some overlapping will be present
|
||||||
FT_Set_Pixel_Sizes(pFace, 0, cellSize.y - cellSize.y / 3);
|
FT_Set_Pixel_Sizes(face.get(), 0, cellSize.y - cellSize.y / 3);
|
||||||
const double sq = std::sqrt(chset.size());
|
const double sq = std::sqrt(chset.size());
|
||||||
const size_t glyphsPerRow = static_cast<size_t>(sq) + (sq - static_cast<size_t>(sq) != 0);
|
const size_t glyphsPerRow = (static_cast<size_t>(sq)) + (sq - static_cast<size_t>(sq) != 0);
|
||||||
const size_t rows = (chset.size() / glyphsPerRow) + (chset.size() % glyphsPerRow != 0);
|
const size_t rows = (chset.size() / glyphsPerRow) + (chset.size() % glyphsPerRow != 0);
|
||||||
const Math::Vector2ui atlasResolution = { glyphsPerRow * cellSize.x, rows * cellSize.y };
|
const Math::Vector2ui atlasResolution = { glyphsPerRow * cellSize.x, rows * cellSize.y };
|
||||||
|
|
||||||
@@ -49,8 +47,8 @@ namespace OpenVulkano::Scene
|
|||||||
// TODO: probably also support keeping coordinates as the integer values native to the font file
|
// TODO: probably also support keeping coordinates as the integer values native to the font file
|
||||||
// but since some algorithms have already been implemented for EM_NORMALIZED mode, currently there is no support for default font metrics (ints)
|
// but since some algorithms have already been implemented for EM_NORMALIZED mode, currently there is no support for default font metrics (ints)
|
||||||
// The coordinates will be normalized to the em size, i.e. 1 = 1 em
|
// The coordinates will be normalized to the em size, i.e. 1 = 1 em
|
||||||
const double scaleFactor = (1. / pFace->units_per_EM);
|
const double scaleFactor = (1. / face->units_per_EM);
|
||||||
SetupAtlasData(atlasResolution, pFace->height * scaleFactor, FontAtlasType::BITMAP);
|
SetupAtlasData(atlasResolution, face->height * scaleFactor, FontAtlasType::BITMAP);
|
||||||
|
|
||||||
size_t loadedGlyphs = 0;
|
size_t loadedGlyphs = 0;
|
||||||
FT_Error error = 0;
|
FT_Error error = 0;
|
||||||
@@ -59,10 +57,10 @@ namespace OpenVulkano::Scene
|
|||||||
Math::Vector2ui gridPos = { 0, 0 };
|
Math::Vector2ui gridPos = { 0, 0 };
|
||||||
for (uint32_t codepoint : chset)
|
for (uint32_t codepoint : chset)
|
||||||
{
|
{
|
||||||
error = FT_Load_Char(pFace, codepoint, FT_LOAD_RENDER);
|
error = FT_Load_Char(face.get(), codepoint, FT_LOAD_RENDER);
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
Logger::APP->error("FT_Load_Char for codepoint {} failed while reading from source {}", codepoint, sourceName);
|
Logger::APP->error("FT_Load_Char for codepoint {} has failed. {}", codepoint, GetFreetypeErrorDescription(error));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,20 +9,19 @@
|
|||||||
#define STBI_MSC_SECURE_CRT
|
#define STBI_MSC_SECURE_CRT
|
||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
#include <stb_image_write.h>
|
#include <stb_image_write.h>
|
||||||
#include <ft2build.h>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
namespace OpenVulkano::Scene
|
namespace OpenVulkano::Scene
|
||||||
{
|
{
|
||||||
std::pair<FontAtlasGeneratorBase::FT_LIB_REC, FontAtlasGeneratorBase::FT_FACE_REC>
|
std::pair<FtLibraryRecPtr, FtFaceRecPtr>
|
||||||
FontAtlasGeneratorBase::InitFreetype(const std::variant<std::string, Array<char>>& source)
|
FontAtlasGeneratorBase::InitFreetype(const std::variant<std::string, Array<char>>& source)
|
||||||
{
|
{
|
||||||
FT_Library library;
|
FT_Library library;
|
||||||
auto error = FT_Init_FreeType(&library);
|
auto error = FT_Init_FreeType(&library);
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Could not initalize freetype library\n");
|
throw std::runtime_error(fmt::format("Could not initalize freetype library. {}", GetFreetypeErrorDescription(error)));
|
||||||
}
|
}
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
if (std::holds_alternative<std::string>(source))
|
if (std::holds_alternative<std::string>(source))
|
||||||
@@ -40,7 +39,7 @@ namespace OpenVulkano::Scene
|
|||||||
}
|
}
|
||||||
else if (error)
|
else if (error)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Font file could not be opened or read or it's corrupted\n");
|
throw std::runtime_error(fmt::format("Font file could not be opened or read or it's corrupted. {}", GetFreetypeErrorDescription(error)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// some fancy font without unicode charmap
|
// some fancy font without unicode charmap
|
||||||
@@ -48,9 +47,17 @@ namespace OpenVulkano::Scene
|
|||||||
{
|
{
|
||||||
throw std::runtime_error("Selected font doesn't contain unicode charmap");
|
throw std::runtime_error("Selected font doesn't contain unicode charmap");
|
||||||
}
|
}
|
||||||
return std::make_pair(FT_LIB_REC(library), FT_FACE_REC(face));
|
return { FtLibraryRecPtr(library), FtFaceRecPtr(face) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string FontAtlasGeneratorBase::GetFreetypeErrorDescription(FT_Error error)
|
||||||
|
{
|
||||||
|
if (const char* s = FT_Error_String(error))
|
||||||
|
{
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return fmt::format("Error code is {}", error);
|
||||||
|
}
|
||||||
|
|
||||||
void FontAtlasGeneratorBase::SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile) const
|
void FontAtlasGeneratorBase::SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile) const
|
||||||
{
|
{
|
||||||
@@ -81,82 +88,75 @@ namespace OpenVulkano::Scene
|
|||||||
fs.write(reinterpret_cast<const char*>(&packedFlag), sizeof(uint32_t));
|
fs.write(reinterpret_cast<const char*>(&packedFlag), sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontAtlasGeneratorBase::SavePng(const std::string& output) const
|
void FontAtlasGeneratorBase::SavePng(std::string output) const
|
||||||
{
|
{
|
||||||
stbi_flip_vertically_on_write(1);
|
stbi_flip_vertically_on_write(1);
|
||||||
if (std::filesystem::path(output).extension() == ".png")
|
if (std::filesystem::path(output).extension() != ".png")
|
||||||
{
|
{
|
||||||
stbi_write_png(output.c_str(), m_atlasData->img->resolution.x, m_atlasData->img->resolution.y, m_channelsCount, m_atlasData->img->data.Data(),
|
output += ".png";
|
||||||
m_channelsCount * m_atlasData->img->resolution.x);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stbi_write_png((output + ".png").c_str(), m_atlasData->img->resolution.x, m_atlasData->img->resolution.y,
|
|
||||||
m_channelsCount, m_atlasData->img->data.Data(), m_channelsCount * m_atlasData->img->resolution.x);
|
|
||||||
}
|
}
|
||||||
|
stbi_write_png(output.c_str(), m_atlasData->img->resolution.x, m_atlasData->img->resolution.y, m_channelsCount,
|
||||||
|
m_atlasData->img->data.Data(), m_channelsCount * m_atlasData->img->resolution.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontAtlasGeneratorBase::SetupAtlasData(Math::Vector2ui textureResolution, double lineHeight,
|
void FontAtlasGeneratorBase::SetupAtlasData(Math::Vector2ui textureResolution, double lineHeight,
|
||||||
FontAtlasType::Type atlasType)
|
FontAtlasType::Type atlasType)
|
||||||
{
|
{
|
||||||
// generate texture
|
// generate texture
|
||||||
|
m_atlasData->img = std::make_unique<Image::Image>();
|
||||||
|
m_atlasData->img->resolution = Math::Vector3ui(textureResolution, 1);
|
||||||
if (m_channelsCount == 1)
|
if (m_channelsCount == 1)
|
||||||
{
|
{
|
||||||
m_atlasData->img = std::make_unique<Image::Image>();
|
|
||||||
m_atlasData->img->data = Array<uint8_t>(textureResolution.x * textureResolution.y);
|
m_atlasData->img->data = Array<uint8_t>(textureResolution.x * textureResolution.y);
|
||||||
m_atlasData->img->resolution = Math::Vector3ui(textureResolution, 1);
|
|
||||||
m_atlasData->img->dataFormat = OpenVulkano::DataFormat::R8_UNORM;
|
m_atlasData->img->dataFormat = OpenVulkano::DataFormat::R8_UNORM;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_atlasData->img = std::make_unique<Image::Image>();
|
|
||||||
// RGBA
|
// RGBA
|
||||||
m_atlasData->img->data = Array<uint8_t>(textureResolution.x * textureResolution.y * 4);
|
m_atlasData->img->data = Array<uint8_t>(textureResolution.x * textureResolution.y * 4);
|
||||||
m_atlasData->img->resolution = Math::Vector3ui(textureResolution, 1);
|
|
||||||
m_atlasData->img->dataFormat = OpenVulkano::DataFormat::R8G8B8A8_UNORM;
|
m_atlasData->img->dataFormat = OpenVulkano::DataFormat::R8G8B8A8_UNORM;
|
||||||
}
|
}
|
||||||
m_atlasData->texture.resolution = m_atlasData->img->resolution;
|
m_atlasData->texture.resolution = m_atlasData->img->resolution;
|
||||||
m_atlasData->texture.textureBuffer = m_atlasData->img->data.Data();
|
m_atlasData->texture.textureBuffer = m_atlasData->img->data.Data();
|
||||||
m_atlasData->texture.format = m_atlasData->img->dataFormat;
|
m_atlasData->texture.format = m_atlasData->img->dataFormat;
|
||||||
m_atlasData->texture.size = m_atlasData->img->data.Size();
|
m_atlasData->texture.size = m_atlasData->img->data.Size();
|
||||||
m_atlasData->texture.m_samplerConfig = &SamplerConfig::NEAREST;
|
|
||||||
m_atlasData->meta.atlasType = atlasType;
|
m_atlasData->meta.atlasType = atlasType;
|
||||||
m_atlasData->meta.lineHeight = lineHeight;
|
m_atlasData->meta.lineHeight = lineHeight;
|
||||||
|
if (atlasType == FontAtlasType::BITMAP)
|
||||||
|
{
|
||||||
|
m_atlasData->texture.m_samplerConfig = &SamplerConfig::NEAREST;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontAtlasGeneratorBase::SetGlyphData(GlyphInfo& info, Math::Vector2d bearing, Math::Vector2d size,
|
void FontAtlasGeneratorBase::SetGlyphData(GlyphInfo& info, Math::Vector2d bearing, Math::Vector2d size,
|
||||||
const Math::AABB& aabb, double advance)
|
const Math::AABB& aabb, double advance)
|
||||||
{
|
{
|
||||||
double bearingX = bearing.x;
|
const double bearingX = bearing.x;
|
||||||
double bearingY = bearing.y;
|
const double bearingY = bearing.y;
|
||||||
double w = size.x;
|
const double w = size.x;
|
||||||
double h = size.y;
|
const double h = size.y;
|
||||||
double l = aabb.min.x;
|
const double l = aabb.min.x;
|
||||||
double r = aabb.max.x;
|
const double r = aabb.max.x;
|
||||||
double t = aabb.max.y;
|
const double t = aabb.max.y;
|
||||||
double b = aabb.min.y;
|
const double b = aabb.min.y;
|
||||||
|
|
||||||
info.xyz[0].x = bearingX;
|
info.xyz[0].x = bearingX;
|
||||||
info.xyz[0].y = h - bearingY;
|
info.xyz[0].y = h - bearingY;
|
||||||
info.xyz[0].z = 0;
|
|
||||||
info.uv[0].x = l / m_atlasData->texture.resolution.x;
|
info.uv[0].x = l / m_atlasData->texture.resolution.x;
|
||||||
info.uv[0].y = b / m_atlasData->texture.resolution.y;
|
info.uv[0].y = b / m_atlasData->texture.resolution.y;
|
||||||
|
|
||||||
info.xyz[1].x = bearingX + w;
|
info.xyz[1].x = bearingX + w;
|
||||||
info.xyz[1].y = h - bearingY;
|
info.xyz[1].y = h - bearingY;
|
||||||
info.xyz[1].z = 0;
|
|
||||||
info.uv[1].x = r / m_atlasData->texture.resolution.x;
|
info.uv[1].x = r / m_atlasData->texture.resolution.x;
|
||||||
info.uv[1].y = b / m_atlasData->texture.resolution.y;
|
info.uv[1].y = b / m_atlasData->texture.resolution.y;
|
||||||
|
|
||||||
info.xyz[2].x = bearingX + w;
|
info.xyz[2].x = bearingX + w;
|
||||||
info.xyz[2].y = bearingY; //h - bearingY + h;
|
info.xyz[2].y = bearingY; //h - bearingY + h;
|
||||||
info.xyz[2].z = 0;
|
|
||||||
info.uv[2].x = r / m_atlasData->texture.resolution.x;
|
info.uv[2].x = r / m_atlasData->texture.resolution.x;
|
||||||
info.uv[2].y = t / m_atlasData->texture.resolution.y;
|
info.uv[2].y = t / m_atlasData->texture.resolution.y;
|
||||||
|
|
||||||
info.xyz[3].x = bearingX;
|
info.xyz[3].x = bearingX;
|
||||||
info.xyz[3].y = bearingY;
|
info.xyz[3].y = bearingY;
|
||||||
info.xyz[3].z = 0;
|
|
||||||
info.uv[3].x = l / m_atlasData->texture.resolution.x;
|
info.uv[3].x = l / m_atlasData->texture.resolution.x;
|
||||||
info.uv[3].y = t / m_atlasData->texture.resolution.y;
|
info.uv[3].y = t / m_atlasData->texture.resolution.y;
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
|
|
||||||
#include "IFontAtlasGenerator.hpp"
|
#include "IFontAtlasGenerator.hpp"
|
||||||
#include "Math/AABB.hpp"
|
#include "Math/AABB.hpp"
|
||||||
#include <ft2build.h>
|
#include "FreetypeHelper.hpp"
|
||||||
#include FT_FREETYPE_H
|
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
@@ -17,38 +16,19 @@ namespace OpenVulkano::Scene
|
|||||||
{
|
{
|
||||||
class FontAtlasGeneratorBase : public IFontAtlasGenerator
|
class FontAtlasGeneratorBase : public IFontAtlasGenerator
|
||||||
{
|
{
|
||||||
struct LibDeleter
|
|
||||||
{
|
|
||||||
void operator()(FT_Library lib)
|
|
||||||
{
|
|
||||||
FT_Done_FreeType(lib);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FaceDeleter
|
|
||||||
{
|
|
||||||
void operator()(FT_Face face)
|
|
||||||
{
|
|
||||||
FT_Done_Face(face);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using FT_LIB_REC = std::unique_ptr<FT_LibraryRec_, LibDeleter>;
|
|
||||||
using FT_FACE_REC = std::unique_ptr<FT_FaceRec_, FaceDeleter>;
|
|
||||||
|
|
||||||
FontAtlasGeneratorBase(int channelsCount) : m_channelsCount(channelsCount) {}
|
FontAtlasGeneratorBase(int channelsCount) : m_channelsCount(channelsCount) {}
|
||||||
void SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile = true) const override;
|
void SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile = true) const override;
|
||||||
std::shared_ptr<AtlasData> GetAtlasData() const { return m_atlasData; }
|
std::shared_ptr<AtlasData> GetAtlasData() const { return m_atlasData; }
|
||||||
int GetAtlasChannelsCount() const { return m_channelsCount; }
|
int GetAtlasChannelsCount() const { return m_channelsCount; }
|
||||||
|
|
||||||
static std::set<uint32_t> LoadAllGlyphs(const std::variant<std::string, Array<char>>& data);
|
static std::set<uint32_t> LoadAllGlyphs(const std::variant<std::string, Array<char>>& data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SavePng(const std::string& output) const;
|
void SavePng(std::string output) const;
|
||||||
void SetupAtlasData(Math::Vector2ui textureResolution, double lineHeight, FontAtlasType::Type atlasType);
|
void SetupAtlasData(Math::Vector2ui textureResolution, double lineHeight, FontAtlasType::Type atlasType);
|
||||||
void SetGlyphData(GlyphInfo& info, Math::Vector2d bearing, Math::Vector2d size, const Math::AABB& aabb, double advance);
|
void SetGlyphData(GlyphInfo& info, Math::Vector2d bearing, Math::Vector2d size, const Math::AABB& aabb, double advance);
|
||||||
static std::pair<FT_LIB_REC, FT_FACE_REC> InitFreetype(const std::variant<std::string, Array<char>>& source);
|
static std::string GetFreetypeErrorDescription(FT_Error error);
|
||||||
|
static std::pair<FtLibraryRecPtr, FtFaceRecPtr> InitFreetype(const std::variant<std::string, Array<char>>& source);
|
||||||
protected:
|
protected:
|
||||||
int m_channelsCount;
|
int m_channelsCount;
|
||||||
std::shared_ptr<AtlasData> m_atlasData;
|
std::shared_ptr<AtlasData> m_atlasData;
|
||||||
|
|||||||
28
openVulkanoCpp/Scene/FreetypeHelper.hpp
Normal file
28
openVulkanoCpp/Scene/FreetypeHelper.hpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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 <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace OpenVulkano::Scene
|
||||||
|
{
|
||||||
|
struct LibDeleter
|
||||||
|
{
|
||||||
|
void operator()(FT_Library lib) { FT_Done_FreeType(lib); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FaceDeleter
|
||||||
|
{
|
||||||
|
void operator()(FT_Face face) { FT_Done_Face(face); }
|
||||||
|
};
|
||||||
|
|
||||||
|
using FtLibraryRecPtr = std::unique_ptr<FT_LibraryRec_, LibDeleter>;
|
||||||
|
using FtFaceRecPtr = std::unique_ptr<FT_FaceRec_, FaceDeleter>;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#if __has_include("msdfgen.h")
|
#if __has_include("msdfgen.h")
|
||||||
|
|
||||||
#include "FontAtlasGenerator.hpp"
|
#include "SdfFontAtlasGenerator.hpp"
|
||||||
#include "Base/Logger.hpp"
|
#include "Base/Logger.hpp"
|
||||||
#include <msdfgen.h>
|
#include <msdfgen.h>
|
||||||
#include <msdfgen-ext.h>
|
#include <msdfgen-ext.h>
|
||||||
@@ -17,11 +17,11 @@ namespace OpenVulkano::Scene
|
|||||||
using namespace msdfgen;
|
using namespace msdfgen;
|
||||||
using namespace msdf_atlas;
|
using namespace msdf_atlas;
|
||||||
|
|
||||||
FontAtlasGeneratorConfig FontAtlasGeneratorConfig::sdfDefaultConfig = { 42, 1.0, 5 };
|
SdfFontAtlasGeneratorConfig SdfFontAtlasGeneratorConfig::sdfDefaultConfig = { 42, 1.0, 5 };
|
||||||
FontAtlasGeneratorConfig FontAtlasGeneratorConfig::msdfDefaultConfig = { 32, 1.0, 3 };
|
SdfFontAtlasGeneratorConfig SdfFontAtlasGeneratorConfig::msdfDefaultConfig = { 32, 1.0, 3 };
|
||||||
|
|
||||||
template<int Channels>
|
template<int Channels>
|
||||||
void FontAtlasGenerator<Channels>::GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
|
void SdfFontAtlasGenerator<Channels>::GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
|
||||||
const std::optional<std::string>& pngOutput)
|
const std::optional<std::string>& pngOutput)
|
||||||
{
|
{
|
||||||
FreetypeHandle* ft;
|
FreetypeHandle* ft;
|
||||||
@@ -32,14 +32,14 @@ namespace OpenVulkano::Scene
|
|||||||
Generate(ft, font, s, pngOutput);
|
Generate(ft, font, s, pngOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int Channels> FontAtlasGenerator<Channels>::FontAtlasGenerator() : FontAtlasGeneratorBase(Channels)
|
template<int Channels> SdfFontAtlasGenerator<Channels>::SdfFontAtlasGenerator() : FontAtlasGeneratorBase(Channels)
|
||||||
{
|
{
|
||||||
if constexpr (Channels == 1) m_config = FontAtlasGeneratorConfig::sdfDefaultConfig;
|
if constexpr (Channels == 1) m_config = SdfFontAtlasGeneratorConfig::sdfDefaultConfig;
|
||||||
else m_config = FontAtlasGeneratorConfig::msdfDefaultConfig;
|
else m_config = SdfFontAtlasGeneratorConfig::msdfDefaultConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int Channels>
|
template<int Channels>
|
||||||
void FontAtlasGenerator<Channels>::GenerateAtlas(const Array<char>& fontData, const std::set<uint32_t>& charset,
|
void SdfFontAtlasGenerator<Channels>::GenerateAtlas(const Array<char>& fontData, const std::set<uint32_t>& charset,
|
||||||
const std::optional<std::string>& pngOutput)
|
const std::optional<std::string>& pngOutput)
|
||||||
{
|
{
|
||||||
FreetypeHandle* ft;
|
FreetypeHandle* ft;
|
||||||
@@ -51,7 +51,7 @@ namespace OpenVulkano::Scene
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<int Channels>
|
template<int Channels>
|
||||||
void FontAtlasGenerator<Channels>::GenerateAtlas(const std::string& fontFile, const Charset& charset,
|
void SdfFontAtlasGenerator<Channels>::GenerateAtlas(const std::string& fontFile, const Charset& charset,
|
||||||
const std::optional<std::string>& pngOutput)
|
const std::optional<std::string>& pngOutput)
|
||||||
{
|
{
|
||||||
// TODO: dynamic atlas and add only those symbols which are not present yet in current atlas
|
// TODO: dynamic atlas and add only those symbols which are not present yet in current atlas
|
||||||
@@ -62,7 +62,7 @@ namespace OpenVulkano::Scene
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<int Channels>
|
template<int Channels>
|
||||||
void FontAtlasGenerator<Channels>::GenerateAtlas(const msdfgen::byte* fontData, int length,
|
void SdfFontAtlasGenerator<Channels>::GenerateAtlas(const msdfgen::byte* fontData, int length,
|
||||||
const Charset& charset,
|
const Charset& charset,
|
||||||
const std::optional<std::string>& pngOutput)
|
const std::optional<std::string>& pngOutput)
|
||||||
{
|
{
|
||||||
@@ -73,7 +73,7 @@ namespace OpenVulkano::Scene
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<int Channels>
|
template<int Channels>
|
||||||
void FontAtlasGenerator<Channels>::InitFreetypeFromFile(FreetypeHandle*& ft, FontHandle*& font,
|
void SdfFontAtlasGenerator<Channels>::InitFreetypeFromFile(FreetypeHandle*& ft, FontHandle*& font,
|
||||||
const std::string& fontFile)
|
const std::string& fontFile)
|
||||||
{
|
{
|
||||||
ft = initializeFreetype();
|
ft = initializeFreetype();
|
||||||
@@ -88,7 +88,7 @@ namespace OpenVulkano::Scene
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<int Channels>
|
template<int Channels>
|
||||||
void FontAtlasGenerator<Channels>::InitFreetypeFromBuffer(FreetypeHandle*& ft, FontHandle*& font,
|
void SdfFontAtlasGenerator<Channels>::InitFreetypeFromBuffer(FreetypeHandle*& ft, FontHandle*& font,
|
||||||
const msdfgen::byte* fontData, int length)
|
const msdfgen::byte* fontData, int length)
|
||||||
{
|
{
|
||||||
ft = initializeFreetype();
|
ft = initializeFreetype();
|
||||||
@@ -103,7 +103,7 @@ namespace OpenVulkano::Scene
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<int Channels>
|
template<int Channels>
|
||||||
void FontAtlasGenerator<Channels>::Generate(FreetypeHandle* ft, FontHandle* font, const Charset& chset,
|
void SdfFontAtlasGenerator<Channels>::Generate(FreetypeHandle* ft, FontHandle* font, const Charset& chset,
|
||||||
const std::optional<std::string>& pngOutput)
|
const std::optional<std::string>& pngOutput)
|
||||||
{
|
{
|
||||||
m_atlasData.reset(new AtlasData);
|
m_atlasData.reset(new AtlasData);
|
||||||
@@ -200,7 +200,7 @@ namespace OpenVulkano::Scene
|
|||||||
deinitializeFreetype(ft);
|
deinitializeFreetype(ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
template class FontAtlasGenerator<1>;
|
template class SdfFontAtlasGenerator<1>;
|
||||||
template class FontAtlasGenerator<3>;
|
template class SdfFontAtlasGenerator<3>;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -20,17 +20,17 @@
|
|||||||
namespace OpenVulkano::Scene
|
namespace OpenVulkano::Scene
|
||||||
{
|
{
|
||||||
|
|
||||||
struct FontAtlasGeneratorConfig
|
struct SdfFontAtlasGeneratorConfig
|
||||||
{
|
{
|
||||||
static FontAtlasGeneratorConfig sdfDefaultConfig;
|
static SdfFontAtlasGeneratorConfig sdfDefaultConfig;
|
||||||
static FontAtlasGeneratorConfig msdfDefaultConfig;
|
static SdfFontAtlasGeneratorConfig msdfDefaultConfig;
|
||||||
int glyphSize;
|
int glyphSize;
|
||||||
double miterLimit;
|
double miterLimit;
|
||||||
msdfgen::Range pixelRange;
|
msdfgen::Range pixelRange;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int Channels>
|
template<int Channels>
|
||||||
class FontAtlasGenerator : public FontAtlasGeneratorBase
|
class SdfFontAtlasGenerator final : public FontAtlasGeneratorBase
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using SdfGenerator = msdf_atlas::ImmediateAtlasGenerator<float, 1, msdf_atlas::sdfGenerator,
|
using SdfGenerator = msdf_atlas::ImmediateAtlasGenerator<float, 1, msdf_atlas::sdfGenerator,
|
||||||
@@ -39,9 +39,9 @@ namespace OpenVulkano::Scene
|
|||||||
msdf_atlas::BitmapAtlasStorage<msdfgen::byte, 3>>;
|
msdf_atlas::BitmapAtlasStorage<msdfgen::byte, 3>>;
|
||||||
public:
|
public:
|
||||||
using Generator = std::conditional<Channels == 1, SdfGenerator, MsdfGenerator>::type;
|
using Generator = std::conditional<Channels == 1, SdfGenerator, MsdfGenerator>::type;
|
||||||
using Config = FontAtlasGeneratorConfig;
|
using Config = SdfFontAtlasGeneratorConfig;
|
||||||
static constexpr int channelsCount = (Channels == 1 ? 1 : 4);
|
static constexpr int channelsCount = (Channels == 1 ? 1 : 4);
|
||||||
FontAtlasGenerator();
|
SdfFontAtlasGenerator();
|
||||||
void GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
|
void GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
|
||||||
const std::optional<std::string>& pngOutput = std::nullopt) override;
|
const std::optional<std::string>& pngOutput = std::nullopt) override;
|
||||||
void GenerateAtlas(const Array<char>& fontData, const std::set<uint32_t>& charset,
|
void GenerateAtlas(const Array<char>& fontData, const std::set<uint32_t>& charset,
|
||||||
@@ -62,7 +62,7 @@ namespace OpenVulkano::Scene
|
|||||||
private:
|
private:
|
||||||
Config m_config;
|
Config m_config;
|
||||||
};
|
};
|
||||||
using SdfFontAtlasGenerator = FontAtlasGenerator<1>;
|
using SdfFontAtlasGeneratorT = SdfFontAtlasGenerator<1>;
|
||||||
using MsdfFontAtlasGenerator = FontAtlasGenerator<3>;
|
using MsdfFontAtlasGenerator = SdfFontAtlasGenerator<3>;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -149,6 +149,10 @@ namespace OpenVulkano::Scene
|
|||||||
m_cfg = config;
|
m_cfg = config;
|
||||||
m_uniBuffer.Init(sizeof(TextConfig), &m_cfg, 3);
|
m_uniBuffer.Init(sizeof(TextConfig), &m_cfg, 3);
|
||||||
m_uniBuffer.binding.stageFlags = ShaderProgramType::FRAGMENT;
|
m_uniBuffer.binding.stageFlags = ShaderProgramType::FRAGMENT;
|
||||||
|
if (m_atlasData->meta.atlasType == FontAtlasType::BITMAP)
|
||||||
|
{
|
||||||
|
m_material.texture->m_samplerConfig = &SamplerConfig::NEAREST;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextDrawable::TextDrawable(const std::shared_ptr<AtlasData>& atlasData, const TextConfig& config)
|
TextDrawable::TextDrawable(const std::shared_ptr<AtlasData>& atlasData, const TextConfig& config)
|
||||||
@@ -268,10 +272,6 @@ namespace OpenVulkano::Scene
|
|||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
m_bbox.Init(bmin, bmax);
|
m_bbox.Init(bmin, bmax);
|
||||||
if (m_atlasData->meta.atlasType == FontAtlasType::BITMAP)
|
|
||||||
{
|
|
||||||
m_material.texture->m_samplerConfig = &SamplerConfig::NEAREST;
|
|
||||||
}
|
|
||||||
SimpleDrawable::Init(m_shader, &m_geometry, &m_material, &m_uniBuffer);
|
SimpleDrawable::Init(m_shader, &m_geometry, &m_material, &m_uniBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,12 +20,6 @@ layout(set = 3, binding = 0) uniform TextConfig
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// interesting results
|
|
||||||
//float distance = texture(texSampler, texCoord).r;
|
|
||||||
//float alpha = smoothstep(textConfig.threshold - textConfig.smoothing, textConfig.threshold + textConfig.smoothing, distance);
|
|
||||||
//outColor = vec4(textConfig.textColor) * alpha;
|
|
||||||
|
|
||||||
|
|
||||||
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(texSampler, texCoord).r);
|
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(texSampler, texCoord).r);
|
||||||
outColor = vec4(textConfig.textColor) * sampled;
|
outColor = vec4(textConfig.textColor) * sampled;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user