three.js基礎前置知識
- 2019 年 10 月 3 日
- 筆記
這一節是純理論知識,用於介紹three.js的入門概念,也就是開發前需要準備的理論基礎。
一,三劍客
當然就是scene,camera,renderer這三個基本要素。
scene是一個用於容納三維空間的場景,相當於一個容器;
camera則是一雙幫助我們觀察3d世界的眼睛;
而renderer是一個渲染器,它負責把無色無相的三維物體繪製成肉眼可見的物體;
二,選什麼相機
選透視相機(PerspectiveCamera)。
簡單來說,透視相機有距離感,遠的物體看起來小一點,近的物體看起來大一點,符合現實生活中的人眼觀感;
而正交投影相機沒有距離感,所有的物體看起來都是在一條直線上;
(左為透視相機,右為正交投影相機)
三,如何生成一個基礎物體?
基礎物體mesh = 幾何結構(geometry)+ 貼片材質(material)
幾何結構就像一個骨架,three.js內置了不少幾何結構,像常見的球體,正方體,圓環等等;
而貼片材質則決定這個骨架的樣式,可以畫上純色,也可以貼上圖片紋理等;
四,該選什麼材質?
材質主要分為與光照沒有任何交集的基礎材質(MeshBasicMaterial),以及必須要光照才能看見,可以配合光照產生陰影效果的標準材質(MeshStandardMaterial);
一般來說,全景圖的視角在物體內部,只觀察圖片紋理,不需要陰影效果,可選用基礎材質;
而像3d物體,給物體打上平行光,顯現出物體的影子,可以讓畫面更真實,因此選用標準材質。但此時環境光要慎用,因為如果物體是純色材質,視覺上環境光會和物體混色。如:在標準材質下:黃色環境光+藍色材質物體 = 視覺上物體呈綠色;
五,初始化透視相機的參數如何設置?
var camera = new PerspectiveCamera(fov, aspect, near, far)幫助我們初始化一個相機,參數依次為:視野,可觀測距離比,最近觀測距離,最遠觀測距離。
如果你和我一樣沒什麼圖形學基礎,不太懂透視,可以使用一個通用的參數設定:
var camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 1000);
六,相機該看哪兒?
默認情況下,相機處於空間直角坐標系的原點;
一般的做法是,通過相機的position屬性把它擺放到三維空間的某個位置;
再通過lookAt屬性設置一下相機該看向哪裡,一般看向物體的正中心(new THREE.Vector3(0, 0, 0));
七,如何實現實時渲染(循環渲染)?
結合requestAnimationFrame獲得一個合適的幀率,然後遞歸調用渲染器的render方法就行了,requestAnimationFrame本質上就是一個非同步延時函數。
程式碼如下所示:
function animate() { renderer.render(scene, camera); requestAnimationFrame(animate); }
八,圖片紋理默認貼在幾何體外部,如何讓其貼在幾何體內壁?
一般做法是將幾何體的scale屬性的某一個坐標設為負值就行了,如:
geometry.scale(- 1, 1, 1);
九,自由拖動查看全景圖,該怎麼搞?
這裡的大體思路是這樣的:根據拖動事件計算出一個新的經緯度,然後通過某種換算公式將新的經緯度換算為三維空間坐標(x,y,z),然後camera看向這個三維坐標。
換言之,就是camera被安裝在球體內部的球心,然後探頭可以轉來轉去,查看球體內壁的不同區域。
關於經緯度轉三維坐標,如果你並不想去過多了解這個轉換函數的具體意義,也可以直接使用,程式碼如下:
function transCoord(sphereRadius,lon,lat) { // 參數分別表示球體的半徑,經度,緯度 lat = Math.max(-85, Math.min(85, lat)); let phi = THREE.Math.degToRad(90 - lat); let theta = THREE.Math.degToRad(lon); camera.target.x = sphereRadius * Math.sin(phi) * Math.cos(theta); camera.target.y = sphereRadius * Math.cos(phi); camera.target.z = sphereRadius * Math.sin(phi) * Math.sin(theta); camera.lookAt(camera.target); }
十,自由拖動查看3d物體,該怎麼弄?
與全景圖相對應,3d物體拖動查看也是很常見的東西;
它的大體思路可能是這樣的:
(1)先把相機安裝在物體外部的某一個點,然後相機探頭固定看著物體中心,當我們拖動物體時,實際上就是在令物體圍著自身的中心點做各種旋轉,相機在外部一動不動,“靜靜地看著物體裝逼”;
(2)然後相機探頭固定看著物體中心,當我們進行拖動時,3d物體不懂,相機在物體外圍的空間“飛來飛去”;
如果你不想考慮這麼多坐標換算的東西,不想搞這麼多數學,也可以當個api的調用者,three.js官方提供了OrbitControls,用來定於用戶對物體的旋轉查看行為,其使用十分簡單。
十一,滑鼠縮放如何比較科學地解決?
滑鼠縮放畫面,其實就是在縮放透視相機的視野(fov);
視野越大,則表示看到的範圍越大,離物體也就越遠;
視野越小,則表示看到的範圍很小,說明離物體很近,有“一葉障目”之感;
明白了這一點,我們就可以通過調用內置api來實現這個縮放的功能,內置的api封裝了很多細節,也簡化了我們的運算,程式碼如下:
function mouseWheelHandler(event) { let fov = camera.fov + event.deltaY * 0.05; camera.fov = THREE.Math.clamp(fov, 10, 75); // 後兩個參數表示最小視野,最大視野,也就是縮放範圍 camera.updateProjectionMatrix(); }
以上就是three.js一些比較入門的理論知識,下一節我們將從一個實際頁面出發,動手完成一個可交互的簡單3d物體。