2

我正在尝试在 three.js 中的脸上画线

一切都很好,除了线条几乎不可见——不管我把它们做得有多厚:它们看起来像这样:

几乎看不见的线条

画线的代码是:

var lgeometry = new THREE.Geometry();
var lmaterial = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 4 } );

var v1 = p1;
var v2 = p2;

lgeometry.vertices.push(v1);
lgeometry.vertices.push(v2);

console.log(lgeometry);
var line = new THREE.Line( lgeometry, lmaterial );

scene.add( line );

我怀疑 - 因为线条正好在表面上,所以它们不会被渲染(这就是所谓的z-fighting吗?)

有没有办法解决这个问题?

我正在考虑:

  • 绘制圆柱体或其他形状而不是线条
  • 沿着法线在曲面上方一条线

有什么建议或方向吗?

4

1 回答 1

1

这可以通过层和模板缓冲区的组合来实现。

工作演示: https ://jsfiddle.net/mmalex/dg417kvn/

如何解决模板缓冲区的 z-fighting 问题


解决方案:

如需解释,请按照以下代码中的注释进行操作:

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);
}
于 2019-03-20T14:18:55.980 回答