在单个渲染过程中添加正和负颜色片段的混合

时间:2015-09-26 22:06:17

标签: webgl shader transparency fragment-shader glblendfunc

我正在开发类似于粒子系统的 WebGL 项目。出于审美目的,我的单个渲染通道配置为混合添加,并且我已禁用深度测试。为了论证,我还将视口缓冲区清除为 50%灰色

gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE, gl.ONE);
gl.disable(gl.DEPTH_TEST);
gl.clearColor(0.5, 0.5, 0.5, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

我已经将顶点缓冲区和索引缓冲区上传到GPU,代表两个部分重叠的三角形。它们的顶点具有 vec3颜色属性。我为每个顶点指定了 50%灰色(0.5,0.5,0.5)的颜色。

当我使用着色器绘制三角形时,我放心地报告我的视口缓冲区现在看起来 50%灰色,其中两个重叠的三角形区域白色。三角形是白色的,因为它们的碎片'颜色值与颜色缓冲区中的颜色值相加。

现在,我重新上传顶点缓冲区并进行以下更改:第二个三角形的顶点颜色现在 -50%灰色(-0.5,-0.5,-0.5)

我希望实现的是我的视口缓冲区看起来 50%灰色,有两个重叠的三角形区域 - 一个白色,一个黑色 - 相交,并在交叉点产生 50%灰色。毕竟,添加负数应该与减去相同幅度的正数相同。

我所看到的是一个 50%灰色视口,其中只有一个三角形区域 - 白色区域。

我认为这是因为我的片段着色器的输出被钳制到下限为零的范围,然后才与颜色缓冲区混合。我想知道如何在WebGL中理想地规避这种限制,而不需要多次渲染过程。

我将通过以下网址测试页面来源中的解决方案:http://rezmason.net/scourge/issues/positive_negative_fragments.html

更新

作为调查,我已尝试在帧缓冲区中执行添加剂混合,然后将帧缓冲区绘制到视口缓冲区,方法是将其纹理化为单位四元组,即两个单独的绘制调用当然,理想情况下,我想避免。

也就是说,因为当我在该缓冲区内执行操作时,我可以明确地将帧缓冲区的格式设置为浮点,没有钳位发生任何值。当我将缓冲区绘制到视口时,我假设最终发生了夹紧,但到那时所有的混合都已完成。

我的问题现在变得非常简单了:有没有办法初始化WebGL或OpenGL上下文,以便将其视口格式化为浮点缓冲区?

1 个答案:

答案 0 :(得分:0)

使用gl.blendEquation( gl.FUNC_SUBTRACT )。然后在着色器中使用正值。

如果你想在中间做点什么,你可以做一些hacky事情:

gl.enable(gl.BLEND);
gl.blendFuncSeparate(gl.ONE_MINUS_SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE);
gl.blendEquation(gl.FUNC_ADD);

它会给你这个等式: equation description

如果将颜色设置为(0.5,0.5,0.5,0),将黑色三角形设置为颜色(0.5,0.5,0.5,1),则可以绘制白色三角形。

如果你想要不同的颜色,我希望你明白这一点。您可以在此处比较不同的混合函数:http://www.andersriggelsen.dk/glblendfunc.php

修改 抱歉,是我的错。你应该改变

gl.blendFuncSeparate(gl.ONE_MINUS_DST_ALPHA, gl.ONE_MINUS_DST_ALPHA, gl.ONE, gl.ONE);

gl.blendFuncSeparate(gl.ONE_MINUS_SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE);

我忘记了哪一个是来源,哪一个是目的地。我已经更新了我的答案。