THREE.JS入門教程 THREE.JS使用前了解

Three.js是一個(gè)偉大的開源WebGL庫(kù),WebGL允許JavaScript操作GPU,在瀏覽器端實(shí)現(xiàn)真正意義的3D。但是目前這項(xiàng)技術(shù)還處在發(fā)展階段,資料極為匱乏,愛好者學(xué)習(xí)基本要通過Demo源碼和Three.js本身的源碼來學(xué)習(xí)。?

國(guó)外網(wǎng)站 aerotwist.com 有六篇較為簡(jiǎn)單的入門教程,我嘗試著將其翻譯過來,與大家分享。?

我在一些實(shí)驗(yàn)項(xiàng)目中使用了Three.js,我發(fā)現(xiàn)它對(duì)快速上手瀏覽器3D編程確實(shí)很有幫助。通過Three.js,你不僅可以創(chuàng)建相機(jī)、物體、光線、材質(zhì)等等,還可以選擇著色器,可以決定使用何種技術(shù)(WebGL、Canvas或SVG)在網(wǎng)頁(yè)上渲染你的3D圖形。Three.js是開源的,你甚至可以參與到這個(gè)項(xiàng)目中來。但現(xiàn)在,我將把重點(diǎn)放在基礎(chǔ)的介紹上,我將向你展示如何使用這個(gè)引擎上。?

盡管Three.js如此奇妙,但有時(shí)候它也會(huì)令人抓狂。比如,你將花費(fèi)大量時(shí)間閱讀例程,做一些逆向工程(在我的情形下)來確定某個(gè)函數(shù)的作用,有時(shí)還要去GitHub上提問。如果你需要提問,Mr. doob和AlteredQualia是極好的選擇。?

1.基礎(chǔ)?

我假定你的三維圖形學(xué)知識(shí)過關(guān),而且也在一定程度上掌握了JavaScript。如果不是這樣,那先去學(xué)一點(diǎn)吧,否則直接看這篇教程,也許會(huì)感到困惑。

在我們的三維世界里,我們有以下這些東西。我會(huì)帶你一步一步創(chuàng)建它們。?

1.場(chǎng)景?

2.渲染器?

3.相機(jī)?

4.物體(帶有材質(zhì)的)?

當(dāng)然,你也可以創(chuàng)造些其他的什么東西,我也希望你如此做。?

2.瀏覽器支持?

簡(jiǎn)單地看一下瀏覽器的支持情況吧。Google家的Chrome瀏覽器支持Three.js,在我的實(shí)驗(yàn)里,無論是對(duì)渲染器的支持程度還是JavaScript解釋器的運(yùn)行速度,Chrome都是做得最好的:它支持Canvas、WebGL和SVG,而且運(yùn)行得非常快。FireFox瀏覽器排在第二位,它的JavaScript引擎的速度比Chrome慢了半拍,但是對(duì)渲染器的支持也很棒,而且FireFox的速度,隨著版本更新也越來越快。Opera瀏覽器正在逐漸增加對(duì)WebGL的支持,Mac上的Safari瀏覽器有一個(gè)開啟WebGL的選項(xiàng)??傮w上,這兩個(gè)瀏覽器僅僅支持Canvas渲染。微軟家的IE9現(xiàn)在只支持Canvas渲染,而且微軟似乎并不樂意支持WebGL這個(gè)新特性,所以我們現(xiàn)在肯定不會(huì)用IE9來做實(shí)驗(yàn)。?

3.設(shè)置場(chǎng)景?

假定你已經(jīng)選擇了一個(gè)支持所有渲染技術(shù)的瀏覽器,而且你準(zhǔn)備通過Canvas或WebGL來渲染場(chǎng)景(這是更標(biāo)準(zhǔn)化的選擇)。Canvas比WebGL有著更廣泛地支持,但是WebGL可以直接在GPU上操作,這意味著你的CPU可以專注地處理非渲染類的工作,比如物理引擎或與用戶交互等。

無論你選擇何種渲染器,你都必須牢記在心的是:JavaScript代碼需要優(yōu)化。三維顯示對(duì)瀏覽器來說不是一項(xiàng)輕松的工作(現(xiàn)在能夠這樣做就很偉大了),所以如果你的渲染太慢了,你需要知道你代碼的瓶頸在何處,如果可能,改善它。

說了這么多,我想你已經(jīng)下載好Three.js源代碼,而且將它引入了你的html文檔了。那么如何開始創(chuàng)建一個(gè)場(chǎng)景呢?就像這樣:?

代碼如下:

// 設(shè)置場(chǎng)景大小?

var WIDTH = 400,?

HEIGHT = 300;?

// 設(shè)置一些相機(jī)參數(shù)?

var VIEW_ANGLE = 45,?

ASPECT = WIDTH / HEIGHT,?

NEAR = 0.1,?

FAR = 10000;?

// 獲取DOM結(jié)構(gòu)中的元素?

// - 假設(shè)我們使用了JQuery?

var $container = $('#container');?

// 創(chuàng)建渲染器、相機(jī)和場(chǎng)景?

var renderer = new THREE.WebGLRenderer();?

var camera =?

new THREE.PerspectiveCamera(?

VIEW_ANGLE,?

ASPECT,?

NEAR,?

FAR);?

var scene = new THREE.Scene();?

// 將相機(jī)加入場(chǎng)景?

scene.add(camera);?

// 相機(jī)的初始位置為原點(diǎn)?

// 將相機(jī)拉回來一些(譯者注:這樣才能看到原點(diǎn))?

camera.position.z = 300;?

// 啟動(dòng)渲染器?

renderer.setSize(WIDTH, HEIGHT);?

// 將渲染器加到DOM結(jié)構(gòu)中?

$container.append(renderer.domElement);?

你看,簡(jiǎn)單吧!?

4.構(gòu)建網(wǎng)格表面?

現(xiàn)在我們有了一個(gè)場(chǎng)景,一個(gè)相機(jī)和一個(gè)渲染器(在我的例子里,當(dāng)然是一個(gè)WebGL渲染器),但我們事實(shí)上什么還沒畫呢。事實(shí)上,Three.js提供了載入某幾種標(biāo)準(zhǔn)格式3D文件的支持,如果你在Blender,Maya,Cinema4D或是什么其他工具中建模,這簡(jiǎn)直太棒了。為了簡(jiǎn)單(畢竟這才剛開始呢?。┪覀兿葋砜紤]基元?;褪腔镜膸缀伪砻?,比如最基本的球體、平面、立方體、圓柱體。利用Three.js可以很方便地創(chuàng)建這些基元:?

?代碼如下:

// 設(shè)置球體參數(shù)(譯者注:球體被劃分為16×16的網(wǎng)格,如果后兩個(gè)參數(shù)取4、2,則生成一個(gè)八面體,請(qǐng)想象)?

var radius = 50,?

segments = 16,?

rings = 16;?

// material覆蓋在geometry上,生成mesh?

var sphere = new THREE.Mesh(?

new THREE.SphereGeometry(?

radius,?

segments,?

rings),?

sphereMaterial);?

// 將mesh加入到場(chǎng)景中?

scene.add(sphere);?

好了,但是球體上的材質(zhì)呢?在代碼中我們使用了一個(gè)sphereMaterial變量,我們還沒定義它呢。那我們就先來看看怎么創(chuàng)建材質(zhì)吧。?

5.材質(zhì)?

毫無疑問,這是Three.js最有用的部分了。這部分提供了幾個(gè)非常易用的通用材質(zhì)模型:?

1.Basic材質(zhì):表示一種不考慮光照的材質(zhì),現(xiàn)在只能這么說了。?

2.Lambert材質(zhì):(譯者注:朗伯面,各向同性反射)。?

3.Phong材質(zhì):(譯者注:馮氏面,有光澤的表面,介于鏡面反射和朗伯反射之間的反射,描述真實(shí)世界的反射)。

除此之外,還有一些其他類型材質(zhì),簡(jiǎn)單起見,就留給你自己探索。事實(shí)上,在使用WebGL類型的渲染器時(shí),材質(zhì)實(shí)在太好用了。為什么呢?因?yàn)樵谠鶺ebGL種你必須親自為每個(gè)渲染編寫著色器,而著色器本身就是個(gè)巨大的工程:簡(jiǎn)單地說著色器是使用GLSL語言(OpenGL的著色器語言)寫的,用來操作GPU的程序,這意味著你要在數(shù)學(xué)上模擬光照,反射等等,這很快就變成一項(xiàng)極為復(fù)雜的工作。多虧有了Three.js你才可以不必去自己編寫著色器,當(dāng)然,如果你想親自編寫的話,你可以使用MeshShaderMaterial,可見這是很靈活的設(shè)定。

現(xiàn)在,讓我們用朗伯面材質(zhì)覆蓋球體:?

代碼如下:

// 創(chuàng)建球體表面的材質(zhì)?

var sphereMaterial =?

new THREE.MeshLambertMaterial(?

{?

color: 0xCC0000?

});?

值得指出的是,創(chuàng)建材質(zhì)的時(shí)候,除了顏色還有很多其他參數(shù)可以指定,比如光滑度和環(huán)境貼圖。你可以需要檢索這個(gè)Wiki頁(yè)面來確認(rèn)哪些是哪些屬性可以設(shè)置在材質(zhì)上,或Three.js引擎提供的任何對(duì)象上。?

6.光?

如果你現(xiàn)在就想渲染場(chǎng)景,你會(huì)看到一個(gè)紅色的圓。雖然我們?cè)谇蝮w上覆蓋了朗伯面材質(zhì),但場(chǎng)景里沒有光。所以按照默認(rèn)設(shè)定,Three.js會(huì)恢復(fù)到滿環(huán)境光,物體的看上去的顏色就是物體表面的顏色。讓我們添加一個(gè)簡(jiǎn)單的點(diǎn)光源:?

代碼如下:

// 創(chuàng)建一個(gè)點(diǎn)光源?

var pointLight =?

new THREE.PointLight(0xFFFFFF);?

// 設(shè)置點(diǎn)光源的位置?

pointLight.position.x = 10;?

pointLight.position.y = 50;?

pointLight.position.z = 130;?

// 將點(diǎn)光源加入場(chǎng)景?

scene.add(pointLight);?

7.渲染循環(huán)?

顯然,關(guān)于渲染器的一切都設(shè)置好了。萬事俱備,我們現(xiàn)在只需要:?

?代碼如下:

// 畫!?

renderer.render(scene, camera);?

你很可能像多次渲染,而不是只渲染一次,所以如果你要去做一個(gè)循環(huán),你應(yīng)該使用requestAnimationFrame。這是目前最好的,在瀏覽器中處理動(dòng)畫的方法,雖然還沒有得到最全面的支持,但我強(qiáng)烈建議你去看一看Paul Irish的博客。?

8.通用的對(duì)象屬性?

如果你花點(diǎn)時(shí)間去瀏覽一遍Three.js的源代碼,你會(huì)發(fā)現(xiàn)很多對(duì)象都繼承自O(shè)bject3D。這個(gè)基類包含了很多有用的屬性,比如位置、旋轉(zhuǎn)和縮放的信息。特別的,我們的球體是一個(gè)Mesh對(duì)象,而Mesh對(duì)象繼承自O(shè)bject3D對(duì)象,但是又增加了些自己的屬性:geometry和material。為什么要說這些?因?yàn)槟阋欢ú粫?huì)只滿足于屏幕中一個(gè)什么都不做的圓球,而這些(譯者注:基類中的)屬性允許你操作Mesh對(duì)象更底層的細(xì)節(jié)和各種各樣的材質(zhì)。?

代碼如下:

// sphere是一個(gè)mesh對(duì)象?

sphere.geometry?

// sphere包含了一些點(diǎn)和面的信息?

sphere.geometry.vertices // 一個(gè)數(shù)組?

sphere.geometry.faces // 另一個(gè)數(shù)組?

// mesh對(duì)象繼承自object3d對(duì)象?

sphere.position // 包含x,y,z?

sphere.rotation // 同上?

sphere.scale // ... 同上?

9.討厭的秘密?

我希望這樣說你能很快弄明白:就是如果你修改了,比如說,一個(gè)mesh對(duì)象的頂點(diǎn)屬性vertices,你會(huì)發(fā)現(xiàn)在渲染循環(huán)中,什么都沒變。為什么?因?yàn)門hree.js將mesh對(duì)象的信息緩存為某種優(yōu)化結(jié)構(gòu)了。你真正要做的是給Three.js一個(gè)標(biāo)識(shí),告訴它如果什么東西改變了,需要重新計(jì)算緩存中的結(jié)構(gòu):?

?代碼如下:

// 設(shè)置geometry為動(dòng)態(tài)的,這樣才允許改變其中的頂點(diǎn)?

sphere.geometry.dynamic = true;?

// 告訴Three.js,需要重新計(jì)算頂點(diǎn)?

sphere.geometry.__dirtyVertices = true;?

// 告訴Three.js,需要重新計(jì)算頂點(diǎn)?

sphere.geometry.__dirtyNormals = true;?

還有更多的標(biāo)識(shí),但我發(fā)現(xiàn)這兩個(gè)是最有用的。你應(yīng)該僅僅標(biāo)識(shí)那些確實(shí)需要實(shí)時(shí)計(jì)算的屬性來避免無謂的運(yùn)算開銷。?

10.小結(jié)?

我希望這篇簡(jiǎn)單的介紹對(duì)你有所幫助。沒什么能比得上卷起袖子親手實(shí)踐了,我強(qiáng)烈建議你這樣做。在瀏覽器里面運(yùn)行3D程序很有意思,而且使用像Three.js這樣一個(gè)引擎免去了很多麻煩,讓你一開始就能專注于那些真正cool的事情。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容