WebGL:将spritebatch渲染到渲染纹理时出现奇怪的行为

7

技术:WebGL / GL

  1. 当我将10k个精灵(使用spritebatch)立即渲染到后台缓冲区时,一切都很好。

10k

good

  1. 当我将其渲染到渲染纹理中时,我遇到了一些奇怪的透明度混合问题(我猜是这个原因。。)。在纹理具有透明像素的地方,透明度计算错误(我认为它应该是累积的)。

10k

bad1

1k

bad2

200黑色背景

bad3

混合配置:

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);
1个回答

3
我已将混合模式更改为:
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);

这是结果:

good

解释:

当你直接渲染到背景缓冲区时,Alpha通道总是设为1.0(除非你使用透明画布)- 因此,无论如何计算Alpha值都不重要。

当你首先渲染到渲染缓冲区(纹理),然后使用这个准备好的纹理来渲染到背景缓冲区时,你需要为RGB和Alpha使用不同的混合模式。

SRC_ALPHA和ONE_MINUS_SRC_ALPHA用于根据SRC和DESC Alpha进行RGB混合(乘法)。

如果Alpha通道也被乘以像素,则会覆盖具有透明像素的纹理中的不透明像素。我们需要对每个像素的Alpha值进行求和而不是乘法。

因此,Alpha函数需要设置为:ONE和ONE_MINUS_SRC_ALPHA,这样Alpha将被累积,而不是乘法。

Luk:我英语不太好(抱歉)。如果有人能“翻译”一下这个解释,我就感激不尽。


很高兴你解决了问题!如果不介意分享,你能解释一下为什么需要分离颜色混合和 Alpha 混合吗? - WacławJasper
@WacławJasper 我已经添加了解释,但我不确定你能否阅读它 :) - l00k
谢谢。很有帮助。非常易懂。当我需要为我的精灵渲染器实现准确的Alpha混合时,这可能会节省我数小时的头痛。 - WacławJasper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接