前言
開始
-
初始化
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
- 渲染優先級