【问题标题】:Render fonts with freetype使用 freetype 渲染字体
【发布时间】:2021-09-23 10:16:58
【问题描述】:

我做了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 是包含 quad 顶点的对象,但在这里并不重要。 quadv 中的纹理是我之前加载的带有字母 a 的纹理。

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

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

【问题讨论】:

    标签: c++ opengl rendering freetype


    【解决方案1】:

    我不记得使用 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了解更多信息

    【讨论】:

    • 非常感谢,现在看起来好多了。现在四边形中只有一个字母,它填满了整个四边形。但是字母颜色现在是红色的,知道如何将其更改为黑色吗?由于某种原因,字母周围的背景也是黑色的。
    • 您现在发出的命令是告诉 opengl 您正在创建的纹理有四个组件。 R G B A,但你只给它 R 作为输入。老实说,我不确定 G B A 的默认值是什么。但是一个解决方案是修改你的着色器,只从纹理中读取 R 值并将其用作 alpha。例如:浮动强度 = texture2D(Texture, Uvs).r; gl_FragColor = vec4(1.0, 1.0, 1.0, 强度);
    • 我查看了 opengl GL_RED 的文档每个元素都是一个红色组件。 GL 将其转换为浮点数并将其组合成一个 RGBA 元素,方法是为绿色和蓝色附加 0,为 alpha 附加 1。每个组件都被限制在 [0,1] 范围内。
    • “假设它是 8 位颜色” 这不是很可靠。你必须实际检查你得​​到的格式(通常是每像素 1 位或 8 位)。
    【解决方案2】:

    位图每个像素包含 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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-10
      • 1970-01-01
      • 2019-05-20
      • 1970-01-01
      • 1970-01-01
      • 2019-04-15
      相关资源
      最近更新 更多