diff --git a/assets/hinted-RosaSans-Regular.ttf b/assets/hinted-RosaSans-Regular.ttf new file mode 100644 index 0000000..7435805 Binary files /dev/null and b/assets/hinted-RosaSans-Regular.ttf differ diff --git a/include/engine/flat_object.hpp b/include/engine/flat_object.hpp new file mode 100644 index 0000000..1192e5e --- /dev/null +++ b/include/engine/flat_object.hpp @@ -0,0 +1,62 @@ +/** + This file is a part of our_dick + Copyright (C) 2022 rexy712 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +#ifndef OUR_DICK_ENGINE_FLAT_OBJECT_HPP +#define OUR_DICK_ENGINE_FLAT_OBJECT_HPP + +#include "math/vec.hpp" + +namespace egn{ + + namespace flat{ + + class object_base + { + protected: + math::vec2f m_position; + math::vec2f m_scale; + float m_orientation; + + public: + object_base(void) = default; + object_base(const math::vec2f& position, float orientation = 0); + object_base(const object_base&) = default; + object_base(object_base&&) = default; + ~object_base(void) = default; + + object_base& operator=(const object_base&) = default; + object_base& operator=(object_base&&) = default; + + void translate(const math::vec2f& distance); + void rotate(float distance); + void scale(const math::vec2f& distance); + void look_at(const math::vec2f& target); + + void set_position(const math::vec2f& pos); + void set_orientation(float orient); + void set_scale(const math::vec2f& scale); + + const math::vec2f& position(void)const; + float orientation(void)const; + const math::vec2f& scale(void)const; + }; + } + +} + +#endif diff --git a/include/engine/font.hpp b/include/engine/font.hpp index b8dd357..278ed8d 100644 --- a/include/engine/font.hpp +++ b/include/engine/font.hpp @@ -24,6 +24,8 @@ #include #include #include //pair +#include +#include //min, max #include "graphics/texture.hpp" #include "config.hpp" @@ -31,7 +33,6 @@ namespace egn{ struct font_character{ - GLuint atlas_texture; math::vec2 atlas_offset; math::vec2 size; math::vec2 bearing; @@ -42,35 +43,34 @@ namespace egn{ float aspect_ratio(void)const; }; - class font + class font_atlas : public gfx::texture { + public: + using map_type = std::map; + private: - std::optional m_atlas; - std::map m_atlas_data; - size_t m_requested_width; - size_t m_requested_height; + map_type m_atlas_data; + size_t m_requested_width, m_requested_height; public: - font(void) = default; - font(gfx::texture&& tex, std::map&& metadata, size_t width, size_t height); - ~font(void) = default; + font_atlas(gfx::texture&& t, map_type&& map, size_t w, size_t h); + font_atlas(const font_atlas&) = default; + font_atlas(font_atlas&&) = default; + ~font_atlas(void) = default; + + font_atlas& operator=(const font_atlas&) = default; + font_atlas& operator=(font_atlas&&) = default; + + map_type& metadata(void); + const map_type& metadata(void)const; + map_type&& release_metadata(void); font_character& operator[](int character); - const font_character& operator[](int character)const; - gfx::texture release_atlas(void); - - gfx::texture& atlas(void); - const gfx::texture& atlas(void)const; - - std::map release_metadata(void); - - bool valid(void)const; - - math::vec2 size(void)const; + math::vec2 glyph_size(void)const; }; - class font_generator + class font { private: static inline bool s_initialized = false; @@ -78,25 +78,84 @@ namespace egn{ private: FT_Face m_face = nullptr; + int m_depth = 3; public: - font_generator(const char* file); - ~font_generator(void); + font(const char* file, int depth = 3); + ~font(void); + + template + font_atlas generate_atlas(size_t glyph_w, size_t glyph_h, Ts&&... ranges); - //params: - // start_codepoint: unicode character at which the atlas starts - // count: number of characters to make in the atlas - // glyph_width: requested pixel width of glyph - // glyph_height: requested pixel height of glyph - // atlas_width: requested pixel width of atlas - // atlas_height: requested pixel height of atlas - font generate_atlas(int start_codepoint, int count, size_t glyph_width, size_t glyph_height); std::optional generate_glyph(char character, int width, int height); + private: + using atlas_meta = std::tuple; + template + void generate_atlas_piece_(gfx::texture& atlas, font_atlas::map_type& metadata, math::vec2& target_pos, const atlas_meta& info, unsigned char* data_buffer, const std::pair& range, Ts&&... ranges); + void generate_atlas_piece_impl_(gfx::texture& atlas, font_atlas::map_type& metadata, math::vec2& target_pos, const atlas_meta& info, unsigned char* data_buffer, const std::pair& range); + template + atlas_meta get_atlas_size_ranges_(Ts&&... ranges); + template + void get_atlas_size_ranges_recurse_(size_t& avg_w, size_t& avg_h, size_t& mgw, size_t& mgh, size_t& count, const std::pair& range, Ts&&... ranges); + void get_atlas_size_ranges_impl_(size_t& avg_w, size_t& avg_h, size_t& mgw, size_t& mgh, size_t& count, const std::pair& range); + private: static bool initialize_freetype_(void); }; + + + + template + void font::generate_atlas_piece_(gfx::texture& atlas, font_atlas::map_type& metadata, math::vec2& target_pos, const atlas_meta& info, unsigned char* data_buffer, const std::pair& range, Ts&&... ranges){ + generate_atlas_piece_impl_(atlas, metadata, target_pos, info, data_buffer, range); + + if constexpr(sizeof...(ranges) > 0){ + generate_atlas_piece_(atlas, metadata, target_pos, info, data_buffer, std::forward(ranges)...); + } + } + template + font_atlas font::generate_atlas(size_t glyph_w, size_t glyph_h, Ts&&... ranges){ + FT_Set_Pixel_Sizes(m_face, glyph_w, glyph_h); + auto [atlas_width, atlas_height, max_glyph_width, max_glyph_height] = get_atlas_size_ranges_(std::forward(ranges)...); + const auto format = (m_depth == 3) ? GL_RGB : GL_RED; + + + gfx::texture atlas(format, atlas_width, atlas_height, GL_UNSIGNED_BYTE, false); + font_atlas::map_type atlas_metadata; + math::vec2 target_position = {0, 0}; + std::unique_ptr dest_data(new unsigned char[max_glyph_height * max_glyph_width * m_depth]); + + generate_atlas_piece_(atlas, atlas_metadata, target_position, std::tuple{atlas_width, atlas_height, max_glyph_width, max_glyph_height}, dest_data.get(), std::forward(ranges)...); + return {std::move(atlas), std::move(atlas_metadata), glyph_w, glyph_h}; + } + template + auto font::get_atlas_size_ranges_(Ts&&... ranges) -> atlas_meta{ + size_t avg_width = 0; + size_t avg_height = 0; + size_t max_glyph_width = 0; + size_t max_glyph_height = 0; + size_t count = 0; + + get_atlas_size_ranges_recurse_(avg_width, avg_height, max_glyph_width, max_glyph_height, count, std::forward(ranges)...); + + avg_width /= count; + avg_height /= count; + const size_t est_width = avg_width * (std::min(size_t{20}, count) + 1); + const size_t est_height = (max_glyph_height * (std::round(count / 20) + 1)); + + return {est_width / m_depth, est_height, max_glyph_width / m_depth, max_glyph_height}; + + } + template + void font::get_atlas_size_ranges_recurse_(size_t& avg_w, size_t& avg_h, size_t& mgw, size_t& mgh, size_t& count, const std::pair& range, Ts&&... ranges){ + get_atlas_size_ranges_impl_(avg_w, avg_h, mgw, mgh, count, range); + if constexpr(sizeof...(ranges) > 0){ + get_atlas_size_ranges_recurse_(avg_w, avg_h, mgw, mgh, count, std::forward(ranges)...); + } + } + } #endif diff --git a/include/engine/text.hpp b/include/engine/text.hpp new file mode 100644 index 0000000..06d1454 --- /dev/null +++ b/include/engine/text.hpp @@ -0,0 +1,72 @@ +/** + This file is a part of our_dick + Copyright (C) 2022 rexy712 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +#ifndef OUR_DICK_ENGINE_TEXT_HPP +#define OUR_DICK_ENGINE_TEXT_HPP + +#include "graphics/vbo.hpp" +#include "graphics/vao.hpp" +#include "graphics/texture.hpp" +#include "graphics/shader_program.hpp" +#include "font.hpp" +#include "math/vec.hpp" +#include "flat_object.hpp" + +#include + +namespace egn{ + + class text_gfx + { + private: + static constexpr int s_size_per_char = sizeof(GLfloat) * 12; + private: + gfx::weak_texture m_atlas; + egn::font_atlas::map_type m_font; + gfx::vbo m_vbo; + gfx::vao m_vao; + size_t m_original_height; + float m_scale; + + public: + text_gfx(const egn::font_atlas& font, int target_px, size_t initsize = 0); + text_gfx(const egn::font_atlas& font, int target_px, const char* t); + + void set_text(const char* string); + + void render(gfx::shader_program& sh, const math::vec2f& pos); + }; + + + class text : public flat::object_base + { + private: + text_gfx m_gfx; + std::string m_text; + + public: + text(const egn::font_atlas& font, const char* string, int target_px, float target_x, float target_y); + + void set_text(const char* string); + + void render(gfx::shader_program& sh); + }; + +} + +#endif diff --git a/include/graphics/resource_manager.hpp b/include/graphics/resource_manager.hpp index 78804ef..8537847 100644 --- a/include/graphics/resource_manager.hpp +++ b/include/graphics/resource_manager.hpp @@ -27,6 +27,8 @@ #include "graphics/texture.hpp" #include "graphics/shader_program.hpp" +#include "engine/font.hpp" + namespace gfx{ namespace detail{ @@ -65,6 +67,7 @@ namespace gfx{ { private: detail::resource_manager m_textures; + detail::resource_manager m_fonts; detail::resource_manager m_texture_arrays; detail::resource_manager m_shaders; @@ -90,6 +93,12 @@ namespace gfx{ gfx::texture* get_texture(const char* file); bool erase_texture(const char* key); + bool has_font(const char* key)const; + template + auto emplace_font(const char* key, Args&&... args); + egn::font_atlas* get_font(const char* file); + bool erase_font(const char* key); + bool has_shader(const char* key)const; template auto emplace_shader(const char* key, Args&&... args); @@ -133,6 +142,10 @@ namespace gfx{ return m_textures.emplace_value(key, std::forward(args)...); } template + auto resource_manager::emplace_font(const char* key, Args&&... args){ + return m_fonts.emplace_value(key, std::forward(args)...); + } + template auto resource_manager::emplace_shader(const char* key, Args&&... args){ return m_shaders.emplace_value(key, std::forward(args)...); } diff --git a/include/graphics/shader_program.hpp b/include/graphics/shader_program.hpp index 65d83f6..be055bc 100644 --- a/include/graphics/shader_program.hpp +++ b/include/graphics/shader_program.hpp @@ -210,8 +210,8 @@ namespace gfx{ void set_uniform(GLuint loc, const texture&, GLuint tex_unit = 0); void set_uniform(const char* name, const texture_array& t, GLuint tex_unit = 0); void set_uniform(GLuint loc, const texture_array& t, GLuint tex_unit = 0); - void set_uniform(const char* name, const weak_texture_handle&, GLuint tex_unit = 0); - void set_uniform(GLuint loc, const weak_texture_handle&, GLuint tex_unit = 0); + void set_uniform(const char* name, const weak_texture&, GLuint tex_unit = 0); + void set_uniform(GLuint loc, const weak_texture&, GLuint tex_unit = 0); //Float vectors void set_uniform(const char* name, const vec2&); diff --git a/include/graphics/texture.hpp b/include/graphics/texture.hpp index 6832822..9686168 100644 --- a/include/graphics/texture.hpp +++ b/include/graphics/texture.hpp @@ -27,25 +27,26 @@ namespace gfx{ class texture; - class weak_texture_handle + class weak_texture { private: - const texture* m_texture; + GLuint m_texture; public: - weak_texture_handle(const texture& tex); - weak_texture_handle(const weak_texture_handle&) = default; - weak_texture_handle(weak_texture_handle&&) = default; - ~weak_texture_handle(void) = default; + weak_texture(GLuint tex); + weak_texture(const texture& tex); + weak_texture(const weak_texture&) = default; + weak_texture(weak_texture&&) = default; + ~weak_texture(void) = default; - weak_texture_handle& operator=(const weak_texture_handle&) = default; - weak_texture_handle& operator=(weak_texture_handle&&) = default; + weak_texture& operator=(const weak_texture&) = default; + weak_texture& operator=(weak_texture&&) = default; GLuint raw(void)const; GLsizei get_width(void)const; GLsizei get_height(void)const; - void bind(void)const; + void bind(GLuint target = GL_TEXTURE_2D)const; void bind_unit(GLuint tunit)const; }; @@ -152,7 +153,7 @@ namespace gfx{ //bind to given texture unit and load into given program uniform location void bind_unit(GLuint tunit)const; - weak_texture_handle create_handle(void)const; + weak_texture create_handle(void)const; private: bool create_texture_storage_(void); diff --git a/include/ttt/font_renderer.hpp b/include/ttt/font_renderer.hpp index be7b817..83e241c 100644 --- a/include/ttt/font_renderer.hpp +++ b/include/ttt/font_renderer.hpp @@ -28,145 +28,18 @@ #include "scene.hpp" #include "engine/font.hpp" - -static constexpr float pixels_to_screen_space(int dim, int window_dim){ - const float ratio = 2.0f / window_dim; - return dim * ratio; -} -static constexpr float screen_space_to_pixels(int dim, int window_dim){ - const float ratio = window_dim / 2.0f; - return dim * ratio; -} -static constexpr float font_scale_ratio(int height, int target_height){ - return ((float)target_height) / height; -} -static constexpr float font_aspect_ratio(const egn::font_character& ch){ - return ((float)ch.size.x()) / ch.size.y(); -} - - -class text -{ -private: - static constexpr int s_size_per_char = sizeof(GLfloat) * 13; -private: - egn::font m_font; - std::string m_text; - gfx::vbo m_vbo; - gfx::vao m_vao; - - float m_scale; - -public: - text(egn::font& font, const char* string, int target_px, float target_x, float target_y, int screen_width, int screen_height): - m_font(font), - m_text(string), - m_vbo(s_size_per_char * strlen(string), gfx::vbo::usage::DYNAMIC_DRAW) - { - constexpr float tmp_color[] = {1,1,1,1}; - - m_scale = font_scale_ratio(m_font.size().y(), target_px); - - math::vec3f target_pos = {target_x, target_y, -1}; - size_t offset = 0; - for(int i = 0;m_text[i] != 0;++i){ - const auto ch = m_font[m_text[i]]; - const math::vec2 letter_size = ch.size * m_scale; - const math::vec2f letter_screen_size = {pixels_to_screen_space(letter_size.x(), screen_width), pixels_to_screen_space(letter_size.y(), screen_height)}; - const math::vec3f position = {target_pos.x() + pixels_to_screen_space(ch.bearing.x() * m_scale, screen_width), - target_pos.y() - (letter_screen_size.y() - pixels_to_screen_space(ch.bearing.y() * m_scale, screen_height)), - target_pos.z()}; - - - m_vbo.buffer(ch.texture_coords[1], sizeof(GLfloat) * 2, offset); - offset += sizeof(GLfloat) * 2; - m_vbo.buffer(ch.texture_coords[2], sizeof(GLfloat) * 2, offset); - offset += sizeof(GLfloat) * 2; - m_vbo.buffer(tmp_color, sizeof(GLfloat) * 4, offset); - offset += sizeof(GLfloat) * 4; - m_vbo.buffer(position, sizeof(GLfloat) * 3, offset); - offset += sizeof(GLfloat) * 3; - m_vbo.buffer(letter_screen_size, sizeof(GLfloat) * 2, offset); - offset += sizeof(GLfloat) * 2; - - target_pos.x() += pixels_to_screen_space(m_scale * ch.advance.x(), screen_width); - } - - //attach a vbo to the vao and assign attribute specs - m_vao.bind_buffer(m_vbo, 0, 0, sizeof(GLfloat) * 13); - - auto attrib = m_vao.get_attribute(0); - attrib.set_float_array(4, 0); - attrib.associate_with(0); - attrib.enable(); - - attrib = m_vao.get_attribute(1); - attrib.set_float_array(4, sizeof(GLfloat) * 4); - attrib.associate_with(0); - attrib.enable(); - - attrib = m_vao.get_attribute(2); - attrib.set_float_array(3, sizeof(GLfloat) * 8); - attrib.associate_with(0); - attrib.enable(); - - attrib = m_vao.get_attribute(3); - attrib.set_float_array(2, sizeof(GLfloat) * 11); - attrib.associate_with(0); - attrib.enable(); - - } - void set_position(float x, float y, int screen_width, int screen_height){ - size_t offset = sizeof(GLfloat) * 8; - math::vec3f target_pos = {x, y, -1}; - for(size_t i = 0;m_text[i] != 0;++i){ - const auto ch = m_font[m_text[i]]; - const math::vec2i letter_size = ch.size * m_scale; - const math::vec2f letter_screen_size = {pixels_to_screen_space(letter_size.x(), screen_width), pixels_to_screen_space(letter_size.y(), screen_height)}; - const math::vec3f position = {target_pos.x() + pixels_to_screen_space(ch.bearing.x() * m_scale, screen_width), - target_pos.y() - (letter_screen_size.y() - pixels_to_screen_space(ch.bearing.y() * m_scale, screen_height)), - target_pos.z()}; - - m_vbo.buffer(position, sizeof(GLfloat) * 3, offset); - offset += sizeof(GLfloat) * 3 + sizeof(GLfloat) * 8; - target_pos.x() += pixels_to_screen_space(m_scale * ch.advance.x(), screen_width); - } - } - - void render(gfx::shader_program& sh){ - m_vao.bind(); - sh.set_uniform("texture1", m_font.atlas()); - glDrawArrays(GL_POINTS, 0, m_text.length()); - } -}; +#include "engine/text.hpp" class font_renderer { -private: - struct vertex{ - math::vec2 pos; - math::vec2 tex_coord; - }; - static constexpr vertex s_vertices[] = { - {{-1.0f, 1.0f}, {0.0f, 1.0f}}, - {{-1.0f, -1.0f}, {0.0f, 0.0f}}, - {{ 1.0f, -1.0f}, {1.0f, 0.0f}}, - {{ 1.0f, -1.0f}, {1.0f, 0.0f}}, - {{ 1.0f, 1.0f}, {1.0f, 1.0f}}, - {{-1.0f, 1.0f}, {0.0f, 1.0f}} - }; private: gfx::shader_program* m_font_shader; - gfx::vbo m_vbo; - gfx::vao m_vao; - gfx::texture* m_texture; - std::unique_ptr m_text; int m_screen_width, m_screen_height; public: - font_renderer(gfx::resource_manager& res, int width, int height, gfx::texture& base_tex); + font_renderer(gfx::resource_manager& res, int width, int height); - void render(scene&); + void render(egn::text&); void resize_viewport(int width, int height); }; diff --git a/include/ttt/font_shader.hpp b/include/ttt/font_shader.hpp index cfa52ca..de686a7 100644 --- a/include/ttt/font_shader.hpp +++ b/include/ttt/font_shader.hpp @@ -25,20 +25,20 @@ namespace font_shader{ #version 430 core layout (location = 0) in vec4 tex_coords; layout (location = 1) in vec4 color; - layout (location = 2) in vec3 position; + layout (location = 2) in vec2 offset; layout (location = 3) in vec2 size; out VS_OUT{ vec4 tex_coords; vec4 color; - vec3 position; + vec2 offset; vec2 size; }vs_out; void main(){ vs_out.tex_coords = tex_coords; vs_out.color = color; - vs_out.position = position; + vs_out.offset = offset; vs_out.size = size; } )glsl"; @@ -51,7 +51,7 @@ static constexpr char geometry_shader_text[] = in VS_OUT{ vec4 tex_coords; vec4 color; - vec3 position; + vec2 offset; vec2 size; }gs_in[]; @@ -59,27 +59,49 @@ static constexpr char geometry_shader_text[] = vec2 tex_coords; flat vec4 color; }gs_out; + + uniform vec2 out_size; + uniform vec2 start_pos; + + //map from [0, max_out] to [0, 2] + float size_to_screen_space(float x, float max_out){ + const float ratio = 2.0 / max_out; + return x * ratio; + } + //map from [0, max_out] to [-1, 1] + float pos_to_screen_space(float x, float max_out){ + return size_to_screen_space(x, max_out) - 1.0; + } + void main(){ //texture coordinates need done botleft->topleft->botright->topright //whereas the position goes topleft->botleft->topright->botright //because freetype generates bitmaps with inverse y axis to opengl - gl_Position = vec4(gs_in[0].position.x, gs_in[0].position.y + gs_in[0].size.y, gs_in[0].position.z, 1.0); + vec2 start_screen_pos = vec2(pos_to_screen_space(start_pos.x, out_size.x), pos_to_screen_space(start_pos.y, out_size.y)); + + const vec3 position = vec3(start_screen_pos.x + size_to_screen_space(gs_in[0].offset.x, out_size.x), + start_screen_pos.y + size_to_screen_space(gs_in[0].offset.y, out_size.y), + -1); + const vec2 size = vec2(size_to_screen_space(gs_in[0].size.x, out_size.x), + size_to_screen_space(gs_in[0].size.y, out_size.y)); + + gl_Position = vec4(position.x, position.y + size.y, position.z, 1.0); gs_out.tex_coords = gs_in[0].tex_coords.xy; gs_out.color = gs_in[0].color; EmitVertex(); - gl_Position = vec4(gs_in[0].position, 1.0); + gl_Position = vec4(position, 1.0); gs_out.tex_coords = gs_in[0].tex_coords.xw; gs_out.color = gs_in[0].color; EmitVertex(); - gl_Position = vec4(gs_in[0].position.x + gs_in[0].size.x, gs_in[0].position.y + gs_in[0].size.y, gs_in[0].position.z, 1.0); + gl_Position = vec4(position.x + size.x, position.y + size.y, position.z, 1.0); gs_out.tex_coords = gs_in[0].tex_coords.zy; gs_out.color = gs_in[0].color; EmitVertex(); - gl_Position = vec4(gs_in[0].position.x + gs_in[0].size.x, gs_in[0].position.y, gs_in[0].position.z, 1.0); + gl_Position = vec4(position.x + size.x, position.y, position.z, 1.0); gs_out.tex_coords = gs_in[0].tex_coords.zw; gs_out.color = gs_in[0].color; EmitVertex(); @@ -101,9 +123,9 @@ static constexpr char fragment_shader_text[] = void main(){ vec4 s = texture(texture1, fs_in.tex_coords); - float alpha = (s.r + s.g + s.b) / 3; - - frag_color = mix(s, fs_in.color, alpha); + float alpha = (s.r + s.g + s.b) / 3.0; + vec4 alpha_texture = vec4(s.rgb, alpha); + frag_color = alpha_texture * fs_in.color; //NOT the dot product in glsl } )glsl"; } diff --git a/include/ttt/pause_state.hpp b/include/ttt/pause_state.hpp index 1fd027a..4a46a34 100644 --- a/include/ttt/pause_state.hpp +++ b/include/ttt/pause_state.hpp @@ -23,12 +23,17 @@ #include "engine/input.hpp" #include "graphics/texture.hpp" #include "screen_renderer.hpp" +#include "font_renderer.hpp" + +#include "engine/text.hpp" class pause_state : public egn::game_state_iface { private: egn::game_state_iface* m_under_state; screen_renderer m_screen_renderer; + font_renderer m_font_renderer; + egn::text m_text; public: pause_state(egn::game& owner, egn::game_state_iface* under); diff --git a/include/ttt/screen_renderer.hpp b/include/ttt/screen_renderer.hpp index 374fff9..ed14402 100644 --- a/include/ttt/screen_renderer.hpp +++ b/include/ttt/screen_renderer.hpp @@ -29,117 +29,6 @@ #include "engine/font.hpp" -static constexpr float pixels_to_screen_space(int dim, int window_dim){ - const float ratio = 2.0f / window_dim; - return dim * ratio; -} -static constexpr float screen_space_to_pixels(int dim, int window_dim){ - const float ratio = window_dim / 2.0f; - return dim * ratio; -} -static constexpr float font_scale_ratio(int height, int target_height){ - return ((float)target_height) / height; -} -static constexpr float font_aspect_ratio(const egn::font_character& ch){ - return ((float)ch.size.x()) / ch.size.y(); -} - - -class text -{ -private: - static constexpr int s_size_per_char = sizeof(GLfloat) * 13; -private: - egn::font m_font; - std::string m_text; - gfx::vbo m_vbo; - gfx::vao m_vao; - - float m_scale; - -public: - text(egn::font& font, const char* string, int target_px, float target_x, float target_y, int screen_width, int screen_height): - m_font(font), - m_text(string), - m_vbo(s_size_per_char * strlen(string), gfx::vbo::usage::DYNAMIC_DRAW) - { - constexpr float tmp_color[] = {1,1,1,1}; - - m_scale = font_scale_ratio(m_font.size().y(), target_px); - - math::vec3f target_pos = {target_x, target_y, -1}; - size_t offset = 0; - for(int i = 0;m_text[i] != 0;++i){ - const auto ch = m_font[m_text[i]]; - const math::vec2 letter_size = ch.size * m_scale; - const math::vec2f letter_screen_size = {pixels_to_screen_space(letter_size.x(), screen_width), pixels_to_screen_space(letter_size.y(), screen_height)}; - const math::vec3f position = {target_pos.x() + pixels_to_screen_space(ch.bearing.x() * m_scale, screen_width), - target_pos.y() - (letter_screen_size.y() - pixels_to_screen_space(ch.bearing.y() * m_scale, screen_height)), - target_pos.z()}; - - - m_vbo.buffer(ch.texture_coords[1], sizeof(GLfloat) * 2, offset); - offset += sizeof(GLfloat) * 2; - m_vbo.buffer(ch.texture_coords[2], sizeof(GLfloat) * 2, offset); - offset += sizeof(GLfloat) * 2; - m_vbo.buffer(tmp_color, sizeof(GLfloat) * 4, offset); - offset += sizeof(GLfloat) * 4; - m_vbo.buffer(position, sizeof(GLfloat) * 3, offset); - offset += sizeof(GLfloat) * 3; - m_vbo.buffer(letter_screen_size, sizeof(GLfloat) * 2, offset); - offset += sizeof(GLfloat) * 2; - - target_pos.x() += pixels_to_screen_space(m_scale * ch.advance.x(), screen_width); - } - - //attach a vbo to the vao and assign attribute specs - m_vao.bind_buffer(m_vbo, 0, 0, sizeof(GLfloat) * 13); - - auto attrib = m_vao.get_attribute(0); - attrib.set_float_array(4, 0); - attrib.associate_with(0); - attrib.enable(); - - attrib = m_vao.get_attribute(1); - attrib.set_float_array(4, sizeof(GLfloat) * 4); - attrib.associate_with(0); - attrib.enable(); - - attrib = m_vao.get_attribute(2); - attrib.set_float_array(3, sizeof(GLfloat) * 8); - attrib.associate_with(0); - attrib.enable(); - - attrib = m_vao.get_attribute(3); - attrib.set_float_array(2, sizeof(GLfloat) * 11); - attrib.associate_with(0); - attrib.enable(); - - } - void set_position(float x, float y, int screen_width, int screen_height){ - size_t offset = sizeof(GLfloat) * 8; - math::vec3f target_pos = {x, y, -1}; - for(size_t i = 0;m_text[i] != 0;++i){ - const auto ch = m_font[m_text[i]]; - const math::vec2i letter_size = ch.size * m_scale; - const math::vec2f letter_screen_size = {pixels_to_screen_space(letter_size.x(), screen_width), pixels_to_screen_space(letter_size.y(), screen_height)}; - const math::vec3f position = {target_pos.x() + pixels_to_screen_space(ch.bearing.x() * m_scale, screen_width), - target_pos.y() - (letter_screen_size.y() - pixels_to_screen_space(ch.bearing.y() * m_scale, screen_height)), - target_pos.z()}; - - m_vbo.buffer(position, sizeof(GLfloat) * 3, offset); - offset += sizeof(GLfloat) * 3 + sizeof(GLfloat) * 8; - target_pos.x() += pixels_to_screen_space(m_scale * ch.advance.x(), screen_width); - } - } - - void render(gfx::shader_program& sh){ - m_vao.bind(); - sh.set_uniform("texture1", m_font.atlas()); - glDrawArrays(GL_POINTS, 0, m_text.length()); - } -}; - class screen_renderer { private: diff --git a/src/engine/flat_object.cpp b/src/engine/flat_object.cpp new file mode 100644 index 0000000..9cf3855 --- /dev/null +++ b/src/engine/flat_object.cpp @@ -0,0 +1,74 @@ +/** + This file is a part of our_dick + Copyright (C) 2022 rexy712 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +#include "engine/flat_object.hpp" +#include "math/math_common.hpp" +#include //signbit, atan + +namespace egn::flat{ + + object_base::object_base(const math::vec2f& position, float orientation): + m_position(position), + m_orientation(orientation){} + + void object_base::translate(const math::vec2f& distance){ + m_position += distance; + } + void object_base::rotate(float distance){ + m_orientation += distance; + } + void object_base::scale(const math::vec2f& distance){ + m_scale += distance; + } + void object_base::look_at(const math::vec2f& target){ + const math::vec2f rel_target = target - m_position; + const float angle = std::atan(rel_target.y() / rel_target.x()); + const int x_sign = std::signbit(rel_target.x()); + const int y_sign = std::signbit(rel_target.y()); + const int quadrant = (x_sign ^ y_sign) + (2 * y_sign); + + //quadrants: + // | + // 1 | 0 + //----------------- + // 2 | 3 + // | + m_orientation = angle + (90.0_deg * quadrant); + } + + void object_base::set_position(const math::vec2f& pos){ + m_position = pos; + } + void object_base::set_orientation(float orient){ + m_orientation = orient; + } + void object_base::set_scale(const math::vec2f& scale){ + m_scale = scale; + } + + const math::vec2f& object_base::position(void)const{ + return m_position; + } + float object_base::orientation(void)const{ + return m_orientation; + } + const math::vec2f& object_base::scale(void)const{ + return m_scale; + } + +} diff --git a/src/engine/font.cpp b/src/engine/font.cpp index ca17aa2..8fe1d9d 100644 --- a/src/engine/font.cpp +++ b/src/engine/font.cpp @@ -28,129 +28,111 @@ namespace egn{ return ((float)size.x()) / size.y(); } + font_atlas::font_atlas(gfx::texture&& t, map_type&& map, size_t w, size_t h): + texture(std::move(t)), + m_atlas_data(std::move(map)), + m_requested_width(w), + m_requested_height(h){} - font::font(gfx::texture&& tex, std::map&& metadata, size_t width, size_t height): - m_atlas(std::move(tex)), - m_atlas_data(std::move(metadata)), - m_requested_width(width), - m_requested_height(height){} - font_character& font::operator[](int character){ + auto font_atlas::metadata(void) -> map_type&{ + return m_atlas_data; + } + auto font_atlas::metadata(void)const -> const map_type&{ + return m_atlas_data; + } + auto font_atlas::release_metadata(void) -> map_type&&{ + return std::move(m_atlas_data); + } + + font_character& font_atlas::operator[](int character){ return m_atlas_data[character]; } - const font_character& font::operator[](int character)const{ - return m_atlas_data.at(character); - } - gfx::texture font::release_atlas(void){ - return gfx::texture(std::move(*m_atlas)); - } - gfx::texture& font::atlas(void){ - return *m_atlas; - } - const gfx::texture& font::atlas(void)const{ - return *m_atlas; - } - std::map font::release_metadata(void){ - return std::map(std::move(m_atlas_data)); - } - bool font::valid(void)const{ - return m_atlas.has_value(); - } - math::vec2 font::size(void)const{ + math::vec2 font_atlas::glyph_size(void)const{ return {m_requested_width, m_requested_height}; } - font_generator::font_generator(const char* file){ + + font::font(const char* file, int depth): + m_depth(depth) + { initialize_freetype_(); - if(FT_New_Face(s_ft, file, 0, &m_face)){ - debug_print_error("Failed to initialize font '%s'\n", file); + if(int err = FT_New_Face(s_ft, file, 0, &m_face);err){ + debug_print_error("Failed to initialize font '%s'. Error %d\n", file, err); } } - font_generator::~font_generator(void){ + font::~font(void){ FT_Done_Face(m_face); } - struct atlas_info{ - size_t width, height; - size_t max_glyph_width, max_glyph_height; - }; - atlas_info get_atlas_size_(FT_Face face, int start_codepoint, int count){ - size_t max_height = 0; - size_t max_width = 0; - size_t avg_width = 0; - size_t avg_height = 0; - for(int i = 0;i < count;++i){ - if(FT_Load_Char(face, i + start_codepoint, FT_LOAD_RENDER | FT_LOAD_TARGET_LCD)){ - debug_print_error("Failed to load character '%c' from font '%s'\n", i, face->family_name); + void font::get_atlas_size_ranges_impl_(size_t& avg_w, size_t& avg_h, size_t& mgw, size_t& mgh, size_t& count, const std::pair& range){ + const int freetype_load_flags = FT_LOAD_RENDER | ((m_depth == 3) ? FT_LOAD_TARGET_LCD : 0); + const size_t start = range.first; + const size_t range_cnt = range.second; + for(size_t i = 0;i < range_cnt;++i){ + if(int err = FT_Load_Char(m_face, i + start, freetype_load_flags);err){ + debug_print_error("Failed to load character '%c' from font '%s'\n", (char)i, m_face->family_name); continue; } - max_width = std::max(max_width, size_t{face->glyph->bitmap.width}); - max_height = std::max(max_height, size_t{face->glyph->bitmap.rows}); - avg_width += face->glyph->bitmap.width; - avg_height += face->glyph->bitmap.rows; + mgw = std::max(mgw, size_t{m_face->glyph->bitmap.width}); + mgh = std::max(mgh, size_t{m_face->glyph->bitmap.rows}); + avg_w += m_face->glyph->bitmap.width; + avg_h += m_face->glyph->bitmap.rows; + ++count; } - avg_width /= count; - avg_height /= count; - size_t est_width = avg_width * (std::min(20, count) + 1); - size_t est_height = (max_height * (std::round(count / 20) + 1)); - - - return {est_width / 3, est_height, max_width / 3, max_height}; } - font font_generator::generate_atlas(int start_codepoint, int count, size_t glyph_width, size_t glyph_height){ - FT_Set_Pixel_Sizes(m_face, glyph_width, glyph_height); + font_character calculate_character(FT_Face face, size_t atlas_w, size_t atlas_h, size_t atlas_x, size_t atlas_y){ + const math::vec2 dest_size = {face->glyph->metrics.width >> 6, face->glyph->metrics.height >> 6}; + const float ratio_w = 1.0f / atlas_w; + const float ratio_h = 1.0f / atlas_h; + const float left = ratio_w * atlas_x; + const float right = ratio_w * (atlas_x + dest_size.x()); + const float bottom = ratio_h * atlas_y; + const float top = ratio_h * (atlas_y + dest_size.y()); - atlas_info ai = get_atlas_size_(m_face, start_codepoint, count); + return font_character {{atlas_x, atlas_y}, + dest_size, + {face->glyph->metrics.horiBearingX >> 6, face->glyph->metrics.horiBearingY >> 6}, + {face->glyph->metrics.horiAdvance >> 6, 0}, //convert from 1/64th pixels to pixels + {{left, top}, {left, bottom}, {right, top}, {right, bottom}}}; + } - gfx::texture atlas(GL_RGB, ai.width, ai.height, GL_UNSIGNED_BYTE, false); - std::map atlas_metadata; - math::vec2 atlas_pos = {0, 0}; - - std::unique_ptr dest_data(new unsigned char[ai.max_glyph_height * ai.max_glyph_width * 3]); + void pack_font_data_(unsigned char* dest, const unsigned char* src, size_t out_width, size_t out_height, int pitch){ + for(size_t j = 0;j < out_height;++j){ + memcpy(dest, src, out_width); + dest += out_width; + src += pitch; + } + } + void font::generate_atlas_piece_impl_(gfx::texture& atlas, font_atlas::map_type& metadata, math::vec2& target_pos, const atlas_meta& info, unsigned char* data_buffer, const std::pair& range){ + const auto& [atlas_width, atlas_height, max_glyph_width, max_glyph_height] = info; + const auto format = (m_depth == 3) ? GL_RGB : GL_RED; + const int freetype_load_flags = FT_LOAD_RENDER | ((m_depth == 3) ? FT_LOAD_TARGET_LCD : 0); + int start_codepoint = range.first; + int count = range.second; for(int i = start_codepoint;i < start_codepoint + count;++i){ - if(FT_Load_Char(m_face, i, FT_LOAD_RENDER | FT_LOAD_TARGET_LCD)){ + if(FT_Load_Char(m_face, i, freetype_load_flags)){ debug_print_error("Failed to load character '%c', from font '%s'\n", i, m_face->family_name); continue; } auto& bitmap = m_face->glyph->bitmap; - const math::vec2 dest_size = {bitmap.width / 3, bitmap.rows}; - - const float ratio_w = 1.0f / ai.width; - const float ratio_h = 1.0f / ai.height; - const float left = ratio_w * atlas_pos.x(); - const float right = ratio_w * (atlas_pos.x() + dest_size.x()); - const float bottom = ratio_h * atlas_pos.y(); - const float top = ratio_h * (atlas_pos.y() + dest_size.y()); - - font_character character{atlas.raw(), - atlas_pos, - dest_size, - {m_face->glyph->bitmap_left, m_face->glyph->bitmap_top}, - {m_face->glyph->advance.x >> 6, m_face->glyph->advance.y >> 6}, //convert from 1/64th pixels to pixels - {{left, top}, {left, bottom}, {right, top}, {right, bottom}}}; - atlas_metadata.emplace(i, character); - if(atlas_pos.x() + dest_size.x() > ai.width){ - atlas_pos.x() = 0; - atlas_pos.y() += ai.max_glyph_height; + const math::vec2 out_size = {bitmap.width / m_depth, bitmap.rows}; + if(target_pos.x() + out_size.x() > atlas_width){ + target_pos.x() = 0; + target_pos.y() += max_glyph_height; } - unsigned char* dest = dest_data.get(); - unsigned char* src = bitmap.buffer; - for(int j = 0;j < bitmap.rows;++j){ - memcpy(dest, src, bitmap.width); - dest += bitmap.width; - src += bitmap.pitch; - } - atlas.set_subimage(dest_data.get(), GL_RGB, GL_UNSIGNED_BYTE, atlas_pos.x(), atlas_pos.y(), dest_size.x(), dest_size.y()); - atlas_pos.x() += dest_size.x(); + font_character character = calculate_character(m_face, atlas_width, atlas_height, target_pos.x(), target_pos.y()); + metadata.emplace(i, character); + + pack_font_data_(data_buffer, bitmap.buffer, bitmap.width, bitmap.rows, bitmap.pitch); + atlas.set_subimage(data_buffer, format, GL_UNSIGNED_BYTE, target_pos.x(), target_pos.y(), out_size.x(), out_size.y()); + target_pos.x() += out_size.x(); } - atlas.generate_mipmap(); - atlas.set_wrap_mode(gfx::texture::wrap::CLAMP_EDGE); - return {std::move(atlas), std::move(atlas_metadata), glyph_width, glyph_height}; } - std::optional font_generator::generate_glyph(char character, int width, int height){ + std::optional font::generate_glyph(char character, int width, int height){ FT_Set_Pixel_Sizes(m_face, width, height); if(FT_Load_Char(m_face, character, FT_LOAD_RENDER | FT_LOAD_TARGET_LCD)){ debug_print_error("Failed to load character '%c', from font '%s'\n", character, m_face->family_name); @@ -162,7 +144,7 @@ namespace egn{ - bool font_generator::initialize_freetype_(void){ + bool font::initialize_freetype_(void){ if(!s_initialized){ if(FT_Init_FreeType(&s_ft)){ return false; diff --git a/src/engine/text.cpp b/src/engine/text.cpp new file mode 100644 index 0000000..3103d61 --- /dev/null +++ b/src/engine/text.cpp @@ -0,0 +1,106 @@ +/** + This file is a part of our_dick + Copyright (C) 2022 rexy712 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +#include "engine/text.hpp" + +namespace egn{ + + text_gfx::text_gfx(const egn::font_atlas& font, int target_px, size_t initsize): + m_atlas(font), + m_font(font.metadata()), + m_vbo(initsize * s_size_per_char, gfx::vbo::usage::DYNAMIC_DRAW), + m_original_height(font.glyph_size().y()), + m_scale(((float)target_px) / m_original_height){} + text_gfx::text_gfx(const egn::font_atlas& font, int target_px, const char* string): + text_gfx(font, target_px, strlen(string)) + { + set_text(string); + + //attach a vbo to the vao and assign attribute specs + m_vao.bind_buffer(m_vbo, 0, 0, s_size_per_char); + + auto attrib = m_vao.get_attribute(0); + attrib.set_float_array(4, 0); + attrib.associate_with(0); + attrib.enable(); + + attrib = m_vao.get_attribute(1); + attrib.set_float_array(4, sizeof(GLfloat) * 4); + attrib.associate_with(0); + attrib.enable(); + + attrib = m_vao.get_attribute(2); + attrib.set_float_array(2, sizeof(GLfloat) * 8); + attrib.associate_with(0); + attrib.enable(); + + attrib = m_vao.get_attribute(3); + attrib.set_float_array(2, sizeof(GLfloat) * 10); + attrib.associate_with(0); + attrib.enable(); + } + void text_gfx::set_text(const char* string){ + m_vbo.clear(); + constexpr float tmp_color[] = {1,1,1,1}; + + math::vec2f pos_offset = {0, 0}; + + for(int i = 0;string[i] != 0;++i){ + if(string[i] == '\n'){ + pos_offset.x() = 0; + pos_offset.y() -= m_original_height * m_scale; + continue; + } + const auto ch = m_font[string[i]]; + const math::vec2 letter_size = ch.size * m_scale; + const math::vec2f char_offset = {(ch.bearing.x() * m_scale) + pos_offset.x(), + ((ch.bearing.y() * m_scale) - letter_size.y()) + pos_offset.y()}; + + m_vbo.buffer(ch.texture_coords[1], sizeof(GLfloat) * 2); + m_vbo.buffer(ch.texture_coords[2], sizeof(GLfloat) * 2); + m_vbo.buffer(tmp_color, sizeof(GLfloat) * 4); + m_vbo.buffer(char_offset, sizeof(GLfloat) * 2); + m_vbo.buffer(letter_size, sizeof(GLfloat) * 2); + + pos_offset.x() += (m_scale * ch.advance.x()); + } + } + void text_gfx::render(gfx::shader_program& sh, const math::vec2f& pos){ + m_vao.bind(); + sh.set_uniform("texture1", m_atlas); + sh.set_uniform("start_pos", pos); + glDrawArrays(GL_POINTS, 0, m_vbo.get_size() / s_size_per_char); + } + + + + text::text(const egn::font_atlas& font, const char* string, int target_px, float target_x, float target_y): + flat::object_base(math::vec2f{target_x, target_y}), + m_gfx(font, target_px, string), + m_text(string){} + + void text::set_text(const char* string){ + m_text = string; + m_gfx.set_text(string); + } + + void text::render(gfx::shader_program& sh){ + m_gfx.render(sh, m_position); + } + +} diff --git a/src/graphics/resource_manager.cpp b/src/graphics/resource_manager.cpp index 976fe94..6453664 100644 --- a/src/graphics/resource_manager.cpp +++ b/src/graphics/resource_manager.cpp @@ -40,6 +40,16 @@ namespace gfx{ return m_textures.erase_value(key); } + bool resource_manager::has_font(const char* key)const{ + return m_fonts.has_value(key); + } + egn::font_atlas* resource_manager::get_font(const char* file){ + return m_fonts.get_value(file); + } + bool resource_manager::erase_font(const char* key){ + return m_fonts.erase_value(key); + } + bool resource_manager::has_shader(const char* key)const{ return m_shaders.has_value(key); } diff --git a/src/graphics/shader_program.cpp b/src/graphics/shader_program.cpp index 9a57c5d..4773bf4 100644 --- a/src/graphics/shader_program.cpp +++ b/src/graphics/shader_program.cpp @@ -501,10 +501,10 @@ namespace gfx{ t.bind_unit(tex_unit); glProgramUniform1i(m_shader_id, loc, tex_unit); } - void shader_program::set_uniform(const char* name, const weak_texture_handle& t, GLuint tex_unit){ + void shader_program::set_uniform(const char* name, const weak_texture& t, GLuint tex_unit){ set_uniform(get_uniform_loc(name), t, tex_unit); } - void shader_program::set_uniform(GLuint loc, const weak_texture_handle& t, GLuint tex_unit){ + void shader_program::set_uniform(GLuint loc, const weak_texture& t, GLuint tex_unit){ t.bind_unit(tex_unit); glProgramUniform1i(m_shader_id, loc, tex_unit); } diff --git a/src/graphics/texture.cpp b/src/graphics/texture.cpp index f1606e6..a87fa24 100644 --- a/src/graphics/texture.cpp +++ b/src/graphics/texture.cpp @@ -301,8 +301,8 @@ namespace gfx{ void texture::bind_unit(GLuint tunit)const{ glBindTextureUnit(tunit, m_tex_id); } - weak_texture_handle texture::create_handle(void)const{ - return weak_texture_handle(*this); + weak_texture texture::create_handle(void)const{ + return weak_texture(*this); } bool texture::create_texture_storage_(void){ @@ -526,24 +526,30 @@ namespace gfx{ - weak_texture_handle::weak_texture_handle(const texture& tex): - m_texture(&tex){} + weak_texture::weak_texture(GLuint tex): + m_texture(tex){} + weak_texture::weak_texture(const texture& tex): + m_texture(tex.raw()){} - GLuint weak_texture_handle::raw(void)const{ - return m_texture->raw(); + GLuint weak_texture::raw(void)const{ + return m_texture; } - GLsizei weak_texture_handle::get_width(void)const{ - return m_texture->get_width(); + GLsizei weak_texture::get_width(void)const{ + GLint retval; + glGetTextureLevelParameteriv(m_texture, 0, GL_TEXTURE_WIDTH, &retval); + return retval; } - GLsizei weak_texture_handle::get_height(void)const{ - return m_texture->get_height(); + GLsizei weak_texture::get_height(void)const{ + GLint retval; + glGetTextureLevelParameteriv(m_texture, 0, GL_TEXTURE_HEIGHT, &retval); + return retval; } - void weak_texture_handle::bind(void)const{ - m_texture->bind(); + void weak_texture::bind(GLuint target)const{ + glBindTexture(target, m_texture); } - void weak_texture_handle::bind_unit(GLuint tunit)const{ - m_texture->bind_unit(tunit); + void weak_texture::bind_unit(GLuint tunit)const{ + glBindTextureUnit(tunit, m_texture); } } diff --git a/src/ttt/font_renderer.cpp b/src/ttt/font_renderer.cpp index 562ccd1..2b3c577 100644 --- a/src/ttt/font_renderer.cpp +++ b/src/ttt/font_renderer.cpp @@ -24,31 +24,21 @@ #include "engine/font.hpp" -font_renderer::font_renderer(gfx::resource_manager& res, int width, int height, gfx::texture& base_tex): - m_vbo(s_vertices, sizeof(s_vertices), gfx::vbo::usage::DYNAMIC_DRAW), - m_texture(&base_tex), - m_text(nullptr), +font_renderer::font_renderer(gfx::resource_manager& res, int width, int height): m_screen_width(width), m_screen_height(height) { m_font_shader = res.emplace_shader("font_shader", util::make_deferred(font_shader::vertex_shader_text, gfx::shader::type::VERTEX), - util::make_deferred(font_shader::geometry_shader_text, gfx::shader::type::GEOMETRY), - util::make_deferred(font_shader::fragment_shader_text, gfx::shader::type::FRAGMENT)).first; + util::make_deferred(font_shader::geometry_shader_text, gfx::shader::type::GEOMETRY), + util::make_deferred(font_shader::fragment_shader_text, gfx::shader::type::FRAGMENT)).first; if(m_font_shader->has_link_error()){ debug_print_error("%s\n", m_font_shader->get_error().c_str()); } - constexpr int target_pixel = 256; - - egn::font_generator f("assets/Woodwarrior-Regular.otf"); - auto font = f.generate_atlas('a', 26, 0, target_pixel); - - m_text.reset(new text(font, "pause", target_pixel, -0.8, -0.8, m_screen_width, m_screen_height)); - resize_viewport(width, height); } -void font_renderer::render(scene&){ +void font_renderer::render(egn::text& t){ //Clear the global state to that which this renderer prefers glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -56,14 +46,10 @@ void font_renderer::render(scene&){ glViewport(0, 0, m_screen_width, m_screen_height); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //Apply our shader and vao m_font_shader->use(); -// m_font_shader->set_uniform("texture1", *m_texture, 0); -// m_vao.bind(); - m_text->render(*m_font_shader); + m_font_shader->set_uniform("out_size", math::vec2f{m_screen_width, m_screen_height}); - //Draw - //glDrawArrays(GL_POINTS, 0, 5); + t.render(*m_font_shader); } void font_renderer::resize_viewport(int width, int height){ diff --git a/src/ttt/pause_state.cpp b/src/ttt/pause_state.cpp index e12e511..d1be43e 100644 --- a/src/ttt/pause_state.cpp +++ b/src/ttt/pause_state.cpp @@ -24,13 +24,21 @@ #include "config.hpp" +static egn::font_atlas generate_font_atlas_from_file(const char* file, int target_height){ + egn::font f(file); + return f.generate_atlas(0, target_height, std::pair{' ', ('~' - ' ')}); +} + pause_state::pause_state(egn::game& owner, egn::game_state_iface* under): game_state_iface(&owner), m_under_state(under), - m_screen_renderer(owner.gfx_resource_manager(), owner.get_width(), owner.get_height(), *owner.gfx_resource_manager().emplace_texture("pause_screen", util::make_deferred("assets/images/pause.png", true)).first){} + m_screen_renderer(owner.gfx_resource_manager(), owner.get_width(), owner.get_height(), *owner.gfx_resource_manager().emplace_texture("pause_screen", util::make_deferred("assets/images/pause.png", true)).first), + m_font_renderer(owner.gfx_resource_manager(), owner.get_width(), owner.get_height()), + m_text(*owner.gfx_resource_manager().emplace_font("hinted-RosaSans-Regular-atlas-50px", util::deferred_function(generate_font_atlas_from_file, "assets/hinted-RosaSans-Regular.ttf", 50)).first, "Pause Menu", 50, 100, 100){} void pause_state::enter(){ m_screen_renderer.resize_viewport(m_owner->get_width(), m_owner->get_height()); + m_font_renderer.resize_viewport(m_owner->get_width(), m_owner->get_height()); } void pause_state::leave(){} void pause_state::handle_input(const egn::input_event& event){ @@ -45,11 +53,12 @@ void pause_state::handle_input(const egn::input_event& event){ }else if(event.ev_type == egn::input_event::type::RESIZE){ m_under_state->handle_input(event); m_screen_renderer.resize_viewport(event.x, event.y); + m_font_renderer.resize_viewport(event.x, event.y); } } void pause_state::update(double){} void pause_state::render(){ - scene tmp; m_under_state->render(); - m_screen_renderer.render(tmp); + //m_screen_renderer.render(tmp); + m_font_renderer.render(m_text); }