WebGL:将 spritebatch 渲染到渲染纹理时的奇怪行为
WebGL: Strange behavior when render spritebatch into render texture
技术:WebGL/GL
- 当我立即将 10k 精灵(使用 spritebatch)渲染到后台缓冲区时,一切正常。
10k
- 当我将它渲染到渲染纹理中时,我遇到了一些关于 alpha 混合的奇怪问题(我猜......)。在纹理具有透明像素的地方,alpha 计算错误(IMO 它应该是累积的)。
10k
1k
200 黑底
混合配置:
gl.enable(gl.BLEND);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
这是我创建渲染缓冲区的方式:
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);
我已将混合模式更改为:
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);
这是结果:
解释:
当您立即渲染到后台缓冲区时,alpha 通道始终设置为 1.0(使用透明 canvas 的情况除外)- 因此如何计算 alpha 并不重要。
当您首先渲染到渲染缓冲区(纹理),然后使用这个准备好的纹理渲染到后台缓冲区时 - 您需要对 alpha 和 rgb 使用不同的混合模式。
SRC_ALPHA 和 ONE_MINUS_SRC_ALPHA 用于根据 SRC 和 DESC alpha 进行 RGB 混合(相乘)。
如果 alpha 通道也相乘,它将覆盖纹理具有透明像素的地方的不透明像素。我们需要对每个像素的 alpha 求和而不是相乘。
因此需要将 alpha func 设置为:ONE 和 ONE_MINUS_SRC_ALPHA 因此 ALPHA 将被累加,而不是相乘。
卢克:
我英语不流利(抱歉)。如果有人对"translate"这个解释这么好,我将不胜感激。
技术:WebGL/GL
- 当我立即将 10k 精灵(使用 spritebatch)渲染到后台缓冲区时,一切正常。
10k
- 当我将它渲染到渲染纹理中时,我遇到了一些关于 alpha 混合的奇怪问题(我猜......)。在纹理具有透明像素的地方,alpha 计算错误(IMO 它应该是累积的)。
10k
1k
200 黑底
混合配置:
gl.enable(gl.BLEND);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
这是我创建渲染缓冲区的方式:
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);
我已将混合模式更改为:
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);
这是结果:
解释:
当您立即渲染到后台缓冲区时,alpha 通道始终设置为 1.0(使用透明 canvas 的情况除外)- 因此如何计算 alpha 并不重要。
当您首先渲染到渲染缓冲区(纹理),然后使用这个准备好的纹理渲染到后台缓冲区时 - 您需要对 alpha 和 rgb 使用不同的混合模式。
SRC_ALPHA 和 ONE_MINUS_SRC_ALPHA 用于根据 SRC 和 DESC alpha 进行 RGB 混合(相乘)。
如果 alpha 通道也相乘,它将覆盖纹理具有透明像素的地方的不透明像素。我们需要对每个像素的 alpha 求和而不是相乘。
因此需要将 alpha func 设置为:ONE 和 ONE_MINUS_SRC_ALPHA 因此 ALPHA 将被累加,而不是相乘。
卢克: 我英语不流利(抱歉)。如果有人对"translate"这个解释这么好,我将不胜感激。