I am trying to blend two textures with an alpha channel over each other.
After looking through the net it appeared that there are no simple ways to solve this. I tried this trick in the fragment shader:
if(gl_FragColor.a < 0.5){
discard;
}
This works for simpler textures with not a lot of alpha variations, like the human sprite in the background. But I want to be able to work with more complex images like the gradient sprite which doesn't work at all.
This is my fragment shader:
precision mediump float;
varying vec3 fragColor;
varying highp vec2 vTextureCoord;
uniform sampler2D uSampler;
void main()
{
vec4 tex = texture2D(uSampler, vTextureCoord);
gl_FragColor = tex * vec4(fragColor, 1.0);
if(gl_FragColor.a < 0.5){
discard;
}
}'
This is my vertex shader:
precision mediump float;
attribute vec3 vertPosition;
attribute vec3 vertColor;
attribute vec2 aTextureCoord;
varying vec3 fragColor;
varying highp vec2 vTextureCoord;
uniform mat4 uPMatrix;
uniform mat4 uMVMatrix;
uniform vec2 uvOffset;
uniform vec2 uvScale;
void main()
{
fragColor = vertColor;
gl_Position = uPMatrix * uMVMatrix * vec4(vertPosition.x, vertPosition.y, vertPosition.z, 1.0);
vTextureCoord = aTextureCoord * uvScale + uvOffset;
}
This is a part of the gl setup I use:
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.SRC_ALPHA, gl.ON);
Currently all sprites are being drawn on the same z axis, 0. However I don't know if the is the source of the problem as I tested giving each object a random z value and the problem persisted.
Edit: In response to Rabbid76's comment.
This works verry well! The alpha is blended but the only problem is that the sprites look "burned":
I tried to alter the fragment shader to this:
<strike>gl_FragColor = tex * vec4(tex.rgb, tex.a);</strike>
But it still looks burned.
Edit 2
I solved it it. gl_FragColor should b:
gl_FragColor = vec4(tex.rgb, tex.a);
and not
gl_FragColor = vec4(fragColor* tex.rgb, tex.a);
otherwise it creates a burn blending effect
Currently all sprites are being drawn on the same z axis, 0.
Since the dept test is enabled (gl.enable(gl.DEPTH_TEST)
), and the default depth function (depthFunc
) is gl.LESS
, the second drawn sprite won't pass the depth test.
You have to disable the depth test:
gl.disable(gl.DEPTH_TEST);
Further I recommend to adapt the blend function (blendFunc
):
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
Or you use Alpha premultiplication. Therefore you have to adapt the fragment shader:
gl_FragColor = tex * vec4(fragColor * tex.rgb, tex.a);
And you have to use the following blend function (blendFunc
):
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
Note, you don't need if(gl_FragColor.a < 0.5) discard;
any more.