bettola/client/src/gfx/txt_renderer.h
Ritchie Cunningham c3316b3da1 [Refactor] Implement batched text rendering.
Overhauls text rendering to improve performance.

Renderer was really ineffient, sending a separate GPU draw call for
every character rendered. This created a bottleneck, especially with
text-heavy UI stuff like the wallpaper.

- The 'TextRenderer' now generates a single texture atlas for all font
  glyhs on load so all characters share a single texture.
- 'begin()' / 'flush()' was added to the 'TextRenderer'. Calls to
  'render_text' now buffer vertex data (position, texture coords,
colour) instead of drawing immediately. A single 'flush()' call at the
end of a pass draws all buffered text in one draw call.
- A simple batching introduced some shitty visual layering bugs. to
  solve this, a staged flushing architecture has been implemented. Each
logical UI component is now responsible for managing its own rendering
passes, beginning and flushing text batches as needed to ensure correct
back-to-front layering.
2025-10-04 18:32:35 +01:00

48 lines
1.1 KiB
C++

#pragma once
#include <ft2build.h>
#include <vector>
#include FT_FREETYPE_H
#include "shader.h"
#include "types.h"
struct TextVertex {
float x, y, s, t, r, g, b;
};
/* State of a single charactrer glyph. */
struct character {
int size[2];
int bearing[2];
unsigned int advance;
float tx, ty; /* x and y offset of glyph in texture atlas. */
float tw, th; /* width and height of glyph in texture atlas. */
};
const int MAX_GLYPHS_PER_BATCH = 10000;
const int VERTICES_PER_GLYPH = 6;
const int MAX_VERTICES = MAX_GLYPHS_PER_BATCH * VERTICES_PER_GLYPH;
class TextRenderer {
public:
TextRenderer(unsigned int screen_width, unsigned int screen_height);
~TextRenderer(void);
void load_font(const char* font_path, unsigned int font_size);
void render_text(const char* text, float x, float y, const Color& color);
float get_text_width(const char* text, float scale);
void begin(void);
void flush(void);
private:
Shader* _txt_shader;
unsigned int _vao, _vbo;
unsigned int _atlas_texture_id;
character _chars[128];
std::vector<TextVertex> _vertices;
float _projecton[16];
};