天天看點

基于 Threejs 的 web 3D 開發入門

作者簡介:朱海洋,進階工程師,增值産品部QQ會員營收團隊負責人,目前團隊負責QQ會員、靓号、SVIP+、大王超會等項目,有豐富的Web前端架構經驗。

随着軟硬體的發展,在PC和移動端浏覽器上進行web 3D開發的條件已經基本成熟了,出現了不少js 3D庫,Threejs是js 3D庫中的佼佼者。國内也有企業開始做一些應用嘗試,某寶2016年雙11就用ThreeJS做了一個比較酷炫的3D宣傳頁面刷爆了朋友圈。

下圖是用Threejs繪制的一個3D立方體動畫的截圖,在這個demo裡,立方體會動态的旋轉,threeJS 30行代碼就可以完成這麼一個demo。Threejs讓沒有豐富3D程式設計經驗的web前端開發人員,也可以快速上手開發web 3D應用。

基于 Threejs 的 web 3D 開發入門

官網對Threejs的介紹非常簡單:“Javascript 3D library”。openGL是一個跨平台3D/2D的繪圖示準,WebGL則是openGL在浏覽器上的一個實作。web前端開發人員可以直接用WebGL接口進行程式設計,但WebGL隻是非常基礎的繪圖API,需要程式設計人員有很多的數學知識、繪圖知識才能完成3D程式設計任務,而且代碼量巨大。Threejs對WebGL進行了封裝,讓前端開發人員在不需要掌握很多數學知識和繪圖知識的情況下,也能夠輕松進行web 3D開發,降低了門檻,同時大大提升了效率。

基于 Threejs 的 web 3D 開發入門

下圖的例子中,使用者可以跟浏覽器互動,通過滑鼠操作360度檢視汽車,點選車門進入到車内,檢視車内立體視圖,如同身臨其境。

基于 Threejs 的 web 3D 開發入門
基于 Threejs 的 web 3D 開發入門
基于 Threejs 的 web 3D 開發入門

3D程式設計跟2D程式設計有較大不同,是以需要掌握一些3D程式設計的基本概念。Threejs的基本要素包括以下幾個方面:場景、相機、光、物體。

場景:是一個三維空間,所有物品的容器。可以把場景想象成一個空房間,接下來我們會往房間裡面放要呈現的物體、相機、光源。

基于 Threejs 的 web 3D 開發入門

相機:Threejs必須要有往場景中添加一個相機,相機用來确定觀察位置、方向、角度,相機看到的内容,就是我們最終在螢幕上看到的内容。在程式運作過程中,可以調整相機的位置、方向、角度。想象一下,在房間裡放了一個錄影機,你不在房間裡面,但可以遠端控制相機移動,錄影機傳給遠端電腦上展示出來的畫面,就是Threejs在螢幕上呈現的畫面。

光:假如沒有光,錄影機看不到任何東西,是以需要往場景中添加光源。為了跟真實世界更加接近,Threejs支援模拟不同光源,展現不同光照效果,有點光源、平行光、聚光燈、環境光等。

物體:有了場景、相機、光,就可以往場景中放物體了,在Threejs中,物體由形狀和材質兩部分組成,形狀決定物品的輪廓,材質則是物體的材料和質感。

Threejs繪制的東西,最終需要在螢幕一塊矩形畫布上顯示出來。為了實作動畫效果,我們需要有一個重繪機制。由于視神經元的反應速度問題,圖像消失後仍然會在人眼殘留1/24秒,隻要一秒内繪制的幀數超過24就能實作流暢的動畫效果。Threejs提供了重繪接口,我們有兩種方式去調用接口實作重繪。一種是setInterval,以固定的時間間隔去調用,可以用于我們對渲染幀數要求比較高的場景,但事實上由于Javascript是單線程的,這種方式并不能100%保證相同的時間間隔調用,如果浏覽器繁忙可能會導緻setInterval的延遲執行;第二種方式是requestAnimationFrame,讓浏覽器自行根據目前cpu負載等情況決定何時重繪,達到最佳幀率。

為了友善描述位置,引入了坐标系,Threejs使用的是右手坐标系,如下圖所示。坐标系的原點位于渲染畫布的幾何中心。我們對物體的位置的描述,也是指物體的幾何中心的位置。

基于 Threejs 的 web 3D 開發入門

相機有正交投影相機和透視投影相機兩種。透視投影跟人眼看到的世界是一樣的,近大遠小;正交投影則遠近都是一樣的大小,三維空間中平行的線,投影到二維空間也一定是平行的。大部分場景都适合使用透視投影相機,因為跟真實世界的觀測效果一樣;在制圖、模組化等場景适合使用正交投影相機,友善觀察模型之間的大小比例。

Threejs中的相機跟真實世界的相機不完全一樣,這裡相機的可見區域是一個立方體,稱為相機的示景體。

示景體是一個長方體,由6個參數确定:THREE.OrthographicCamera(left, right, top, bottom, near, far),這6個參數規定了相機示景體的左、右、上、下、前、後六個面的位置。

基于 Threejs 的 web 3D 開發入門

示景體是一個梯形體,由四個參數确定:THREE.PerspectiveCamera(fov, aspect, near, far)

基于 Threejs 的 web 3D 開發入門

fov是相機在豎直方向的張角,aspect則是寬高比,即width/height,通常設為畫布的寬高比,near和far分别是近平面和遠平面與相機的距離。

考慮一種比較簡單的場景,相機示景體的遠近平面和坐标系中的xy平面平行,進而示景體遠近平面上的内容剛好可以垂直投影到畫布上,并且示景體中與xy平面平行的任何一個平面,投影到畫布上剛好等于畫布大小。假如透視投影相機的近平面的大小為axb,遠平面大小為2ax2b,則一張axb大小的紙放在近平面上,投影到畫布時剛好鋪滿整張畫布;放到遠平面上則隻能占據畫布面積的1/4(遠平面的面積是近平面的4倍)。正是因為透視投影相機的示景體近小遠大,才會導緻同樣一個物品放在不同位置顯示出近大遠小的效果。而正交投影相機因為遠近平面大小一樣,是以同一個物品距離相機的遠近不影響物體在畫布上投影展示的大小。

物體由幾何形狀(Geometry)和材質(Material)組成。同樣的幾何形狀,不同材質構成了不同物體,比如球狀,有籃球、玻璃球、水晶球等。

Threejs提供了一些常見的幾何形狀,有三維的也有二維的,三維的比如長方體、球體、圓柱體、環等,二維的比如長方形、圓形、扇形等。如果預設提供的形狀不能滿足需求,也可以自定義,通過定義頂點和頂點之間的連線繪制自定義幾何形狀,更複雜的模型還可以用模組化軟體模組化後導入。

計算機是如何繪制幾何形狀的呢?我們知道,計算機隻能繪制直線,那麼曲線和3D形狀如何繪制出來呢?

1、繪制圓形。如下圖所示,通過繪制多邊形實作近似的圓形效果,當多邊形的邊數足夠多的時候,兩條邊之間的過渡就顯得平滑,多邊形看起來就足夠圓了。

基于 Threejs 的 web 3D 開發入門

2、繪制3D模型。常用的做法是用三角形組成的網格來模拟,如下圖所示,用足夠多的三角形時,兔子的身體看起來就足夠平滑,跟真實兔子比較接近。著名的斯坦福兔子模型用了69451個三角形。

基于 Threejs 的 web 3D 開發入門

Threejs提供了幾種比較有代表性的材質,常用的有漫反射、鏡面反射兩種材質,還可以引入外部圖檔,貼到物體表面,稱為紋理貼圖。

現實世界豐富多彩,不是Threejs的幾種預設幾何形狀和材質所能表達的,實際運用中,很多時候需要用到外部模型,通過3D模組化軟體建構物體的三維模型并導出模型檔案,Threejs導入模型檔案進行使用。

基于 Threejs 的 web 3D 開發入門

光源主要是以下幾種:1)、環境光,所有角度看到的亮度一樣,通常用來為整個場景指定一個基礎亮度,沒有明确光源位置;2)、點光源,一個點發出的光源,照到不同物體表面的亮度線性遞減;3)、平行光,亮度與光源和物體之間的距離無關,隻與平行光的角度和物體所在平面有關;4)、聚光燈,投射出的是類似圓錐形的光線。

本文對Threejs程式設計做了一下簡單介紹,目的是讓讀者對Threejs程式設計有個基本認識。紙上得來終覺淺,絕知此事要躬行!建議到Threejs官網首頁看看那些有趣的demo,着手寫一些簡單的demo進行實踐。目前web 3D應用因為浏覽器渲染性能、模型體積過大等原因,并沒有大規模使用起來,隻限于在品牌宣傳等部分領域嘗試使用。我剛好經曆過浏覽器2D資料可視化繪圖由flash向JS轉變的過程(2012年前後),相信随着軟硬體性能的提升和網絡速度的提升,web 3D應用也會慢慢的推廣使用起來。

文章來自:小時光茶社 公衆号