【问题标题】:OpenGL, blending transparent textures with object colorOpenGL,将透明纹理与对象颜色混合
【发布时间】:2014-04-19 00:48:28
【问题描述】:

我可以将片段着色器设置为显示对象的颜色或对象的纹理颜色。我的问题是,我怎样才能将这两者结合起来,这样我才能得到一张带有砖块线条的透明图片,然后在下面显示不同的颜色,这样通过改变物体的颜色,你就可以改变砖块的颜色。

我尝试在片段着色器中使用 mix(),但它只向我显示 glClearColor,它是透明的,而不是我分配的红色!

我的片段着色器:

#version 120

uniform sampler2D diffuse;

varying vec3 shared_colors;
varying vec2 shared_texCoords;

void main() {
    vec4 color = vec4(shared_colors, 1);
    vec4 texture = texture2D(diffuse, shared_texCoords);
    vec4 finalColor = vec4(mix(color.rgb, texture.rgb, 1), 1);

    gl_FragColor = finalColor;
}

编辑:添加纹理加载功能:

void Texture::createTexture(SDL_Surface *rawImage, GLenum format) {
    //Convert to a texture of pure color pixels for OpenGL
    SDL_Surface *image = SDL_CreateRGBSurface(NULL, rawImage->w, rawImage->h, 32, 0, 0, 0, 0);
    SDL_BlitSurface(rawImage, NULL, image, NULL);

    //Generate texture
    glGenTextures(1, &m_texture);

    //Tell OpenGL to use this texture
    glBindTexture(GL_TEXTURE_2D, m_texture);

    //Set texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    //Generate texture from image
    glTexImage2D(GL_TEXTURE_2D, 0, 4, image->w, image->h, 0, format, GL_UNSIGNED_BYTE, image->pixels);

    m_dimension = new PixelSize(image->w, image->h);

    //Free loaded images
    SDL_FreeSurface(rawImage);
    SDL_FreeSurface(image);
}

【问题讨论】:

  • 您不应该使用 4 作为内部格式。在旧版本的 OpenGL 中,这是允许的(这意味着选择任何具有 4 个组件的格式),但正确使用的是 GL_RGBA 或更好的是 GL_RGBA8。你的着色器是 GLSL 1.20,所以你的实现可能不支持GL_RGBA8,但它肯定会理解GL_RGBA
  • 我会试试看是否有帮助 =)
  • 嗯,这并没有改变我的处境。它们都运行得很好,但没有发生任何不同。
  • 老实说,我认为这不会改变任何事情。但规格。不再允许使用组件的数量,因此至少您的代码现在更具可移植性:P 我相信您传递给 SDL_CreateRGBSurface (...) 的掩码应该归咎于您的恒定 alpha 值。在小端机器(例如 x86)上,我认为您需要 0xff000000 的 alpha 掩码(最后一个参数)。对于所有其他颜色通道,您可以使用 0 的遮罩,但 alpha 需要显式遮罩。
  • 我设法找到了问题所在!我确实需要 RGB 组件的遮罩。我用了 0x00ff0000, 0x0000ff00, 0x000000ff

标签: c++ opengl textures fragment-shader


【解决方案1】:

您应该仔细查看 mix (...) 以了解为什么将 1 用于 a 没有任何意义(它返回 y)。

让我们从考虑通常的 alpha 混合函数开始:GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA

这意味着获取源的 Alpha 通道并将其乘以源颜色(片段颜色),然后将其添加到 Alpha 通道的倒数乘以目标颜色(帧缓冲区)。

  AlphaBlend = SrcRGBA * SrcA + Dst RGBA * (1.0 - SrcA)

现在,如果您查看mix (...) 的实现,它应该看起来很熟悉:

  x * (1.0 - a) + y * a

显然,对于a != 0.5 (1.0 - 0.5 = 的任何值,这取决于顺序>0.5),更重要的是,在这种情况下,如果您为 a 使用 1.0 值(因为这会乘以 x 0.0)。

【讨论】:

  • 我尝试使用 mix(color.rgb, texture.rgb, texture.a),起初我认为它是正确的,但我只得到一个没有纹理的红色对象。我的程序中是否还有其他地方可能缺少行?
  • Ofc,我不能指望你知道,因为你没有剩下的代码,但我是否需要设置任何特定的 OpenGL 属性或运行任何函数来启用混合?
  • 不,这实际上并不是严格意义上的混合。它与一个非常特定的混合函数做同样的事情,但混合与片段着色器的输出和颜色缓冲区中已经存在的值一起工作。至于你的另一个问题,听起来你的纹理对于 alpha 通道有一个常量 0.0,这很有趣,因为没有 alpha 通道的纹理隐式返回 1.0 的 alpha 值.
  • 秒,我会添加我的纹理加载器,里面可能有一些奇怪的东西=P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
  • 1970-01-01
  • 1970-01-01
  • 2012-10-28
  • 2021-02-18
  • 2017-09-23
相关资源
最近更新 更多