Due to the fact that OpenGL ES does not provide any kind of fonts, we need think a way to create the characters and display them efficiently. In order to use fonts in OpenGL ES, we will use a widely used technique called: bitmapped fonts. That is, we store into a texture all characters of a font (there are many programs that produces this kind of textures). The texture will be black (0,0,0) in the places that we want it will be transparent (we will not render the whole quad, only the character inside), and white (1,1,1) in the places we want to see (the character itself). This will allow us, with a blend function of (GL_ONE, GL_ONE).
Because we have a white color, we can safely use glColor4x call to color our font.
Also, we need the right texture coordinates to isolate the right character in the texture, so we will precompute all texture coordinates for characters from 0 to 127 (our texture has 128 characters) in order to access directly to them in runtime, and draw a textured-blended-quad (actually, a triangle strip, because we do not have quads…).
So first we will create a suitable texture, with all characters that we will need. This texture has 8 rows and 16 columns, and each cell has 16×16 texels, and the characters are stored in the ASCII order. We need to isolate the texture coordinates of a character, so we do the next computations:
const float rows = 8.0f;
const float columns = 16.0f;
const float xoffset = 1.0f / columns;
const float yoffset = 1.0f / rows;
const float cx = (float)(c % 16) * xoffset;
const float cy = (float)(c / 16) * yoffset;
Where c is the ASCII code of the character we want to access, substracting 32, because in our texture we do not store the first 32 ASCII characters. cx and cy are the initial position, in both axis, of the character. With these two values we have the texture coordinates of the first corner of the quad.
The BitmappedFont class will encapsulate all this code:
class BitmappedFont {
public:
BitmappedFont(GLuint textureFontID, int fontWidth = 15, int fontHeight = 15);
~BitmappedFont();
static void EnableStates(); //Begin Print
void Print(int x, int y, const char *fmt, ...);
static void DisableStates(); //EndPrint
private:
GLuint m_textureFontID;
int m_fontWidth,m_fontHeight;
//2 = st, 4 = vertices per character, 8 = rows, 16 = columns
static GLfixed m_textureCoordinates[2 * 4 * 8 * 16];
/*boolean to compute texture coordinates only when the first
instance is created*/
static bool m_instanced;
};
