小隨筆:利用Shader給斯坦福兔子長毛和實現雪地效果

0x00 前言

發現最近沒有了寫長篇大論的激情,可能是到了冬天了吧。所以這篇小文只是簡單介紹下如何在Unity中利用shader很簡單的實現雪地效果以及毛皮效果,當然雖然標題寫在了一起,但其實這是倆事。

最後和大家分享一下這兩個小Demo。

0x01 斯坦福兔子和它的毛

我相信對圖形學有興趣的童靴們一定經常會見到這個上鏡率超高的兔子。

關於它的典故各位可以看看龔大的回答:斯坦福兔子模型的來源和故事有哪些?

當然,我用的兔子也是從斯坦福的網站上找到的。

graphics.stanford.edu/~

ok,導入到我們的Unity引擎中。

可以看到這個醜醜的兔子已經端坐在場景內了。

接下來就開始我們對兔子的改造行動吧。

既然要生成皮毛,那麼是否需要皮毛的網格數據呢?是的。

那麼皮毛的網格要根據什麼來生成呢?

要生在兔子的身體上,所以兔子的原始網格信息提供了皮毛的網格信息。

ok,那麼具體要怎麼做呢?很簡單,Geometry Shader就是干這個的。而我們只需要根據兔子的網格信息,以每一個triangle為一個單位,在這個triangle上生成一個向外指的「金字塔」就可以了。

也就是說,在原有triangle的基礎上又新生成了3個指向外面的triangle,形成毛皮的效果。

[maxvertexcount(9)]n void geom(triangle v2g IN[3], inout TriangleStream<g2f> tristream)n {n g2f o;n ...nn for (uint i = 0; i < 3; i++)n {n o.vertex = UnityObjectToClipPos(IN[i].vertex);n tristream.Append(o);nn o.vertex = UnityObjectToClipPos(IN[index].vertex);n tristream.Append(o);nn o.vertex = UnityObjectToClipPos(float4(centerPos, 1));n tristream.Append(o);nn tristream.RestartStrip();n }n }n

因此總共會生成9個頂點,3個新三角形共同組成一根毛。

Demo地址:

github.com/chenjd/Stanf

0x02 雪地痕迹的效果

實現雪地印痕的思路其實也很簡單,即記錄玩家移動過程中的位置,之後再根據這些數據修改雪地的mesh即可。

所以,很簡單的,我們在unity中只需要一個在玩家頭頂上的正交相機和一個rendertexture就可以記錄玩家的移動過程中的位置了。

之後在shader文件中先用vs根據rendertexture的數據修改雪地mesh的相關頂點位置,同時為了更方便地實現光照的效果,接下來使用surface shader,實現光照。

void vert(inout appdata_full vertex)n {n vertex.vertex.y -= tex2Dlod(_SnowTrackTex, float4(vertex.texcoord.xy, 0, 0)).r * _SnowTrackFactor;n }nn void surf (Input IN, inout SurfaceOutputStandard o) {n fixed4 c = tex2D(_MainTex, IN.uv_MainTex);n o.Albedo = c.rgb;n o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));n o.Alpha = c.a;n }n

好了,最後的效果就是下面這樣的。

Demo地址:

github.com/chenjd/Unity

0x03 後記

當然,如果有更多的三角形以上效果會更加真實精細。所以有時候會搭配Tessellation的處理,提供更多的三角形,提供更多的精確性。

-EOF-

最後打個廣告,歡迎支持我的書《Unity 3D腳本編程》

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


推薦閱讀:

Hypereal Pano VR頭顯試用記
【遊戲框架系列】簡單的圖形學(三)——光源

TAG:计算机图形学 | Unity游戏引擎 | 游戏开发 |