【问题标题】:alpha blending in webgl works not correctlywebgl 中的 alpha 混合工作不正确
【发布时间】:2015-03-23 17:59:50
【问题描述】:

代码:

gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LESS);

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

在“多余”的图形上绘制的问题:
如何纠正?
附言阿尔法=0.9

【问题讨论】:

    标签: javascript webgl alpha alphablending


    【解决方案1】:

    您将 zNear 和 zFar 设置为什么视角?有没有可能你把它设置得太近了,你的立方体的背面被剪掉了?请参阅下面的示例,它设置得太近了。这看起来不像你的问题,但很难说。

    您还在对多边形进行排序吗?当渲染透明的东西时,你通常必须从前到后绘制。对于像球体、金字塔或立方体这样的凸面对象,您可以在启用剔除的情况下绘制两次,首先使用gl.cullFace(gl.FRONT) 仅绘制背面三角形,即距离相机较远的三角形,然后再次使用gl.cullFace(gl.BACK) 仅绘制正面三角形,靠近相机的三角形。

    还有一个问题是您是否正确地为画布提供了预乘 alpha?大多数着色器都这样做

    gl_FragColor = someUnpremultipliedAlphaColor;
    

    但默认情况下您需要提供预乘的 alpha 颜色

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

    或者您可以将画布设置为使用未预乘的颜色

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

    window.onload = function() {
      // Get A WebGL context
      var canvas = document.getElementById("c");
      var gl = canvas.getContext("webgl");
      if (!gl) {
        return;
      }
      
      var programInfo = webglUtils.createProgramInfo(gl, ["vs", "fs"]);
      var createFlattenedVertices = function(gl, vertices) {
        return webglUtils.createBufferInfoFromArrays(
            gl,
            primitives.makeRandomVertexColors(
                primitives.deindexVertices(vertices),
                {
                  vertsPerColor: 6,
                  rand: function(ndx, channel) {
                    return channel < 3 ? ((128 + Math.random() * 128) | 0) : 255;
                  }
                })
          );
      };
    
      var bufferInfo   = createFlattenedVertices(gl, primitives.createCubeVertices(1));
      
      function degToRad(d) {
        return d * Math.PI / 180;
      }
    
      var cameraAngleRadians = degToRad(0);
      var fieldOfViewRadians = degToRad(60);
      var uniforms = {
        u_color: [1, 1, 1, 0.8],
        u_matrix: null,
      };
      
      var zClose = false;
      var zNear = 1;
      var zFar  = 3;
      var zElem = document.getElementById("z");
      var bElem = document.getElementById("b");
      bElem.addEventListener('click', toggleZDepth, false);
      toggleZDepth();
      
      function toggleZDepth() {
        zClose = !zClose;
        zFar = zClose ? 3.5 : 4;
        zElem.innerHTML = zFar;    
      }
      
      function drawScene() {
        
        gl.enable(gl.CULL_FACE);
        gl.enable(gl.DEPTH_TEST);
        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    
        var aspect = canvas.clientWidth / canvas.clientHeight;
        var projectionMatrix =
            makePerspective(fieldOfViewRadians, aspect, zNear, zFar);
        
        var time = Date.now() * 0.0005;
        var radius = 3;
    
        var cameraPosition = [Math.cos(time) * radius, 1, Math.sin(time) * radius];
        var target = [0, 0, 0];
        var up = [0, 1, 0];
        var cameraMatrix = makeLookAt(cameraPosition, target, up);
        var viewMatrix = makeInverse(cameraMatrix);
    
        uniforms.u_matrix = matrixMultiply(viewMatrix, projectionMatrix);
    
        gl.useProgram(programInfo.program);
        webglUtils.setBuffersAndAttributes(gl, programInfo.attribSetters, bufferInfo);
        webglUtils.setUniforms(programInfo.uniformSetters, uniforms);
        
        // draw back facing polygons first
        gl.cullFace(gl.FRONT);
        gl.drawArrays(gl.TRIANGLES, 0, bufferInfo.numElements);
        // now draw front facing polygons
        gl.cullFace(gl.BACK);
        gl.drawArrays(gl.TRIANGLES, 0, bufferInfo.numElements);
        
        requestAnimationFrame(drawScene);
      }
      drawScene();
    }
    canvas { 
      border: 1px solid black;
    }
    #overlay {
      position: absolute;
      top: 20px;
      left: 20px;
      z-index: 2;
    }
    <script src="//webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
    <script src="//webglfundamentals.org/webgl/resources/webgl-3d-math.js"></script>
    <script src="//webglfundamentals.org/webgl/resources/primitives.js"></script>
    <canvas id="c" width="400" height="200"></canvas>  
    <div id="overlay">
      <button id="b">toggle z-far</button>
      <div>z-far = <span id="z"></span></div>
    </div>
    <!-- vertex shader -->
    <script id="vs" type="x-shader/x-vertex">
    attribute vec4 a_position;
    attribute vec4 a_color;
    
    varying vec4 v_color;
    
    uniform mat4 u_matrix;
    
    void main() {
       gl_Position = u_matrix * a_position;
       v_color = a_color;   
    }
    </script>
    <!-- fragment shader -->
    <script id="fs" type="x-shader/x-fragment">
    precision mediump float;
    
    uniform vec4 u_color;
    varying vec4 v_color;
    
    void main() {
       vec4 color = v_color * u_color;
       gl_FragColor = vec4(color.rgb * color.a, color.a);  // premultiply color
    }
    </script>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-22
      • 1970-01-01
      • 2017-02-27
      • 1970-01-01
      相关资源
      最近更新 更多