gpt4 book ai didi

WebGL:如何正确混合 alpha channel png

转载 作者:行者123 更新时间:2023-12-04 05:29:12 27 4
gpt4 key购买 nike

我对 OpenGL 很陌生,对 WebGL 甚至更新。我正在尝试绘制带有 alpha channel 的纹理四边形。但是,我无法正确混合。

这是我要找的结果

This is the result I'm looking for

这就是 WebGL 结果的样子

And this is what the WebGL result looks like

如您所见,骰子边缘有一种白色轮廓,而原始图像中没有。

这就是我在 WebGL 中进行混合的方式

        gl.clearColor(0.5, 0.5, 0.5, 1);
gl.disable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

这是我的片段着色器:
precision mediump float;

varying vec2 vUV;

uniform sampler2D texture;

void main(void) {
vec4 frag = texture2D(texture, vUV);
gl_FragColor = frag;
}

知道为什么会这样吗?顺便说一句,我不是在创建 mipmap。

最佳答案

这已在 SO 上的其他地方得到回答,但是......

WebGL Canvases 默认需要预乘 alpha。 WebGL Canvas 合成在网页上(混合到页面上)。所以 ...

您是否希望您的 WebGL 图像与网页混合?

如果否,您不想与网页混合,请执行以下操作之一

  • 关闭 Canvas 中的 alpha
    var gl = someCanvas.getContext("webgl", { alpha: false });
  • 确保您的 alpha 值保持在 1.0

    最简单的方法是在渲染后清除它
    gl.colorMask(false, false, false, true);
    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);

  • 如果是,您确实想与网页混合,然后执行以下操作之一
  • 确保您写入 Canvas 的值是预乘的 alpha 值。
  • 告诉浏览器 Canvas 中的值没有预乘
    var gl = someCanvas.getContext("webgl", {premultipliedAlpha: false});

  • 最重要的是,默认情况下,加载到 WebGL 中的图像使用未预乘的 alpha 这意味着您要么需要
  • 将 Canvas 设置为不预乘
  • 在着色器中自己做乘法
    gl_FragColor.rgb *= gl_FragColor.a;
  • 将纹理加载到 WebGL 时告诉 WebGL 预乘纹理
    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);

  • 假设你的 Canvas 是预乘的,你希望你的混合函数是
    gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);

    那是因为您不需要将源乘以 alpha 因为它已经预乘

    这是通过在着色器中乘以 alpha 来与页面混合的示例。紫色条纹是 CSS 背景。图像被绘制两次,一次填充 Canvas ,一次在 1/2 大小的顶部。你可以看到它都正确混合了。

    var vs = `
    attribute vec4 position;
    varying vec2 v_texcoord;
    uniform mat4 u_matrix;
    void main() {
    gl_Position = u_matrix * position;
    v_texcoord = position.xy * .5 + .5;
    }
    `;

    var fs = `
    precision mediump float;
    varying vec2 v_texcoord;
    uniform sampler2D u_tex;
    void main() {
    gl_FragColor = texture2D(u_tex, v_texcoord);
    gl_FragColor.rgb *= gl_FragColor.a;
    }
    `;

    var gl = document.querySelector("canvas").getContext("webgl");
    var m4 = twgl.m4;
    var programInfo = twgl.createProgramInfo(gl, [vs, fs]);
    var bufferInfo = twgl.primitives.createXYQuadBufferInfo(gl);

    var tex = twgl.createTexture(gl, {
    src: "https://i.imgur.com/iFom4eT.png",
    crossOrigin: "",
    }, render);

    function render() {
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);

    gl.useProgram(programInfo.program);
    twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
    twgl.setUniforms(programInfo, {
    u_tex: tex,
    u_matrix: m4.identity(),
    });
    twgl.drawBufferInfo(gl, bufferInfo);

    twgl.setUniforms(programInfo, {
    u_tex: tex,
    u_matrix: m4.scaling([0.5, 0.5, 1]),
    });
    twgl.drawBufferInfo(gl, bufferInfo);
    }
    canvas {
    background-color: purple;
    background-image: linear-gradient(45deg, rgba(255, 255, 255, 1) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 1) 50%, rgba(255, 255, 255, 1) 75%, transparent 75%, transparent);
    background-size: 50px 50px;
    }
    <script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
    <canvas></canvas>


    这是将 Canvas 设置为未预乘的示例。唯一的区别是我通过了 {premultipliedAlpha: false}getContext .我删除了 gl_FragColor.rgb *= gl_FragColor.a .而且,我将混合函数更改为 gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
    var vs = `
    attribute vec4 position;
    varying vec2 v_texcoord;
    uniform mat4 u_matrix;
    void main() {
    gl_Position = u_matrix * position;
    v_texcoord = position.xy * .5 + .5;
    }
    `;

    var fs = `
    precision mediump float;
    varying vec2 v_texcoord;
    uniform sampler2D u_tex;
    void main() {
    gl_FragColor = texture2D(u_tex, v_texcoord);
    }
    `;

    var gl = document.querySelector("canvas").getContext("webgl", {
    premultipliedAlpha: false,
    });
    var m4 = twgl.m4;
    var programInfo = twgl.createProgramInfo(gl, [vs, fs]);
    var bufferInfo = twgl.primitives.createXYQuadBufferInfo(gl);

    var tex = twgl.createTexture(gl, {
    src: "https://i.imgur.com/iFom4eT.png",
    crossOrigin: "",
    }, render);

    function render() {
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

    gl.useProgram(programInfo.program);
    twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
    twgl.setUniforms(programInfo, {
    u_tex: tex,
    u_matrix: m4.identity(),
    });
    twgl.drawBufferInfo(gl, bufferInfo);

    twgl.setUniforms(programInfo, {
    u_tex: tex,
    u_matrix: m4.scaling([0.5, 0.5, 1]),
    });
    twgl.drawBufferInfo(gl, bufferInfo);
    }
    canvas {
    background-color: purple;
    background-image: linear-gradient(45deg, rgba(255, 255, 255, 1) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 1) 50%, rgba(255, 255, 255, 1) 75%, transparent 75%, transparent);
    background-size: 50px 50px;
    }
    <script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
    <canvas></canvas>

    关于WebGL:如何正确混合 alpha channel png,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39341564/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com