某些字符的位图字体无法正确呈现
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,y
、width, height
为输入坐标,xoffset
、yoffset
为书写坐标。
整个渲染过程应该是这样的(伪代码)
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;
经过此修改,文本正确显示如下 -
我正在从这里生成位图字体纹理 - https://snowb.org/
“Name - wxyz”的字体呈现如下 -
该代码与 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,y
、width, height
为输入坐标,xoffset
、yoffset
为书写坐标。
整个渲染过程应该是这样的(伪代码)
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;
经过此修改,文本正确显示如下 -