UE4程序化建模工具開發(fā)教程「植被建模」(ue4程序化植物)
Unreal Engine最好的部分之一就是它對那些偏藝術的人來說是無障礙的。隨著虛幻引擎4的首次發(fā)布,人們發(fā)現(xiàn)自己可以制作整個游戲,而不必觸及C 。從那時起,人們一直在挑戰(zhàn)藍圖的極限,Epic則通過更新擴展工具集來做出回應。
Unreal引擎中一個非常強大的部分是程序化網(wǎng)格(procedural mesh)組件,它接收數(shù)組輸入并輸出靜態(tài)網(wǎng)格。
將程序化網(wǎng)格與渲染到紋理(render to texture)功能相結(jié)合,可以完全在引擎中程序化地創(chuàng)建紋理資源!
這很有用,因為:
- 你可以準確地看到資產(chǎn)在構建時的外觀。
- 在構建資產(chǎn)時就可以在其環(huán)境中看到該資產(chǎn)。
- 更新都是實時的。
這有大量的潛在應用,我一直在研究風格化的植被(Foliage)生成,對于傳統(tǒng)建模工具而言這是一個痛苦的任務,而程序化網(wǎng)格則非常適合用于解決這個問題,因為游戲樹主要由簡單的形狀(圓柱體和平面)組成,并且更多地是關于這些形狀的正確放置和輕微變化,而不是它們各自的復雜性。
使用程序網(wǎng)格組件構建的一些樹:
如果你有興趣試用該工具,可以在此處下載。
使用此工具時,我建議增加項目設置中的最大循環(huán)計數(shù)(Max Loop Count)。如果超過項目設置的最大循環(huán)計數(shù),我們的幾何圖形將無法正確構建!
1、程序化創(chuàng)建三角形
讓我們從簡單的網(wǎng)格對象開始,渲染一個三角形。創(chuàng)建新的Actor藍圖并添加程序化網(wǎng)格組件。創(chuàng)建DrawTriangle函數(shù),并將其插入到構造腳本中:
添加兩個數(shù)組:
- 向量數(shù)組,用來表示頂點
- 整數(shù)數(shù)組,用來表示頂點數(shù)組的目標索引
在這里我們有三角形的三個頂點和創(chuàng)建該三角形所需的整數(shù)順序。注意我們需要列出頂點的順序,如果存儲0,1,2,則三角形將會方向錯誤。
程序化網(wǎng)格組件輸出到Create Mesh Section(創(chuàng)建網(wǎng)格截面)函數(shù),并將上述數(shù)組鏈接到對應的輸入中。
嘿!我們成功制作了一個三角形!
2、程序化創(chuàng)建平面
現(xiàn)在讓我們更復雜一點,做一個平面。首先需要添加更多的數(shù)組。我們需要補充:
- 法線向量數(shù)組
- 切線結(jié)構向量數(shù)組
- UV二維矢量數(shù)組
別擔心,我們將用一些小技巧獲得法線和切線!
請記住,就像以前一樣,我們需要先清理數(shù)組數(shù)據(jù)。
然后創(chuàng)建Draw Quad函數(shù),并添加兩個嵌套循環(huán),用來處理x 和 y的每個 值。
然后取當前的 x 和 y 值,乘以一個值(距離),并將其添加到向量數(shù)組中,最后將UV當前 x 和 y 值除以其總計(長度)以獲得歸一化值。
然后,我們可以使用Create Grid Mesh Triangles(創(chuàng)建網(wǎng)格三角形)功能自動生成指定數(shù)量的三角形。雖然以后無法使用它,但就目前而言,這是生成三角形數(shù)據(jù)網(wǎng)格的簡單方法。
我們還需要法線和切線,這樣我們就可以使用Calculate? Tangents for Mesh(計算網(wǎng)格的切線)函數(shù)來得到結(jié)果。
下面是最終得到的完整函數(shù),點擊鏈接查看放大的視圖:
下面是構造腳本:
結(jié)果:
3、程序化創(chuàng)建圓柱體
一旦有了網(wǎng)格,將形狀從平面更改為圓柱體就是一件簡單的事情:我們不再將定點與網(wǎng)格對齊,而是將它們纏繞在軸上。
取我們之前創(chuàng)建的 X 和 XLength 值,將它們相除以得到歸一值,然后乘以 360,從而得出角度。我們希望圍繞 z 軸旋轉(zhuǎn) x 軸,因此獲取這些值并將它們插入,并通過與浮點數(shù)相乘來控制距離。
像這樣將此新計算與原始的 x*float 交換,點擊鏈接 查看大圖。
現(xiàn)在我們的平面就變成了圓柱體!
如果我們?nèi)w一化的y或z值,并用1-x反轉(zhuǎn),則創(chuàng)建一個圓錐體!
4、讀取網(wǎng)格數(shù)據(jù)
我們需要的最后一個元素是讀取網(wǎng)格數(shù)據(jù)。Get? Section from Static Mesh(從靜態(tài)網(wǎng)格體獲取截面)函數(shù)可以從任何網(wǎng)格中獲取數(shù)據(jù)并輸出供我們使用?,F(xiàn)在,我們可以對任何網(wǎng)格進行采樣,對其進行修改,然后將其散布在表面上。
現(xiàn)在,我們已經(jīng)有了構建程序化內(nèi)容所需的基礎。在下一部分中,我們將介紹如何利用這些工具制作一個簡單的樹生成器。
5、程序化生成植被
在深入研究植被生成工具開發(fā)之前,我強烈建議你下載并嘗試一下,否則我們將討論的一些主題將非常抽象!你可能還會注意到一些未涵蓋的對pivot painter的引用。這是我目前正在開發(fā)的額外功能,尚未完成!
樹葉工具分為五個單獨的藍圖:
1、父藍圖 Tree Parent
- 保存將在所有子項之間共享的數(shù)據(jù)。
- 樹干、樹枝和樹葉藍圖均繼承自它。
2、樹干 Trunk
- 繼承自Tree Parent
- 樣條控制的網(wǎng)格
- 只制作一個網(wǎng)格
- 提供大量用戶控制
3、樹枝 Branch
- 繼承自Tree Parent
- 沿表面或隨機生成多個樹枝
- 用戶控制僅限于隨機變量范圍
- 可以相互疊加
4、樹葉 Leaf
- 繼承自Tree Parent
- 讀取網(wǎng)格數(shù)組并沿樹干/樹枝或隨機放置
- 不能有子節(jié)點
5、合成器 Compositer
- 以TreeParent數(shù)組為輸入,將網(wǎng)格重建為單個資產(chǎn)
- 檢測并合并重復材質(zhì),以減少材質(zhì)數(shù)量
你可能會想,為什么要這樣做???好吧,分解樹有多種好處:
- 在層次結(jié)構上進行更改時不必重繪整個網(wǎng)格
- 快速分離和隱藏資產(chǎn)的元素
- 刪除部分而不會破壞整個樹
- 資源將組件化,因此可以將樹的一部分復制粘貼到其他樹上
- 拆分隨機種子生成,以便獲得更多控制
所有這些元素結(jié)合在一起,讓用戶構建一個模塊化的組件堆棧,這些組件"應該"允許他們制作任何類型的樹!
6、父藍圖 – Tree Parent
為了避免重復工作,我們應該首先創(chuàng)建一個作為基礎的父藍圖,其他藍圖需要繼承父藍圖。這很有用,因為我們放入父藍圖中的任何數(shù)據(jù)都將在其后代藍圖中共享。例如,每個資產(chǎn)類型都需要一個材質(zhì)引用和一組網(wǎng)格數(shù)組,以便將信息添加到父級,以便傳播到其子級。
將程序化網(wǎng)格組件添加到TreeParent藍圖中。
我們還需要一些變量,每個子藍圖都需要這些變量。
Base:
- Material:應用于網(wǎng)格的材質(zhì),這意味著我們每個組件只支持一種材質(zhì)。
- ProcMesh,一個包含頂點、三角形、UV 和頂點顏色等制作網(wǎng)格所需的數(shù)組的結(jié)構。法線在具有函數(shù)后生成。
- RandomSeed,隨機種子,隨機化網(wǎng)格的一部分。
References:
- Parrent,樹藍圖變量,用于引用其所有者。
- Root,表示網(wǎng)格合成工具,用于獲取存儲順序。
- ChildRefs,父藍圖數(shù)組,用于告訴父級對象進行更新。
- Ts,轉(zhuǎn)換數(shù)組的數(shù)組,用于存儲樹枝信息??梢园阉胂蟪蓸涞墓羌?。父藍圖引用此內(nèi)容來獲取生成位置。
一個共享函數(shù),它告訴子數(shù)組中的資產(chǎn)進行更新。每次更改組件時都會調(diào)用它(但請記住,在我們創(chuàng)建之前,這些函數(shù)或強制轉(zhuǎn)換都不存在)。
如果我們不更新子組件,則樹將很快斷開連接。
7、樹干 Trunk
樹干藍圖應繼承自 TreeParent,并且基于可編輯樣條曲線。從添加組件下拉列表中選擇樣條線就可以將其添加到任何藍圖中,就像我們對程序化網(wǎng)格組件所做的那樣。
可以看到我們已經(jīng)繼承的組件:
在構造腳本中,我們添加了一個名為 Draw 的新函數(shù)。我們將對藍圖自身及其所有子藍圖進行此調(diào)用。
Draw函數(shù)檢查父樹干是否已存在,如果存在,則沿父樣條移動組件,否則將直接移動以創(chuàng)建網(wǎng)格。最后,通知子項使用"Update Children"進行更新。
I在 Create Base Segments中,我們清理歷史幾何數(shù)據(jù),計算新數(shù)據(jù),然后重新繪制網(wǎng)格,在這個教程中,這一模式我們將反復運用。
對于幾何圖形,我們需要兩個整數(shù),一個用于長度段的數(shù)量,另一個用于徑向段的數(shù)量。
獲取我們想要的樣條長度和長度段數(shù),將它們除以得到每個點之間的距離,并將其設置為稱為對于我們的幾何圖形,我們需要兩個整數(shù),一個用于長度段的數(shù)量,另一個用于徑向段的數(shù)量。
獲取我們想要的樣條長度和長度段數(shù),將它們除以得到每個點之間的距離,并將其設置為稱為Segment Distance(段距離)的浮點數(shù)。
然后循環(huán)處理每個長度段,并得到樣條線上指定距離處的變換。長度將是當前循環(huán)序號 * 段距離??梢允褂?x 或 y 來控制軀干的厚度。將其乘以暴露的值,為網(wǎng)格添加均勻大小。
你可能需要在此處旋轉(zhuǎn),以使其與樹枝的旋轉(zhuǎn)對齊。
將轉(zhuǎn)換存儲在數(shù)組中,這非常重要,因為我們需要一種通用方法來了解樹枝在空間的位置,并且并非每個藍圖都有樣條組件。稍后將添加到 Ts 數(shù)組(在 TreeParent 中創(chuàng)建)。
然后,我們在Draw Radius函數(shù)中圍繞該變換繪制頂點。這類似于我們之前繪制幾何圖形的方式。單擊鏈接以查看完整圖表。
這里唯一的主要區(qū)別是我們制作三角形數(shù)組的方式。這對于樹干來說是不必要的,但對于多個樹枝來說絕對至關重要。網(wǎng)格三角形函數(shù)只期望單一網(wǎng)格,但是如果我們想制作多個單獨的網(wǎng)格,需要偏移三角形計數(shù)器。
完成所有這些操作后,我們需要獲取基本轉(zhuǎn)換數(shù)組,并將其設置為 Ts 數(shù)組。此處的索引表示多個分支,但由于我們只創(chuàng)建一個段,因此僅將其設置為索引 0。
一旦獲得了所有數(shù)據(jù),剩下的就是繪制網(wǎng)格了!
8、樹枝 Branch
希望你現(xiàn)在已經(jīng)識別出這種模式,清除舊數(shù)據(jù)并生成新數(shù)據(jù)。樹枝藍圖需要接收一個父級(如果存在),并沿其分散多個樹枝。如果父藍圖不存在,我們將直接散落在地上。
上面沒有什么新內(nèi)容,因此讓我們繼續(xù)Make Branch Data(制作樹枝數(shù)據(jù)),此函數(shù)的大部分內(nèi)容是為我們正在創(chuàng)建的每個樹枝查找生成點(點擊鏈接查看大圖)。
首先要確定是否有父藍圖。如果是這樣,我們得到父級的 T 數(shù)組,這是一個轉(zhuǎn)換數(shù)組。每個樹枝都是一個新的轉(zhuǎn)換數(shù)組。這意味著,如果父樹枝有 8 個分支,而我們選擇創(chuàng)建 4 個分支,則它總共生成 32 個分支。如果父藍圖是樹干,則 T 數(shù)組將只有一個轉(zhuǎn)換條目。
如果它沒有父級,那么繼續(xù)循環(huán)進行分支計數(shù)并計算出歸一化距離。
下一步是弄清楚每個分支的起源應該是什么。如果沒有父級,只需獲取對象的原點即可。如果存在父級,則獲取當前變換數(shù)組并根據(jù)規(guī)范化距離查找位置。還可以在此處添加鉗位值以縮小范圍。
這里有一個圖表,如果這聽起來令人困惑,可以更好地解釋它。在下圖中,頂部值是需要轉(zhuǎn)換為轉(zhuǎn)換數(shù)組的規(guī)范化距離。乘以轉(zhuǎn)換索引計數(shù),得到最接近的索引,余數(shù)是下一個索引之間的距離。此計算將給我們一個沿變換長度的粗略距離。
生成最小和最大矢量之間的隨機位置。
合并位置,使用自定義宏修改旋轉(zhuǎn)并修改比例。
整理出原點旋轉(zhuǎn)是一個非常重要的元素。為了獲得易于控制的結(jié)果,可以使用圍繞索引旋轉(zhuǎn)并使用方向矢量以避免鎖定(鏈接)。
一旦獲得原點后,將其添加到pivot數(shù)組并創(chuàng)建分支。
在樹干示例中,我們使用樣條線進行變換,然后圍繞它構建幾何圖形。
我們不能在這里這樣做,因為樣條不存在。相反,我們必須生成這些點(鏈接)。
這里我們?nèi)≡c。
抓取當前垂直長度。我們需要這個來抵消我們的三角形計數(shù)。三角形數(shù)組只是引用頂點數(shù)組上的索引,因此需要偏移量來保持三角形引用的正確性。生成最小值/最大值之間的隨機分支長度。
然后對于分支上的每個點。
找出下一個點的位置。接受最后一個變換,通過乘以方向矢量來抵消它。通過一些受控的旋轉(zhuǎn)稍微調(diào)整它。
再次創(chuàng)建網(wǎng)格數(shù)據(jù),就像我們之前所做的那樣。
分支藍圖的重要功能是它是可堆疊的。我們應該能夠在樹枝上的樹枝上建立分支,等等。
可能遇到的唯一問題是我們的分支計數(shù)是指數(shù)級的。如果第一層有 6 個分支,第 2 層和第 3 層有 4 個分支,我們將得到 96 個分支,而不是 14 個分支。如果我們添加包含 4 個分支的第 4 層,則得到 384 個分支。整個操作都使用循環(huán),這意味著如果數(shù)字太大,我們將遇到很多麻煩。
9、樹葉 Leaf
樹葉不能有子級,因此它們將始終處于各自層次結(jié)構的末尾。藍圖將對網(wǎng)格數(shù)組進行采樣,并將它們分散到樹干或樹枝資源中。我們在這里可以做的一個有用的技巧是使用渲染實例而不是繪制幾何圖形,這可以大大提高性能。在這里,我們添加一個切換開關來表示是否利用此優(yōu)化。
對于此組件,創(chuàng)建一個可由用戶設置的網(wǎng)格數(shù)組。對于每個網(wǎng)格,使用get section from static mesh(從靜態(tài)網(wǎng)格體獲取部分)函數(shù)來獲取每個對象的數(shù)據(jù)并將其存儲以供以后使用(鏈接)。
與樹枝藍圖相同,清除舊數(shù)據(jù),檢查父數(shù)據(jù),然后循環(huán)處理。
找到與以前相同的生成點,然后創(chuàng)建網(wǎng)格或添加實例。
添加網(wǎng)格數(shù)據(jù)非常簡單(鏈接)。
我們得到三角形偏移量,并選擇一個要復制的網(wǎng)格。
按長度偏移三角形。按生成點轉(zhuǎn)換頂點數(shù)據(jù),將其全部存儲在數(shù)組中。
10、合并
組裝完各個組件后,需要將它們整理到一個可以導出的統(tǒng)一網(wǎng)格中。函數(shù)可以作為按鈕向編輯器公開,而不是在構造腳本中運行它。這允許在運行腳本時進行更高級別的控制。
在此功能中,我們清除舊數(shù)據(jù),構建唯一的材質(zhì)數(shù)組(這避免了使用重復材料創(chuàng)建任何資產(chǎn)),必要時重建網(wǎng)格數(shù)據(jù)并輸出網(wǎng)格。作為優(yōu)化,我們應該重建網(wǎng)格以避免大量重復的材質(zhì)分配。
將組件整理成一組數(shù)組(鏈接)。
檢查我們構建的材質(zhì)數(shù)組在長度上是否與組件數(shù)組相匹配。如果材質(zhì)比組件少,我們知道是一些共享的材質(zhì)。
此時,我們必須遍歷每個組件的三角形數(shù)據(jù)并對其進行偏移,以便在組合在一起時與頂點數(shù)組對齊。
最后,采用新的數(shù)據(jù)結(jié)構并創(chuàng)建一個靜態(tài)網(wǎng)格。
單擊合成器上的程序網(wǎng)格組件,然后按"創(chuàng)建靜態(tài)網(wǎng)格"按鈕。這將提示選擇一個位置,選擇一個名稱就可以了:
11、結(jié)論
這只是你可以使用過程網(wǎng)格組件創(chuàng)建的資產(chǎn)類型的一個示例。有各種各樣的可能性,也不僅限于編輯器創(chuàng)建,你也可以在游戲中使用此功能!
我們也不能在不提到Houdini的情況下完成一篇關于程序化工具的文章,這是一個純粹專注于程序化內(nèi)容生成的出色工具。它有一個很棒的UE4插件,你可以用它來處理Houdini引擎資源。
原文鏈接:http://www.bimant.com/blog/ue4-procedural-foliage-tool/