可以在着色器中轻松完成剪辑。使用一些计算,您甚至可以拥有一个例如像球体这样的剪切区域。在与坐标系正交的平面上进行裁剪是最简单的。在顶点着色器中计算像素的世界位置:
worldPosition = modelMatrix * vec4( position, 1.0 );
在片段着色器中,如果像素的绘制超出您的裁剪限制,则丢弃它:
if ( worldPosition.x > clippingLimitX ) {
discard;
}
但是,这将使网格在剪裁边缘处保持打开状态。要关闭它,请使用模板缓冲区。使用显示背面的场景减少模板。然后使用显示剪裁正面的场景来增加模板。
这些场景中使用的材质不应该是可见的,所以禁用它们的颜色和深度写入:
new THREE.ShaderMaterial( { colorWrite: false, depthWrite: false, ... } );
使用模板渲染位于剪切平面位置的平面。禁用模板后,渲染剪裁的正面。
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 );
我做了一个演示,展示了如何同时在多个平面上进行剪辑:
http://daign.github.io/clipping-with-caps/
我没有使用内置的 three.js 剪裁平面,因为要让这个演示工作,我必须使用一个着色器来渲染模板,该着色器确定剪裁平面是否背对相机,并且只进行剪裁在那些面向相机的平面上。