top of page

Text Rendering!

  • Writer: Pablo Narvaja
    Pablo Narvaja
  • Dec 31, 2019
  • 3 min read

Last time we had the 2D renderer done but what is a 2D renderer without some text right?


This feature was delayed because I run into some trouble. The first thing I wanted to do was to use freetype and then make the texture atlases at runtime or bake them before release but I couldnt make freetype to work in my engine; after a week of debugging I decided to go with another aproach, bake the texture atlas outside the engine with Hiero and reading the glyphs definitions from the *.fnt files.


The Hiero pipeline

I discoverd this tool in this video tutorial and I couldnt see the same page stats as in the video so I did it by try and error later on in the writing of this post I learn how to make them appear. Lets see the interface.


Yellow: Choose the font you desire. If you want load a custom font choose file and open the .ttf or .otf file you desire.

Green: The glyphs you want. There are some presets like EXTENDED(all glyphs) HEHE (basic glyphs) and ASCII.

Red: These are the texture atlas dimensions.

Purple: I added some padding so no glyph intesect another (this happens in some fonts).

Blue: You need to choose Glyph cache first. Then you set the biggest size of the font while maintaining 1 page(single texture).


To save the font you go "FILE->SAVE BMfont file" you put the name and hit save. You will see that it saves 2 files a png texture and a fnt file.


Reading the files

This is how the fnt files looks like:

I ignore all inside the red rectangle and jump to the first char and store the info in this struct:

So:

advance_cursor = xdvance.

Offset = vec2(xoffset, yoffset).

Size = vec2(width, height).

Tex_offset = vec2(x,y).

Tex_extent = tex_offset + size.


And then I devide tex_offset and tex_extent by image_width to the x component and by image_height to the y component beacuse we need the texture coordinates to be in the range [0, 1].


But a font is composed of a characters sets and a texture atlas right? well yes but actually no. Some fonts need kerning. Kerning as wikipedia states "is the process of adjusting the spacing between characters in a proportional font, to achieve a visually pleasing result."

There are 2 types of kering, metrics and optical. Optical calculate metrics on the fly, we wont be using that one, instead we will be using the manually metrics pairs given by the font designer. These values can be found at the end of the fnt file as shown below:

I marked in green the glyphs that we read before, I personally ignore the kernings count but it could be used to reserve memory before hand to make the code faster.

So we have pairs of caharacters with the amount of kerning to apply between them so my font class looks like this:

Size is to know what is the max size in pixel of the font so I dont loose quality when using them. The glyphs_atlas is the texture hiero made for us. Glyphs are the glyphs we loaded before and then is the kerningPairs. Is a map of maps to make the search fast.


Rendering the text

To render the text I do it just like when I render sprites but I change the binded texture to be the glyphs_atlas. If we remember the Quad class looked like this:

The color this time is the color of the text. The transform is where the glyph is.

And the uv_coords is where the glyph is in the altas.

With that in mind now I'll show you how I create the quads accordingly.



So I added another vector<Quad> called m_text where all the info for the text will be and I add a quad for every character of text I submit to the renderer. The calculations are simple but too long for me to post here.

Then I render the text as always on top like this:


Extra

I also added some variations to the methods already in the renderer2d for relative to the screen positioning and scaling and text alignment.


That's it for this post, folks. Bye!


Comments


  • facebook
  • linkedin
  • youtube
  • generic-social-link
  • Grey LinkedIn Icon
  • Facebook
  • YouTube

2019 Pablo Narvaja. Llamathrust GameEngine

bottom of page