2d - 为什么透明像素在 WebGL 中不能正确混合

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

最佳答案

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

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 感兴趣

关于2d - 为什么透明像素在 WebGL 中不能正确混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59205157/

相关文章:

graphics - 将任意 2D 多边形投影到 3D 三角形网格上的最佳方法?

canvas - 将一个 Three.js 网格导出为 OBJ 或 STL

javascript - putImageData(),如果新像素是透明的,如何保留旧像素?

android - 在 ImageButton 中设置背景颜色并在背景上设置图像 - Android

java - 如何在LWJGL中绘制透明纹理?

android - 我可以在 android 2d 中用条纹或点填充形状吗

c# - 单卡怎么拖

canvas - webGL/openGL 中多个 2D 点光源的最高效方法? [动态灯光]

java - 找不到符号: implements Drawable

php - 遍历二维 bool 数组,只留下最大的连续 "2D blob of ones"