我正在渲染带有旋转字符的字体图集,因为我的整个文本框已旋转。 现在我想计算文本框轮廓以呈现彩色背景。
如果我只计算渲染顶点的最小包围矩形,则会产生未对齐的框,因为字符在纹理图集中旋转(参见1)。我还渲染了纹理切口以更好地理解问题(参见2):
角色地图集创建代码:
#include <ft2build.h>
#include FT_FREETYPE_H
....
FT_Face face = ...
int height = ...
int angle = ...
FT_Set_Pixel_Sizes(face, 0, height);
FT_GlyphSlot g = face->glyph;
int roww = border;
int rowh = 0;
int w = 0;
int h = 0;
FT_Matrix matrix; /* transformation matrix */
const float angleF = angle / 180.f * PI;
matrix.xx = (FT_Fixed)(cos(angleF) * 0x10000L);
matrix.xy = (FT_Fixed)(-sin(angleF) * 0x10000L);
matrix.yx = (FT_Fixed)(sin(angleF) * 0x10000L);
matrix.yy = (FT_Fixed)(cos(angleF) * 0x10000L);
FT_Set_Transform(face, &matrix, 0);
memset(character, 0, sizeof character);
/* Find minimum size for a texture holding all visible ASCII characters */
for (int i = 32; i < Character::MAXIMUM; i++) {
if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
fprintf(stderr, "Loading character %c failed! Height is %d\n", i, height);
continue;
}
if (roww + g->bitmap.width + 1 + border >= MAXWIDTH) {
w = std::max(w, roww);
h += rowh;
roww = border;
rowh = 0;
}
roww += g->bitmap.width + 1 + border;
rowh = std::max(rowh, (int)g->bitmap.rows + border);
}
w = std::max(w, roww);
h += rowh + border;
glUseProgram(0);
glEnable(GL_TEXTURE_2D);
/* Create a texture that will be used to hold all ASCII glyphs */
glActiveTexture(GL_TEXTURE0);
if (!OpenGLResourceManager::emptyTexture(tex, w, h, 1)) {
// Texture loading failed. Keep this atlas empty
glDisable(GL_TEXTURE_2D);
return;
}
tex.bindTexture();
/* We require 1 byte alignment when uploading texture data */
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
{
//Fill texture with black to prevent texture bleeding
std::vector<GLubyte> emptyData(w * h, 0);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_LUMINANCE, GL_UNSIGNED_BYTE, &emptyData[0]);
}
/* Clamping to edges is important to prevent artifacts when scaling */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/* Linear filtering usually looks best for text */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* Paste all glyph bitmaps into the texture, remembering the offset */
int ox = border;
int oy = border;
rowh = 0;
for (int i = 32; i < Character::MAXIMUM; i++) {
if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
fprintf(stderr, "Loading character %c failed!\n", i);
continue;
}
if (ox + g->bitmap.width + 1 + border >= MAXWIDTH) {
oy += rowh;
rowh = 0;
ox = border;
}
glTexSubImage2D(GL_TEXTURE_2D, 0, ox, oy, g->bitmap.width, g->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer);
character[i].ax = g->advance.x >> 6;
character[i].ay = g->advance.y >> 6;
character[i].bw = g->bitmap.width;
character[i].bh = g->bitmap.rows;
character[i].bl = g->bitmap_left;
character[i].bt = g->bitmap_top;
character[i].tx = ox / (float)w;
character[i].ty = oy / (float)h;
rowh = std::max(rowh, (int)g->bitmap.rows + border);
ox += g->bitmap.width + 1 + border;
}
glBindTexture(GL_TEXTURE_2D, NULL);
glDisable(GL_TEXTURE_2D);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); //Standard
如何获取文本的视觉边界(而不是顶点边界)?
更新:必须为像素完美字体旋转纹理而不是顶点,请参阅以下特写:
(请忽略投影中的差异)