以圆柱体为例,通过改变material.side绘制同一物体所显示的效果是不同的,见下图。
圆柱体_前

圆柱体_后

若剖切面正好是圆柱体的顶面所在面,那么圆柱体_后与圆柱体_前的差值部分正好就是剖切面,所以借助模板测试便可实现剖切面的绘制。
先看一下圆柱体_后、圆柱体_前、剖切面的材质参数设置。圆柱体_后和圆柱体_前都需要关闭深度检测、深度写入、颜色写入,因为他们的主要目的是使模板缓冲区中最终记录插值部分即剖切面。模板缓冲区初始值都是0,圆柱体_后的模板测试行为是总是通过且通过后值+1,圆柱体_前的模板测试行为是总是通过且通过后值-1。经过圆柱体_后和圆柱体_前的绘制之后只有差值部分的模板值非0。此时绘制剖切面,设置模板引用值为0,设置测试方式为不相等也就是不等于引用值时通过。最终通过的部分就是剖切面真正需要绘制的部分。
// 后
const backMat = new THREE.MeshBasicMaterial();
backMat.depthWrite = false;
backMat.depthTest = false;
backMat.colorWrite = false;
backMat.stencilWrite = true;
backMat.stencilFunc = THREE.AlwaysStencilFunc;
backMat.side = THREE.BackSide;
backMat.clippingPlanes = [ plane ];
backMat.stencilFail = THREE.IncrementWrapStencilOp;
backMat.stencilZFail = THREE.IncrementWrapStencilOp;
backMat.stencilZPass = THREE.IncrementWrapStencilOp;
// 前
const frontMat = new THREE.MeshBasicMaterial();
frontMat.depthWrite = false;
frontMat.depthTest = false;
frontMat.colorWrite = false;
frontMat.stencilWrite = true;
frontMat.stencilFunc = THREE.AlwaysStencilFunc;
frontMat.side = THREE.FrontSide;
frontMat.clippingPlanes = [ plane ];
frontMat.stencilFail = THREE.DecrementWrapStencilOp;
frontMat.stencilZFail = THREE.DecrementWrapStencilOp;
frontMat.stencilZPass = THREE.DecrementWrapStencilOp;
// 剖切面
const cutPlaneMat = new THREE.MeshBasicMaterial();
cutPlaneMat.stencilWrite = true;
cutPlaneMat.stencilRef = 0;
cutPlaneMat.stencilFunc = THREE.NotEqualStencilFunc;
cutPlaneMat.stencilFail = THREE.ReplaceStencilOp;
cutPlaneMat.stencilZFail = THREE.ReplaceStencilOp;
cutPlaneMat.stencilZPass = THREE.ReplaceStencilOp;
另外还需要通过renderOrder设置渲染顺序,保证圆柱体_后、圆柱体_前先绘制,之后在绘制剖切面。如果剖切面存在多个在绘制一个之后需要清除模板缓冲区后,再绘制下一个。
案例及源码见three官网,点击查看.
本文介绍了一种利用Three.js实现三维模型剖切面绘制的方法。通过调整材质参数和使用模板测试,可以精确地显示出物体的剖切效果。具体步骤包括设置前后材质参数、配置模板操作,并控制渲染顺序。
221

被折叠的 条评论
为什么被折叠?



