OpenGL FreeType:奇怪的纹理

时间:2014-07-17 08:58:58

标签: c++ opengl textures freetype

在我初始化库并加载纹理后,我得到http://postimg.org/image/4tzkq4uhl

但是当我将这一行添加到纹理代码时:

std::vector<unsigned char> buffer(w * h, 0);

我得到http://postimg.org/image/kqycmumvt

为什么在我添加特定代码时会发生这种情况,为什么信函会成倍增加呢?我已经搜索了关于FreeType的示例和教程,我看到其中一些更改了缓冲区数组,但是我并没有真正理解它,所以如果你能向我解释一下,我可以更好地处理它。

纹理加载:

Texture::Texture(FT_GlyphSlot slot) {
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

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

    int w = slot->bitmap.width;
    int h = slot->bitmap.rows;

    // When I remove this line, the black rectangle below the letter reappears.
    std::vector<unsigned char> buffer(w * h, 0);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, slot->bitmap.width, slot->bitmap.rows, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, slot->bitmap.buffer);

    glGenerateMipmap(GL_TEXTURE_2D);

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

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}

Fragment Shader:

#version 330

in vec2 uv;
in vec4 tColor;

uniform sampler2D tex;

out vec4 color;

void main () {
    color = vec4(tColor.rgb, texture(tex, uv).a);
}

2 个答案:

答案 0 :(得分:1)

您要为GL_LUMINANCE_ALPHA传递的数据格式指定glTexImage2D()。根据我在这里找到的相应FreeType文档:

http://www.freetype.org/freetype2/docs/reference/ft2-basic_types.html#FT_Pixel_Mode

没有FT_Pixel_Mode值指定slot->bitmap.buffer中的数据实际上是亮度-α。 GL_LUMINANCE_ALPHA是一种每像素2个字节的格式,当数据用于指定RGBA图像时,第一个字节用于R,G和B,第二个字节用于A。

根据您显示的数据,slot->bitmap.pixel_mode最有可能是FT_PIXEL_MODE_GRAY,这意味着位图数据是每个像素1个字节。在这种情况下,您需要使用GL_ALPHA格式:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, slot->bitmap.width, slot->bitmap.rows, 0,
             GL_ALPHA, GL_UNSIGNED_BYTE, slot->bitmap.buffer);

如果pixel_mode不是FT_PIXEL_MODE_GRAY,那么您必须相应地调整格式,或者如果格式不是,则可能会创建数据的副本由glTexImage2D()支持。

如果指定GL_LUMINANCE_ALPHA而不是GL_ALPHA,则会导致垃圾邮件的原因是它读取的数据是您传入的数据中包含的数据的两倍。读取的数据内容超出了分配的位图数据未定义,并且可能会根据您声明/分配的其他变量而改变。

如果您想使用核心配置文件中仍支持的纹理格式而不是已弃用的GL_LUMINANCE_ALPHAGL_ALPHA,则可以使用GL_R8代替。由于这种格式只有一个组件,而不是GL_RGBA中的四个组件,因此这也将减少75%的纹理内存:

glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, slot->bitmap.width, slot->bitmap.rows, 0,
             GL_RED, GL_UNSIGNED_BYTE, slot->bitmap.buffer);

这也需要在着色器中稍作更改才能读取r组件而不是a组件:

color = vec4(tColor.rgb, texture(tex, uv).r);

答案 1 :(得分:0)

解决了它。我在代码中添加了以下内容,效果很好。

GLubyte * data = new GLubyte[2 * w * h];

    for( int y = 0; y < slot->bitmap.rows; y++ )
    {

        for( int x = 0; x < slot->bitmap.width; x++ )
        {

            data[2 * ( x + y * w )] = 255;
            data[2 * ( x + y * w ) + 1] = slot->bitmap.buffer[x + slot->bitmap.width * y];

        }

    }

我不知道我添加的那条特定行发生了什么,但现在它可以正常工作。