font rendering. rotation and immediate mode
parent
1afe267163
commit
0a0b87fc55
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 3.25)
|
||||
include(FetchContent)
|
||||
|
||||
set(BLT_GRAPHICS_VERSION 1.0.12)
|
||||
set(BLT_GRAPHICS_VERSION 1.1.0)
|
||||
set(BLT_GRAPHICS_TEST_VERSION 0.0.1)
|
||||
|
||||
project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION})
|
||||
|
|
|
@ -119,17 +119,98 @@ namespace blt::gfx
|
|||
class font_renderer_t
|
||||
{
|
||||
public:
|
||||
struct render_context
|
||||
static constexpr blt::vec2f DEFAULT_SCALE{1, 1};
|
||||
static constexpr blt::vec4 DEFAULT_COLOR = blt::make_color(0.8, 0.8, 0.8);
|
||||
|
||||
struct render_context_t
|
||||
{
|
||||
blt::vec2f position, bounds;
|
||||
blt::vec2f scale;
|
||||
blt::vec4 color;
|
||||
blt::vec4 color = DEFAULT_COLOR;
|
||||
float z_index = 0;
|
||||
float current_size = 0;
|
||||
float rotation = 0;
|
||||
|
||||
explicit render_context_t(float current_size): current_size(current_size)
|
||||
{}
|
||||
|
||||
render_context_t& setPosition(float x, float y)
|
||||
{
|
||||
position = {x, y};
|
||||
return *this;
|
||||
}
|
||||
|
||||
render_context_t& setPosition(const blt::vec2f& new_position)
|
||||
{
|
||||
position = new_position;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render_context_t& setRotation(float r)
|
||||
{
|
||||
rotation = r;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render_context_t& setColor(const blt::vec4f& new_color)
|
||||
{
|
||||
color = new_color;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render_context_t& setColor(float r, float g, float b, float a = 1)
|
||||
{
|
||||
color = {r, g, b, a};
|
||||
return *this;
|
||||
}
|
||||
|
||||
render_context_t& setBounds(const blt::vec2f& new_bounds)
|
||||
{
|
||||
bounds = new_bounds;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render_context_t& setBounds(float width, float height)
|
||||
{
|
||||
return setBounds({width, height});
|
||||
}
|
||||
|
||||
render_context_t& setUnrestrictedBounds()
|
||||
{
|
||||
bounds = {};
|
||||
return *this;
|
||||
}
|
||||
|
||||
render_context_t& setSize(const float new_scale)
|
||||
{
|
||||
current_size = new_scale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render_context_t& setZIndex(float new_z_index)
|
||||
{
|
||||
z_index = new_z_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] const vec2f& getPosition() const
|
||||
{ return position; }
|
||||
|
||||
[[nodiscard]] const vec2f& getBounds() const
|
||||
{ return bounds; }
|
||||
|
||||
[[nodiscard]] float getSize() const
|
||||
{ return current_size; }
|
||||
|
||||
[[nodiscard]] float getRotation() const
|
||||
{ return rotation; }
|
||||
|
||||
[[nodiscard]] const vec4& getColor() const
|
||||
{ return color; }
|
||||
};
|
||||
|
||||
struct text_index_t
|
||||
{
|
||||
std::string text;
|
||||
float size;
|
||||
std::string font;
|
||||
|
||||
bool operator==(const text_index_t& rhs) const;
|
||||
|
@ -145,14 +226,28 @@ namespace blt::gfx
|
|||
|
||||
compiled_text_t& recompile();
|
||||
|
||||
compiled_text_t& setPosition(float x, float y)
|
||||
{
|
||||
position = {x, y};
|
||||
return *this;
|
||||
}
|
||||
|
||||
compiled_text_t& setPosition(const blt::vec2f& pos)
|
||||
{
|
||||
position = pos;
|
||||
return *this;
|
||||
}
|
||||
|
||||
compiled_text_t& setRotation(float r)
|
||||
{
|
||||
rotation = r;
|
||||
return *this;
|
||||
}
|
||||
|
||||
compiled_text_t& setBounds(const blt::vec2f& limit)
|
||||
{
|
||||
if (limit == bounds)
|
||||
return *this;
|
||||
bounds = limit;
|
||||
recompile();
|
||||
return *this;
|
||||
|
@ -175,12 +270,6 @@ namespace blt::gfx
|
|||
return *this;
|
||||
}
|
||||
|
||||
compiled_text_t& setPosition(float x, float y)
|
||||
{
|
||||
position = {x, y};
|
||||
return *this;
|
||||
}
|
||||
|
||||
compiled_text_t& setColor(float r, float g, float b, float a = 1)
|
||||
{
|
||||
color = {r, g, b, a};
|
||||
|
@ -189,9 +278,13 @@ namespace blt::gfx
|
|||
|
||||
compiled_text_t& setSize(float size)
|
||||
{
|
||||
if (current_size == size)
|
||||
return *this;
|
||||
current_size = size;
|
||||
scale = {size / generator.get_generated_size(), size / generator.get_generated_size()};
|
||||
recompile();
|
||||
// size only changes computation if there are bounds on the text.
|
||||
if (bounds.x() != 0 || bounds.y() != 0)
|
||||
recompile();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -216,9 +309,37 @@ namespace blt::gfx
|
|||
[[nodiscard]] float getZIndex() const
|
||||
{ return z_index; }
|
||||
|
||||
[[nodiscard]] float getRotation() const
|
||||
{ return rotation; }
|
||||
|
||||
void save_to(render_context_t& save)
|
||||
{
|
||||
save.position = position;
|
||||
save.bounds = bounds;
|
||||
save.color = color;
|
||||
save.z_index = z_index;
|
||||
save.current_size = current_size;
|
||||
save.rotation = rotation;
|
||||
}
|
||||
|
||||
void restore_from(const render_context_t& restore)
|
||||
{
|
||||
setPosition(restore.position);
|
||||
setBounds(restore.bounds);
|
||||
setColor(restore.color);
|
||||
setZIndex(restore.z_index);
|
||||
setSize(restore.current_size);
|
||||
setRotation(restore.rotation);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit compiled_text_t(font_generator_t& generator);
|
||||
|
||||
void bind() const
|
||||
{
|
||||
vao.bind();
|
||||
}
|
||||
|
||||
void draw();
|
||||
|
||||
struct text_render_info_t
|
||||
|
@ -237,10 +358,11 @@ namespace blt::gfx
|
|||
vertex_array_t vao{};
|
||||
std::vector<text_render_info_t> renders;
|
||||
blt::vec2f position, bounds;
|
||||
blt::vec2f scale = {1, 1};
|
||||
blt::vec4 color = blt::make_color(0.8, 0.8, 0.8);
|
||||
blt::vec2f scale = DEFAULT_SCALE;
|
||||
blt::vec4 color = DEFAULT_COLOR;
|
||||
float z_index = 0;
|
||||
float current_size = 0;
|
||||
float rotation = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -263,7 +385,7 @@ namespace blt::gfx
|
|||
|
||||
compiled_text_t* create_text(std::string_view str, float size, std::string_view font = "__default");
|
||||
|
||||
compiled_text_t* render_text(std::string_view str, float size, std::string_view font = "__default");
|
||||
render_context_t& render_text(std::string_view str, float size, std::string_view font = "__default");
|
||||
|
||||
void destroy_text(compiled_text_t* text);
|
||||
|
||||
|
@ -277,6 +399,7 @@ namespace blt::gfx
|
|||
|
||||
blt::hashmap_t<text_index_t, compiled_text_t*> rendered_strings;
|
||||
blt::hashmap_t<compiled_text_t*, text_index_t> text_ptr_to_text_index;
|
||||
blt::hashmap_t<compiled_text_t*, std::vector<render_context_t>> render_list;
|
||||
|
||||
blt::hashset_t<compiled_text_t*> last_rendered_strings;
|
||||
blt::hashset_t<compiled_text_t*> currently_rendered_strings;
|
||||
|
@ -304,7 +427,6 @@ struct std::hash<blt::gfx::font_renderer_t::text_index_t>
|
|||
{
|
||||
blt::size_t hash = 0;
|
||||
blt::gfx::detail::hash_combine(hash, std::hash<std::string>{}(key.text));
|
||||
blt::gfx::detail::hash_combine(hash, std::hash<float>{}(key.size));
|
||||
blt::gfx::detail::hash_combine(hash, std::hash<std::string>{}(key.font));
|
||||
|
||||
return hash;
|
||||
|
|
|
@ -201,28 +201,44 @@ namespace blt::gfx
|
|||
glActiveTexture(GL_TEXTURE0);
|
||||
for (auto [text, index] : text_ptr_to_index)
|
||||
{
|
||||
// stupid hack
|
||||
if (text_ptr_to_text_index.find(text) != text_ptr_to_text_index.end())
|
||||
continue;
|
||||
text->bind();
|
||||
blt::mat4x4 transform;
|
||||
transform.translate(text->position);
|
||||
transform.scale(text->scale);
|
||||
transform.rotateZ(blt::toRadians(text->rotation));
|
||||
font_shader->setMatrix("transform", transform);
|
||||
font_shader->setFloat("z_index", text->z_index);
|
||||
font_shader->setVec4("color", text->color);
|
||||
text->draw();
|
||||
}
|
||||
|
||||
for (auto& text : currently_rendered_strings)
|
||||
for (auto& [text, list] : render_list)
|
||||
{
|
||||
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();
|
||||
text->bind();
|
||||
render_context_t before{text->current_size};
|
||||
text->save_to(before);
|
||||
for (const auto& context : list)
|
||||
{
|
||||
text->restore_from(context);
|
||||
|
||||
blt::mat4x4 transform;
|
||||
transform.translate(text->position);
|
||||
transform.scale(text->scale);
|
||||
transform.rotateZ(blt::toRadians(text->rotation));
|
||||
font_shader->setMatrix("transform", transform);
|
||||
font_shader->setFloat("z_index", text->z_index);
|
||||
font_shader->setVec4("color", text->color);
|
||||
text->draw();
|
||||
}
|
||||
text->restore_from(before);
|
||||
|
||||
if (last_rendered_strings.find(text) != last_rendered_strings.end())
|
||||
last_rendered_strings.erase(text);
|
||||
}
|
||||
render_list.clear();
|
||||
|
||||
for (auto& text : last_rendered_strings)
|
||||
{
|
||||
|
@ -231,6 +247,7 @@ namespace blt::gfx
|
|||
cached_deallocated_text_objects.emplace_back(std::move(added_texts[text_ptr_to_index[text]]));
|
||||
text_ptr_to_index.erase(text);
|
||||
}
|
||||
last_rendered_strings.clear();
|
||||
|
||||
for (auto& text : currently_rendered_strings)
|
||||
last_rendered_strings.insert(text);
|
||||
|
@ -269,25 +286,32 @@ namespace blt::gfx
|
|||
return ptr;
|
||||
}
|
||||
|
||||
font_renderer_t::compiled_text_t* font_renderer_t::render_text(std::string_view str, float size, std::string_view font)
|
||||
font_renderer_t::render_context_t& font_renderer_t::render_text(std::string_view str, float size, std::string_view font)
|
||||
{
|
||||
auto str_iter = rendered_strings.find(text_index_t{std::string(str), size, std::string(font)});
|
||||
auto str_iter = rendered_strings.find(text_index_t{std::string(str), std::string(font)});
|
||||
compiled_text_t* ptr;
|
||||
if (str_iter != rendered_strings.end())
|
||||
{
|
||||
currently_rendered_strings.insert(str_iter->second);
|
||||
return str_iter->second;
|
||||
ptr = str_iter->second;
|
||||
currently_rendered_strings.insert(ptr);
|
||||
ptr->setSize(size);
|
||||
} else
|
||||
{
|
||||
auto index = added_texts.size();
|
||||
added_texts.emplace_back(allocate_text());
|
||||
ptr = added_texts.back().get();
|
||||
ptr->setText(str, size);
|
||||
|
||||
text_ptr_to_text_index[ptr] = text_index_t{std::string(str), std::string(font)};
|
||||
rendered_strings[text_index_t{std::string(str), std::string(font)}] = ptr;
|
||||
text_ptr_to_index[ptr] = index;
|
||||
|
||||
currently_rendered_strings.insert(ptr);
|
||||
}
|
||||
auto index = added_texts.size();
|
||||
added_texts.emplace_back(allocate_text());
|
||||
auto ptr = added_texts.back().get();
|
||||
ptr->setText(str, size);
|
||||
|
||||
text_ptr_to_text_index[ptr] = text_index_t{std::string(str), size, std::string(font)};
|
||||
rendered_strings[text_index_t{std::string(str), size, std::string(font)}] = ptr;
|
||||
text_ptr_to_index[ptr] = index;
|
||||
|
||||
currently_rendered_strings.insert(ptr);
|
||||
return ptr;
|
||||
auto& vec = render_list[ptr];
|
||||
vec.emplace_back(size);
|
||||
return vec.back();
|
||||
}
|
||||
|
||||
font_renderer_t::compiled_text_t& font_renderer_t::compiled_text_t::setText(std::string_view str, float size, std::string_view f)
|
||||
|
@ -315,7 +339,6 @@ namespace blt::gfx
|
|||
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)
|
||||
|
@ -415,7 +438,7 @@ namespace blt::gfx
|
|||
|
||||
bool font_renderer_t::text_index_t::operator==(const font_renderer_t::text_index_t& rhs) const
|
||||
{
|
||||
return text == rhs.text && blt::f_equal(size, rhs.size) && font == rhs.font;
|
||||
return text == rhs.text && font == rhs.font;
|
||||
}
|
||||
|
||||
bool font_renderer_t::text_index_t::operator!=(const font_renderer_t::text_index_t& rhs) const
|
||||
|
|
Loading…
Reference in New Issue