OpenGL Text Renderer
Fontloads one or more MiniFont objects by scanning for files likeTimesNewRoman0.fnt,TimesNewRoman1.fnt, etc.MiniFontparses each.fntfile, collecting character metrics (positions, offsets) and kerning info.Fontthen combines all.tgapages into a single array texture, so one texture object can store multiple pages (and multiple sizes).TextBoxis an object that can display a string inside a bounding rectangle, handling:- Word-wrap, forced line breaks (
\n), and hyphenation if a single word exceeds the width. - Selection of the mini-font that best fits the bounding box (trying smaller indexes if needed).
- Truncation from the bottom if it still exceeds the height.
- Generating vertex data (quads) for rendering.
- Word-wrap, forced line breaks (
TextRendererholds references to allTextBoxobjects and a shader (2d.vsh,2d.fsh) that does the final draw call.TextTableprovides a simple CSV-based system for localization and placeholder substitution (e.g."{playerName}" -> "Alice").
At runtime, the application:
- Initializes the Wolf window/input/GL environment.
- Loads fonts and text boxes, hooking up text via either direct strings or IDs from a CSV file.
- Renders them in an orthographic projection.
- Dynamically re-wraps/truncates text if the content or bounding box changes.
Open BmFont
Chooose a font [Since you're going to be repeating these steps start with the largest font you want]
Export it as a .fnt file and choose .txt font descriptor & .tga for textures
Ctrl + S to save it and make sure to place it within "data/Fonts/"
Name the file a simple name for example "Arial0"
Repeat the process for each font size and name it accordingly (Arial1, Arial2, etc.)
Finally, in main write the following line of code to load the font:
Font* font = m_textRenderer->createFont("TimesNewRoman");
Make sure to use the name only without the number afterwards. ex. Arial0 would be written as createFont("Arial")
Everything else is done automatically
Unified Array Texture
- All pages of a given font are merged into one texture array. This greatly simplifies binding in OpenGL and avoids multiple texture switches per letter.
Multiple Font Sizes
- By scanning filenames (
"MyFont0.fnt","MyFont1.fnt", etc.), you take care of all sizes - The program automatically picks smaller fonts if text won’t fit the bounding box at size=1.
- By scanning filenames (
Wrapping & Truncation
- Single-word overflow triggers hyphenation.
- Forced breaks
\nare accounted for. - If final text still exceeds the box height, it’s truncated from the bottom with an ellipsis (
"...").
TextTable Integration
- Simple CSV-based approach to store multiple languages or dynamic placeholders (e.g.,
{scoreValue}). - Automatic re-substitution if the table changes language or placeholder data.
- Simple CSV-based approach to store multiple languages or dynamic placeholders (e.g.,
Decoupled Rendering
TextRendereronly draws all boxes; eachTextBoxmanages its own geometry.- This keeps it flexible for adding or removing text boxes at runtime.
You get a scalable text-rendering system that can handle multiple fonts, multiple languages, on-the-fly changes, and robust word-wrapping/truncation — all driven by array textures for efficiency.