使用 freetype 渲染字体

时间:2021-07-14 12:20:43

标签: c++ opengl rendering freetype

我制作了 opengl 渲染引擎,我可以渲染形状、3d 形状和纹理。然后我想渲染字体。我使用 freetype 库来做到这一点。但我有一个严重的问题。当我渲染字体时,它看起来很糟糕。首先我会解释我是如何初始化 freetype 和加载字体的,然后我是如何渲染纹理的,这样你就可以看到它是否有任何错误。

  1. 我像这样初始化 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);
    
  2. 然后我将它加载到我的纹理中:

    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;
    };
    
  3. 从缓冲函数中加载如下所示:

    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 的纹理。

代码对我来说看起来很正常,但是当我运行它时,纹理看起来像这样:

enter image description here

无论纹理大小或四边形大小,字母都是三倍。 整个形象很糟糕。

2 个答案:

答案 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);
}
相关问题