threejs官方demo:clipping.html源碼學習

前言

gihub源碼
效果演示

開始

  1. 初始化

    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();
    	}
    
  2. 如何設置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// 設置裁剪的影子是否會影響
      });
    
    1. side是設置渲染的程度,有3個值BackSideFrontSideDoubleSide
      如果是backside則代表渲染隻影響內層
      如果是frontside則代表渲染隻影響外層
      如果是doubleside則代表渲染2層都有影響
      意義:如果對於一些幾何體確認只渲染表面,就可以設置單層渲染,可以減低性能的消耗。
      這個大家在使用的時候設置下就可以清晰的看見區別。
    2. clippingPlanes綁定裁剪平面
    3. 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個參數
分別是

  1. 被裁剪的幾何體geometry
  2. 裁剪平面plane
  3. 渲染優先級
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章