1. 程式人生 > 實用技巧 >three.js 離屏渲染

three.js 離屏渲染

需求:

1、全景圖展示

2、全景圖切換的時候做淡進淡出效果

需求講解:

如果只是做單獨的全景圖切換、可以不用離屏渲染效果、因全景圖內還有部分功能點、介紹點等

如果單個場景進行淡進淡出的話、直接調整該場景模型的透明度就可以了、但這裡涉及到了多層模型的問題、會存在切換黑屏、批量迴圈的問題(迴圈用多了總是不好的)

實際實現方式:

1、材料:

兩個場景(Scene)、

兩個相機(透視相機PerspectiveCamera

正交相機OrthographicCamera)、

一個控制器(OrbitControls)、

兩個渲染器(WebGLRendererWebGLRenderTarget)、

動畫執行外掛(Tween) // 一個數值變換的庫、自行百度

2、步驟

一、建立一個正常的場景使用正交相機進行瀏覽

二、建立一個快取場景WebGLRenderTarget (之後的所有場景更新都是在這個快取場景內進行的)

三、在展示場景內增加一個物體、將快取場景載入展示(buffer_target.texture 快取場景可以直接使用texture引數進行賦值)

四、場景迴圈渲染(兩個渲染器都要更新、單獨更新某一個都是不行的、還有就是注意渲染順序 必須先渲染快取場景)

五、 新增場景 並切換到新的場景(這裡要更新的引數有:控制器控制的場景更換、主場景的兩個物體位置、舊物體的透明度、以及舊場景的清除工作)

記得要想更改看到的內容的話、一定是要更改快取場景的資料。

還有就是場景切換記得要做限制。否則切換的時候多次建立場景的話、就GG了 哈哈 !!

這個就是我個人的用法、其實完全可以用兩個場景重複使用的方式、這樣的話就不怕同時建立多個場景的問題、只是我這裡用不到 所有就麼有研究、有興趣的可以自己嘗試一下。

反正也不知道是不是正統的方式、我這樣是可以實現、或許你有更簡單的方式也歡迎告知、謝謝 !!

完成!!

建立展示場景:

 init() {
      // 主場景: 離屏渲染
      this.scene = new THREE.Scene();
      // this.scene.background = new THREE.Color('red')
this.renderer = new THREE.WebGLRenderer(); this.renderer.setSize(window.innerWidth, window.innerHeight); document .getElementById("container") .appendChild(this.renderer.domElement); // 主場景相機 var aspect = this.width / this.height; var halfWidth = window.innerWidth / 2; var halfHeight = window.innerHeight / 2; this.camera = new THREE.OrthographicCamera( -halfWidth, halfWidth, halfHeight, -halfHeight, -1, 10000 ); this.camera.lookAt(0, 0, 0); //看向位置 this.camera.position.set(-1, 0, -1); this.scene.add(this.camera); this.newscene(); },

建立快取場景(個人是將新建場景和更換場景的函式複用的、場景不合適你也可以寫兩個函式進行處理):

newscene(event) {
      // 新建場景

      var nowscene = this.scene.children[1];
      (this.width = document.documentElement.clientWidth),
        (this.height = document.documentElement.clientHeight);
      console.log("更新場景", this.width, this.height);

      var new_scene = new THREE.Scene();
      var new_target = new THREE.WebGLRenderTarget();
      // 相機設定
      new_target.setSize(this.width, this.height);
      var new_camera = new THREE.PerspectiveCamera(
        75,
        this.width / this.height,
        1,
        1000
      );
      new_camera.lookAt(0, 0, 0); //看向位置
      if (nowscene) {
        var nowdata = this.buffer_camera.position; //保留當前相機位置、
        new_camera.position.set(nowdata.x, nowdata.y, nowdata.z);
      } else {
        // 首次載入
        new_camera.position.set(-0.1, 0, -0.1);
      }
      new_scene.add(new_camera);

      this.assignment(new_scene, new_target, new_camera); //更新操作場景引數
      this.renderer.setSize(this.width, this.height);
      // 建立場景貼圖
      var skyGeometry = new THREE.BoxGeometry(100, 100, 100);
      var skyMaterial = new THREE.MeshFaceMaterial(
        this.lodingsex(this.NowModel.ivtimg)
      );
      var skyBox = new THREE.Mesh(skyGeometry, skyMaterial); //建立一個完整的天空盒,填入幾何模型和材質的引數
      skyBox.name = "img_model";
      skyBox.modeltype = 0;
      skyBox.scale.set(-1, 1, 1);
      new_scene.add(skyBox); //在場景中加入天空盒

      this.Addspot(this.NowModel.spot);

      // 更新場景展示模型
      var geometry = new THREE.PlaneGeometry(this.width, this.height, 10);
      var material = new THREE.MeshBasicMaterial({
        // color: 0xffff00,
        side: THREE.DoubleSide,
        map: this.buffer_target.texture,
      });
      var plane1 = new THREE.Mesh(geometry, material);
      plane1.name = this.NowModel.name;

      console.log(plane1);
      if (nowscene) {
        // 首次載入不執行載入動畫
        // 執行淡進淡出動畫
        console.log(
          "場景:",
          this.scene,
          "模型:",
          plane1,
          "相機:",
          this.camera
        );
        plane1.position.set(-1, 0, -1);
      } else {
        plane1.position.set(0, 0, 0);
      }
      this.scene.add(plane1);
    },

更新控制引數:

assignment(scene, target, camera) {
      // 控制器與場景資訊更新
      this.buffer_scene = scene;
      this.buffer_target = target;
      this.buffer_camera = camera;

      this.orbitControls = new OrbitControls(
        this.buffer_camera,
        this.renderer.domElement
      );
      this.orbitControls.enableDamping = true;
      this.orbitControls.enableZoom = false;
      this.orbitControls.dampingFactor = 0.05;
      //  this.orbitControls.update();
    },

渲染器更新(記得加到主動畫函式裡面):

    render() {
      // 渲染器
      this.renderer.setRenderTarget(this.buffer_target);
      this.renderer.render(this.buffer_scene, this.buffer_camera);
      this.renderer.setRenderTarget(null);
      this.renderer.render(this.scene, this.camera);
    },

淡進淡出動畫(這是之前說的模型位置、透明度調整動畫):

animateOpacity(event1, event2) {
      // 淡進淡出動畫
      console.log(event1, event2)
      event2.position.set(-1, 0, -1);
      event1.material.transparent = true; // 允許透明度設定
      event1.position.set(0, 0, 0);
      var tween = new TWEEN.Tween({
        o: 1, 
        x: -1,
        y: 0,
        z: -1,
        x1: 0,
        y1: 0,
        z1: 0,
      });
      let self = this;
      tween.to({
      o: 0, 
      x: 0,
      y: 0, 
      z: 0, 
      x1: -1, 
      y1: 0, 
      z1: -1 }, 1000);
      tween.onUpdate(function (obj) {
        // 更新場景透明度、調整場景2的展示位置
        event1.material.opacity = this.o;
        // event1.position.set(this.x1,this.y1,this.z1);
        event2.position.set(this.x, this.y, this.z);
      });
      tween.onComplete(function () {
        // 場景清空並刪除載入場景模型
        event1.geometry.dispose();
        event1.material.dispose();
        self.scene.remove(event1);
        self.animatetype = true; // 開啟可進入動畫入口
      });
      tween.easing(TWEEN.Easing.Cubic.InOut);
      tween.start();
    },