webgl中的alpha混合工作不正确

时间:2015-03-23 17:59:50

标签: javascript webgl alpha alphablending

代码:

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

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

在绘制“多余”的数字时会出现问题:enter image description here
如何纠正? 附:阿尔法= 0.9

1 个答案:

答案 0 :(得分:2)

你的观点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();
}
&#13;
canvas { 
  border: 1px solid black;
}
#overlay {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 2;
}
&#13;
<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>
&#13;
&#13;
&#13;