three.js 離屏渲染
需求:
1、全景圖展示
2、全景圖切換的時候做淡進淡出效果
需求講解:
如果只是做單獨的全景圖切換、可以不用離屏渲染效果、因全景圖內還有部分功能點、介紹點等
如果單個場景進行淡進淡出的話、直接調整該場景模型的透明度就可以了、但這裡涉及到了多層模型的問題、會存在切換黑屏、批量迴圈的問題(迴圈用多了總是不好的)
實際實現方式:
1、材料:
兩個場景(Scene)、
兩個相機(透視相機PerspectiveCamera、
正交相機OrthographicCamera)、
一個控制器(OrbitControls)、
兩個渲染器(WebGLRenderer、WebGLRenderTarget)、
動畫執行外掛(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(); },