首页 > 解决方案 > alpha 如何在禁用混合的 webGL 中工作?

问题描述

我在点模式下渲染了几个顶点,禁用了混合,下面是相关代码:

var canvas = htmlToElement('<canvas width="100" height="100" style="margin:auto;display:block;"></canvas>');
        document.body.appendChild(canvas);

        gl = canvas.getContext('experimental-webgl');


        var vertices = [
            -0.5,  0.5, 0.0,
             0.0,  0.5, 0.0,
        ];
        var vertLen = vertices.length / 3;


        var vertex_buffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
        gl.bindBuffer(gl.ARRAY_BUFFER, null);

        var vertShader = createShader(document.getElementById('vert').textContent, gl.VERTEX_SHADER);
        var fragShader = createShader(document.getElementById('frag').textContent, gl.FRAGMENT_SHADER);

        var shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertShader);
        gl.attachShader(shaderProgram, fragShader);
        gl.linkProgram(shaderProgram);
        gl.useProgram(shaderProgram);


        gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
        var coord = gl.getAttribLocation(shaderProgram, "coordinates");
        gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(coord);


        gl.clearColor(0, 0, 0, 1);
        gl.enable(gl.DEPTH_TEST);
        gl.clear(gl.COLOR_BUFFER_BIT);

        gl.viewport(0, 0, canvas.width, canvas.height);

        gl.disable(gl.BLEND);
        //gl.blendEquation(gl.FUNC_ADD);
        //gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);

        gl.drawArrays(gl.POINTS, 0, vertLen);

这是片段着色器:

<script type='x-shader/x-fragment' id='frag'>
        void main(void) {

            gl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);
        } 
    </script>

这就是我得到的:

在此处输入图像描述

这张图片上的红色是 [255,27,32]。

所以我的问题是,在没有混合的情况下,将半透明红色转换为 [255,27,32] 的公式是什么?

我认为它在OpenGL中是一样的吗?

标签: webgl

解决方案


你是什​​么意思它是[255,27,32]?你是怎么得到那个号码的?

就像所有 HTML 元素一样,该<canvas>元素与 HTML 页面的其余部分混合,因此“通常”如果您将 1、0、0、0.5 放入片段着色器中,那么 255、0、0、127 将写入画布中。

然后画布将与页面混合。画布后面的内容取决于您的 CSS。也许你有<canvas style="background: purple;"></canvas>或者你的 CSS 设置为

body {
  background: #123456;
}

背景可以是您设置的任何内容

默认情况下,画布将被混合,假设画布内的颜色使用“预乘 alpha”,这意味着颜色 (255, 0, 0, 127) 是无效颜色

预乘 alpha 表示 R、G 和 B 已乘以 alpha。当 R 为 1 且 alpha 0.5 时,最高 R 可以为 0.5(因为 1.0 乘以 0.5 为 0.5)

因此,在这种情况下发生的事情在 HTML 规范中是未定义的。

premultipledAlpha: false您可以通过在创建 WebGL 上下文时传递来告诉浏览器使用未预乘的 alpha 在画布之上绘制画布。alpha: false您还可以在创建上下文时关闭画布中的 alpha 。(虽然 IIRC 在 Safari 中不起作用,但 Safari 是新的 IE

例子:

test('#normal', {});
test('#unpremultiplied-alpha', {premultipliedAlpha: false});
test('#no-alpha', {alpha: false});

function test(selector, options) {
  const canvas = document.querySelector(selector);
  const gl = canvas.getContext('webgl', options);
  
  gl.clearColor(0, 0, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.enable(gl.SCISSOR_TEST);
  gl.scissor(32, 32, 64, 64);
  gl.clearColor(0.5, 0.25, 0.125, 0.5);
  gl.clear(gl.COLOR_BUFFER_BIT);
}
/* make the background stripes */
html, body {
  height: 100%;
  background: repeating-linear-gradient(
    45deg,
    lime,
    lime 10px,
    orange 10px,
    orange 20px
  );
}
canvas {
  border: 1px solid black;
}
<canvas width="128" height="128" id="normal"></canvas>
<canvas width="128" height="128" id="unpremultiplied-alpha"></canvas>
<canvas width="128" height="128" id="no-alpha"></canvas>


推荐阅读