这可以通过层和模板缓冲区的组合来实现。
工作演示: https ://jsfiddle.net/mmalex/dg417kvn/
解决方案:
如需解释,请按照以下代码中的注释进行操作:
document.fixZFighting = function() {
// 1. Get the current WebGL context
const gl = renderer.getContext();
// 2. Set rendering order: mesh before line,
// because we want mesh to initialize stencil buffers before line rendering.
cube.renderOrder = 1;
line.renderOrder = 2;
// 3. Provide render callbacks
cube.onBeforeRender = function() {
// enable stencil buffer test
gl.enable(gl.STENCIL_TEST);
// do it just for all mesh pixels
gl.stencilFunc(gl.ALWAYS, 1, 0xFF);
// ... with no masking
gl.stencilMask(0xFF);
// ... simply increment stencil buffer value for each draw call,
// (important, here we have
gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
}
cube.onAfterRender = function() {
// nothing to do
}
line.onBeforeRender = function() {
// don't rely on z-Buffer for line, disable depth check
gl.disable(gl.DEPTH_TEST);
// enable stencil buffer check instead
gl.enable(gl.STENCIL_TEST)
gl.stencilMask(0x00);
// render line only where stencil buffer was incremented exactly twice
gl.stencilFunc(gl.EQUAL, 2, 0xFF);
}
line.onAfterRender = function() {
// restore flags to initial order
gl.disable(gl.STENCIL_TEST);
gl.enable(gl.DEPTH_TEST);
}
// don't let user click the button twice
document.getElementById("btn").setAttribute("disabled", true);
}