Freetype 字形在加载到 openGL 时换行

Freetype glyphs wrap when loaded into openGL

我正在尝试通过 freetype 加载 TrueTypeFonts 并使用 openGL 显示它们,这就是我得到的结果:

如您所见,大部分都很好,但如果您仔细观察,每个字形的边界似乎都有一些小的不协调之处。我注意到这些奇怪的线条实际上是从另一边传递过来的像素。尤其是 'T' 和 'h',您可以在其中看到与纹理的另一侧相对应的小条。不同的字体也会发生这种情况。下面是负责将字形位图缓冲区复制到 openGL 中的代码:

    void load(FT_GlyphSlot glyphSlot, double loadedHeight){
        this->loadedHeight = loadedHeight;
        int width = glyphSlot->bitmap.width;
        int height = glyphSlot->bitmap.rows;

        sizeRatios = Vector2D(width / loadedHeight, height / loadedHeight);
        offsetRatios = Vector2D(glyphSlot->bitmap_left / loadedHeight, glyphSlot->metrics.horiBearingY / loadedHeight);
        advanceRatios = Vector2D((glyphSlot->advance.x >> 6) / loadedHeight, (glyphSlot->advance.y >> 6) / loadedHeight);

        std::cout << width << ", " << height << std::endl;

        GLubyte * textureData = new GLubyte[width * height * 4];

        for(int y = 0; y < height; y++){
            for(int x = 0; x < width; x++){
                for(int i = 0; i < 4; i++){
                    textureData[(x + y * width) * 4 + i] = glyphSlot->bitmap.buffer[x + width * y];
                }
            }
        }

        texture.bind();
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        texture.load(GL_TEXTURE_2D, 0, GL_RGBA, glyphSlot->bitmap.width, glyphSlot->bitmap.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);
        // glGenerateMipmap(GL_TEXTURE_2D);

        delete [] textureData;
    }

字体的大小在别处设置并与我要加载的字形插槽一起传递给此方法。纹理对象只是一个 class 创建纹理句柄并跟踪它,加载只是将参数直接传递给 glTexImage2D()。

我试过使用模数旋转将像素移动一个,它在垂直方向上有效,但在水平方向上无效。我还尝试通过将格式更改为 GL_RED 将缓冲区直接传递到加载来加载纹理,如 here 所述,但问题并没有消失,所以我认为它甚至可能是freetype 的缺陷?

我想知道是否有一些我不理解的基本纹理加载元素。

如果您需要一些额外的源代码来了解问题所在,请询问。

GL_TEXTURE_WRAP_S/GL_TEXTURE_WRAP_T默认为GL_REPEAT.

改用GL_CLAMP_TO_EDGE