WebGL: Strange behavior when render spritebatch into render texture

Tech: WebGL / GL

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

    好

  • 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);
    

    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:

    好

    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.

    链接地址: http://www.djcxy.com/p/28022.html

    上一篇: native:ListView,如何从顶部推新的行

    下一篇: WebGL:将spritebatch渲染为渲染纹理时的奇怪行为