Freetype 和 OpenGL 的问题
嘿,我在使用 Freetype 2 库加载的 openGL 中绘制文本时遇到了一个奇怪的问题。这是我所看到的屏幕截图。
示例 http://img203.imageshack.us/img203/3316/freetypeweird.png
这是我用于加载和渲染文本的代码位。
class Font
{
Font(const String& filename)
{
if (FT_New_Face(Font::ftLibrary, "arial.ttf", 0, &mFace)) {
cout << "UH OH!" << endl;
}
FT_Set_Char_Size(mFace, 16 * 64, 16 * 64, 72, 72);
}
Glyph* GetGlyph(const unsigned char ch)
{
if(FT_Load_Char(mFace, ch, FT_LOAD_RENDER))
cout << "OUCH" << endl;
FT_Glyph glyph;
if(FT_Get_Glyph( mFace->glyph, &glyph ))
cout << "OUCH" << endl;
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
Glyph* thisGlyph = new Glyph;
thisGlyph->buffer = bitmap_glyph->bitmap.buffer;
thisGlyph->width = bitmap_glyph->bitmap.width;
thisGlyph->height = bitmap_glyph->bitmap.rows;
return thisGlyph;
}
};
相关的字形信息(宽度、高度、缓冲区)存储在以下结构中
struct Glyph {
GLubyte* buffer;
Uint width;
Uint height;
};
最后,为了渲染它,我有一个名为 RenderFont 的类。
class RenderFont
{
RenderFont(Font* font)
{
mTextureIds = new GLuint[128];
mFirstDisplayListId=glGenLists(128);
glGenTextures( 128, mTextureIds );
for(unsigned char i=0;i<128;i++)
{
MakeDisplayList(font, i);
}
}
void MakeDisplayList(Font* font, unsigned char ch)
{
Glyph* glyph = font->GetGlyph(ch);
glBindTexture( GL_TEXTURE_2D, mTextureIds[ch]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
glyph->width,
glyph->height,
0,
GL_ALPHA,
GL_UNSIGNED_BYTE,
glyph->buffer);
glNewList(mFirstDisplayListId+ch,GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, mTextureIds[ch]);
glBegin(GL_QUADS);
glTexCoord2d(0,1); glVertex2f(0,glyph->height);
glTexCoord2d(0,0); glVertex2f(0,0);
glTexCoord2d(1,0); glVertex2f(glyph->width,0);
glTexCoord2d(1,1); glVertex2f(glyph->width,glyph->height);
glEnd();
glTranslatef(16, 0, 0);
glEndList();
}
void Draw(const String& text, Uint size, const TransformComponent* transform, const Color32* color)
{
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTranslatef(100, 250, 0.0f);
glListBase(mFirstDisplayListId);
glCallLists(text.length(), GL_UNSIGNED_BYTE, text.c_str());
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glLoadIdentity();
}
private:
GLuint mFirstDisplayListId;
GLuint* mTextureIds;
};
有人能看到这里发生了什么奇怪的事情会导致乱码吗?这很奇怪,因为如果我更改字体大小或 DPI,那么一些正确显示的字母会变成乱码,而其他之前乱码的字母会正确显示。
Hey, i'm having a weird issue with drawing text in openGL loaded with the Freetype 2 library. Here is a screenshot of what I'm seeing.
example http://img203.imageshack.us/img203/3316/freetypeweird.png
Here are my code bits for loading and rendering my text.
class Font
{
Font(const String& filename)
{
if (FT_New_Face(Font::ftLibrary, "arial.ttf", 0, &mFace)) {
cout << "UH OH!" << endl;
}
FT_Set_Char_Size(mFace, 16 * 64, 16 * 64, 72, 72);
}
Glyph* GetGlyph(const unsigned char ch)
{
if(FT_Load_Char(mFace, ch, FT_LOAD_RENDER))
cout << "OUCH" << endl;
FT_Glyph glyph;
if(FT_Get_Glyph( mFace->glyph, &glyph ))
cout << "OUCH" << endl;
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
Glyph* thisGlyph = new Glyph;
thisGlyph->buffer = bitmap_glyph->bitmap.buffer;
thisGlyph->width = bitmap_glyph->bitmap.width;
thisGlyph->height = bitmap_glyph->bitmap.rows;
return thisGlyph;
}
};
The relevant glyph information (width, height, buffer) is stored in the following struct
struct Glyph {
GLubyte* buffer;
Uint width;
Uint height;
};
And finally, to render it, I have this class called RenderFont.
class RenderFont
{
RenderFont(Font* font)
{
mTextureIds = new GLuint[128];
mFirstDisplayListId=glGenLists(128);
glGenTextures( 128, mTextureIds );
for(unsigned char i=0;i<128;i++)
{
MakeDisplayList(font, i);
}
}
void MakeDisplayList(Font* font, unsigned char ch)
{
Glyph* glyph = font->GetGlyph(ch);
glBindTexture( GL_TEXTURE_2D, mTextureIds[ch]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
glyph->width,
glyph->height,
0,
GL_ALPHA,
GL_UNSIGNED_BYTE,
glyph->buffer);
glNewList(mFirstDisplayListId+ch,GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, mTextureIds[ch]);
glBegin(GL_QUADS);
glTexCoord2d(0,1); glVertex2f(0,glyph->height);
glTexCoord2d(0,0); glVertex2f(0,0);
glTexCoord2d(1,0); glVertex2f(glyph->width,0);
glTexCoord2d(1,1); glVertex2f(glyph->width,glyph->height);
glEnd();
glTranslatef(16, 0, 0);
glEndList();
}
void Draw(const String& text, Uint size, const TransformComponent* transform, const Color32* color)
{
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTranslatef(100, 250, 0.0f);
glListBase(mFirstDisplayListId);
glCallLists(text.length(), GL_UNSIGNED_BYTE, text.c_str());
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glLoadIdentity();
}
private:
GLuint mFirstDisplayListId;
GLuint* mTextureIds;
};
Can anybody see anything weird going on here that would cause the garbled text? It's strange because if I change the font size, or the DPI, then some of the letters that display correctly become garbled, and other letters that were garbled before then display correctly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我对 FreeType 不熟悉,但从图片来看,字符的宽度与缓冲区的大小没有直接关系(即 glyph->buffer 不指向 glyph->buffer 的数组)宽度*字形->高度字节)。
作为猜测,我想说所有字符在内存中都有一个宽度(而不是它们在屏幕上使用的大小),可能是字形所有宽度中最大的,但是您使用每个字符加载它们宽度而不是正确的宽度。因此,只有使用全宽度的字形才是正确的。
I'm not familiar with FreeType, but from the picture, it looks like the width of the characters is not directly related to the size of the buffers (ie. glyph->buffer does not point to an array of glyph->width*glyth->height bytes).
As a guess, I'd say that all the chars have a single width in memory (as opposed to the size they use on screen), probably the biggest of all the widths of the glyphs, but you load them with a per-char width instead of the correct one. So, only the glyphs that use the full width are correct.
使用:
这也让我很恼火,但是你需要告诉 OpenGL 使用你给它的间距,而不是它期望的正常 32 位边界。图像的间距会发生变化,但在纹理创建之前如果没有这些调用,
OpenGL
就不知道使用较小的打包对齐方式。我这样做:
我可能可以将 255(白色)移动到字符串初始化函数中,然后只需使用
FreeType
中的值作为我的 alpha 值,但这种方式似乎更具描述性,而且速度并不快我的使用中的一个问题。地址和数据[0] 现在包含
GL_LUMINANCE_ALPHA 外部
格式,类型为GL_UNSIGNED_CHAR
,大小为_Width*_Height
。这应该会让任何从事这些工作的人的生活变得更轻松。Use:
This annoyed the heck out of me too, but you need to tell OpenGL to use the spacing you give it, not the normal 32-bit boundaries it expects. The pitch of the images changes, but
OpenGL
doesn't know to use smaller packing alignments without these calls before your texture creation.I do it like this:
I could probably move the 255 (White) into the String initialization function then just use the values in
FreeType
for my alpha values, but this way seems more descriptive and speed isn't an issue in my usage.The Address &Data[0] now contains a
GL_LUMINANCE_ALPHA external
format, with typeGL_UNSIGNED_CHAR
and size_Width*_Height
. This should make anyone who does this stuff's life easier.您确定
FT_Glyph
实际上是位图字形吗?确保使用FT_Glyph_To_Bitmap
或者,由于您似乎不需要随后存储 FT_Glyph,您可以这样做:
请参阅 此处获取有关
FT_Bitmap
的文档。请注意,下次调用FT_Load_Char
时,bitmap
中的数据将不再有效。您还存在许多内存管理问题。
您使用
new Glyph
来分配您的字形,但永远不要调用delete。
由于您只需要临时创建一个字形来生成纹理和显示列表,因此您应该使用std::auto_ptr
。您从未调用
FT_Glyph_Done
,因此您分配的所有FT_Glyph
永远不会释放。Are you sure that the
FT_Glyph
is actually a bitmap glyph? Make sure you useFT_Glyph_To_Bitmap
first.Alternatively, since you don't seem to need to store the
FT_Glyph
s around afterwards, you can just do:See here for the docs on
FT_Bitmap
. Just note that the next time you callFT_Load_Char
, the data inbitmap
will no longer be valid.You also have a number of issues with memory management.
You use
new Glyph
to allocate your glyphs, but never calldelete.
Since you just need to temporarily make a glyph to generate the texture and display list, you should use anstd::auto_ptr<Glyph>
.You never call
FT_Glyph_Done
, so all thoseFT_Glyph
s you allocated are never released.“16”应该是以磅为单位的字体大小。因此,在翻译时,您应该使用 glyph->width 而不是“16”。此外,某些字母可能需要字距调整以获得最佳外观的文本。例如,在不使用字距调整的情况下,“AV”可能看起来像“AV”。
"16" should be the size of font in points. So, while translating you should use glyph->width instead of "16". Moreover, some letters may require kerning for best-looking texts. For example "AV" may look like "A V" without kerning usage.