7
votes

Tech: WebGL / GL

  1. When I render 10k sprites (using spritebatch) immediately into back buffer everything is ok.

10k

good

  1. When I render it into render texture I gets some strange problem with alpha blending (I guess..). In places where texture has transparent pixels the alpha is calculated wrongly (IMO it should be cumulative).

10k

bad1

1k

bad2

200 with black background

bad3

Blend config:

gl.enable(gl.BLEND);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

This is how I create render buffer:

this._texture = this.gl.createTexture();
this.gl.bindTexture(this.gl.TEXTURE_2D, this._texture);
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.width, this.height, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);

this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);


this.renderBuffer = this.gl.createFramebuffer();

this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.renderBuffer);
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, this._texture, 0);
1

1 Answers

3
votes

I have changed blending mode to:

gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);

This is result:

good

Explanation:

When you render immediately into back buffer alpha canal is always set to 1.0 (except the cases when you use transparent canvas) - So it doesn't matter how alpha is being calculated.

When you render first into the render buffer (texture) and later this prepared texture is used to render into back buffer - you need to use different blend modes for alpha and rgb.

SRC_ALPHA and ONE_MINUS_SRC_ALPHA is used for RGB mixing (multiply) depending on SRC and DESC alpha.

If alpha canal would be also multiplied it would override opaque pixels in places where texture has transparent pixels. We need to sum alpha of each pixel not multiply.

So alpha func need to be set to: ONE and ONE_MINUS_SRC_ALPHA so ALPHA will be cumulated, not multiplied.

Luk: I'm not fluent in English (sorry). If someone would be so nice to "translate" this explanation I would be grateful.