Freetype Library 提供三重纹理和奇怪的符号

Freetype Library gives triple textures and weird symbols

目前正在处理一个 android ndk/opengl 项目,我正在尝试使用 freetype 作为我的字体渲染库,但是当我将文本渲染到屏幕上时,我总是收到一个奇怪的错误。以下是一些示例文本的显示内容:(注意:底部的应该是 "This is")

设置:

void TextRenderer::SetupGlyphs(std::string fontPath, int size){
    __android_log_print(ANDROID_LOG_INFO, "SetupGlyphs", "Font location: %s", fontPath.c_str());
    if(shadersInitialized == 0)
        CreateShader();
    glUseProgram(this->shader);

    // FreeType
    FT_Library ft;
    if (FT_Init_FreeType(&ft))
        __android_log_print(ANDROID_LOG_INFO, "SetupGlyphs", "ERROR::FREETYPE: Could not init FreeType Library.");

    FT_Face face;
    if (FT_New_Face(ft, fontPath.c_str(), 0, &face))
        __android_log_print(ANDROID_LOG_INFO, "SetupGlyphs", "ERROR::FREETYPE: Failed to load font: %s", fontPath.c_str());

    FT_Set_Pixel_Sizes(face, 0, size);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    for (GLubyte c = 0; c < 128; c++){
        if(FT_Load_Char(face, c, FT_LOAD_RENDER)){
            __android_log_print(ANDROID_LOG_INFO, "SetupGlyphs", "ERROR::FREETYPE: Failed to load Glyph");
            continue;
        }
        GLuint texture;
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexImage2D(
                GL_TEXTURE_2D,
                0,
                GL_RGB,
                face->glyph->bitmap.width,
                face->glyph->bitmap.rows,
                0,
                GL_RGB,
                GL_UNSIGNED_BYTE,
                face->glyph->bitmap.buffer
        );
        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);

        Character character = {
                texture,
                ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
                ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
                static_cast<GLuint>(face->glyph->advance.x)
        };
        characters.insert(std::pair<GLchar, Character>(c, character));
    }
    glBindTexture(GL_TEXTURE_2D, 0);
    FT_Done_Face(face);
    FT_Done_FreeType(ft);
}

渲染:

void TextRenderer::RenderTexts()
{
    if(shadersInitialized == 0)
        CreateShader();
    // Activate corresponding render state
    glUseProgram(this->shader);

    GLuint projectionLocation = glGetUniformLocation(this->shader, "projection");
    glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, projectionMatrix);

    for (int i=0; i<projects.size(); i++) {

        ProjectLabel project = projects.at(i);
        glUniform3f(glGetUniformLocation(this->shader, "textColor"), project.textColor.x, project.textColor.y, project.textColor.z);
        glActiveTexture(GL_TEXTURE0);

        GLuint vertexBuffer;
        glGenBuffers(1, &vertexBuffer);

        /* Set up the VBO for our vertex data */
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);

        // Iterate through all characters
        std::string::const_iterator c;
        GLuint x = project.x;
        for (c = project.text.begin(); c != project.text.end(); c++)
        {

            Character ch = characters[*c];

            GLfloat xpos = x + ch.Bearing.x;
            GLfloat ypos = project.y - (ch.Size.y - ch.Bearing.y);

            GLfloat w = ch.Size.x;
            GLfloat h = ch.Size.y;
            // Update VBO for each character
            GLfloat vertices[6*4] = {
                     xpos,     ypos + h,   0.0, 0.0 ,
                     xpos,     ypos,       0.0, 1.0 ,
                     xpos + w, ypos,       1.0, 1.0 ,

                     xpos,     ypos + h,   0.0, 0.0 ,
                     xpos + w, ypos,       1.0, 1.0 ,
                     xpos + w, ypos + h,   1.0, 0.0
            };

            glBindTexture(GL_TEXTURE_2D, ch.TextureID);

            glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
            glDrawArrays(GL_TRIANGLES, 0, 6);

            x += (ch.Advance / 64); // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))
        }
        glDisableVertexAttribArray(0);
    }
    glBindTexture(GL_TEXTURE_2D, 0);

}

因此,对于可能发现此 post 的任何人,我在网上搜索了几个小时,试图找出为什么一切看起来都很时髦,我找到了答案。 Freetype 没有通过 GL_RGB 对齐(至少在我的项目中没有),而是通过 GL_LUMINANCE 对齐。通过更改 glTexImage2D 中的此类内容,我解决了上述问题,以及 SIGABRT 我也遇到的错误。

TLDR;

glTexImage2D(
            GL_TEXTURE_2D,
            0,
            GL_RGB,                        => GL_LUMINANCE
            face->glyph->bitmap.width,
            face->glyph->bitmap.rows,
            0,
            GL_RGB,                        => GL_LUMINANCE
            GL_UNSIGNED_BYTE,
            face->glyph->bitmap.buffer
    );