【问题标题】:OpenGL FreeType: weird textureOpenGL FreeType:奇怪的纹理
【发布时间】:2014-07-17 08:58:58
【问题描述】:

在我初始化库并加载纹理后,我得到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);
}

片段着色器:

#version 330

in vec2 uv;
in vec4 tColor;

uniform sampler2D tex;

out vec4 color;

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

【问题讨论】:

  • 您将纹理环绕设置为重复,您在问为什么纹理重复?
  • @BartekBanachewicz 即使我更改 GL_REPEAT 也会这样做,如果它应该重复,那么为什么它会这样重复?
  • 等等...这行代码与您对纹理所做的操作完全无关。你在做别的事情。
  • @BartekBanachewicz 这就是它如此奇怪的原因。我只改变那条线,纹理也会改变。

标签: c++ opengl textures freetype


【解决方案1】:

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

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

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

根据您显示的数据,slot-&gt;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);

【讨论】:

  • 您是对的,但 GL_ALPHA 不是已弃用吗?无论如何,我发布了我为解决问题所做的工作。
  • 您的问题是问题发生的原因,我没有在您的回答中看到这一点。是的,GL_ALPHAGL_LUMINANCE_ALPHA 已被弃用。由于您在代码中使用了它,因此我建议使用最近的亲戚。如果你想使用现代格式,像GL_R8 这样的格式会更有效,只使用你现在使用的空间的 25%。
【解决方案2】:

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

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];

        }

    }

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多