Font rendering in Direct3D
For those of you wanting to render your own custom fonts I've come up with something that may help you.
Code:
class CTextData
{
protected:
IDirect3DTexture9 *m_pTextTexture;
IDirect3DTexture9 *m_pBackground;
float m_fUIncrement;
float m_fWidth;
float m_fVIncrement;
char m_szGlyphOrder[128];
int m_iGlyphsPerRow;
//Notes for rendering text correctly
//StartU=(GlyphNum % GlyphsPerRow) * UIncrement)
//TempV=int(GlyphNum / GlyphsPerRow)
//StartV=(float)TempV* VIncrement
...
};
This is a simple process. You have two textures, or just one if you want. They should contain alpha information in them but they don't have to. You could create fading lines of text with this as well.
The core of the system lies in m_szGlyphOrder. This is just an array of ASCII characters. When a line of text is rendered here is what happens.
1. The texture is set to the font bitmap.
2. The current character position is retrieved from the glyph array
3. This position is converted to u,v coords based on the font bitmap information.
4. A quad is created with the derived u,v coords and/or alpha information per vertex as well as diffuse, specular, etc.
5. The quad is rendered
6. Goto 2 until text is rendered.
An alternate method would be to render the text to a scratch texture and increment the width/height counters as needed for the final quad. Render each section of the font bitmap to the scratch texture and when you find you have hit a space or a non-glyph, set the texture to the scratch texture, draw the quad using vertex information based on the current width/height counters and render the quad.
m_uIncrement - the normalized width of one glyph cell (normalized as it relates to the width and height of the entire font bitmap).
m_vIncrement - the normalized height of one glyph cell
m_fWidth - the width of the bitmap
m_iGlyphsPerRow - how many characters are represented in one row of the font bitmap. For instance:
ABCDEF
GHIJKL
GlyphsPerRow would be 7. The GlyphArray would look like this:
ABCDEFGHIJKL
Apply these formulas to the glyph position and you will get the u,v position of the glyph in the font bitmap.
StartU=(GlyphNum % GlyphsPerRow) * UIncrement)
TempV=int(GlyphNum / GlyphsPerRow)
StartV=(float)TempV* VIncrement
Then the u,v coords for the vertices are:
Upper left - StartU,StartV
Upper right - StartU+m_fUIncrement,StartV
Lower left - StartU,StartV+m_fVIncrement
Lower right - StartU+m_fUIncrement,StartV+m_fVIncrement
Note this method uses 1 texture thus saving a lot of memory. You are simply indexing into the bitmap in order to display the correct portion of the bitmap - the correct letter. A background texture can be used as well - either for each letter (background bitmap is as large as font bitmap) or one bitmap for all letters.