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. 渲染优先级
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章