WebGL Drawing Bitmap Font
Overview
One of the advantages of using WebGL is you don't need an addtional library to draw 2D text over the WebGL screen. You can place HTML text elements directly over the <canvas> element. However, if you want to render a text in a 3D space, you need additional work to do. One way is using a 3D geometry/path for each character and draw 3D character objects one by one in 3D space. The second method is storing the characters in a texture map and render each character into a plane/quad one by one.
This page explains the second option, how to generate and draw a bitmap font in WebGL.
Generating Bitmap Font
Sometime, you want to draw 2D text overlay or to display text directly into a 3D scene. There is a great tool to generate bitmap-based font, Bitmap Font Generator from AngelCode.com. This tool allows to convert the system fonts to a bitmap texture and configuration file. And, this texture can be used with WebGL by mapping a section of the texture map to a quad. The configurarion file specifies the texture coordinates of each character, size, horizontal/vertical offsets and kerning values between 2 characters.
The following is an example of BMFont settings and a bitmat texture generatedby BMFont.



For 2D text overlay, you only need to generate an exact font size that you want, for example 24-pixel high text wll be displayed as 24 pixels. However, you need to create a bigger font for 3D perspective space because the text will be rendered bigger or small depending on the distance from the view. I recommend to generate twice bigger size than the 2D version, e.g. 48 pixel high.
BitmapFont Class
BitmapFont class is to parse the font configuration file and the associated texture file to draw a text onto the 3D scene. The configuration file specifies the size, offet from the the base line and kerning of each character (spacing information for the next character).
BitmapFont | |
---|---|
Function | Description |
loadFont(url) | Parse the FNT file and texture file from URL |
drawText(text, x,y,z, c) | Draw the text at the given position (If c is true, the text is aligned centered.) |
getTextWidth(text) | Calculate the required width of the given text (Used to determine the staring position of the text) |
setScale(sx,sy) | Rescale each charater |
Since the width and height values in the font configuration file is integer, relative to the dimension of the bitmap texture file. So, the text size must be re-scaled by setScale() depending on the scene size where the text is drawn. The following is a typical usage of BitmapFont;
let gl = {}; // global var
...
// create a bitmap font object
gl.font = new BitmapFont(gl);
gl.font.loadFont("arial48.fnt"); // load FNT and texture
gl.font.setScale(0.01, 0.01); // resize font for 3D
...
// draw text at (0,0,0)
gl.uniform4fv(gl.program.uniform.materialDiffuse, new Float32Array([1,0,0,1]));
gl.font.drawText("WebGL", 0,0,0, ture); // center aligned
...
Please note that drawText() is not optimized for drawing performance because it renderes each character one at a time. If you draw to many characters on the scene, it may slow down the rendering.
Example: Drawing Bitmap Font
This demo load a bitmap font from the font list, and draw sample texts around 3 corners of a 2x2x2 cube at (1, 1, 1), (1, -1, 1) and (1, 1, -1).
Since the text is always facing to the camera, you need a special shader program to ignore the camera orientation. Please see gles_sprite.vert and gles_sprite.frag shaders for detail.
Fullscreen Demo: test_font.html
GitHub Repo: test_font.html