WebGL:为什么透明画布在alpha为0时会显示clearColor颜色分量?

时间:2013-12-03 21:27:25

标签: webgl

这是一个显示我问题的简单峰值:

<html>
<head>
    <title>Clear Color</title>
    <style type="text/css">
        #stage {
            background-color: rgba(127,127,127,1);
        }
    </style>
</head>
<body>
    <canvas id="stage" width="100", height="100"></canvas>
    <script type="text/javascript">
        var options = {
            alpha: true,
            premultipliedAlpha: true
        };
        var ctx = document.getElementById("stage").getContext("webgl", options);
        ctx.clearColor(1, 0, 0, 0);
        ctx.enable(ctx.BLEND);
        ctx.blendFuncSeparate(
            ctx.SRC_ALPHA, ctx.ONE_MINUS_SRC_ALPHA,
            ctx.ONE, ctx.ONE_MINUS_SRC_ALPHA
        );
        ctx.clear(ctx.COLOR_BUFFER_BIT);
    </script>
</body>
</html>

blendFunc是这样的:
(sR * sA)+(dR *(1-sA))= rR
(sG * sA)+(dG *(1-sA))= rG
(sB * sA)+(dB *(1-sA))= rB
(sA * 1)+(dA *(1-sA))= rA

...转换为此(我认为):
(1 * 0)+(0.5 *(1-0))= 0.5
(0 * 0)+(0.5 *(1-0))= 0.5
(0 * 0)+(0.5 *(1-0))= 0.5
(0 * 1)+(1.0 *(1-0))= 1.0

为什么我看到浅粉色画布而不仅仅是CSS声明的灰色?粉红色显然是来自我的clearColor,但为什么在alpha分量为0时显示红色?

1 个答案:

答案 0 :(得分:4)

默认情况下,WebGL要求您的颜色使用预乘alpha 。 1,0,0,0是无效的颜色,因为(0,0)*的rgb(0)= 0,0,0而不是1,0,0因此它是无效的颜色且规范未定义无效的颜色。不同浏览器的结果会有所不同。

您有几个选择

  • 告诉WebGL你的颜色不是预乘的

    gl = canvas.getContext("experimental-webgl", { premultipliedalpha: false });
    
  • 摆脱alpha通道

    gl = canvas.getContext("experimental-webgl", { alpha: false });
    
  • 预乘你的alpha

    var r = 1;
    var g = 0;
    var b = 0;
    var a = 0;
    gl.clearColor(r * a, g * a, b * a, a);
    

    类似地,在着色器中要么传递预乘颜色,要么在最后传递预乘。

    gl_FragColor = vec4(color.rgb * color.a, color.a);
    

您的混合设置无效。它们仅在您调用gl.drawXXX时使用,当画布与背景合成时不会使用它们。