为什么WebGL中的透明像素没有正确混合?

3

我的代码的结果:

奇怪

问题在于,我的图像中透明的部分没有正确地与之前绘制的内容混合。我知道可以使用

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。如果我更改两个图像在缓冲区中的绘制顺序,则问题不存在。由于它们将在程序运行时动态旋转,因此这不是一个选项。


很遗憾,每帧处理成千上万个点是不可行的。只能舍弃它。谢谢。 - Sebastian Frederick
1个回答

3

如果没有更多的代码,很难确定您的问题,但看起来像是深度测试的问题。

enter image description here

假设我理解正确,你正在绘制两个矩形?如果你先绘制红色矩形再绘制蓝色矩形,那么根据深度测试设置的方式,当X区域被绘制时,蓝色矩形将无法通过深度测试。通常通过对所绘制的内容进行排序来解决这个问题,确保首先绘制更远的物体。
对于一个“网格”来说,你可以通过在正确方向上遍历网格本身而不是“排序”来完成排序。
另一方面,如果你的透明度全部为100%,则有丢弃的优势,并且可以从前往后绘制。这是因为在这种情况下,通过从前往后绘制,红色四边形绘制(未被丢弃)的像素将在深度测试时被蓝色四边形拒绝。深度测试通常会在运行某个像素的片段着色器之前进行优化。如果深度测试表明该像素不会被绘制,则没有必要为该像素运行片段着色器,节省时间。不幸的是,一旦你有任何不是100%不透明或100%透明的透明度,就需要进行排序并从后往前绘制。其中一些问题在this article中有所涉及。
一些注意事项:
  1. 你提到了移动设备和WebGL2,但是iOS上没有WebGL2。

  2. 你说你正在使用POINTS进行绘图。规范只要求大小为1像素的POINTS。看起来你在60像素大小的点上是安全的,但为了安全起见,最好使用三角形进行绘制,因为点还有其他问题

  3. 你可能也对具有深度的精灵感兴趣。


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