Three. js開發指南:
基于WebGL和HTML5在網頁上渲染
3D圖形和動畫(原書第3版)
Learn Three.js: Programming 3D animations and visualizations for the web with HTML5 and WebGL, Third Edition

[美] 喬斯·德克森(Jos Dirksen)著
周翀 張薇 譯
第1章
使用Three.js建立你的第一個三維場景
現代浏覽器直接通過JavaScript就可以實作非常強大的功能。使用HTML5的标簽可以很容易地添加語音和視訊,而且在HTML5提供的畫布上可以添加具有互動功能的元件。現在,現代浏覽器也開始支援WebGL。通過WebGL可以直接使用顯示卡資源來建立高性能的二維和三維圖形,但是直接使用WebGL程式設計來從JavaScript建立三維動畫場景十分複雜而且還容易出問題。使用Three.js庫可以簡化這個過程。Three.js帶來的好處有以下幾點:
- 建立簡單和複雜的三維幾何圖形。
- 建立虛拟現實(VR)和增強現實(AR)場景。
- 在三維場景下建立動畫和移動物體。
- 為物體添加紋理和材質。
- 使用各種光源來裝飾場景。
- 加載三維模型軟體所建立的物體。
- 為三維場景添加進階的後期處理效果。
- 使用自定義的着色器。
- 建立點雲(即粒子系統)。
通過幾行簡單的JavaScript代碼,你可以建立從簡單三維模型到類似圖1.1(在浏覽器中通路
http://www.vill.ee/eye)所示的具有真實感的場景。
本章将會通過示例來闡述Three.js的工作原理,但是不會對其中的技術細節進行深入探究,這些細節我們将會在後面的章節中介紹。本章主要涵蓋以下幾方面:
- 使用Three.js所需的工具。
- 下載下傳本書所需的源碼和示例。
- 建立第一個Three.js場景。
- 使用材質、光源和動畫來完善第一個場景。
- 引入輔助庫以統計和控制場景。
首先将會對Three. js進行簡單的介紹,然後再講解第一個示例及其代碼。在開始之前我們先來看下目前主流浏覽器對WebGL的支援情況,幾乎所有浏覽器的桌面版和移動版均支援WebGL,唯一的例外是移動版迷你Opera浏覽器(Opera Mini),因為這個浏覽器有一種特殊的工作模式,可以在Opera伺服器端進行頁面渲染,而Opera伺服器往往禁止運作JavaScript。不過從8.0版開始,Opera Mini的預設工作模式已改為使用iOS Safari引擎渲染頁面,進而也可以很好地支援JavaScript和WebGL。但是新版Opera Mini仍然可以被設定為不支援JavaScript的“迷你模式”(mini mode)。
除了IE的一些低版本浏覽器,基本所有的現代浏覽器都支援Three.js。如果想在低版本的IE浏覽器上運作Three.js,你還需要做額外的操作。對于IE10和更低的版本,你可以安裝iewebgl插件,下載下傳位址為
https://github.com/iewebgl/iewebgl。
使用WebGL能夠建立出具有互動性的3D模型,而且這些模型在電腦和手機裝置上都能夠很好地運作。
本書主要使用Three.js提供的基于WebGL的渲染器。但是Three.js也提供了基于CSS 3D的渲染器,使用其API能夠很容易地建立出三維場景,而且這個渲染器的優點在于幾乎所有手機和電腦上的浏覽器都支援CSS 3D,并且可以在三維空間内渲染HTML元素。第7章會進一步介紹如何使用CSS 3D。
通過本章的學習,你可以直接建立第一個三維場景,而且這個場景可以在上述的所有浏覽器中運作。目前我們不會介紹太多Three.js的複雜特性,但是在本章結束的時候你能夠建立出如圖1.2所示的場景。
通過建立這個場景,你可以學到Three.js的基礎知識,并可以建立第一個動畫。在開始實作這個示例之前,我們會先介紹幾個工具,這些工具可以幫助你更友善地使用Three.js。我們還會介紹如何下載下傳本書所用到的示例。
1.1 準備工作
Three.js是一個JavaScript庫,是以你隻需要一個文本編輯器和支援Three.js的浏覽器就可以使用Three.js來建立WebGL應用。這裡推薦如下幾款JavaScript文本編輯器:
- Visual Studio Code:Visual Studio Code是微軟公司面向所有常見作業系統推出的一款免費編輯器。該編輯器能夠基于源程式裡的類型和函數聲明以及導入庫,提供效果良好的文法高亮和代碼補全功能。同時它還具有簡潔明了的使用者界面,以及對JavaScript的完美支援。下載下傳位址為 https:/ / code. visualstudio. com /。
- WebStorm: WebStorm是JetBrains公司旗下的一款JavaScript編輯工具。它支援代碼補全、自動部署和代碼調試功能。除此之外,WebStorm還支援GitHub和其他各種版本控制器。讀者可從 http://www.jetbrains.com/webstorm/ 下載下傳一個試用版本。
- Notepad++:Notepad++是Windows作業系統下的通用文本編輯器,它支援各種程式設計語言文法高亮度顯示,而且可以很容易地對JavaScript進行布局和格式化。Notepad++的下載下傳位址為 http://notepad-plus-plus.org/
- Sublime Text: Sublime Text是一款對JavaScript支援非常好的文本編輯器。除此之外,Sublime Text 的一大亮點是支援多重選擇—同時選擇多個區域,然後同時進行編輯。這些功能提供了一個很好的JavaScript程式設計環境。Sublime Text是一個收費閉源軟體,下載下傳位址為 http://www.sublimetext.com/
除此之外,還有很多可以編寫JavaScript進而建立Three.js應用的開源和商用編輯器。還有一款基于雲的代碼編輯平台Cloud9,網址是
http://c9.io, 該平台可以連接配接GitHub賬号,由此可以直接擷取本書相關的代碼和示例。
除了使用這些文本編輯器來運作本書相關的代碼和示例,Three.js自身也提供了線上場景編輯器,通路位址為
http://threejs.org/editor。使用該編輯器,可以用圖形化方法建立Three.js場景。
雖然現代浏覽器基本都支援WebGL并能運作Three.js應用,但是本書所采用的是Chrome浏覽器。因為Chrome是對WebGL支援最好的浏覽器,并且擁有強大的JavaScript代碼調試功能。如圖1.3所示,使用調試器的斷點和控制台功能可以快速地定位問題。在本書中,還會進一步介紹各種調試的方法和技巧。
Three.js就介紹到此,下面就開始擷取源碼并建立我們的第一個場景。
1.2 擷取源碼
本書所有的源碼都可以從GitHub(
https://github.com/)擷取。GitHub是基于Git的線上代碼倉庫,你可以使用它來存儲、通路源碼和進行版本控制。擷取GitHub上源碼的方式有以下兩種:
- 通過Git擷取代碼倉庫
- 下載下傳并解壓縮檔案檔案
接下來會詳細講解這兩種方式。
1.2.1 通過Git擷取代碼倉庫
Git是開源、分布式的版本控制系統,本書的示例都是基于Git進行建立和版本管理的,GitHub倉庫的通路位址為
https://github.com/josdirksen/learning-threejs如果你已經在作業系統中安裝了Git的用戶端,那麼就可以使用git指令來克隆示例的代碼倉庫。如果你還沒有安裝,可以通路
http://git-scm.com下載下傳,或者使用GitHub公司自己為Mac或Windows系統提供的用戶端。在安裝完Git用戶端後,打開控制台并在你想要存儲代碼的目錄中運作如下的指令:
如圖1.4所示,代碼就開始下載下傳了。
下載下傳完畢後,在learning-threejs-third檔案夾中會看到本書所用的所有的示例。
1.2.2 下載下傳并解壓縮檔案檔案
如果你不想使用Git的方式從GitHub上擷取源碼,那麼還可以在GitHub上下載下傳檔案檔案。在浏覽器上通路
https://github.com/josdirksen/learning-threejs-third,點選右側的Clone or download按鈕。如圖1.5所示。
解壓檔案到指定的目錄,這樣就可以擷取所有的示例了。
1.2.3 測試示例
現在你已經下載下傳或者克隆了示例源碼,下面我們就來測試示例是否能夠正常工作,進而了解工程的目錄結構。本書的示例是按照章節進行組織的。如果要運作本書的示例,你可以使用浏覽器打開HTML檔案,或者安裝本地Web伺服器。第一種方法對于簡單的示例是可行的,但是如果示例中需要下載下傳外部資源時,比如模型或者紋理圖像,那麼僅僅使用浏覽器打開HTML檔案是行不通的。這個時候,我們就需要本地Web伺服器來確定外部資源正确加載。接下來我們會介紹幾種安裝本地伺服器的方式,如果你無法安裝本地伺服器但使用Chrome或Firefox浏覽器,那麼我們也會介紹如何禁用安全性檢測來運作示例。
接下來,我們将會介紹幾種安裝本地伺服器的方式,依據系統的配置,你可以選擇最合适的方式。
1.适用于Unix/Mac系統的基于Python的Web伺服器
大部分的Unix/Linux/Mac系統預設安裝了Python,在示例源碼目錄中運作如下的指令就可以将本地Web伺服器啟動起來了。
在你下載下傳了源碼的目錄中執行上述指令。
2.基于NPM的Web伺服器
如果你已經在使用Node.js了,那麼你肯定已經安裝了NPM。使用NPM,有兩個方式可以快速地搭建本地Web伺服器:第一種方式是使用http-server子產品,如下所示:
第二種方式是使用simple-http-server,如下所示:
第二種方式的缺點在于無法自動地顯示目錄清單,而第一種方式是可以的。
3. Mac/Windows上的輕量級伺服器—Mongoose
如果你還沒有安裝Python或者NPM,那麼還有一個簡單、輕量級的Web伺服器—Mongoose。首先,從
https://code.google.com/p/mongoose/downloads/list下載下傳你的系統所支援的二進制安裝檔案。如果你使用的是Windows系統,那麼将下載下傳好的二進制檔案複制到示例所在的目錄,輕按兩下即可啟動一個運作于該目錄下的Web伺服器。
對于其他的作業系統,則須将下載下傳的二進制檔案複制到指定的目錄中,但是啟動的方式不是輕按兩下,而是通過指令行的方式,如圖1.6所示。
在這兩種情況下都會在8080端口啟動一個本地Web伺服器。本書的示例目錄如圖1.7所示。
點選各章節的目錄就可以擷取相應章節的示例。在本書講解提到某個示例時會指出示例的名稱和所在的檔案夾,這樣你就可以找到該示例的源代碼以便測試運作或自行研究。
4.禁用Firefox和Chrome的安全性檢測
如果你使用的是Chrome浏覽器,有種方式可以禁用安全性設定,這樣就可以在沒有Web伺服器的情況下檢視示例。需要注意的是,應盡量避免用下面的方法通路真正的網站,因為這樣做會使浏覽器向各種惡意代碼敞開大門。用下面的指令可以啟動Chrome浏覽器同時禁用所有安全特性。
- 對于Windows作業系統:
- 對于Linux作業系統:
- 對于Mac OS作業系統:
通過這種方式啟動Chrome浏覽器就可以直接運作本地檔案系統中的示例。
對于Firefox浏覽器來說,還需要其他的配置。打開Firefox浏覽器并在位址欄内輸入about:config會看到圖1.8所示的頁面。
在該頁面中點選“I抣l be careful, I promise!”按鈕,然後就會列出所有用于調整Firefox的屬性。在搜尋框中輸入security.fileuri.strict_origin_policy,并将其值修改為false。如圖1.9所示。
這時候就可以使用Firefox浏覽器直接運作本書的示例了。
到現在為止,你應該已經安裝了Web伺服器或者禁用了浏覽器的安全性設定,那麼就開始建立第一個三維場景吧。
1.3 搭建HTML架構
首先我們将會建立空的HTML架構,後面的示例将在這個架構的基礎上完成。具體如下所示:
你應該已經發現了,這個架構是個僅包含一些基本元素的HTML網頁。在
标簽中列出了示例所使用的外部JavaScript庫,在這裡至少要包含Three.js庫。此外,這裡還包含一個控制器庫TrackballControls.js。有了它便可以利用滑鼠任意移動錄影機,以便從不同角度觀察場景。在标簽中最後一個被包含的JavaScript檔案是本章的示例程式,檔案名為01-01.js。最後,在标簽中我們還添加了幾行CSS代碼,這些CSS代碼用于移除Three.js場景網頁中的滾動條。在标簽中我們隻添加了一個元素,當我們寫Three.js代碼時,會把Three.js渲染器的輸出指向這個元素。在架構網頁的最後還有少量JavaScript代碼。這些代碼将在網頁加載完成後被自動調用,我們利用這個機會調用init()函數。init()函數也在01-01.js檔案中定義,它将為Three.js場景做必要的初始化設定。不過在本章中,init()函數暫時僅僅向控制台視窗列印目前Three.js的版本資訊。
在浏覽器中打開本章示例代碼檔案并觀察控制台視窗,可以看到如圖1.10所示的内容。
在
元素中包含Three.js的源代碼。Three.js有兩個不同的版本:
- three.min.js:這個版本的JS庫一般應用于網上部署Three.js時。該版本是使用UglifyJS壓縮過的,它的大小是普通Three.js版本的四分之一。本書示例所使用的是2018年7月釋出的Three.js r95版本。
- three.js:這個是普通的Three.js庫。為了便于進行代碼調試和了解Three.js的源碼,本書的示例使用的都是這個庫。
接下來,我們将會建立第一個三維對象并将其渲染到已經定義好的
元素中。
1.4 渲染并檢視三維對象
在這一步,我們将會建立第一個場景并添加幾個物體和錄影機。我們的第一個示例将會包含表1.1所列對象。
下面将會通過代碼示例(帶注釋的代碼在檔案chapter-01/is/01-02.js中)來解釋如何建立場景并渲染三維對象:
在浏覽器中将示例打開,看到的結果和我們的目标,即本章開始時所展示的那張渲染圖接近,但效果還有些差距。目前的效果如圖1.1所示。
接下來将會對代碼進行分析,這樣我們就可以了解代碼是如何工作的:
在代碼中,首先定義了場景(scene)、錄影機(camera)和渲染器(renderer)對象。場景是一個容器,主要用于儲存、跟蹤所要渲染的物體和使用的光源。如果沒有THREE.Scene對象,那麼Three.js就無法渲染任何物體,在第2章還會對THREE.Scene進行詳細介紹。示例中所要渲染的方塊和球體稍後将會添加到場景對象中。
在示例中我們還定義了錄影機對象,錄影機決定了能夠在場景看到什麼。在第2章,你還會進一步了解錄影機對象能夠接受的參數。接下來,我們定義了渲染器對象,該對象會基于錄影機的角度來計算場景對象在浏覽器中會渲染成什麼樣子。最後WebGLRenderer将會使用電腦顯示卡來渲染場景。
如果你已經看了Three.js的源碼和文檔(網址為
http://threejs.org),你會發現除了基于WebGL的渲染器外,還有其他的渲染器,比如基于HTML canvas的渲染器、基于CSS的渲染器,甚至還有基于SVG的渲染器。盡管它們也能夠渲染簡單的場景,但是不推薦使用,因為它們已經停止更新、十分耗CPU的資源,而且也缺乏對一些功能的支援,比如材質和陰影。
在示例中,我們調用setClearColor方法将場景的背景顔色設定為接近黑色(new THREE. Color(0X00000000)),并通過setSize方法設定場景的大小。使用window.innerWidth和window.innerHeight可将整個頁面視窗指定為渲染區域。
到目前為止,我們已經建立了空白的場景、渲染器和錄影機,但是還沒有渲染任何東西。接下來将會在代碼中添加軸和平面:
如代碼所示,我們建立了坐标軸(axes)對象并設定軸線的粗細值為20,最後調用scene.add方法将軸添加到場景中。接下來要建立平面(plane),平面的建立分為兩步來完成。首先,使用THREE.Plane Geometry(60,20)來定義平面的大小,在示例中将寬度設定為60,高度設定為20。除了設定高度和寬度,我們還需要設定平面的外觀(比如顔色和透明度),在Three.js中通過建立材質對象來設定平面的外觀。在本例中,我們将會建立顔色為0xAAAAAA的基本材質(THREE.MeshBasicMaterial)。然後,将大小和外觀組合進Mesh對象并指派給平面變量。在将平面添加到場景之前,還需要設定平面的位置:先将平面圍繞x軸旋轉90度,然後使用position屬性來定義其在場景中的位置。如果你對Mesh對象感興趣,那麼可以檢視第2章中的示例06-mesh-properties.html,該示例詳細介紹了旋轉和定位。最後,我們将平面添加到場景中。
使用同樣的方式将方塊和球體添加到平面中,但是需要将線框(wireframe)屬性設定為true,這樣物體就不會被渲染為實體物體。接下來就是示例的最後一部分:
現在,所有物體都已經添加到場景中的合适位置。在之前我們提到過,錄影機将決定哪些東西會被渲染到場景中。在這段代碼中,我們使用x、y、z的位置屬性來設定錄影機的位置。為了確定所要渲染的物體能夠被錄影機拍攝到,我們使用lookAt方法指向場景的中心,預設狀态下錄影機是指向(0,0,0)位置的。最後需要做的就是将渲染的結果添加到HTML架構的
元素中。我們使用JavaScript來選擇需要正确輸出的元素并使用appendChild方法将結果添加到div元素中。最後告訴渲染器使用指定的錄影機來渲染場景。
接下來,我們還會使用光照、陰影、材質和動畫來美化這個場景。
1.5 添加材質、光源和陰影效果
在Three.js中添加材質和光源是非常簡單的,做法和前一節講的基本一樣。首先我們在場景中添加一個光源(完整代碼請參見示例js/03-03.js)。代碼如下所示:
通過THREE.SpotLight定義光源并從其位置(spotLight.position.set(-40,60,-10))照射場景。通過将castShadow屬性設定為true,THREE.js的陰影功能被啟用。此外,上面的代碼還通過設定shadow.mapSize、shadow.camera.far和shadow.camera.near三個參數來控制陰影的精細程度。有關光源屬性的更多細節将在第3章詳細介紹。如果這時候渲染場景,那麼你看到的結果和沒有添加光源時是沒有差別的。這是因為不同的材質對光源的反應是不一樣的。我們使用的基本材質(THREE.MeshBasicMaterial)不會對光源有任何反應,基本材質隻會使用指定的顔色來渲染物體。是以,我們需要改變平面、球體和立方體的材質:
如代碼所示,我們将場景中物體的材質改為MeshLambertMaterial。Three.js中的材質MeshPhysicalMaterial和MeshStandardMaterial(以及被棄用的MeshPhongMaterical)在渲染時會對光源産生反應。
渲染的結果如圖1.12所示,但是這還不是我們想要的結果。
雖然立方體和球體已經好看了很多,但是還缺少陰影的效果。
由于渲染陰影需要耗費大量的計算資源,是以預設情況下Three.js中是不會渲染陰影的。為了渲染陰影效果,我們需要對代碼做如下修改:
首先通過設定shadowMapEnabled屬性為“true”來告訴渲染器需要陰影效果。這時候如果檢視修改的效果,那麼你将會發現還是沒有任何差別,因為你還需要明确地指定哪個物體投射陰影、哪個物體接受陰影。在示例中,我們通過将相應的屬性設定為“true”來指定球體和立方體在地面上投射陰影。代碼如下所示:
接下來我們還需要定義能夠産生陰影的光源。因為并不是所有的光源都能夠産生陰影,但是通過THREE.SpotLight定義的光源是能夠産生陰影的。我們隻要将屬性castShadow設定為true就可以将陰影渲染出來了,代碼如下所示:
這樣,場景中就有了光源産生的陰影,效果如圖1.13所示。
仔細觀察01-03.js的源代碼會發現,這段程式還建立了一個擁有不同物體的場景。若将那些名為createXXX的函數的注釋去掉,并且删除前面已經建立的立方體和球,場景中便會出現一些更複雜的物體。這些物體将展示出如圖1.13所示的更複雜的陰影。
最後一個将要添加到場景中的效果是簡單動畫。在第9章中,你将會學習使用更進階的動畫。
1.6 讓你的場景動起來
如果希望我們的場景動起來,那麼首先需要解決的問題是如何在特定的時間間隔重新渲染場景。在HTML5和相關的JavaScript API出現之前,是通過使用setInterval(function,interval)方法來實作的。比如,通過setInterval()方法指定某個函數每100毫秒調用一次。但是這個方法的缺點在于它不管浏覽器目前正在發生什麼(比如正浏覽其他網頁),它都會每隔幾毫秒執行一次。除此之外,setInterval()方法并沒與螢幕的重新整理同步。這将會導緻較高的CPU使用率和性能不良。
1.6.1 引入requestAnimationFrame()方法
幸運的是,現代浏覽器通過requestAnimationFrame函數為穩定而連續的渲染場景提供了良好的解決方案。通過這個函數,你可以向浏覽器提供一個回調函數。你無須定義回調間隔,浏覽器将自行決定最佳回調時機。你需要做的是在這個回調函數裡完成一幀繪制操作,然後将剩下的工作交給浏覽器,它負責使場景繪制盡量高效和平順地進行。這個功能使用起來也非常簡單(完整源碼在04-04.js檔案中),你隻需要建立負責繪制場景的回調函數:
在renderScene()方法中,requestAnimationFrame()方法又一次被調用了,這樣做的目的是保證動畫能夠持續運作。接下來我們還需要對代碼做的修改是:在場景建立完畢後,不再調用renderer.render()方法,而是調用renderScene()來啟動動畫,代碼如下:
這時候如果運作代碼,效果和之前的示例相比沒有任何差別,這是因為我們還沒有為物體添加任何動畫效果。在添加動畫之前,我們先來介紹一個輔助庫,這個庫也是Three.js作者開發的,主要用于檢測動畫運作時的幀數。在動畫運作時,該庫可以在一個圖檔中顯示畫面每秒傳輸幀數。
為了能夠顯示幀數,首先我們需要在HTML的
标簽中引入這個輔助庫:
然後初始化幀數統計子產品并将它添加到頁面上。
上面的函數初始化幀數統計子產品,并用輸入的type參數來設定将要顯示的統計内容。它可以是:每秒渲染的幀數、每渲染一幀所花費的時間或者記憶體占用量。最後,在前面介紹過的init函數末尾調用上述函數來初始化統計子產品。
由于initStats函數并不是本章示例所特有的操作,是以它的實作代碼并不在本章的示例代碼中,而是像其他有用的輔助函數一樣儲存在輔助函數庫util.js檔案中。
輔助函數庫在HTML頁面代碼的開始部分被引用。
示例代碼為統計幀數顯示所做的最後一件事,是在renderScene函數中每渲染完一幀後,調用stats.update函數更新統計。
添加完上述代碼之後再次運作示例,統計圖形将會顯示在浏覽器左上方,如圖1.15所示。
1.6.2 旋轉立方體
引入requestAnimationFrame()方法并配置完統計對象之後,接下來就該添加動畫代碼了。在本節中,我們将擴充renderScene()方法來實作紅色立方體圍繞軸進行旋轉。代碼如下所示:
看起來是不是很簡單?我們所做的隻是在每次調用renderScene()時使得每個坐标軸的rotation屬性增加0.02,其效果就是立方體将圍繞它的每個軸進行緩慢的旋轉。在下一節中我們将讓藍色球體彈跳起來,這個實作起來也不是特别難。
1.6.3 彈跳球
為了讓小球彈跳起來,隻需要在renderScene()方法中添加如下代碼即可:
旋轉立方體時我們修改的是rotation屬性;而讓小球彈跳起來,我們所要修改的是球體在場景中的位置(position)屬性。我們的目的是讓小球依照一條好看的、光滑的曲線從一個地方跳到另一個地方,如圖1.16所示。
為了實作這個效果,我們需要同時改變球體在x軸和y軸的位置。Math.cos()和Math.sin()方法使用step變量就可以建立出球體的運作軌迹。在這裡不具體展開解釋它們是怎麼工作的,現在你隻需要知道step+=0.04定義了球體彈跳的速度就可以,在第8章中還會詳細介紹這些方法是如何用于實作動畫的。圖1.17展示的就是球體在彈跳中的效果。
在結束本章之前,我還想在場景中引入幾個輔助庫。可能你已經發現,在建立類似三維場景和動畫時,我們需要嘗試很多次才能夠确定最合适的速度和顔色。如果有一個GUI(可視化圖形界面)允許我們在運作期間修改這些屬性,那麼事情就會變得很簡單。幸運的是,這樣的GUI是存在的。
1.7 使用dat.GUI簡化試驗流程
Google員工建立了名為dat.GUI的庫(相關文檔見
http://code.google.com/p/dat-gui/),使用這個庫可以很容易地建立出能夠改變代碼變量的界面元件。在本章最後,将會使用data.GUI庫為我們的示例添加使用者操作界面,使得我們可以:
- 控制小球彈跳的速度;
- 控制立方體的旋轉。
就像引入統計對象一樣,首先我們需要在HTML的
标簽中添加這個庫,代碼如下所示:
接下來我們需要定義一個JavaScript對象,該對象将儲存希望通過dat.GUI改變的屬性。在JavaScript代碼中添加如下的JavaScript對象:
在這個JavaScript對象中,我們定義了兩個屬性—this.rotationSpeed 和this.bouncing Speed,以及它們的預設值。接下來需要将這個JavaScript對象傳遞給data.GUI對象,并設定這兩個屬性的取值範圍,如下所示:
立方體旋轉速度(rotationSpeed)和球體彈跳速度(bouncingSpeed)的取值範圍為0~0.5。現在需要做的就是在renderScene()中直接引用這兩個屬性,這樣當我們在dat.GUI中修改這兩個屬性的值時,就可以影響相應物體的旋轉速度和彈跳速度。代碼如下所示:
現在運作這個示例(05-control-gui.html)時,你就會看到一個可以控制彈跳速度和旋轉速度的使用者界面。如圖1.18所示。
讀者應該還記得在本章開頭時建立的架構頁面代碼中,我們引用了TrackballControl.js檔案。該檔案用于實作利用滑鼠移動錄影機,以便以不同角度觀察場景。這一點将在第9章詳細介紹。該檔案同樣需要初始化。由于它需要響應文檔對象模型(DOM)元素的事件,它的初始化代碼必須出現在下面代碼中的appendChild函數調用之後。
initTrackballControls函數也定義于util.js檔案中,它的具體實作将在本書後面章節中詳細介紹。最後,與幀數統計子產品相似,TrackballControl.js庫也需要在render函數渲染完一幀後更新。
至此本章的代碼便已完成。再次打開05-control-gui.html檔案時,可以通過按下滑鼠左鍵并移動滑鼠來轉動錄影機,以便從不同角度觀察場景。此外,按S鍵可以拉近或拉遠錄影機,按D鍵可以平移錄影機。如圖1.19所示。
後續章節中的所有實踐都将使用這個庫來移動錄影機。
在運作這個示例并改變浏覽器大小的時候,你可能已經發現場景是不會随着浏覽器大小的改變而自動做出調整的。那麼在接下來的小節中,我們會添加本章的最後一個特性來解決這一問題。
1.8 場景對浏覽器的自适應
當浏覽器大小改變時改變錄影機是很容易實作的。首先我們需要做的就是為浏覽器注冊一個事件監聽器,如下所示:
這樣,每當浏覽器尺寸改變時onResize()方法就會被執行。在onRaise()方法中需要更新錄影機和渲染器,代碼如下:
對于錄影機,需要更新它的aspect屬性,這個屬性表示螢幕的長寬比;對于渲染器,需要改變它的尺寸。最後我們需要将變量camera、renderer和scene的定義移到init()方法的外面,這樣其他的方法(如onResize()方法)也可以通路它們。代碼如下所示:
運作示例06-screen-size-change.html并改變浏覽器的大小,就可以看到實際的效果。
1.9 總結
本章到此結束。在這一章裡你學到了如下内容:如何搭建開發環境,如何擷取本書相關的源碼和示例;使用Three.js渲染場景時,首先需要做的是建立THREE.Scene對象,添加錄影機、光源和需要渲染的物體;如何給場景添加陰影和動畫效果;添加輔助庫dat.GUI和stats.js建立使用者控制界面和快速擷取場景渲染時的幀數。
在下一章中我們将會進一步擴充這個示例,你将會學到更多Three.js中非常重要的場景構模組化塊。