【发布时间】: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
代码:
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
您将 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>
【讨论】: