webgl中的alpha混合工作不正确 [英] alpha blending in webgl works not correctly

查看:80
本文介绍了webgl中的alpha混合工作不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码:

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

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

绘制多余数字的问题:

如何更正?

PS alpha = 0.9

Problem in that on a figure "superfluous" is drawn:
how to correct it?
P.S. alpha=0.9

推荐答案

你的观点zNear和zFar设置为什么?是否有可能将它设置得太近而且你的立方体背面被裁剪了?请参阅下面的示例,它设置得太近了。这看起来不像你的问题,但很难说。

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.

你也在排序你的多边形吗?渲染透明物品时,通常需要从前到后绘制。对于像球体,金字塔或立方体这样的凸形物体,您可以在剔除时绘制两次,首先使用 gl.cullFace(gl.FRONT)来仅绘制背面三角形,那些远离相机的,然后再用 gl.cullFace(gl.BACK)来绘制前面的三角形,那些更靠近相机的那些。

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.

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

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

gl_FragColor = someUnpremultipliedAlphaColor;

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

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;
}

<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>

这篇关于webgl中的alpha混合工作不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆