Bitmap font rendering, UV generation and vertex placement

Posted by jack on Game Development See other posts from Game Development or by jack
Published on 2011-01-10T06:07:59Z Indexed on 2011/01/10 6:59 UTC
Read the original article Hit count: 300

Filed under:
|
|
|
|

I am generating a bitmap, however, I am not sure on how to render the UV's and placement. I had a thread like this once before, but it was too loosely worded as to what I was looking to do.

What I am doing right now is creating a large 1024x1024 image with characters evenly placed every 64 pixels. Here is an example of what I mean. I then save the bitmap X/Y information to a file (which is all multiples of 64).

However, I am not sure how to properly use this information and bitmap to render. This falls into two different categories, UV generation and kerning. Now I believe I know how to do both of these, however, when I attempt to couple them together I will get horrendous results.

For example, I am trying to render two different text arrays, "123" and "njfb". While ignoring the texture quality (I will be increasing the texture to provide more detail once I fix this issue), here is what it looks like when I try to render them.

http://img64.imageshack.us/img64/599/badfontrendering.png

Now for the algorithm. I am doing my letter placement with both GetABCWidth and GetKerningPairs. I am using GetABCWidth for the width of the characters, then I am getting the kerning information for adjust the characters.

Does anyone have any suggestions on how I can implement my own bitmap font renderer? I am trying to do this without using external libraries such as angel bitmap tool or freetype. I also want to stick to the way the bitmap font sheet is generated so I can do extra effects in the future.

Rendering Algorithm

for(U32 c = 0, vertexID = 0, i = 0; c < numberOfCharacters; ++c, vertexID += 4, i += 6) 
{ 

    ObtainCharInformation(fontName, m_Text[c]);

    letterWidth = (charInfo.A + charInfo.B + charInfo.C) * scale;

    if(c != 0)
    {

        DWORD BytesReq = GetGlyphOutlineW(dc, m_Text[c], GGO_GRAY8_BITMAP, &gm, 0, 0, &mat);
        U8 * glyphImg= new U8[BytesReq];
        DWORD r = GetGlyphOutlineW(dc, m_Text[c], GGO_GRAY8_BITMAP, &gm, BytesReq, glyphImg, &mat);

        for (int k=0; k<nKerningPairs; k++)
        {
            if ((kerningpairs[k].wFirst == previousCharIndex) && (kerningpairs[k].wSecond == m_Text[c])) {
                letterBottomLeftX += (kerningpairs[k].iKernAmount * scale);
                break;
            }
        }

        letterBottomLeftX -= (gm.gmCellIncX * scale);
    }

    SetVertex(letterBottomLeftX, 0.0f, zFight, vertexID);
    SetVertex(letterBottomLeftX, letterHeight, zFight, vertexID + 1);
    SetVertex(letterBottomLeftX + letterWidth, letterHeight, zFight, vertexID + 2);
    SetVertex(letterBottomLeftX + letterWidth, 0.0f, zFight, vertexID + 3);
    zFight -= 0.001f;

    float BottomLeftX = (F32)(charInfo.bitmapXOrigin) / (float)m_BitmapWidth;
    float BottomLeftY = (F32)(charInfo.bitmapYOrigin + charInfo.charBitmapHeight) / (float)m_BitmapWidth;

    float TopLeftX = BottomLeftX;
    float TopLeftY = (F32)(charInfo.bitmapYOrigin) / (float)m_BitmapWidth;

    float TopRightX = (F32)(charInfo.bitmapXOrigin + charInfo.B - charInfo.C) / (float)m_BitmapWidth;
    float TopRightY = TopLeftY;

    float BottomRightX = TopRightX;
    float BottomRightY = BottomLeftY;

    SetTextureCoordinate(TopLeftX, TopLeftY, vertexID + 1);
    SetTextureCoordinate(BottomLeftX, BottomLeftY, vertexID + 0);
    SetTextureCoordinate(BottomRightX, BottomRightY, vertexID + 3);
    SetTextureCoordinate(TopRightX, TopRightY, vertexID + 2);

    /// index setting

    letterBottomLeftX += letterWidth;

    previousCharIndex = m_Text[c];

}

© Game Development or respective owner

Related posts about c++

Related posts about graphics