From 0a0b87fc5566211cb7375d9c1b361ba3e91a3545 Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Thu, 14 Nov 2024 16:01:53 -0500 Subject: [PATCH] font rendering. rotation and immediate mode --- CMakeLists.txt | 2 +- build_emscript.sh | 0 include/blt/gfx/renderer/font_renderer.h | 152 ++++++++++++++++++++--- resources/fonts/a.out | Bin src/blt/gfx/renderer/font_renderer.cpp | 71 +++++++---- 5 files changed, 185 insertions(+), 40 deletions(-) mode change 100755 => 100644 build_emscript.sh mode change 100755 => 100644 resources/fonts/a.out diff --git a/CMakeLists.txt b/CMakeLists.txt index 174acd7..cf5e4cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}) diff --git a/build_emscript.sh b/build_emscript.sh old mode 100755 new mode 100644 diff --git a/include/blt/gfx/renderer/font_renderer.h b/include/blt/gfx/renderer/font_renderer.h index 0816c57..fedc329 100644 --- a/include/blt/gfx/renderer/font_renderer.h +++ b/include/blt/gfx/renderer/font_renderer.h @@ -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; } @@ -215,10 +308,38 @@ 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 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 rendered_strings; blt::hashmap_t text_ptr_to_text_index; + blt::hashmap_t> render_list; blt::hashset_t last_rendered_strings; blt::hashset_t currently_rendered_strings; @@ -304,7 +427,6 @@ struct std::hash { blt::size_t hash = 0; blt::gfx::detail::hash_combine(hash, std::hash{}(key.text)); - blt::gfx::detail::hash_combine(hash, std::hash{}(key.size)); blt::gfx::detail::hash_combine(hash, std::hash{}(key.font)); return hash; diff --git a/resources/fonts/a.out b/resources/fonts/a.out old mode 100755 new mode 100644 diff --git a/src/blt/gfx/renderer/font_renderer.cpp b/src/blt/gfx/renderer/font_renderer.cpp index b5e4270..376f802 100644 --- a/src/blt/gfx/renderer/font_renderer.cpp +++ b/src/blt/gfx/renderer/font_renderer.cpp @@ -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