为什么透明像素无法在WebGL中正确混合

时间:2019-12-06 00:24:39

标签: 2d webgl transparency alpha blending

我的代码的结果: Weird

基本上,问题是什么,我图像的透明部分无法与之前绘制的图像正确融合。我知道我可以做

if(alpha<=0){discard;}

在片段着色器中,唯一的问题是我计划拥有大量片段,并且不希望移动设备上每个片段的if语句。

以下是我与Alpha和深度测试相关的代码:

var gl = canvas.getContext("webgl2",
{
    antialias : false,
    alpha : false,
    premultipliedAlpha: false,
}
);

gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.GREATER);   

此外,这些都是纹理gl.POINTS我正在绘制。如果更改两个图像在缓冲区中的绘制顺序,则不存在此问题。它们将在程序运行时动态旋转,因此这不是一个选择。

1 个答案:

答案 0 :(得分:1)

不清楚没有更多代码的问题是什么,但看起来像是深度测试问题。

enter image description here

假设我正确理解您正在绘制2个矩形?如果您先绘制红色的蓝色,然后再绘制蓝色的红色,那么根据深度测试设置的不同,绘制X区域时蓝色的蓝色将无法通过深度测试。

通常,您可以通过对绘画内容进行排序来解决此问题,并确保先将其拉远。

对于“平铺”网格,通常可以按照正确的方向移动网格本身进行排序,而不是“排序”

反之,如果您所有的透明度都是100%绘制或不绘制,则丢弃具有其优势,您可以前后绘制。原因是在那种情况下,从前到后绘制,当通过深度测试绘制蓝色四边形时,由红色四边形绘制(不丢弃)的像素将被拒绝。深度测试通常经过优化,可以在为特定像素运行片段着色器之前进行。如果深度测试表明不会绘制像素,则没有理由甚至为该像素运行片段着色器,从而节省了时间。不幸的是,一旦您有了任何不是100%不透明或100%不透明的透明度,那么您就需要排序并拉回最前面。 this article

中涵盖了其中一些问题

一些注意事项:

  1. 您在代码示例中提到了移动设备,并提到了WebGL2。 iOS上没有WebGL2

  2. 您说过要用POINTS绘图。规范说仅需要1个像素的POINTS。 It looks like you're safe up to points of size 60,但为了安全起见,通常最好将三角形绘制为there are other isses with points

  3. 您可能还对sprites with depth

  4. 感兴趣