gh_font: True Type Font Module (Lua and Python)


Lua programming in GeeXLab

A new font module called gh_font has been added to GeeXLab since version 0.10.x. Let’s see how this module works.

gh_font is a module that uses true type fonts to draw 2D / 3D text. GeeXLab has others true type font functions in the gh_utils module (ftgl_font_xxx() functions). These true type font functions are based on the FreeTypeGL library. They work fine but are limited to OpenGL because FreeTypeGL is an OpenGL based lib.

gh_font is not limited to OpenGL: we can use it with Vulkan and Direct3D 12 too. Another small difference between gh_font and gh_utils.ftgl_font_xxx() is that gh_font can only load *.ttf files while the FreeTypeGL functions can load *.ttf and *.otf files. TTF files are the most numerous so this small lack is not dramatic.

gh_font is used by the new kx framework (more about it in another article) to display all information in OpenGL and Vulkan demos.

Here are the steps to create and use a font object with gh_font.

1/ create a font object:

local demo_dir = gh_utils.get_demo_dir()
local ttf_filename = demo_dir .. "./SoulMission.ttf"
local font_size = 64
local font_texture_size = 512
font = gh_font.create(ttf_filename, font_size, font_texture_size, font_texture_size)

 
2/ build the font texture:

gh_font.build_texture(font)

 
3/ retrieve the font texture for drawing

font_tex = gh_font.get_texture(font)

 
The next steps are usually done in a FRAME script.

4/ Reset the font. This must be done every frame for dynamic texts or once for static texts.

gh_font.clear(font)

 
5/ Write text. x and y are in screen coordinates (the point 0;0 is the top-left corner).

x = 20 
y = 40
gh_font.text_2d(font, x, y, r, g, b, a, "GeeXLab is amazing!")

 
6/ Once all texts have been written, we can update the font and render it using the GPU program font_prog (see the source code at the end of the article):

gh_font.update(font, 0)
 
gh_gpu_program.bind(font_prog)
gh_gpu_program.uniform1i(font_prog, "tex0", 0)
gh_texture.bind(font_tex, 0)
gh_font.render(font)


GeeXLab - True Type font example

 
In some cases, the knowledge of the text width can be useful. With the text width, you can, for example, center the font:

local text = "Hello world"
local text_width = gh_font.get_text_width(f, text)
local x = screen_width/2 - text_width/2
local y = screen_height/2
gh_font.text_2d(f, x, y, 1.0, 1.0, 1.0, 1.0, text)


GeeXLab - True Type font example

 
A new function added in GeeXLab 0.12.1.x allows to draw a sentence and to color each word (or part of the sentence) with a particular color. This new function is text_2d_v2(). This function does not have x and y parameters because it uses the current position of the text. For example
the following example:


GeeXLab - True Type font example

 
is produced by:

gh_font.text_2d(f, x, y, 1.0, 1.0, 1.0, 1.0, "GeeXLab ")
gh_font.text(f, 1.0, 1.0, 0.0, 1.0, "is... ")
gh_font.text(f, 0.0, 1.0, 0.0, 1.0, "awesome!")

 
GeeXLab demos related to this article are available in the code sample pack in the gl21/font-truetype/ folder.

 
The font GPU program used in most GeeXLab demos is the following:

<gpu_program name="font_prog" >
    <raw_data_vs><![CDATA[	 
#version 120
uniform mat4 gxl3d_ViewProjectionMatrix;
uniform mat4 gxl3d_ModelMatrix;
uniform vec4 gxl3d_Viewport;
varying vec4 Vertex_UV;
varying vec4 Vertex_Color;
void main()
{
  vec4 P = gl_Vertex;
  vec4 Pw = gxl3d_ModelMatrix * P;
  Pw.x = Pw.x - gxl3d_Viewport.z/2;
  Pw.y = Pw.y + gxl3d_Viewport.w/2;
  gl_Position = gxl3d_ViewProjectionMatrix * Pw;		
  Vertex_UV = gl_MultiTexCoord0;
  Vertex_Color = gl_Color;
}
  ]]></raw_data_vs>
    <raw_data_ps><![CDATA[	 
#version 120
uniform sampler2D tex0;
varying vec4 Vertex_UV;
varying vec4 Vertex_Color;
void main (void)
{
  vec2 uv = Vertex_UV.xy;
  float t = texture2D(tex0,uv).r;
  gl_FragColor = vec4(t * Vertex_Color.rgb, 1.0); 
}
    ]]></raw_data_ps>
  </gpu_program>