最近看官方視頻,看到肖月大佬提到用Ribbon的方法製作植物生長。一直也對這比較感興趣,所以花時間試著做了一下。還有很多地方需要完善,希望大家多多提提意見。
目前首選的考慮當然是Houdini,這就需要Houdini To Niagara來完成信息傳導。相關的插件地址:
https://github.com/sideeffects/HoudiniNiagara
https://github.com/sideeffects/SideFXLabs
一個是UE引擎的,一個Houdini的。網上有很多教程講了如何安裝插件,我就不贅述了。插件默認可以傳遞很多屬性(點是關鍵),包括位置,ID,旋轉,大小,Type等。
首先當然是在Houdini中製作我們所需的植物。我只需要植物的最終形態,只需要當前幀的數據,植物的生長效果在引擎內完成。
在最開始,對於Ribbon部分。我設想傳遞點的位置,大小來確定Ribbon。

首先Circle,Scatter節點在圓內創建幾個點 ,作為最開始的根部。而後用AttributeRandomize分別對N,pscale進行隨機化(確定曲線的朝向以及長度)。對於主幹用Line和Resample做出一根很多點的線。

通過Length設置點的數量,更改TreatPolygon使線更加平滑。並且勾選curveu屬性,此屬性根據曲線長度進行0~1的賦值。


AttributeVOP節點,通過curveu進行曲線採樣,然後採樣的值與Noise相乘來改變點的位置,將Noise的Frequency、Roughness、Amplitude節點用滑鼠中鍵提升為參數,這樣就可以對曲線進行彎曲操作了。曲線的左端保持為0,讓連接處的點不發生偏轉。最後用CopyToPoint節點將散布的點的屬性傳遞給曲線。

至於AttributeWrangle定義的屬性有什麼用,這在後面將會提到,現在我們專註構建基礎形狀。出與美術的考慮使用Twist對曲線進行扭曲。

這樣主幹部分就完成了。

隨後用OrientAlongCurve使法線沿著曲線方向對齊,再對N和pcale進行隨機化處理,Scatter產生點以進行下一層級的生成。其他的就和上面的一樣,Copy&Paste改下參數名稱就行了。



接下來,我想要在枝條末端生長花。為此,GroupRange節點就是選擇枝條的最後一個點,並作為END的組。這個不能放在CopyToPoint的節點後面,不然你只會得到一朵花。別問我怎麼知道,都是淚。

那麼一個關鍵的問題來了,怎麼確定花的朝向了。這個就要用到四元數了,我們首先OrientAlongCurve讓法線沿著曲線的方向。而後用AttributeWrangle寫上我們的朝向。我們只關注前三行關於方向的。1.定義旋轉矩陣m,該矩陣的作用是讓花的模型的Y軸(0,1,0)(參考UE方向)對齊到@N法線方向。2.對模型進行旋轉,旋轉的軸向是@N,旋轉的角度用參數ang來控制然後與ptnum相乘讓每朵花的旋轉值不同。3.最後把矩陣m參與矩陣運算賦予orient。

後面的就是Copy&Paste過程了,然後瘋狂的調整參數來達到你想要的美術效果。最後的花我沒有進行方向的調整,因為這朵花相對較小,在UE里我就用GPU粒子朝向攝像機來解決,已獲得那微小的性能提升。
好,做完了!!!准備導出到UE.

最後我們把需要導出的點用Merge合在一起,用我們安裝好的插件的Niagara節點,選擇渲染當前幀。導出!



什麼,你問我,多了幾個屬性和節點。那是後來的事了,因為我把這個導進UE里一看。

CrazyWork!!!
好了,不皮了。導進UE里,我們還面對幾個問題。
我們該怎麼區分每個層級,區分不同的花以及枝幹。
UE里的Ribbon怎麼一條線連到底呢,怎麼判斷Ribbon那是起點,那是終點。
怎麼做植物生長的效果。
通過查閱官方示例以及其他大佬的視頻文章之後,慢慢的解決了。
1. 在每次CopyToPoint節點之前,創建一個新的屬性Type用來區分他們。

需要注意的是花我們記得把之前的END組給上。
2. UE官方提到Particle.RibbonID和RibbonLinkOrder決定Ribbon的鏈接方式,但我仍然不明白究竟如何鏈接的。於是自己創建一個測試的粒子系統,把上面提到的兩個變數賦予隨機值。結果如下:

從第一張圖不難發現,RibbonID一樣時,Ribbon才會連起來,從第二張第三張圖我們發現Ribbon的鏈接順序取決於LinkOrder的大小。

RibbonID我們可以在CopyToPoint節點之前用ptnum賦值。LinkOrder則用之前提到過的curveu、1、2來賦值。忽視掉那些被注釋掉的黃色代碼,本來打算用pscale來做Ribbon的Width的,但由於樹枝間的接縫問題以及LinkOrder的出現我沒有用這種方法。
3. 植物的生長是通過對ID的重新排序得到的,我們得出每個點到原點的距離,並以此來進行重新排序。

然後在UE里根據這個值做出生長的效果。

以上就是整個Houdini的工作了。接下來導進UE里。

在安裝好HoudiniNiagara插件後,我們找到官方自帶的發射器,以此為模版。

我們只需要起始狀態就行了,不需要變化,可以把Update里的Sample刪除。然後把我們自己得到的點的數據到進來。

檢查一下點的屬性是否是我們想要的。


枝條用Ribbon發射器,UV就用默認的。Width等下我們自己設定。
Niagara里我們只是定義了枝條的發光顏色,枝條和花的材質都用的Masked的材質模式,用半透明模式消耗大,可能還會出現半透明排序問題。枝條的基礎顏色,粗糙度,法線都是在材質里完成的。考慮到文章篇幅原因,材質我就不展示了,都是一些基本的UV流動,扭曲,溶解等。

Ribbon形狀設定為Tube。

隨後我們初始化LifeTime,Position,RibbonWidth。

發射器默認自帶了一些Houdini的屬性,將Houdini.Position賦予到Particle.Position里。

至於我們自定義的屬性,需要像上面那樣手動寫進去。
接下來還剩一個問題,RibbonWidth的屬性如何定義了,我們可以用Type確定那一層級,用Linkorder進行曲線採樣來確定Width。

首先進行判斷那一層級,根據結果來設定Width。

將我們所寫的賦值給RibbonWidth,HType用Houdini.Type復制,TypeNum則是確定我們需要對那一層級進行編輯,0為主幹,1為Branch_1~~~以此類推。至於Width我們用A*B賦值。

A用LinkOrder進行曲線採樣,確定枝乾的形狀。ScaleCurve設置枝乾的大小。
B是一個Noise,與A相乘賦予每個枝條更加隨機的變化。
Noise是採樣CurlNoise實現的,因為這樣的噪音的隨機是一種偽隨機。

第一個是我們想要的Random,第二種是賦予隨機值。

這個是參考官方的CurlNoiseForce寫的。通過粒子的位置,Age實現對Noise的採樣,採樣出來的值歸一化,用Lerp節點重新映射,這樣我們便於方便的調整。

我想對Width做0.9~1.1的隨機變化。

其他的就是Copy&Paste過程了,我們只需要改變TypeNum確定改變那根枝條就行了。後面的枝條在曲線開始初給了一個相對較小的值,這樣枝條的連接處更加好看。

至於生長我們需要新定義一個Particle屬性,TimeShiftByID。這個雖然看起來比上面簡單,但其實花了我比較長時間想出來的。Age屬性是一個每秒增加1的動態屬性。再引入一個新的浮點數,定義生長的速度。最後和ID進行運算。(Age-ID*GrowSpeed)/GrowSpeed。(GrowSpeed不能為0),假如GrowSpeed為1,那麼ID為0的粒子在0~1S內的TimeShiftByID為0~1;ID為1的粒子在1~2S內的TimeShiftByID為0~1;ID為2的粒子在2~3S內的TimeShiftByID為0~1。假如GrowSpeed為2,那麼ID為0的粒子在0~2S內的TimeShiftByID為0~1;ID為1的粒子在2~4S內的TimeShiftByID為0~1;ID為2的粒子在4~6S內的TimeShiftByID為0~1以此類推。這樣將TimeShiftByID進行採樣就能實現很多效果。

最後我們給到GrowSpeed一個很小的值來確定生長時間,其實這裡還可以根據ID調整GrowSpeed來讓開始時生長的更快,結束時生長的慢一些。但是由於太快了,難以察覺我就沒加。而後我們根據TimeShiftByID給EmissiveColor進行設值,這樣就實現了植物生長的效果以及發光的效果。

我也通過DynamicMaterialParameters給材質中的溶解(Dissolve)參數賦值,其實這個和Alpha的功能有些重合,不過影響不大,在實現花的生長要靠溶解來更好的實現。
終於到最後的階段了,首先花的模型是通過Blender做的。

首先建一個平面,保證模型的UV是正方形方便貼圖製作。然後對平面用表面細分和陣列修改器進行編輯和復制。期間手動用衰減對點進行編輯,使其更加隨機化,最後平滑著色就OK了。

花的貼圖在SD裡面做的,紅色通道儲存著Albedo的信息,綠色通道儲存著EmissiveColor的信息,藍色通道儲存著溶解貼圖的信息。

通過IF判斷Type來確定花的生長位置和數量。

初始化花的基礎信息,花的大小設置一個隨機值就行了。

注意這裡的橫坐標的值很大,不是1,我給到的是3500,否則太快看不到發光生長。通過溶解來實現花的生長。到此為止,就沒有什麼新的東西了,後面的第二種花和前面的製作思路差不多。
其實做這個初衷是想用GPU粒子實現的,但我把Ribbon切換到GPU時發生錯誤,我看了下NiagaraDebugger發現,RibbonID和RibbonLinkOrder現在好像不能傳遞給GPU Ribbon,那樣的話可以實現更大數量的植物模擬了。由於東西比較多,難免會出現錯誤,歡迎大家指出。









