Fragment shader and coloring a texture

21,824

Your blending mode assumed pre-multiplied alpha, which normally is a great choice. But it requires the RGB values to be multiplied with the alpha value. The alpha value only controls, how much of the background gets added to the incoming fragments in that mode. So to make RGB "fade out" they must be modulated by the alpha value as well.

Now when you're messing with that alpha value to be constant, your RGB values no longer match that premultiplication. Try this instead for your red tinting:

gl_FragColor = tex + vec4(0.5, 0, 0, 1)*tex.a;

This adds a alpha modulated red to the texture.

In the case you expect the image to disappear completely, you'd require a different blending mode, namely GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, but with that you require a non-premultiplied-alpha image, or you compensate that premultiplication in the shader:

gl_FragColor = vec4(tex.rgb/tex.a, tex.a);
Share:
21,824

Related videos on Youtube

vertti
Author by

vertti

Senior consultant, software architect, programming language nerd, fitness enthusiast and proud father of two.

Updated on September 14, 2020

Comments

  • vertti
    vertti over 3 years

    I'm trying to make sense of adjusting texture colors with a fragment shader. My fragment shader is super simple:

    uniform sampler2D sampler;
    
    void main() {
      vec4 tex = texture2D ( sampler, uvVarying );
      gl_FragColor = vec4(tex.r, tex.g, tex.b, tex.a);
    }
    

    This draws my dog texture as expected: normal dog

    if I then change the shader to

      gl_FragColor = vec4(tex.r, tex.g, tex.b, 1.0);
    

    the result is what I expected, transparency info is lost:

    no transparency

    but if I instead set it to:

      gl_FragColor = vec4(tex.r, tex.g, tex.b, 0.0);
    

    I was expecting it to disappear completely, but instead I get:

    green dog

    What is going on??

    And to my original problem: I wanted to add a little red tint to my texture with:

      gl_FragColor = vec4(tex.r + 0.5, tex.g, tex.b, tex.a);
    

    Now, I was expecting it to have same transparency info as the original texture, but instead I get this:

    red dog

    What am I missing here. The texture is using default blending of the engine which is src = GL_ONE, dst = GL_ONE_MINUS_SRC_ALPHA.

    • vertti
      vertti over 10 years
      Ok, it seems to have something to do with the fact that the texture has premultiplied alpha. If I load the texture without that, it looks like what I expected.
  • Jessy
    Jessy over 10 years
    I disagree that use premultiplied alpha is "normally is a great choice", because I consider "normal" to be using compressed textures, and with compression, premultiplied blending results in value aberration along edges. Premultiplying in the shader, instead of baking it into .rgb, is of course frequently useful.