我制作了 opengl 渲染引擎,我可以渲染形状、3d 形状和纹理。然后我想渲染字体。我使用 freetype 库来做到这一点。但我有一个严重的问题。当我渲染字体时,它看起来很糟糕。首先我会解释我是如何初始化 freetype 和加载字体的,然后我是如何渲染纹理的,这样你就可以看到它是否有任何错误。
我像这样初始化 freetype 并加载字体:
FT_Library library;
FT_Face face;
FT_GlyphSlot slot;
FT_Init_FreeType(&library);
FT_New_Face(library, "arial.ttf", 0, &face);
FT_Set_Char_Size(face, 0, 20 * 64, 300, 300);
slot = face->glyph;
FT_Load_Char(face, 'a', FT_LOAD_RENDER);
然后我将它加载到我的纹理中:
this->tex.LoadFromBuffer(slot->bitmap.buffer, slot->bitmap.width, slot->bitmap.rows);
tex 对象只是看起来像这样的纹理容器:
class Texture
{
public:
void LoadFromBuffer(unsigned char* buf, int w, int h);
float sizex, sizey;
GLuint texName;
};
从缓冲函数中加载如下所示:
void Texture::LoadFromBuffer(unsigned char* buf, int w, int h)
{
this->sizex = w;
this->sizey = h;
glGenTextures(1, &this->texName);
glBindTexture(GL_TEXTURE_2D, this->texName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, buf);
glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(buf);
}
然后创建纹理,我在小队中使用 opengl 正常渲染它:
void Renderer::Render(Quad& quadv)
{
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D, quadv.texture->texName);
glBegin(GL_QUADS);
glColor3f(quadv.color.r, quadv.color.g, quadv.color.b);
glTexCoord2f(0.0, 0.0); glVertex2f(quadv.vertices[0].x, quadv.vertices[0].y);
glTexCoord2f(1.0, 0.0); glVertex2f(quadv.vertices[1].x, quadv.vertices[1].y);
glTexCoord2f(1.0, 1.0); glVertex2f(quadv.vertices[2].x, quadv.vertices[2].y);
glTexCoord2f(0.0, 1.0); glVertex2f(quadv.vertices[3].x, quadv.vertices[3].y);
glEnd();
glDisable(GL_TEXTURE_2D);
}
Quadv 是包含四边形顶点的对象,但在这里并不重要。 quadv 中的纹理是我之前加载的带有字母 a 的纹理。
代码对我来说看起来很正常,但是当我运行它时,纹理看起来像这样:
无论纹理大小或四边形大小,字母都是三倍。 整个形象很糟糕。
答案 0 :(得分:0)
我不记得使用 FT 时默认的 PixelMode 是什么。 但在我看来,您认为 FT 提供的位图是 32 位 RGBA 颜色,但事实可能并非如此。
我假设它是 8 位颜色。尝试更改:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, buf);
到
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, buf);
我们将作为输入格式的 GL_RGB 替换为 GL_RED,这样 tex 图像函数期望每个像素有 1 个分量。 FT2 Documentation 了解更多信息
答案 1 :(得分:0)
位图每个像素包含 1 个通道,以单个字节编码。由于您使用的是旧版 OpenGL,我建议您使用内部纹理格式 GL_ALPHA
。因此,纹理的每个元素都被视为单个 alpha 分量。
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, buf);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, buf);
启用 Blending 以仅显示字形的不透明部分:
void Renderer::Render(Quad& quadv)
{
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D, quadv.texture->texName);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBegin(GL_QUADS);
glColor3f(quadv.color.r, quadv.color.g, quadv.color.b);
glTexCoord2f(0.0, 0.0); glVertex2f(quadv.vertices[0].x, quadv.vertices[0].y);
glTexCoord2f(1.0, 0.0); glVertex2f(quadv.vertices[1].x, quadv.vertices[1].y);
glTexCoord2f(1.0, 1.0); glVertex2f(quadv.vertices[2].x, quadv.vertices[2].y);
glTexCoord2f(0.0, 1.0); glVertex2f(quadv.vertices[3].x, quadv.vertices[3].y);
glEnd();
glDisable(GL_TEXTURE_2D);
}