Search code examples
c++textgraphicsbitmap

Bitmap fonts not rendering correctly for some characters


I am generating the bitmap font texture from here - https://snowb.org/

The font for "Name - wxyz" is rendering as below -

example

The code is very much similar to the one posted for this question - Bitmap font rendering issue, so I will only post my code for the quad and texture coordinate calculation for the characters (I am using orthographic projection with identity view matrix)-

// beginOffsetX and beginOffsetY is just some offset where I want the text to appear
// fontAtlasWidth and fontAtlasHeight is size of texture
// texData contains all the parameters that can be read from the font.txt generated from the same bitmap generator website (parameters are described later below)

   float xAdvance = 0.0f;
   fontVertices.resize(texData.size() * 4);
   fontTexCoords.resize(texData.size() * 4);
   for (unsigned int i = 0; i < texData.size(); i++)
   {
      float xcoordBegin = beginOffsetX + xAdvance;
      float xcoordEnd = beginOffsetX + xAdvance + texData[i].width;
      float ycoordBegin = beginOffsetY;
      float ycoordEnd = beginOffsetY + texData[i].height;

      fontVertices[4u * i + 0] = geometry_utils::vec3{ xcoordBegin, ycoordEnd, 0.0f };
      fontVertices[4u * i + 1] = geometry_utils::vec3{ xcoordBegin, ycoordBegin, 0.0f };
      fontVertices[4u * i + 2] = geometry_utils::vec3{ xcoordEnd, ycoordEnd, 0.0f };
      fontVertices[4u * i + 3] = geometry_utils::vec3{ xcoordEnd, ycoordBegin, 0.0f };

      float xtexcoordBegin = texData[i].x;
      float xtexcoordEnd = texData[i].x + texData[i].width / fontAtlasWidth;
      float ytexcoordBegin = texData[i].y;
      float ytexcoordEnd = texData[i].y + texData[i].height / fontAtlasHeight;

      fontTexCoords[4u * i + 0] = geometry_utils::vec2{ xtexcoordBegin, ytexcoordBegin };
      fontTexCoords[4u * i + 1] = geometry_utils::vec2{ xtexcoordBegin, ytexcoordEnd };
      fontTexCoords[4u * i + 2] = geometry_utils::vec2{ xtexcoordEnd, ytexcoordBegin };
      fontTexCoords[4u * i + 3] = geometry_utils::vec2{ xtexcoordEnd, ytexcoordEnd };

      xAdvance += texData[i].width;
   }

Issue -

As you can see some of the fonts are not rendering correctly. Small case 'y' is appearing as capital 'Y', hyphen '-' is appearing as '_', and space ' ' is not appearing at all. The font text file generated from https://snowb.org/ contains these parameters for every character from ascii 32 to 125, below is one example-

char id=33 x=331 y=52 width=14 height=42 xoffset=-1 yoffset=-1 xadvance=13 page=0 chnl=15

Out of these, as you can see in the above code, I am using only x,y, width, height and xAdvance. Attempting to use xOffset/fontAtlasWidth and yoffset/fontAtlasHeight in the texture coordinates did not fix these issues and also further messed up the other characters.

Could you please guide me as to what I need to modify in my calculations to get all the characters to render correctly?

Edit:

Adding the y-offset as this,

      float xtexcoordBegin = texData[i].x;
      float xtexcoordEnd = texData[i].x + texData[i].width / fontAtlasWidth ;
      float ytexcoordBegin = texData[i].y - texData[i].yOffset / fontAtlasHeight;
      float ytexcoordEnd = texData[i].y + texData[i].height / fontAtlasHeight;

results in image like this

enter image description here

This is if the yoffset is added instead -

enter image description here


Solution

  • The thing that worked for me with the code I have added to the question was to modify the y vertex coordinate as such

          float ycoordBegin = beginOffsetY - texData[i].height - texData[i].yOffset;
          float ycoordEnd = beginOffsetY - texData[i].yOffset;
    

    With this modification the text appears correctly as below -

    enter image description here