Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fragment shader and coloring a texture

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.

like image 799
vertti Avatar asked Sep 13 '13 10:09

vertti


People also ask

What is a fragment in shading?

A Fragment Shader is the Shader stage that will process a Fragment generated by the Rasterization into a set of colors and a single depth value. The fragment shader is the OpenGL pipeline stage after a primitive is rasterized. For each sample of the pixels covered by a primitive, a "fragment" is generated.

What are fragment shaders used for?

Fragment Shader is used in variable, uniform variable, and local variables to perform fragment processing, texturing, and per-fragment lighting.

What is the difference between a vertex and fragment shaders?

There are several kinds of shaders, but two are commonly used to create graphics on the web: Vertex Shaders and Fragment (Pixel) Shaders. Vertex Shaders transform shape positions into 3D drawing coordinates. Fragment Shaders compute the renderings of a shape's colors and other attributes.


1 Answers

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);
like image 142
datenwolf Avatar answered Nov 04 '22 00:11

datenwolf