font rendering works now
parent
29a7923269
commit
b84d29ee9b
|
@ -1,7 +1,7 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
set(BLT_GRAPHICS_VERSION 1.0.7)
|
set(BLT_GRAPHICS_VERSION 1.0.8)
|
||||||
set(BLT_GRAPHICS_TEST_VERSION 0.0.1)
|
set(BLT_GRAPHICS_TEST_VERSION 0.0.1)
|
||||||
|
|
||||||
project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION})
|
project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION})
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace blt::gfx
|
||||||
struct bounded_t
|
struct bounded_t
|
||||||
{
|
{
|
||||||
font::glyph_t glyph;
|
font::glyph_t glyph;
|
||||||
// starting point
|
// starting point inside texture atlas
|
||||||
blt::vec2ui min;
|
blt::vec2ui min;
|
||||||
// ending point of the glyph, inside texture atlas
|
// ending point of the glyph, inside texture atlas
|
||||||
blt::vec2ui max;
|
blt::vec2ui max;
|
||||||
|
@ -49,18 +49,18 @@ namespace blt::gfx
|
||||||
public:
|
public:
|
||||||
explicit font_texture_atlas(blt::i32 dimensions);
|
explicit font_texture_atlas(blt::i32 dimensions);
|
||||||
|
|
||||||
added_font_results_t add_font(const font::font_file_t& file);
|
added_font_results_t add_font(const font::font_file_t& file, float size);
|
||||||
|
|
||||||
added_font_results_t add_font(const font::font_file_t& file, blt::u64 start);
|
added_font_results_t add_font(const font::font_file_t& file, blt::u64 start, float size);
|
||||||
|
|
||||||
bounded_t& get_glyph(blt::u64 c)
|
bounded_t& get_glyph(blt::u64 c, float size)
|
||||||
{ return glyphs.at(c); }
|
{ return glyphs.at(size).at(c); }
|
||||||
|
|
||||||
[[nodiscard]] const bounded_t& get_glyph(blt::u64 c) const
|
[[nodiscard]] const bounded_t& get_glyph(blt::u64 c, float size) const
|
||||||
{ return glyphs.at(c); }
|
{ return glyphs.at(size).at(c); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
blt::hashmap_t<blt::u64, bounded_t> glyphs;
|
blt::hashmap_t<float, blt::hashmap_t<blt::u64, bounded_t>> glyphs;
|
||||||
blt::u32 used_width = 0;
|
blt::u32 used_width = 0;
|
||||||
blt::u32 used_height = 0;
|
blt::u32 used_height = 0;
|
||||||
};
|
};
|
||||||
|
@ -90,11 +90,14 @@ namespace blt::gfx
|
||||||
{
|
{
|
||||||
if (!(size >= atlas.min_size && size <= atlas.max_size))
|
if (!(size >= atlas.min_size && size <= atlas.max_size))
|
||||||
continue;
|
continue;
|
||||||
if (atlas.min_char > c && atlas.max_char < c)
|
if (c >= atlas.min_char && c <= atlas.max_char)
|
||||||
return *atlas.atlas;
|
return *atlas.atlas;
|
||||||
}
|
}
|
||||||
throw std::runtime_error("Character not found inside atlases at this size");
|
throw std::runtime_error("Character not found inside atlases at this size");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] blt::i32 get_dimensions() const
|
||||||
|
{ return dimensions; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
blt::i32 dimensions;
|
blt::i32 dimensions;
|
||||||
|
@ -111,27 +114,89 @@ namespace blt::gfx
|
||||||
public:
|
public:
|
||||||
explicit compiled_text_t(font_generator_t& generator);
|
explicit compiled_text_t(font_generator_t& generator);
|
||||||
|
|
||||||
void change_text(std::string_view str);
|
void change_text(std::string_view str, float size);
|
||||||
|
|
||||||
|
compiled_text_t& setPosition(const blt::vec2f& pos)
|
||||||
|
{
|
||||||
|
position = pos;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
compiled_text_t& setScale(const blt::vec2f& s)
|
||||||
|
{
|
||||||
|
scale = s;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
compiled_text_t& setColor(const blt::vec4f& c)
|
||||||
|
{
|
||||||
|
color = c;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
compiled_text_t& setPosition(float x, float y)
|
||||||
|
{
|
||||||
|
position = {x, y};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
compiled_text_t& setScale(float x, float y)
|
||||||
|
{
|
||||||
|
scale = {x, y};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
compiled_text_t& setColor(float r, float g, float b, float a = 1)
|
||||||
|
{
|
||||||
|
color = {r, g, b, a};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
compiled_text_t& setZIndex(float s)
|
||||||
|
{
|
||||||
|
z_index = s;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const vec2f& getPosition() const
|
||||||
|
{ return position; }
|
||||||
|
|
||||||
|
[[nodiscard]] const vec2f& getScale() const
|
||||||
|
{ return scale; }
|
||||||
|
|
||||||
|
[[nodiscard]] const vec4f& getColor() const
|
||||||
|
{ return color; }
|
||||||
|
|
||||||
|
[[nodiscard]] float getZIndex() const
|
||||||
|
{ return z_index; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void draw();
|
void draw();
|
||||||
|
|
||||||
struct text_render_info_t
|
struct text_render_info_t
|
||||||
{
|
{
|
||||||
vertex_array_t vao{};
|
font_texture_atlas* texture = nullptr;
|
||||||
font_texture_atlas* texture{};
|
blt::size_t render_start = 0;
|
||||||
blt::size_t render_count = 0;
|
blt::size_t render_count = 0;
|
||||||
|
|
||||||
text_render_info_t() = default;
|
text_render_info_t(font_texture_atlas* texture, size_t renderStart, size_t renderCount):
|
||||||
|
texture(texture), render_start(renderStart), render_count(renderCount)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
font_generator_t& generator;
|
font_generator_t& generator;
|
||||||
std::vector<std::unique_ptr<text_render_info_t>> renders;
|
vertex_array_t vao{};
|
||||||
|
std::vector<text_render_info_t> renders;
|
||||||
|
blt::vec2f position;
|
||||||
|
blt::vec2f scale = {1, 1};
|
||||||
|
blt::vec4 color = blt::make_color(1, 1, 1);
|
||||||
|
float z_index = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit font_renderer_t();
|
explicit font_renderer_t();
|
||||||
|
|
||||||
|
void create_default(blt::i32 dimensions = 0);
|
||||||
void create(const std::vector<float>& generated_font_sizes, blt::i32 dimensions = 0);
|
void create(const std::vector<float>& generated_font_sizes, blt::i32 dimensions = 0);
|
||||||
|
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
@ -141,9 +206,15 @@ namespace blt::gfx
|
||||||
generator->add_font(file);
|
generator->add_font(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
compiled_text_t* create_text(std::string_view str);
|
void add_default_font(std::string_view path);
|
||||||
|
|
||||||
|
void add_default_font(const blt::u8* data, blt::size_t size, bool compressed = false);
|
||||||
|
|
||||||
|
compiled_text_t* create_text(std::string_view str, float size);
|
||||||
|
|
||||||
void destroy_text(compiled_text_t* text);
|
void destroy_text(compiled_text_t* text);
|
||||||
|
|
||||||
|
void render();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<font_generator_t> generator;
|
std::unique_ptr<font_generator_t> generator;
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#include <string>
|
#include <string>
|
||||||
const std::string shader_2d_font_frag = R"("
|
const std::string shader_2d_font_frag = R"("
|
||||||
#version 300 es
|
#version 300 es
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
|
|
||||||
layout (location = 0) out vec4 FragColor;
|
layout (location = 0) out vec4 FragColor;
|
||||||
in vec2 uv;
|
in vec2 uv;
|
||||||
|
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
uniform vec4 color;
|
uniform vec4 color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
FragColor = texture(tex, uv).r * color;
|
FragColor = texture(tex, uv).r * color;
|
||||||
}
|
if (FragColor.a < 0.2)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
")";
|
")";
|
||||||
#endif
|
#endif
|
|
@ -18,9 +18,10 @@ layout (std140) uniform GlobalMatrices
|
||||||
};
|
};
|
||||||
|
|
||||||
uniform float z_index;
|
uniform float z_index;
|
||||||
|
uniform mat4 transform;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = ovm * vec4(vertex.xy, z_index, 1.0);
|
gl_Position = ovm * transform * vec4(vertex.xy, z_index, 1.0);
|
||||||
uv = vertex.zw;
|
uv = vertex.zw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,18 +25,27 @@
|
||||||
namespace blt::gfx
|
namespace blt::gfx
|
||||||
{
|
{
|
||||||
font_texture_atlas::font_texture_atlas(blt::i32 dimensions): texture_gl2D(dimensions, dimensions, GL_R8)
|
font_texture_atlas::font_texture_atlas(blt::i32 dimensions): texture_gl2D(dimensions, dimensions, GL_R8)
|
||||||
{}
|
|
||||||
|
|
||||||
font_texture_atlas::added_font_results_t font_texture_atlas::add_font(const font::font_file_t& file)
|
|
||||||
{
|
{
|
||||||
return add_font(file, file.character_min_index);
|
bind();
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
font_texture_atlas::added_font_results_t font_texture_atlas::add_font(const font::font_file_t& file, blt::u64 start)
|
font_texture_atlas::added_font_results_t font_texture_atlas::add_font(const font::font_file_t& file, float size)
|
||||||
|
{
|
||||||
|
return add_font(file, file.character_min_index, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
font_texture_atlas::added_font_results_t font_texture_atlas::add_font(const font::font_file_t& file, blt::u64 start, float size)
|
||||||
{
|
{
|
||||||
blt::u32 max_height = 0;
|
blt::u32 max_height = 0;
|
||||||
blt::u64 min_index_used = file.character_max_index;
|
blt::u64 min_index_used = file.character_max_index;
|
||||||
blt::u64 max_index_used = start;
|
blt::u64 max_index_used = start;
|
||||||
|
file.font.set_pixel_sizes(0, static_cast<blt::u32>(size));
|
||||||
|
|
||||||
|
const blt::u32 padding = 2;
|
||||||
|
|
||||||
for (auto i = start; i < file.character_max_index; i++)
|
for (auto i = start; i < file.character_max_index; i++)
|
||||||
{
|
{
|
||||||
// returns an empty optional if there is no error code
|
// returns an empty optional if there is no error code
|
||||||
|
@ -46,10 +55,14 @@ namespace blt::gfx
|
||||||
|
|
||||||
auto width = face->glyph->bitmap.width;
|
auto width = face->glyph->bitmap.width;
|
||||||
auto height = face->glyph->bitmap.rows;
|
auto height = face->glyph->bitmap.rows;
|
||||||
max_height = std::max(max_height, height);
|
|
||||||
|
auto texture_width = width + padding;
|
||||||
|
auto texture_height = height + padding;
|
||||||
|
|
||||||
|
max_height = std::max(max_height, texture_height);
|
||||||
|
|
||||||
// if adding this width overflows, we need to move to the next row.
|
// if adding this width overflows, we need to move to the next row.
|
||||||
if (used_width + width > static_cast<blt::u32>(getWidth()))
|
if (used_width + texture_width > static_cast<blt::u32>(getWidth()))
|
||||||
{
|
{
|
||||||
used_height += max_height;
|
used_height += max_height;
|
||||||
max_height = 0;
|
max_height = 0;
|
||||||
|
@ -66,14 +79,14 @@ namespace blt::gfx
|
||||||
auto begin_height = used_height;
|
auto begin_height = used_height;
|
||||||
auto end_width = used_width + width;
|
auto end_width = used_width + width;
|
||||||
auto end_height = used_height + height;
|
auto end_height = used_height + height;
|
||||||
used_width += width;
|
used_width += texture_width;
|
||||||
|
|
||||||
// BLT_TRACE("%d %d %d %d", begin_width, begin_height, width, height);
|
// BLT_TRACE("%d %d %d %d", begin_width, begin_height, width, height);
|
||||||
// upload the texture
|
// upload the texture
|
||||||
upload(face->glyph->bitmap.buffer, GL_RED, 0, static_cast<blt::i32>(begin_width), static_cast<blt::i32>(begin_height),
|
upload(face->glyph->bitmap.buffer, GL_RED, 0, static_cast<blt::i32>(begin_width), static_cast<blt::i32>(begin_height),
|
||||||
static_cast<blt::i32>(width), static_cast<blt::i32>(height), GL_UNSIGNED_BYTE);
|
static_cast<blt::i32>(width), static_cast<blt::i32>(height), GL_UNSIGNED_BYTE);
|
||||||
|
|
||||||
glyphs.insert(std::pair{i, bounded_t{
|
glyphs[size].insert(std::pair{i, bounded_t{
|
||||||
font::glyph_t{
|
font::glyph_t{
|
||||||
{width, height},
|
{width, height},
|
||||||
{face->glyph->bitmap_left, face->glyph->bitmap_top},
|
{face->glyph->bitmap_left, face->glyph->bitmap_top},
|
||||||
|
@ -81,6 +94,8 @@ namespace blt::gfx
|
||||||
{begin_width, begin_height}, {end_width, end_height}}
|
{begin_width, begin_height}, {end_width, end_height}}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
bind();
|
||||||
|
generateMipmaps();
|
||||||
return {-1ul, min_index_used, max_index_used};
|
return {-1ul, min_index_used, max_index_used};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +113,6 @@ namespace blt::gfx
|
||||||
min_size = std::min(size, min_size);
|
min_size = std::min(size, min_size);
|
||||||
max_size = std::max(size, max_size);
|
max_size = std::max(size, max_size);
|
||||||
auto& vec = atlases;
|
auto& vec = atlases;
|
||||||
file.font.set_pixel_sizes(0, static_cast<blt::u32>(size));
|
|
||||||
|
|
||||||
if (vec.empty())
|
if (vec.empty())
|
||||||
vec.emplace_back(std::make_unique<font_texture_atlas>(dimensions), min_size, max_size, file.character_min_index, 0);
|
vec.emplace_back(std::make_unique<font_texture_atlas>(dimensions), min_size, max_size, file.character_min_index, 0);
|
||||||
|
@ -106,15 +120,17 @@ namespace blt::gfx
|
||||||
blt::u64 start_index = file.character_min_index;
|
blt::u64 start_index = file.character_min_index;
|
||||||
while (start_index != -1ul)
|
while (start_index != -1ul)
|
||||||
{
|
{
|
||||||
auto results = vec.back().atlas->add_font(file, start_index);
|
auto results = vec.back().atlas->add_font(file, start_index, size);
|
||||||
vec.back().min_char = results.min_index_used;
|
vec.back().min_char = results.min_index_used;
|
||||||
vec.back().max_char = results.max_index_used;
|
vec.back().max_char = results.max_index_used;
|
||||||
vec.back().min_size = min_size;
|
vec.back().min_size = min_size;
|
||||||
vec.back().max_size = max_size;
|
vec.back().max_size = max_size;
|
||||||
min_size = size;
|
|
||||||
max_size = size;
|
|
||||||
if (results.last_inserted_index != -1ul)
|
if (results.last_inserted_index != -1ul)
|
||||||
|
{
|
||||||
vec.emplace_back(std::make_unique<font_texture_atlas>(dimensions), min_size, max_size, start_index, 0);
|
vec.emplace_back(std::make_unique<font_texture_atlas>(dimensions), min_size, max_size, start_index, 0);
|
||||||
|
min_size = size;
|
||||||
|
max_size = size;
|
||||||
|
}
|
||||||
start_index = results.last_inserted_index;
|
start_index = results.last_inserted_index;
|
||||||
// BLT_INFO("%f, %ld", size, start_index);
|
// BLT_INFO("%f, %ld", size, start_index);
|
||||||
}
|
}
|
||||||
|
@ -126,12 +142,13 @@ namespace blt::gfx
|
||||||
extern float square_vertices[20];
|
extern float square_vertices[20];
|
||||||
extern const unsigned int square_indices[6];
|
extern const unsigned int square_indices[6];
|
||||||
|
|
||||||
font_renderer_t::font_renderer_t()
|
font_renderer_t::font_renderer_t() = default;
|
||||||
{}
|
|
||||||
|
|
||||||
void font_renderer_t::create(const std::vector<float>& generated_font_sizes, blt::i32 dimensions)
|
void font_renderer_t::create(const std::vector<float>& generated_font_sizes, blt::i32 dimensions)
|
||||||
{
|
{
|
||||||
font_shader = shader_t::make_unique(shader_2d_font_vert, shader_2d_font_frag);
|
font_shader = shader_t::make_unique(shader_2d_font_vert, shader_2d_font_frag);
|
||||||
|
font_shader->bind();
|
||||||
|
font_shader->bindAttribute(0, "vertex");
|
||||||
font::create();
|
font::create();
|
||||||
if (dimensions == 0)
|
if (dimensions == 0)
|
||||||
{
|
{
|
||||||
|
@ -145,11 +162,19 @@ namespace blt::gfx
|
||||||
|
|
||||||
void font_renderer_t::cleanup()
|
void font_renderer_t::cleanup()
|
||||||
{
|
{
|
||||||
|
for (auto& n : added_texts)
|
||||||
|
n = nullptr;
|
||||||
|
for (auto& c : cached_text_objects)
|
||||||
|
c = nullptr;
|
||||||
|
added_texts.clear();
|
||||||
|
cached_text_objects.clear();
|
||||||
|
text_ptr_to_index.clear();
|
||||||
|
font_shader = nullptr;
|
||||||
generator = nullptr;
|
generator = nullptr;
|
||||||
blt::gfx::font::cleanup();
|
blt::gfx::font::cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
font_renderer_t::compiled_text_t* font_renderer_t::create_text(std::string_view str)
|
font_renderer_t::compiled_text_t* font_renderer_t::create_text(std::string_view str, float size)
|
||||||
{
|
{
|
||||||
std::unique_ptr<font_renderer_t::compiled_text_t> ptr;
|
std::unique_ptr<font_renderer_t::compiled_text_t> ptr;
|
||||||
if (!cached_text_objects.empty())
|
if (!cached_text_objects.empty())
|
||||||
|
@ -160,7 +185,7 @@ namespace blt::gfx
|
||||||
{
|
{
|
||||||
ptr = std::make_unique<compiled_text_t>(*generator);
|
ptr = std::make_unique<compiled_text_t>(*generator);
|
||||||
}
|
}
|
||||||
ptr->change_text(str);
|
ptr->change_text(str, size);
|
||||||
auto index = added_texts.size();
|
auto index = added_texts.size();
|
||||||
added_texts.push_back(std::move(ptr));
|
added_texts.push_back(std::move(ptr));
|
||||||
text_ptr_to_index[added_texts.back().get()] = index;
|
text_ptr_to_index[added_texts.back().get()] = index;
|
||||||
|
@ -176,21 +201,108 @@ namespace blt::gfx
|
||||||
added_texts.erase(added_texts.begin() + static_cast<blt::ptrdiff_t>(index));
|
added_texts.erase(added_texts.begin() + static_cast<blt::ptrdiff_t>(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void font_renderer_t::compiled_text_t::change_text(std::string_view str)
|
void font_renderer_t::render()
|
||||||
|
{
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
font_shader->bind();
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
for (auto& text : added_texts)
|
||||||
|
{
|
||||||
|
blt::mat4x4 transform;
|
||||||
|
transform.translate(text->position);
|
||||||
|
transform.scale(text->scale);
|
||||||
|
font_shader->setMatrix("transform", transform);
|
||||||
|
font_shader->setFloat("z_index", text->z_index);
|
||||||
|
font_shader->setVec4("color", text->color);
|
||||||
|
text->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void font_renderer_t::create_default(blt::i32 dimensions)
|
||||||
|
{
|
||||||
|
create({9, 11, 12, 13, 14, 16, 18, 24, 32, 36, 40, 48, 52, 64, 72, 96, 106}, dimensions);
|
||||||
|
|
||||||
|
add_default_font(reinterpret_cast<const blt::u8*>(font::default_font_compressed_data), font::default_font_compressed_size, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void font_renderer_t::add_default_font(std::string_view path)
|
||||||
|
{
|
||||||
|
font::font_face_t default_font_face{path};
|
||||||
|
font::font_file_t default_font{default_font_face, 0, 128};
|
||||||
|
add_font(default_font);
|
||||||
|
}
|
||||||
|
|
||||||
|
void font_renderer_t::add_default_font(const blt::u8* data, blt::size_t size, bool compressed)
|
||||||
|
{
|
||||||
|
font::font_face_t default_font_face{data, size, compressed};
|
||||||
|
font::font_file_t default_font{default_font_face, 0, 128};
|
||||||
|
add_font(default_font);
|
||||||
|
}
|
||||||
|
|
||||||
|
void font_renderer_t::compiled_text_t::change_text(std::string_view str, float size)
|
||||||
{
|
{
|
||||||
static std::vector<float> vertices;
|
static std::vector<float> vertices;
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
|
renders.clear();
|
||||||
|
|
||||||
|
font_texture_atlas* last_texture = nullptr;
|
||||||
|
blt::size_t draw_start = 0;
|
||||||
|
blt::size_t draw_count = 0;
|
||||||
|
|
||||||
|
float x = 0;
|
||||||
|
// TODO: parker UTF8
|
||||||
for (const auto& c : str)
|
for (const auto& c : str)
|
||||||
{
|
{
|
||||||
|
auto& texture = generator.get_texture(size, c);
|
||||||
|
|
||||||
|
if (last_texture == nullptr)
|
||||||
|
last_texture = &texture;
|
||||||
|
else if (last_texture != &texture)
|
||||||
|
{
|
||||||
|
renders.emplace_back(last_texture, draw_start, draw_count);
|
||||||
|
draw_start += draw_count;
|
||||||
|
draw_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& ch = texture.get_glyph(c, size);
|
||||||
|
auto dims = static_cast<float>(generator.get_dimensions());
|
||||||
|
|
||||||
|
float x_pos = x + static_cast<float>(ch.glyph.bearing.x());
|
||||||
|
float y_pos = -static_cast<float>(ch.glyph.size.y() - ch.glyph.bearing.y());
|
||||||
|
|
||||||
|
auto w = static_cast<float>(ch.glyph.size.x());
|
||||||
|
auto h = static_cast<float>(ch.glyph.size.y());
|
||||||
|
|
||||||
|
auto texture_min_x = static_cast<float>(ch.min.x()) / dims;
|
||||||
|
auto texture_min_y = static_cast<float>(ch.min.y()) / dims;
|
||||||
|
auto texture_max_x = static_cast<float>(ch.max.x()) / dims;
|
||||||
|
auto texture_max_y = static_cast<float>(ch.max.y()) / dims;
|
||||||
|
|
||||||
|
// BLT_TRACE("%c: %f | xy[%f %f] wh[%f %f] | min[%f %f] max[%f %f] |", c, x, x_pos, y_pos, w, h, texture_min_x, texture_min_y, texture_max_x, texture_max_y);
|
||||||
|
|
||||||
|
std::array<float, 6 * 4> local_vert = {
|
||||||
|
x_pos, y_pos + h, texture_min_x, texture_min_y,
|
||||||
|
x_pos, y_pos, texture_min_x, texture_max_y,
|
||||||
|
x_pos + w, y_pos, texture_max_x, texture_max_y,
|
||||||
|
|
||||||
|
x_pos, y_pos + h, texture_min_x, texture_min_y,
|
||||||
|
x_pos + w, y_pos, texture_max_x, texture_max_y,
|
||||||
|
x_pos + w, y_pos + h, texture_max_x, texture_min_y
|
||||||
|
};
|
||||||
|
vertices.insert(vertices.end(), local_vert.begin(), local_vert.end());
|
||||||
|
draw_count += 6;
|
||||||
|
x += static_cast<float>(ch.glyph.advance >> 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BLT_TRACE("size: %ld %ld %ld", draw_count, vertices.size(), vertices.size() / 4);
|
||||||
|
|
||||||
|
renders.emplace_back(last_texture, draw_start, draw_count);
|
||||||
|
vao.getBuffer(0).update(static_cast<long>(vertices.size() * sizeof(float)), vertices.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
font_renderer_t::compiled_text_t::compiled_text_t(font_generator_t& generator): generator(generator)
|
font_renderer_t::compiled_text_t::compiled_text_t(font_generator_t& generator): generator(generator)
|
||||||
{
|
{
|
||||||
renders.emplace_back();
|
|
||||||
auto& vao = renders.back()->vao;
|
|
||||||
auto vbo = vertex_array_t::make_vbo({});
|
auto vbo = vertex_array_t::make_vbo({});
|
||||||
vbo->vbo.create();
|
vbo->vbo.create();
|
||||||
vbo->vbo.bind();
|
vbo->vbo.bind();
|
||||||
|
@ -201,6 +313,17 @@ namespace blt::gfx
|
||||||
|
|
||||||
void font_renderer_t::compiled_text_t::draw()
|
void font_renderer_t::compiled_text_t::draw()
|
||||||
{
|
{
|
||||||
|
font_texture_atlas* last_texture = nullptr;
|
||||||
|
vao.bind();
|
||||||
|
for (const auto& render : renders)
|
||||||
|
{
|
||||||
|
if (last_texture != render.texture)
|
||||||
|
{
|
||||||
|
last_texture = render.texture;
|
||||||
|
render.texture->bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, static_cast<int>(render.render_start), static_cast<int>(render.render_count));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue