0x00 前言
上一篇小隨筆《小隨筆:利用Shader給斯坦福兔子長毛和實現雪地效果》中,我和大家聊了聊著名的斯坦福兔子和利用geometry shader實現的一些效果。這篇文章繼續沿用了同樣來自斯坦福的另一個模型Armadillo,同樣也使用了geometry shader來實現效果的表現。
0x01 凶惡的怪物和爆炸
當然,用之前的斯坦福兔子的模型做爆炸的效果也是可以的,但是考慮到要讓一個那么可愛的模型變成沙礫總覺得不太好,所以長相自帶怪物屬性的模型Armadillo就成了一個不錯的選擇。

不過另一個讓我選擇Armadillo的原因其實是因為它的面數和頂點數相對來說更多,可以看到它有106289個頂點和212574個多邊形組成,所以用來做爆炸成為沙礫的效果要更好。

ok,現在讓我們把Armadillo的obj文件導入到Unity內,可以看到這個怪物已經站立在我們的場景內了。接下來我們就要利用geometry shader來實現我們想要的爆炸沙粒化的效果了。

之前提到Geometry Shader的時候,往往是利用它來生成更多新的頂點和多邊形來實現我們期望的效果,例如利用它在GPU上生成草體,實現真實草的實時渲染。
但是Geometry Shader不僅可以生成新的圖元,同時它還可以減少頂點和多邊形的輸出,以實現一些有趣的效果,比如這篇小文章的例子,利用Geometry Shader來實現怪獸的爆炸和沙粒化效果。

而我們要做的也很簡單,就是在Geometry Shader內將輸入的由3個頂點組成的三角形圖元修改為只有一個頂點組成的點圖元。而輸出的這個點的坐標我們可以很簡單的使用三角形的中心點坐標。
float3 tempPos = (IN[0].vertex + IN[1].vertex + IN[2].vertex) / 3;
o.vertex = UnityObjectToClipPos(tempPos);
這樣,組成怪獸的網格就由三角形圖元變成了點圖元,而且頂點數量也隨之減少,至於怪物本身也變成了下面這個樣子。

但是這個時候的模型是靜止的,因此也看不出爆炸甚至是沙礫的效果。所以接下來我們就要讓怪物的模型隨着時間運動起來。
而一個大家都知道的運動學公式就可以用來實現這個效果:

其中的S就是頂點的最新位置,v0和a的值可以作為一個uniform變量傳入shader,運動方向可以是沿着三角形的法線方向,而t的來源則是Unity內置的變量_Time的y分量。
這樣,需要的幾個變量我們就有了:
//速度的值加速度的值
float _Speed;
float _AccelerationValue;
float _StartTime
//法線
float3 v1 = IN[1].vertex - IN[0].vertex;
float3 v2 = IN[2].vertex - IN[0].vertex;
float3 norm = normalize(cross(v1, v2));
...
//時間
float realTime = _Time.y - _StartTime;
之后只要帶入運動學公式就好了:
tempPos += norm * (_Speed * realTime + .5 * _AccelerationValue * pow(realTime, 2));
最后的效果就變成了這樣:

Demo地址:chenjd/Unity-Miscellaneous-Shaders
0x02 后記
ok,以上就是我這周的小隨筆。希望大家能有所收獲。哦,對了,我用的obj文件各位可以到這里下載:http://www.prinmath.com/csci5229/OBJ/index.html。
-EOF-
最后打個廣告,歡迎支持我的書《Unity 3D腳本編程》

歡迎大家關注我的公眾號慕容的游戲編程:chenjd01

