如何使WebGL画布透明化

21

是否可以实现带有透明背景的WebGL画布?我想让网页内容通过画布可见。

这是我现在拥有的:http://i50.tinypic.com/2vvq7h2.png

如您所见,WebGL画布后面的文本是不可见的。当我在CSS中更改Canvas元素的样式并添加以下代码时:

opacity: 0.5;

页面将会呈现如下形式:http://i47.tinypic.com/302ys9c.png

这几乎是我想要的,但不完全符合我的要求——由于CSS alpha设置的缘故,文本颜色当然不是相同的黑色,而蓝色形状的颜色也不同于第一张图片中的蓝色。

感谢任何帮助!

2个回答

22

WebGL 默认是透明的。以下是一个示例。

const gl = document.getElementById("c").getContext("webgl");
gl.clearColor(0.5, 0, 0, 0.5);
gl.clear(gl.COLOR_BUFFER_BIT);
pre {
    padding-left: 50px;
    font-family: sans-serif;
    font-size: 20px;
    font-weight: bold;
}

canvas {
    z-index: 2;
    position: absolute;
    top: 0px;
    border: 1px solid black;
}
<pre>
Some 
text
under
the
canvas
</pre>
<canvas id="c"></canvas>

请注意,浏览器假定画布中的像素代表预乘阿尔法值。这意味着,例如,如果您将清除颜色更改为(1,0,0,0.5),则您将得到在HTML中没有看到的东西。
我的意思是预乘阿尔法意味着RGB部分已经被alpha值乘以了。因此,如果您的RGB起始值为1,0,0,而alpha为0.5。那么如果您将RGB乘以alpha,则会得到RGB的0.5,0,0。这就是浏览器默认期望的内容。
如果WebGL中的像素为1,0,0,0.5,则对浏览器来说没有意义,您将获得奇怪的效果。
例如请参见:

const gl = document.getElementById("c").getContext("webgl");
gl.clearColor(1, 0, 0, 0.5);
gl.clear(gl.COLOR_BUFFER_BIT);
pre {
    padding-left: 50px;
    font-family: sans-serif;
    font-size: 20px;
    font-weight: bold;
}

canvas {
    z-index: 2;
    position: absolute;
    top: 0px;
    border: 1px solid black;
}
<pre>
Some 
text
under
the
canvas
</pre>
<canvas id="c"></canvas>

注意,即使您认为黑色文字的透明度为0.5 = 50%的黑色文字和50%的红色WebGL画布,它也变成了红色。那是因为红色没有被预乘。

您可以通过确保在WebGL中创建的值表示预乘值来解决此问题,或者在创建WebGL上下文时告诉浏览器您的WebGL像素未经预乘。

const gl = canvas.getContext("webgl", { premultipliedAlpha: false });

现在1,0,0,0.5像素再次有效。示例:

const gl = document.getElementById("c").getContext("webgl", {
  premultipliedAlpha: false,
});
gl.clearColor(1, 0, 0, 0.5);
gl.clear(gl.COLOR_BUFFER_BIT);
pre {
    padding-left: 50px;
    font-family: sans-serif;
    font-size: 20px;
    font-weight: bold;
}

canvas {
    z-index: 2;
    position: absolute;
    top: 0px;
    border: 1px solid black;
}
<pre>
Some 
text
under
the
canvas
</pre>
<canvas id="c"></canvas>

你可以选择任何一种方式实现这个效果。许多GL程序期望使用非预乘alpha,而HTML5的其他部分都期望使用预乘alpha,所以WebGL提供了这两个选项。


谢谢你的解释,它帮助我更好地理解WebGL的基础知识。 - Jack Sean
“where as all other parts of HTML5 expect premultlipled alpha so WebGL gives you both options”是什么意思?在我看来,当我们将premultipliedAlpha设置为false时,我们得到的不透明度与CSS不透明度相同,这似乎与您所说的相反。我认为,“HTML5的所有其他部分”指的是使用CSS不透明度的所有内容,在这种情况下,我记得我们使用非预乘格式的rgba()。例如,在CSS中,rgba(1,1,1,0)是100%透明的,无论RGB值如何(非预乘)。 - trusktr
我所说的HTML的所有其他部分包括普通图像、2D画布和视频。CSS不是HTML :) - gman

19

WebGL 默认支持 alpha 透明度,但您需要使用它。最基本的是,在 gl.clear 操作之前,确保将清除颜色设置为透明的 gl.clearColor(0, 0, 0, 0)

如果你想绘制半透明对象,那么涉及到混合操作和排序绘制,但看起来你只是希望未绘制区域是透明的,上述操作就足够了。


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