代码之家  ›  专栏  ›  技术社区  ›  Elias

webgl 2d将两个透明纹理叠加在一起

  •  1
  • Elias  · 技术社区  · 8 年前

    我正在尝试将两种纹理与alpha通道相互混合。

    enter image description here

    if(gl_FragColor.a < 0.5){
        discard;
    }
    

    这适用于没有太多alpha变化的简单纹理,例如背景中的人类精灵。但是我想能够处理更复杂的图像,比如渐变精灵,它根本不起作用。

    precision mediump float;
    varying vec3 fragColor;
    varying highp vec2 vTextureCoord;
    uniform sampler2D uSampler;
    void main()
    {
        vec4 tex = texture2D(uSampler, vTextureCoord);
        gl_FragColor = tex * vec4(fragColor, 1.0);
        if(gl_FragColor.a < 0.5){
        discard;
    }
    }'
    

    这是我的顶点着色器:

    precision mediump float;
    
    attribute vec3 vertPosition;
    attribute vec3 vertColor;
    attribute vec2 aTextureCoord;
    varying vec3 fragColor;
    varying highp vec2 vTextureCoord;
    uniform mat4 uPMatrix;
    uniform mat4 uMVMatrix;
    
    uniform vec2 uvOffset;
    uniform vec2 uvScale;
    
    void main()
    {
      fragColor = vertColor;
      gl_Position = uPMatrix * uMVMatrix * vec4(vertPosition.x, vertPosition.y, vertPosition.z, 1.0);
      vTextureCoord = aTextureCoord * uvScale + uvOffset;
    }
    

    这是我使用的总账设置的一部分:

    gl.enable(gl.DEPTH_TEST);
    gl.enable(gl.BLEND);
    gl.blendEquation(gl.FUNC_ADD);
    gl.blendFunc(gl.SRC_ALPHA, gl.ON);
    

    这很有效!

    enter image description here

    <strike>gl_FragColor = tex * vec4(tex.rgb, tex.a);</strike>
    

    但它看起来还是烧焦了。

    编辑2

    我解决了。gl_FragColor应b:

    gl_FragColor = vec4(tex.rgb, tex.a);
    

    gl_FragColor = vec4(fragColor* tex.rgb, tex.a);
    

    否则会产生燃烧混合效果

    1 回复  |  直到 8 年前
        1
  •  2
  •   Rabbid76    8 年前

    因为dept测试已启用( gl.enable(gl.DEPTH_TEST) ),和默认深度函数( depthFunc )是 gl.LESS ,第二个绘制的精灵将无法通过深度测试。
    您必须禁用深度测试:

    gl.disable(gl.DEPTH_TEST);
    


    此外,我建议调整混合功能( blendFunc

    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    

    或者你使用 Alpha premultiplication . 因此,您必须调整片段着色器:

    gl_FragColor = tex * vec4(fragColor * tex.rgb, tex.a);
    

    你必须使用下面的混合函数( ):

    gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
    

    if(gl_FragColor.a < 0.5) discard;