Three.JS Object Clipping?

前端 未结 2 1779
无人共我
无人共我 2020-12-15 01:46

I am trying to section my 3D models using three.js in a way similar to how Unity can:

I have been playing around with the camera controls and of course I can adjust

相关标签:
2条回答
  • 2020-12-15 01:57

    Clipping can be easily done in the shader. Using some calculations you could even have a for example sphere like clipping area. Clipping at a plane orthogonal to the coordinate system is the easiest. In the vertex shader calculate the world position of the pixel:

    worldPosition = modelMatrix * vec4( position, 1.0 );
    

    In the fragment shader discard the drawing of the pixel if it is beyond your clipping limit:

    if ( worldPosition.x > clippingLimitX ) {
        discard;
    }
    

    This will however leave the mesh open at the clipping edge. To close it use a stencil buffer. Decrement the stencil with a scene showing the backfaces. Then increment the stencil with a scene showing the clipped front faces. The materials used in these scenes should not be visible so disable their color and depth write:

    new THREE.ShaderMaterial( { colorWrite: false, depthWrite: false, ... } );
    

    Use the stencil to render a plane that is located at the clipping planes position. After disabling the stencil render the clipped front faces.

    renderer.autoClear = false;
    renderer.clear();
    
    var gl = renderer.context;
    
    renderer.state.setStencilTest( true );
    
    renderer.state.setStencilFunc( gl.ALWAYS, 1, 0xff );
    renderer.state.setStencilOp( gl.KEEP, gl.KEEP, gl.INCR );
    renderer.render( backStencilScene, camera );
    
    renderer.state.setStencilFunc( gl.ALWAYS, 1, 0xff );
    renderer.state.setStencilOp( gl.KEEP, gl.KEEP, gl.DECR );
    renderer.render( frontStencilScene, camera );
    
    renderer.state.setStencilFunc( gl.EQUAL, 1, 0xff );
    renderer.state.setStencilOp( gl.KEEP, gl.KEEP, gl.KEEP );
    renderer.render( capsScene, camera );
    
    renderer.state.setStencilTest( false );
    
    renderer.render( scene, camera );
    

    I made a demo showing how to clip at more than one plane at once:

    http://daign.github.io/clipping-with-caps/

    I didn't use the build-in three.js clipping planes because for this demo to work I have to render the stencil using a shader that determines whether a clipping plane is facing away from the camera or not, and only clip at those planes facing the camera.

    0 讨论(0)
  • 2020-12-15 02:05

    Clipping is now supported.

    Here is the pattern to follow. Adapt it according to your use case.

    var localPlane = new THREE.Plane( new THREE.Vector3( 0, - 1, 0 ), 1 );
    
    var globalPlane = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 1 );
    
    renderer.clippingPlanes = [ globalPlane ];
    
    renderer.localClippingEnabled = true;
    
    var material = new THREE.MeshPhongMaterial( {
        clippingPlanes: [ localPlane ],
        clipShadows: true
    } );
    

    See these three.js examples:

    https://threejs.org/examples/webgl_clipping.html https://threejs.org/examples/webgl_clipping_advanced.html

    three.js r.85

    0 讨论(0)
提交回复
热议问题