某些字符的位图字体无法正确呈现

Bitmap fonts not rendering correctly for some characters

我正在从这里生成位图字体纹理 - https://snowb.org/

Name - wxyz”的字体呈现如下 -

该代码与 post 针对此问题编写的代码非常相似 - ,因此我将只 post 我的四边形和纹理坐标计算代码字符(我正在使用带有单位视图矩阵的正交投影)-

// 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;
   }

问题 -

如您所见,某些字体无法正确呈现。小写字母 'y' 显示为大写字母 'Y',连字符“-”显示为“_”,而 space ' ' 根本没有出现。 从 https://snowb.org/ 生成的字体文本文件包含从 ascii 32 到 125 的每个字符的这些参数,下面是一个示例-

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

其中,如您在上面的代码中所见,我仅使用了 x、y、宽度、高度和 xAdvance。尝试在纹理坐标中使用 xOffset/fontAtlasWidth 和 yoffset/fontAtlasHeight 并没有解决这些问题,而且还进一步弄乱了其他字符。

能否指导我在计算中需要修改哪些内容才能正确呈现所有字符?

编辑:

这样添加 y 偏移量,

      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;

结果像这样

这是如果添加了 yoffset -

正如评论中所建议的,偏移量具有不同的含义。

x,ywidth, height为输入坐标,xoffsetyoffset为书写坐标。

整个渲染过程应该是这样的(伪代码)

int cursor_x = 0;
int cursor_y = 0;

for (auto const &i : my_string) {
    auto const &tex = texData[i]; // let throw if not found
    for (int y = 0; y < tex.height; y++) {
        for (int x = 0; x < tex.width; x++) {
            auto x_pos = x + cursor_x + tex.xoffset;
            auto y_pos = y + cursor_y + tex.yoffset;

            my_canvas.setPixel(x_pos, y_pos,
                font_png.getPixel(x + tex.x, y + tex.y));
        }
    }
    cursor_x += tex.xadvance;
}

我添加到问题中的代码对我有用的是修改 y 顶点坐标

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

经过此修改,文本正确显示如下 -