• 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();
        },
  • 相关阅读:
    day 80 视图家族
    day 79 drf 多表关联操作
    day 78 drf 序列化
    day 77 drf中请求、渲染、解析、异常、响应模块的二次封装
    day 76 drf
    python小知识
    请求 渲染 解析 异常 响应模块
    子组件
    vue基础(2)
    vue基础
  • 原文地址:https://www.cnblogs.com/yc-c/p/14090013.html
Copyright © 2020-2023  润新知