使用 Freetype 和 OpenGL 渲染字体

Posted

技术标签:

【中文标题】使用 Freetype 和 OpenGL 渲染字体【英文标题】:Rendering fonts with Freetype and OpenGL 【发布时间】:2014-12-03 11:38:30 【问题描述】:

我有问题 freetype 和 OpenGL。我只需要在单个纹理上绘制所有加载的符号。这是:

    FT_Init_FreeType(&lib);
    FT_New_Face(lib, "C:\\verdana.ttf", 0, &face);
    FT_Set_Pixel_Sizes(face, 0, size);

    auto ww = 256 * size;
    auto hh = size;

    std::vector<unsigned char> buffer(ww * hh, 0);

    int off = 0;

    for (int c = 0; c < 256; c++)
    
        FT_UInt GlyphIndex;

        GlyphIndex = FT_Get_Char_Index(face, c);

        FT_Load_Char(face, GlyphIndex, FT_LOAD_RENDER);

        FT_Bitmap bmp = face->glyph->bitmap;

        int advance = (face->glyph->advance.x >> 6);
        int bW = bmp.width; 
        int bH = bmp.rows;

        for (int h = 0; h < bH; ++h) 
            for (int w = 0; w < bW; ++w) 

                buffer[h * bW + off + w] = bmp.buffer[w + bW * h];
            
        

        off += advance;

    


    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, ww, hh, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &buffer[0]);

我尝试了很多方法来做到这一点。但我得到的只是绝对黑色的质地...... 我的代码有什么问题?

【问题讨论】:

您是否检查了从 FT_Init_FreeType、FT_New_Face 等返回的错误代码?此外,可能还需要调用 FT_Set_Char_Size。 我在代码的任何部分都没有发现错误。我已经用 FT_Set_Pixel_Sizes 设置了字符大小。 但是你也不检查错误。每个 freetype 函数都会返回一个值,指示它是成功/失败。例如:error = FT_Init_FreeType( &amp;library ); if ( error ) failed; 相信我,我在发布之前已经这样做了...... 我刚刚注意到的另一件事:FT_Load_Char 假定字符代码作为第二个参数而不是字形索引。难道你的意思是 FT_Load_Glyph? 【参考方案1】:

我认为问题在于 0-255 之间的某些值是不可见或不可绘制的字符,这就是为什么你什么也得不到。

您应该检查 GlyphIndex:

GlyphIndex = FT_Get_Char_Index(face, c);
if (!GlyphIndex) continue;

那么你可以期待 freetype 为你绘制其余的字符。

【讨论】:

【参考方案2】:

哈利路亚,我有办法了!

这应该是这样的:

for (int c = 0; c < 256; c++)
    
        FT_UInt GlyphIndex;

        GlyphIndex = FT_Get_Char_Index(face, c);

        FT_Load_Char(face, GlyphIndex, FT_LOAD_RENDER);

        FT_Bitmap bmp = face->glyph->bitmap;

        int advance = (face->glyph->advance.x >> 6);
        int bW = bmp.width; 
        int bH = bmp.rows;

        for (int h = 0; h < bH; ++h) 
            for (int w = 0; w < bW; ++w) 

                buffer[h * ww + off + w] = bmp.buffer[w + bW * h];
            
        

        off += advance;

    


    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, ww, hh, 0, GL_RED, GL_UNSIGNED_BYTE, &buffer[0]);

【讨论】:

以上是关于使用 Freetype 和 OpenGL 渲染字体的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL FreeType2 位图不渲染

◮OpenGL-文本渲染

◮OpenGL-文本渲染

什么是使用 Pango 使用 FreeType 字体将文本渲染为图像的简单示例?

FreeType2 - 字体更小

fedora25配置 Infinality 字体渲染增强