<address id="ttjl9"></address>

      <noframes id="ttjl9"><address id="ttjl9"><nobr id="ttjl9"></nobr></address>
      <form id="ttjl9"></form>
        <em id="ttjl9"><span id="ttjl9"></span></em>
        <address id="ttjl9"></address>

          <noframes id="ttjl9"><form id="ttjl9"></form>

          THREE.JS實現看房自由(VR看房)

          2023-2-1    前端達人


          一、前言

          概述:基于WebGL的三維引擎,目前是國內資料最多、使用最廣泛的三維引擎,可以制作一些3D可視化項目

          在這里插入圖片描述

          目前隨著元宇宙概念的爆火,THREE技術已經深入到了物聯網、VR、游戲、數據可視化等多個平臺,今天我們主要基于THREE實現一個三維的VR看房小項目

          二、基礎知識

          在這里插入圖片描述

          Three.js一般分為三個部分:場景、相機、渲染器,這三個主要的分支就構成了THREE.JS的主要功能區,這三大部分還有許多細小的分支,這些留到我們后續抽出一些章節專門講解一下。

          在這里插入圖片描述

          工作流程:場景——相機——渲染器

          實際生活中拍照角度立方體網格模型和光照組成了一個虛擬的三維場景,相機對象就像你生活中使用的相機一樣可以拍照,只不過一個是拍攝真實的景物,一個是拍攝虛擬的景物。拍攝一個物體的時候相機的位置和角度需要設置,虛擬的相機還需要設置投影方式,當你創建好一個三維場景,相機也設置好,就差一個動作“咔”,通過渲染器就可以執行拍照動作。

          三、場景

          概述:場景主要由網絡模型與光照組成,網絡模型分為幾何體與材質

          3.1 網絡模型

          幾何體就像我們小時候學我們就知道點線面體四種概念,點動成線,線動成面,面動成體,而材質就像是是幾何體上面的涂鴉,有不同的顏色、圖案…

          例子如下:

          在這里插入圖片描述

          //打造酷炫三角形 for (let i = 0; i < 50; i++) { const geometry = new THREE.BufferGeometry(); const arr = new Float32Array(9); for (let j = 0; j < 9; j++) { arr[j] = Math.random() * 5; } geometry.setAttribute('position', new THREE.BufferAttribute(arr, 3)); let randomColor = new THREE.Color(Math.random(), Math.random(), Math.random()); const material = new THREE.MeshBasicMaterial({ color: randomColor, transparent: true, opacity:0.5, }); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); } 
                  
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17

          [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-UlBSgxKr-1666681292595)(https://gitee.com/riskbaby/picgo/raw/master/blog/202209211037215.png#pic_center)]

          const geometry = new THREE.BoxGeometry(100, 100, 100); const material = new THREE.MeshStandardMaterial({ color: 0x0000ff }); const cube = new THREE.Mesh(geometry, material); scene.add(cube); 
                  
          • 1
          • 2
          • 3
          • 4

          在這里插入圖片描述

          const geometry = new THREE.ConeGeometry(5, 15, 32);//底面半徑 高 側邊三角分段 const material = new THREE.MeshStandardMaterial({ color: 0x0000ff }); const clone = new THREE.Mesh(geometry, material); scene.add(clone); 
                  
          • 1
          • 2
          • 3
          • 4

          3.2 光照

          3.2.1 環境光

          概念:光照對three.js的物體全表面進行光照測試,有可能會發生光照融合

          在這里插入圖片描述

          //環境光 const ambient = new THREE.AmbientLight(0x404040); scene.add(ambient); 
                  
          • 1
          • 2
          • 3

          3.2.2 平行光

          概念:向特定方向發射的光,太陽光也視作平行的一種,和上面比較,物體變亮了

          //平行光  顏色 強度 const directionalLight = new THREE.DirectionalLight(0xffffff, 1); directionalLight.position.set(100, 100, 100);//光源位置 directionalLight.target = cube;//光源目標 默認 0 0 0 scene.add(directionalLight); 
                  
          • 1
          • 2
          • 3
          • 4
          • 5

          3.2.3 點光源

          概念:由中間向四周發射光、強度比平行光小

          在這里插入圖片描述

          // 顏色 強度 距離 衰退量(默認1) const pointLight = new THREE.PointLight(0xff0000, 1, 100, 1); pointLight.position.set(50, 50, 50); scene.add(pointLight); 
                  
          • 1
          • 2
          • 3
          • 4
          • 5

          3.2.4 聚光燈

          概念:家里面的節能燈泡,強度較好

          在這里插入圖片描述

          //聚光燈 const spotLigth = new THREE.PointLight(0xffffff); spotLigth.position.set(50, 50, 50); spotLigth.target = cube; spotLigth.angle = Math.PI / 6; scene.add(spotLigth); 
                  
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6

          3.2.5 半球光

          概念:光源直接放置于場景之上,光照顏色從天空光線顏色漸變到地面光線顏色

          在這里插入圖片描述

          //半球光 const light = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);//天空 場景  scene.add(light); 
                  
          • 1
          • 2
          • 3

          四、相機

          4.1 正交相機

          在這里插入圖片描述

          參數(屬性) 含義
          left 渲染空間的左邊界
          right 渲染空間的右邊界
          top 渲染空間的上邊界
          bottom 渲染空間的下邊界
          near near屬性表示的是從距離相機多遠的位置開始渲染,一般情況會設置一個很小的值。 默認值0.1
          far far屬性表示的是距離相機多遠的位置截止渲染,如果設置的值偏小小,會有部分場景看不到。 默認值1000
          let width = window.innerWidth; let height = window.innerHeight; const camera = new THREE.OrthographicCamera(width / - 2, width / 2, height / 2, height / - 2, 1, 1000); scene.add(camera); camera.position.set(100, 200, 100); 
                  
          • 1
          • 2
          • 3
          • 4
          • 5

          4.2 透視相機

          在這里插入圖片描述

          參數 含義 默認值
          fov fov表示視場,所謂視場就是能夠看到的角度范圍,人的眼睛大約能夠看到180度的視場,視角大小設置要根據具體應用,一般游戲會設置60~90度 45
          aspect aspect表示渲染窗口的長寬比,如果一個網頁上只有一個全屏的canvas畫布且畫布上只有一個窗口,那么aspect的值就是網頁窗口客戶區的寬高比 window.innerWidth/window.innerHeight
          near near屬性表示的是從距離相機多遠的位置開始渲染,一般情況會設置一個很小的值。 0.1
          far far屬性表示的是距離相機多遠的位置截止渲染,如果設置的值偏小,會有部分場景看不到 1000
          let width = window.innerWidth; let height = window.innerHeight; const camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000); camera.position.set(150, 100, 300); camera.lookAt(scene.position); 
                  
          • 1
          • 2
          • 3
          • 4
          • 5

          五、渲染器

          概述:從WEBGL的角度來看,three就是對它的進一步封裝,想要進一步了解渲染器這方面的知識點還需要了解一下WEBGL,這里我們就不做過多介紹了。

          六、貼圖紋理

          6.1 基礎介紹

          概述:這部分對于我們是否能夠給別人呈現一個真實的渲染場景來說,很重要,比如下面一個普普通通的正方體,我們只要一加上貼圖,立馬不一樣了。

          以前

          在這里插入圖片描述

          之后

          在這里插入圖片描述

          6.2 環境貼圖

          概述:目前有許許多多的貼圖,比如基礎、透明、環境、法線、金屬、粗糙、置換等等,今天我們呢主要講解一下環境和一點 HDR處理

          THREE的世界里面,坐標抽x、y、z的位置關系圖如下所示:

          2

          紅、綠、藍分別代表x、z、y,我們的貼圖就是在px nx py ny pz nz這六個方向防止一張圖片,其中p就代表坐標軸的正方向

          CubeTextureLoader:加載CubeTexture的一個類。 內部使用ImageLoader來加載文件。

          //場景貼圖 const sphereTexture = new THREE.CubeTextureLoader().setPath('./textures/course/environmentMaps/0/'); const envTexture= sphereTexture.load([ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ]); //場景添加背景 scene.background = envTexture; //場景的物體添加環境貼圖(無默認情況使用) scene.environment = envTexture; const sphereGeometry = new THREE.SphereGeometry(5, 30, 30); const sphereMaterial = new THREE.MeshStandardMaterial({ roughness: 0,//設置粗糙程度 metalness: 1,//金屬度 envMap:envTexture, }); const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); scene.add(sphere); 
                  
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25

          gif圖片有點大上傳不了,我就截了幾張圖

          在這里插入圖片描述

          在這里插入圖片描述

          在這里插入圖片描述

          請添加圖片描述

          請添加圖片描述

          6.3 HDR處理

          概述:高動態范圍圖像,相比普通的圖像,能夠提供更多的動態范圍和圖像細節,一般被運用于電視顯示產品以及圖片視頻拍攝制作當中。

          在這里插入圖片描述

          import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader; const rgbeLoader = new RGBELoader().setPath('./textures/course/hdr/'); //異步加載 rgbeLoader.loadAsync('002.hdr').then((texture) => { //設置加載方式 等距圓柱投影的環境貼圖 texture.mapping = THREE.EquirectangularReflectionMapping; scene.background = texture; }) 
                  
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9

          七、拓展

          7.1 坐標系

          概述:坐標軸能夠更好的反饋物體的位置信息,紅、綠、藍分別代表x、z、y

          在這里插入圖片描述

          const axesHelper = new THREE.AxesHelper(20);//里面的數字代表坐標抽長度 scene.add(axesHelper); 
                  
          • 1
          • 2

          7.2 控制器

          概述:通過鼠標控制物體和相機的移動、旋轉、縮放

          導包

          import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' 
                  
          • 1

          應用

          const controls = new OrbitControls(camera, renderer.domElement) 
                  
          • 1

          自旋轉

          在這里插入圖片描述

          controls.autoRotate = true 
                  
          • 1

          必須在render函數調用update實時更新才奏效

          7.3 自適應

          概述:根據屏幕大小自適應場景
          在這里插入圖片描述

          //自適應屏幕 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight
              camera.updateProjectionMatrix() renderer.setSize(window.innerWidth, window.innerHeight) renderer.setPixelRatio(window.devicePixelRatio) }) 
                  
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7

          設置相機的寬高比、重新更新渲染相機、渲染器的渲染大小、設備的像素比

          7.4 全屏響應

          概述:雙擊進入全屏,再次雙擊/ESC退出全屏

          在這里插入圖片描述

          window.addEventListener('dblclick', () => { let isFullScreen = document.fullscreenElement if (!isFullScreen) { renderer.domElement.requestFullscreen() } else { document.exitFullscreen() } }) 
                  
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9

          7.5 信息面板

          概述;通過操作面板完成界面的移動物體的相關應用

          鏈接:https://www.npmjs.com/package/dat.gui

          //安裝npm npm install --save dat.gui //如果出現...標記錯誤,安裝到開發依賴就可以了 npm i --save-dev @types/dat.gui 
                  
          • 1
          • 2
          • 3
          • 4

          1

          //界面操作 const gui = new dat.GUI(); //操作物體位置 gui .add(cube.position, 'x') .min(0) .max(10) .step(0.1) .name('X軸移動') .onChange((value) => { console.log('修改的值為' + value); }) .onFinishChange((value) => { console.log('完全停止' + value); }); //操作物體顏色 const colors = { color: '#0000ff', }; gui .addColor(colors, 'color') .onChange((value) => { //修改物體顏色 cube.material.color.set(value); }); 
                  
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26

          7.6 頻率檢測

          概述:檢測幀率

          導包

          import Stats from 'three/addons/libs/stats.module.js'; 
                  
          • 1

          應用

          const stats = new Stats(); document.body.appendChild(stats.dom); 
                  
          • 1
          • 2

          自變化

          20221021_110002

          stats.update() 
                  
          • 1

          必須在render函數調用update實時更新才奏效

          7.7 導航網格

          概述:底部二維平面的網格化,幫助我們更好的創建場景

          在這里插入圖片描述

          const gridHelper = new THREE.GridHelper(10, 20)//網格大小、細分次數 scene.add(gridHelper) 
                  
          • 1
          • 2

          八、源碼

          //導入包 import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; import * as dat from 'dat.gui'; import Stats from 'three/addons/libs/stats.module.js'; let scene,camera,renderer //場景 scene = new THREE.Scene(); //坐標抽 const axesHelper = new THREE.AxesHelper(20); scene.add(axesHelper); //場景貼圖 const sphereTexture = new THREE.CubeTextureLoader().setPath('./textures/course/environmentMaps/0/'); const envTexture= sphereTexture.load([ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ]); //場景添加背景 scene.background = envTexture; //場景的物體添加環境貼圖(無默認情況使用) scene.environment = envTexture; const sphereGeometry = new THREE.SphereGeometry(5, 30, 30); const sphereMaterial = new THREE.MeshStandardMaterial({ roughness: 0,//設置粗糙程度 metalness: 1,//金屬度 envMap:envTexture, }); const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); scene.add(sphere); //光照 const ambient = new THREE.AmbientLight(0xffffff); scene.add(ambient); const directionalLight = new THREE.DirectionalLight(0xffffff, 0.05); directionalLight.position.set(10,10,10); directionalLight.lookAt(scene.position); scene.add( directionalLight ); //相機 camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2000, ); camera.position.set(10,10,20); camera.lookAt(scene.position); scene.add(camera); //渲染器 renderer = new THREE.WebGLRenderer({ //防止鋸齒 antialias: true, }); renderer.setSize(window.innerWidth, window.innerHeight); // renderer.setClearColor(0xb9d3ff, 1); document.body.appendChild(renderer.domElement); //鼠標控制器 const controls = new OrbitControls(camera, renderer.domElement); //阻尼 必須在 render函數調用  controls.update(); controls.dampingFactor = true; controls.autoRotate=true const stats=new Stats() document.body.appendChild(stats.dom); function render () { renderer.render(scene, camera); requestAnimationFrame(render); controls.update();//調用 stats.update() } render(); //全屏操作 window.addEventListener('dblclick', () => { //查詢是否全屏 let isFullScene = document.fullscreenElement; console.log(isFullScene); if (!isFullScene) { renderer.domElement.requestFullscreen(); } else { document.exitFullscreen(); } }) //自適應 window.addEventListener('resize', () => { //寬高比 camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio);//設置像素比 }) //界面操作 const gui = new dat.GUI(); //操作物體位置 gui .add(sphere.position, 'x') .min(0) .max(10) .step(0.1) .name('X軸移動') .onChange((value) => { console.log('修改的值為' + value); }) .onFinishChange((value) => { console.log('完全停止' + value); }); //操作物體顏色 const colors = { color: '#0000ff', }; gui .addColor(colors, 'color') .onChange((value) => { //修改物體顏色 sphere.material.color.set(value); }); 
                  
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69
          • 70
          • 71
          • 72
          • 73
          • 74
          • 75
          • 76
          • 77
          • 78
          • 79
          • 80
          • 81
          • 82
          • 83
          • 84
          • 85
          • 86
          • 87
          • 88
          • 89
          • 90
          • 91
          • 92
          • 93
          • 94
          • 95
          • 96
          • 97
          • 98
          • 99
          • 100
          • 101
          • 102
          • 103
          • 104
          • 105
          • 106
          • 107
          • 108
          • 109
          • 110
          • 111
          • 112
          • 113
          • 114
          • 115
          • 116
          • 117
          • 118
          • 119
          • 120
          • 121
          • 122
          • 123
          • 124
          • 125
          • 126
          • 127
          • 128
          • 129
          • 130
          • 131
          • 132
          • 133
          • 134
          • 135
          • 136
          • 137
          • 138
          • 139
          • 140
          • 141
          • 142
          • 143

          日歷

          鏈接

          個人資料

          藍藍設計的小編 http://www.syprn.cn

          存檔

          亚洲va欧美va天堂v国产综合