前言
开始
-
初始化
function init() { // 初始化 camera = new THREE.PerspectiveCamera( 36, window.innerWidth / window.innerHeight, 0.25, 16 ); camera.position.set(0, 1.3, 3); scene = new THREE.Scene(); // 灯光 // Lights scene.add(new THREE.AmbientLight(0x505050)); var spotLight = new THREE.SpotLight(0xffffff); spotLight.angle = Math.PI / 5; spotLight.penumbra = 0.2; spotLight.position.set(2, 3, 3); spotLight.castShadow = true; spotLight.shadow.camera.near = 3; spotLight.shadow.camera.far = 10; spotLight.shadow.mapSize.width = 1024; spotLight.shadow.mapSize.height = 1024; scene.add(spotLight); var dirLight = new THREE.DirectionalLight(0x55505a, 1); dirLight.position.set(0, 3, 0); dirLight.castShadow = true; dirLight.shadow.camera.near = 1; dirLight.shadow.camera.far = 10; dirLight.shadow.camera.right = 1; dirLight.shadow.camera.left = -1; dirLight.shadow.camera.top = 1; dirLight.shadow.camera.bottom = -1; dirLight.shadow.mapSize.width = 1024; dirLight.shadow.mapSize.height = 1024; scene.add(dirLight); // 裁剪平面 // ***** Clipping planes: ***** var localPlane = new THREE.Plane(new THREE.Vector3(0, -1, 0), 0.8); var globalPlane = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0.1); // 几何体 var material = new THREE.MeshPhongMaterial({ color: 0x80ee10, shininess: 1000, side: THREE.DoubleSide, // 设置裁剪平面 // ***** Clipping setup (material): ***** clippingPlanes: [localPlane], clipShadows: false }); var geometry = new THREE.TorusKnotBufferGeometry(0.4, 0.08, 95, 20); object = new THREE.Mesh(geometry, material); object.castShadow = true; scene.add(object); var ground = new THREE.Mesh( new THREE.PlaneBufferGeometry(9, 9, 1, 1), new THREE.MeshPhongMaterial({ color: 0xa0adaf, shininess: 150 }) ); ground.rotation.x = -Math.PI / 2; // rotates X/Y to X/Z ground.receiveShadow = true; scene.add(ground); // Renderer renderer = new THREE.WebGLRenderer(); renderer.shadowMap.enabled = true; renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); // window.addEventListener("resize", onWindowResize, false); document.body.appendChild(renderer.domElement); // ***** Clipping setup (renderer): ***** var globalPlanes = [globalPlane], Empty = Object.freeze([]); // 全局裁剪 renderer.clippingPlanes = Empty; // GUI sets it to globalPlanes // 是否可以裁剪 renderer.localClippingEnabled = true; // control var controls = new OrbitControls(camera, renderer.domElement); controls.target.set(0, 1, 0); controls.update(); var gui = new GUI(), folderLocal = gui.addFolder("Local Clipping"), propsLocal = { get Enabled() { return renderer.localClippingEnabled; }, set Enabled(v) { renderer.localClippingEnabled = v; }, get Shadows() { return material.clipShadows; }, set Shadows(v) { material.clipShadows = v; }, get Plane() { return localPlane.constant; }, set Plane(v) { localPlane.constant = v; } }, folderGlobal = gui.addFolder("Global Clipping"), propsGlobal = { get Enabled() { return renderer.clippingPlanes !== Empty; }, set Enabled(v) { renderer.clippingPlanes = v ? globalPlanes : Empty; }, get Plane() { return globalPlane.constant; }, set Plane(v) { globalPlane.constant = v; } }; folderLocal.add(propsLocal, "Enabled"); folderLocal.add(propsLocal, "Shadows"); folderLocal.add(propsLocal, "Plane", 0.3, 1.25); folderGlobal.add(propsGlobal, "Enabled"); folderGlobal.add(propsGlobal, "Plane", -0.4, 3); // Start startTime = Date.now(); }
-
如何设置clip
一般使用裁剪都使用plane
生成一个平面进行裁剪var localPlane = new THREE.Plane(new THREE.Vector3(0, -1, 0), 0.8); var globalPlane = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0.1);
-
第一个参数是平面生成的方向
localPlane
是一个平行xy面的平面globalPlane
是平行yz方向的平面
-
第二个参数是
constant
的值- 用于指定裁剪的位置
然后被裁剪的几何体与裁剪进行绑定
var material = new THREE.MeshPhongMaterial({ color: 0x80ee10, shininess: 1000, // 这个值也很有意思 side: THREE.DoubleSide, // 设置裁剪平面 // ***** Clipping setup (material): ***** clippingPlanes: [localPlane], clipShadows: false// 设置裁剪的影子是否会影响 });
side
是设置渲染的程度,有3个值BackSide
、FrontSide
、DoubleSide
如果是backside
则代表渲染只影响内层
如果是frontside
则代表渲染只影响外层
如果是doubleside
则代表渲染2层都有影响
意义:如果对于一些几何体确认只渲染表面,就可以设置单层渲染,可以减低性能的消耗。
这个大家在使用的时候设置下就可以清晰的看见区别。clippingPlanes
绑定裁剪平面clipShadows
设置影子是否会守裁剪的影响
-
全局裁剪
这个例子也提供了一个快速进行全局裁剪的方法
直接对renderer
渲染器进行裁剪
renderer.clippingPlanes = panel//设置全局裁剪平面
// 是否可以裁剪
renderer.localClippingEnabled = true;
拓展:多个裁剪平面
这个也是官方例子有说明
演示地址
我们直接看关键的部分
function createPlaneStencilGroup(geometry, plane, renderOrder) {
var group = new THREE.Group();
var baseMat = new THREE.MeshBasicMaterial();
baseMat.depthWrite = false;
baseMat.depthTest = false;
baseMat.colorWrite = false;
baseMat.stencilWrite = true;
baseMat.stencilFunc = THREE.AlwaysStencilFunc;
// back faces
var mat0 = baseMat.clone();
mat0.side = THREE.BackSide;
mat0.clippingPlanes = [plane];
mat0.stencilFail = THREE.IncrementWrapStencilOp;
mat0.stencilZFail = THREE.IncrementWrapStencilOp;
mat0.stencilZPass = THREE.IncrementWrapStencilOp;
var mesh0 = new THREE.Mesh(geometry, mat0);
mesh0.renderOrder = renderOrder;
group.add(mesh0);
// front faces
var mat1 = baseMat.clone();
mat1.side = THREE.FrontSide;
mat1.clippingPlanes = [plane];
mat1.stencilFail = THREE.DecrementWrapStencilOp;
mat1.stencilZFail = THREE.DecrementWrapStencilOp;
mat1.stencilZPass = THREE.DecrementWrapStencilOp;
var mesh1 = new THREE.Mesh(geometry, mat1);
mesh1.renderOrder = renderOrder;
group.add(mesh1);
return group;
}
这里有3个参数
分别是
- 被裁剪的几何体geometry
- 裁剪平面plane
- 渲染优先级