Three.js 進(jìn)階之旅:實(shí)現(xiàn)王國之淚神廟能量光環(huán)

摘要
如封面圖所示,本文將基于?Vue3 + Three.js + GLSL
?的相關(guān)知識,實(shí)現(xiàn)游戲《塞爾達(dá)傳說:王國之淚》中低配版神廟能量光環(huán)效果。通過本文的閱讀和學(xué)習(xí),你將學(xué)習(xí)到的知識點(diǎn)包括:在?Three.js
?中創(chuàng)建螺旋上升曲線的多種方法、如何給模型添加動態(tài)漸變色的紋理材質(zhì)、以及如何給能量光環(huán)添加發(fā)光效果、如何使用?AI
?能力生成卡通風(fēng)格全景?HDR
?等。

效果
本文實(shí)現(xiàn)的效果如下圖所示,頁面由卡通風(fēng)格?HDR
?全景背景、簡易的石頭形狀的神廟以及具有發(fā)光效果和旋轉(zhuǎn)動畫的能量光環(huán)構(gòu)成,頁面初次加載時(shí)鏡頭由遠(yuǎn)到近緩動拉近,使用鼠標(biāo)可以對模型進(jìn)行縮放和旋轉(zhuǎn)操作。(本文重點(diǎn)實(shí)現(xiàn)內(nèi)容是螺旋上升的發(fā)光能量環(huán),至于神廟,為了頁面完整我找了一個形狀類似的石頭模型來代替???
)。

預(yù)覽圖片使用的是?GIF
,為了節(jié)約體積對其進(jìn)行了壓縮和減幀,建議通過以下預(yù)覽鏈接訪問頁面,大屏瀏覽效果更佳啊?卓
。
?????
?在線預(yù)覽地址:dragonir.github.io/zelda-shrine/
本專欄系列代碼托管在?Github
?倉庫【threejs-odessey】,后續(xù)所有目錄也都將在此倉庫中更新。
??
?代碼倉庫地址:git@github.com:dragonir/threejs-odessey.git

原理
在開始實(shí)現(xiàn)之前,我們先整理總結(jié)下本文中將應(yīng)用到的知識點(diǎn),該部分內(nèi)容主要討論如何實(shí)現(xiàn)神廟光環(huán)的外形和紋理材質(zhì)的相關(guān)原理。首先我們來看看在游戲中的神廟截圖,可以觀察到,神廟光環(huán)是一個形態(tài)類似輕盈的氣流的螺旋上升的圓弧,螺旋的底部圓的半徑較大,頂部圓的半徑較小,顏色是綠色和藍(lán)色的漸變。
螺旋上升的曲線
對于螺旋上升的圓弧形狀,我在實(shí)踐過程中找到以下幾種可行的實(shí)現(xiàn)方式。
實(shí)現(xiàn)方式 ①:Line2
在?Three.js
?使用?Line
?類繪制線條時(shí),無法為線條設(shè)置寬度,此時(shí)可以使用?Three.js
?自帶的?Line2
?類來實(shí)現(xiàn)寬線效果。我們可以像下面這樣簡單使用?Line2
?來創(chuàng)建一個螺旋形狀,單獨(dú)引入需要用到的資源?LineMaterial
、LineGeometry
、Line2
?來創(chuàng)建用于寬線的材質(zhì)、幾何體和網(wǎng)格模型。首先通過循環(huán)調(diào)用三角函數(shù)創(chuàng)建了一組在空間中螺旋上升的?THREE.Vector3
?點(diǎn)數(shù)組?points
,然后使用該數(shù)組,通過?THREE.CatmullRomCurve3
?創(chuàng)建曲線,最后使用?Line2
?將曲線轉(zhuǎn)換渲染為網(wǎng)格模型并添加到場景中。

??
?THREE.CatmullRomCurve3:是 Three.js 中表示三維空間中的 Catmull-Rom 曲線的一個類,它通過給定的一組點(diǎn)來創(chuàng)建曲線。可以通過 getPoints() 方法獲取曲線上的一系列點(diǎn),該方法返回一個包含指定數(shù)目點(diǎn)的數(shù)組,這些點(diǎn)均勻的分布在曲線上。
該方法可以生成螺旋上升的曲線模型,它也是Three.js 官方寬線示例的用法,大家可以通過以下鏈接查看源碼詳細(xì)實(shí)現(xiàn)。
??
?源碼地址:?https://github.com/mrdoob/three.js/blob/master/examples/webgl_lines_fat_raycasting.html
實(shí)現(xiàn)方式 ②:THREE.Curve
另一種實(shí)現(xiàn)螺旋上升的曲線的方法是使用?THREE.Curve
,它是?Three.js
?中表示曲線的一個基類,我們可以像下面這樣通過繼承?THREE.Curve
?來實(shí)現(xiàn)用于創(chuàng)建螺旋上升曲線的類,它接收?4
?個參數(shù)?radiusTop, radiusBottom, height, turns
,分別表示螺旋曲線頂部圓的半徑、底部圓的半徑、高度,螺旋的次數(shù),然后在?getPoint
?方法中使用上述參數(shù),通過三角函數(shù)構(gòu)建螺旋上升的曲線形狀,并返回組成曲線的點(diǎn)。
本文實(shí)例中,就是采用該方法來實(shí)現(xiàn)神廟螺旋上升的的能量光環(huán)的。
??
?THREE.Curve:可以創(chuàng)建自定義曲線,除了可以自定義 getPoint() 方法創(chuàng)建不同的曲線效果之外,還可以自定義 getTangent() 等方法來獲取每個點(diǎn)的切線向量等來控制曲線的外觀和行為。
發(fā)光且半透明漸變的紋理
解決能量光環(huán)的形狀問題后,現(xiàn)在考慮如何實(shí)現(xiàn)具有?????
?藍(lán)綠漸變色且發(fā)光和運(yùn)動的紋理材質(zhì)。為了實(shí)現(xiàn)這樣的效果,我搜集了很多資料,最終也僅僅實(shí)現(xiàn)了本文實(shí)例頁面中這種簡易的效果???
。
實(shí)現(xiàn)方式 ① 光線拖尾軌跡發(fā)生器
首先想到的方式是通過建模的方法解決這個問題,通過搜索大量資料發(fā)現(xiàn)Blender插件-光線拖尾軌跡發(fā)生器Light Trails Generator 1.1正好滿足我的需求,它是一款免費(fèi)的?Blender
?插件,使用它可以非常容易地創(chuàng)建出漂亮的光線效果。But,但是導(dǎo)出的時(shí)候模型的材質(zhì)丟失了,只能導(dǎo)出白模,我試著導(dǎo)出?gltf
、glb
、obj
、fbx
?等格式都不行,于是放棄了,打算通過代碼實(shí)現(xiàn)。(放個鉤子???
?在這里,等待一個精通?Blender
?且可以正常導(dǎo)出附帶材質(zhì)的光線模型的大佬)

實(shí)現(xiàn)方式 ② 著色器
半透明、漸變色、且具有流動動畫……通過?Three.js
?現(xiàn)有的基礎(chǔ)材質(zhì)是無法滿足需求的,只能通過支持加載自定義著色器的?THREE.ShaderMaterial
?著色器材質(zhì)來實(shí)現(xiàn)。在片段著色器中,我們可以通過紋理采樣、噪聲、顏色插值等方式對每個像素的紋理信息和其他參數(shù)進(jìn)行處理,實(shí)現(xiàn)最終神廟能量光環(huán)動態(tài)的光環(huán)效果。
??
?關(guān)于?Three.js
?中著色器的相關(guān)基礎(chǔ)知識,可以閱讀本專欄的其他文章:《Shader著色器入門》、《Shader著色器基礎(chǔ)圖案》
AI生成塞爾達(dá)風(fēng)格全景HDR ?
本文示例頁面的塞爾達(dá)風(fēng)格全景背景圖,是使用???
?AI繪圖工具
?生成的,skybox.blockadelabs.com?網(wǎng)站可以免費(fèi)生成卡通風(fēng)格的全景圖,我們只需在頁面底部的輸入框中輸入描述正向關(guān)鍵字和反向關(guān)鍵字即可根據(jù)文案生成對應(yīng)的全景圖片,比如在本實(shí)例中,我輸入的正向關(guān)鍵字是?breath of the wild, zelda, link, tree, flower, forest, river
,AI就生成了如下所示的全景?HDR
?圖片,我們還可以選在左側(cè)下拉框中的的繪制模型風(fēng)格,比如有電子藝術(shù)、迪士尼畫風(fēng)、水彩等多種風(fēng)格可以選擇。生成圖片后還可以在以當(dāng)前圖片為基礎(chǔ),在上面添加或修改。

關(guān)于???
?AI
?生成卡通風(fēng)格?HDR
?全景圖,大家感興趣的話,自己動手試試吧,以下是我生成的比較好看的幾張。


實(shí)現(xiàn)
資源引入
引入開發(fā)本案例頁面所有需要的資源,OrbitControls
?是鏡頭軌道控制器,可以使用鼠標(biāo)拖動旋轉(zhuǎn)視角;EffectComposer
、UnrealBloomPass
、RenderPass
?是后期效果渲染器和后期通道,用于給神廟能量光環(huán)添加發(fā)光效果;GLTFLoader
?用于加載?glb/gltf
?格式的模型文件;TWEEN
?和?Animations
?方法用于給初始化鏡頭添加一些絲滑的動畫效果;portalVertexShader
?和?portalFragmentShader
?分別是用于生成神廟能量光環(huán)材質(zhì)的頂點(diǎn)著色器和片段著色器。
場景初始化
初始化場景、相機(jī)、控制器等常規(guī)方法,可以通過?renderer.toneMapping
?等屬性來微調(diào)頁面整體的渲染效果。
創(chuàng)建全景背景
在這里,我們使用?AI
?生成的全景圖片作為場景的背景,可使用該開源工具HDRI-to-CubeMap將生成的全景圖片裁切成?6
?張,然后通過以下方法,就可以為場景添加全景效果背景了

創(chuàng)建能量光環(huán)模型
接著,我們使用原理中介紹的方法,創(chuàng)建出一條螺旋上升的的曲線形狀,然后使用?THREE.TubeGeometry
?創(chuàng)建出管狀的幾何體,給它添加一個基礎(chǔ)材質(zhì),就能實(shí)現(xiàn)如下圖所示的效果。
?? THREE.TubeGeometry
是?Three.js
?圖形庫用于創(chuàng)建具有管狀形狀的幾何體的類,可以生成沿著路徑的管狀幾何體。
THREE.TubeGeometry(path,?tubularSegments,?radius,?radialSegments,?closed)
path
:是?THREE.Curve
?類型的路徑對象,可以是?THREE.CatmullRomCurve3
?或其他類似的曲線對象,用于確定管狀幾何體的形狀。tubularSegments
:管狀幾何體的段數(shù),即沿路徑分割的部分?jǐn)?shù)目。radius
:管狀幾何體的半徑大小。radialSegments
:每個管狀幾何體段中圓周的分割數(shù)。closed
:布爾值,表示管狀幾何體是否閉合。

添加著色器材質(zhì)
然后,我們使用原理中介紹的著色器來給模型創(chuàng)建著色器材質(zhì),在著色器材質(zhì)中我們設(shè)置需要動態(tài)修改的同一變量如?time
、color
?等。讓后將該材質(zhì)添加到上面步驟創(chuàng)建的螺旋幾何體上,就可以實(shí)現(xiàn)如下圖所示的效果。
添加發(fā)光后期效果
發(fā)光效果使用了?Three.js
?自帶的?UnrealBloomPass
?輝光后期通道,可以像下面這樣創(chuàng)建一個?EffectComposer
,接著添加一個?RenderPass
?作為第一個通道,它會將我們的場景?scene
?和相機(jī)?camera
?渲染到第一個渲染目標(biāo)。最后添加一個?BloomPass
,它將對輸入結(jié)果的表面進(jìn)行模糊處理,從而使得場景產(chǎn)生輝光效果。

???
?關(guān)于 Three.js 后期處理原理介紹和示例,可以查閱本專欄的另一篇文章《Three.js 進(jìn)階之旅:后期處理》
添加神廟模型
最后,我們完善一下場景,由于建模能力有限,無法還原出游戲中的神廟模型,本案例中我們使用?GLTFLoader
?加載器添加一個?glb
?格式的類似神廟形狀石頭模型,將其放在能量光環(huán)下面,調(diào)整好兩者的位置。當(dāng)模型加載完成時(shí)我們可以使用?TWEEN.js
?添加一個鏡頭由遠(yuǎn)到近的動畫,使頁面更加絲滑。

??
?源碼地址:?https://github.com/dragonir/threejs-odessey

總結(jié)
本文中主要包含的知識點(diǎn)包括:
創(chuàng)建自定義路徑的曲線的多種方式
創(chuàng)建漸變紋理材質(zhì)的方法
給場景模型添加后期發(fā)光效果
使用AI能力生成圖片
想了解其他前端知識或其他未在本文中詳細(xì)描述的Web 3D開發(fā)技術(shù)相關(guān)知識,可閱讀我往期的文章。如果有疑問可以在評論中留言,如果覺得文章對你有幫助,不要忘了一鍵三連哦 ??。

附錄
[1].??? Three.js 打造繽紛夏日3D夢中情島
[2].??? Three.js 實(shí)現(xiàn)炫酷的賽博朋克風(fēng)格3D數(shù)字地球大屏
[3].??? Three.js 實(shí)現(xiàn)2022冬奧主題3D趣味頁面,含冰墩墩
[4].??? Three.js 實(shí)現(xiàn)3D開放世界小游戲:阿貍的多元宇宙
[5].??? Three.js 進(jìn)階之旅:全景漫游-高階版在線看房
…
【Three.js 進(jìn)階之旅】系列專欄訪問 ??
更多往期【3D】專欄訪問 ??
更多往期【前端】專欄訪問 ??

參考
[1].?threejs.org
