I’m sure it’s something you’ve seen many times in BGE games. Text that looks like this:
Or maybe even like this:
The first is pixelated, and the second has aliasing artefacts. Here’s a comparison of three types of text:
The bottom one is properly anti-aliased.
Why is this an issue?
Blender’s font system works by turning the font (a vector graphic) into a tile sheet (pixels). It does so at a certain resolution. Then it samples the texture sheet based on the nearest pixel. This is unlike regular textures, which get mipmapped and linearly interpolated. After fiddling around with the source, it became apparent that this is because the same font rendering process is used for blender’s main interface. Applying mipmapps and linear filtering resulted in blurry text for the whole of blender!
The font-tilesheet itself is properly anti-aliased, just the sampling of the image when it’s rendered is poor. As a result, if we match the tile-sheet resolution with the resolution displayed in-game, then we can achieve perfectly anti-aliased text. Just to complicate things, the number you put into a font’s “resolution” using pythons API is not the pixel size of the tilesheet - or the number of pixels per character. Coming from the source code we have:
#define BGE_FONT_RES 100 ... snip ... // HARDCODED MULTIPLICATION FACTOR - this will affect the render resolution directly const float RES = BGE_FONT_RES * m_resolution; const float size = fabs(m_fsize * NodeGetWorldScaling() * RES);
For those that don’t understand C, this translates as:
A font objects resolution is measured in units of 100px/bu
[SUB]Side note: this is why animating the scale of a font object results in very poor performance.[/SUB]
As a result, once we have computed the ideal size of our image, we need to scale it by this factor. In practice, this looks like the function:
import bge def fix_text(obj): '''Compute a font object's ideal resolution assuming an orthographic camera''' # Defined in blender source: an object 1 unit high with a resultion of 1 will have 100px default_px_per_bu = 100 window_width = bge.render.getWindowWidth() # Measure the size of the font object (height) text = obj.text obj.text = '|' obj_height = obj.dimensions obj.text = text if not obj.scene.active_camera.perspective: view_width = obj.scene.active_camera.ortho_scale else: raise Exception("Only for orthographic cameras at the moment") pixel_ratio = window_width / view_width # pixels / bu obj_pixels = pixel_ratio * obj_height obj.resolution = obj_pixels / obj_height / default_px_per_bu
Currently I only have support in that function for orthographic cameras, because on a perspective camera, the font will change size as the camera moves. So, the above code is only useful for creating GUI’s and menu’s