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();
    },
原文地址:https://www.cnblogs.com/yc-c/p/14090013.html