Question

To render text with OpenGL I take the textured quad approach, I draw a quad for every character that needs to be represented. I store all the character texture information in a single texture, and use glScalef and glTranslatef on the texture matrix to select the correct character in the texture. At first I only put a few characters in the image used to create the texture and it worked well.

Since then I needed to render more characters, like lower case letters. I tried adding more characters, but now my text ends up unaligned and smaller.

Is there a proper way to create character maps, or is my approach all together wrong?

Note: I am using a mono-style font so font dimensions should not be the issue, however I would like to add support for fonts with non-uniform size characters as well.

EDIT: I'm using a vertex buffer for drawing rather than immediate mode.

EDIT 2: The texture containing the character map has 9 rows, each with 11 characters. Since the characters are the same size, I use glscalef on the texture matrix to 1/9 the width of the texture, and 1/11 the height. The VBO defines the quad (0,0),(1,0),(0,1),(1,1) and tex coords (0,0),(1,0),(0,1),(1,1). The nonalignment seems to be due to my transformations not fitting each glyph exactly. How are the optimal bounds for each glyph calculated?

Was it helpful?

Solution

In hopes that this may be useful to others. The optimal glyph bounds can be calculated by first normalizing the pixel offsets of each letter so that they are numbers within the range of 0 and 1. The widths and heights can also be normalized to determine the correct bounding box. If the widths and heights are uniform, like in mono fonts, static width and height values may be used for computing the glyph bounds.

Saving an array of pixel position values for each glyph would be tedious to calculate by hand, so it is better to start the first glyph at the first pixel of the character map and keep no spacing in between each letter. This would make calculating the bottom left uv coordinates easy with for loops

void GetUVs(Vector2* us, Vector2* vs, float charWidth, float charHeight, int cols, int rows)
{
    for (int x = 0; x < cols; x++)
    {
        for (int y = 0; y < rows; y++)
        {
            int index = x + cols * y;
            us[index].x = x * charWidth;
            vs[index].y = y * charHeight;
        }
    }
}

The rest of the bounds could be calculated by adding the width, the height, and the width and height respectively.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top