alpha blending in webgl works not correctly

前端 未结 1 1672
名媛妹妹
名媛妹妹 2021-01-26 14:02

code:

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

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

Problem

1条回答
  •  忘掉有多难
    2021-01-26 14:32

    What is your perspective zNear and zFar set to? Is it possible you're setting it too close and the back of your cube is being clipped? See sample below where it's set too close. That doesn't look like your issue but it's hard to tell.

    Also are you sorting your polygons? When rendering transparent things you generally have to draw front to back. For a convex object like a sphere, pyramid, or cube you can draw twice with culling on, first with gl.cullFace(gl.FRONT) to draw only the backfacing triangles, the ones further from the camera, and then again with gl.cullFace(gl.BACK) to draw only the front facing triangles, the ones closer to the camera.

    Yet another issue is are you correctly providing premultiplied alpha to the canvas? Most shaders do this

    gl_FragColor = someUnpremultipliedAlphaColor;
    

    But by default you need to provide pre-multiplied alpha colors

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

    Or you can set the canvas to use un-premultiplied colors

    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;
    }
    
    
    
      
    
    z-far =

    0 讨论(0)
提交回复
热议问题