小隨筆:寫一個基於幾何生成方法的描邊效果

0x00 前言

進入金秋九月之後,周末參加的社區活動反而多了起來。因此不像之前一樣有富餘的時間來寫一些長文了,在考慮寫點什麼的時候突然想到了上一篇文章《利用GPU實現翻頁效果》中利用shader實現了一個有趣的翻書的效果。那麼這篇文章不妨也來效仿一下寫一個shader來實現某種效果,只不過篇幅上可能更短、效果更簡單,當然寫作的時間也更碎片化了,所以《小隨筆》似乎是一個不錯的標題。

0x01 先來點理論知識

本文要實現的內容是一個很常見的描邊效果。

(本文的模型來自:RTS Mini Legion Lich)

實現的思路來自《Real Time Rendering》的相關章節,即基於幾何生成方法的描邊。相關的理論內容已經有不少文章都提到過,這裡簡單概況一下就是在繪製模型時用兩個pass,第一遍正常繪製模型;第二遍繪製則要將模型正面剔除——正面剔除的原因在下面的演示中我會告訴各位——接著在vs中修改頂點位置,將頂點沿著法線方向膨脹一定距離,然後在fs中將模型用純色輸出即可。

(圖片來自:【翻譯】西川善司「實驗做出的遊戲圖形」「GUILTY GEAR Xrd -SIGN-」中實現的「純卡通動畫的實時3D圖形」的秘密,前篇(2))

0x02 再來點實際操作

好了,現在就讓我們來實現這個效果吧。

首先我們顯然總共需要兩個pass,但是我們先實現一個pass,將模型正常的繪製出來。

// 第一個pass用來渲染正常的模型n Passn {n CGPROGRAMn #pragma vertex vertn #pragma fragment fragnn #include "UnityCG.cginc"nn struct appdatan {n float4 vertex : POSITION;n float2 uv : TEXCOORD0;n };nn struct v2fn {n float2 uv : TEXCOORD0;n float4 vertex : SV_POSITION;n };nn sampler2D _MainTex;n float4 _MainTex_ST;nn v2f vert (appdata v)n {n v2f o;n o.vertex = UnityObjectToClipPos(v.vertex);n o.uv = TRANSFORM_TEX(v.uv, _MainTex);n return o;n }nn fixed4 frag (v2f i) : SV_Targetn {n fixed4 col = tex2D(_MainTex, i.uv);n return col;n }n ENDCGn

經過這次繪製,屏幕上出現了正常的模型。

OK,下面第二個pass要來了。

由於這次我們需要使用法線信息,所以我們可以直接使用Unity內建的appdata_base作為vs的輸入,它包含了頂點的法線信息。

而由於這次vs和fs之間並沒有數據的傳遞,因此vs只需要輸出位置到SV_POSITION,而fs只需要輸出純色到SV_Target即可。

float4 vert(appdata_base v) : SV_POSITIONn {n ...n }nn fixed4 frag() : SV_Target {n return _OutlineColor;n }n

除此之外,在vs中我們不能直接使用在model空間的法線信息,因此還要將頂點的法線信息從model空間轉換到clip空間。

float3 normal = mul((float3x3) UNITY_MATRIX_MVP, v.normal);n

然後將頂點沿著法線方向膨脹一定距離:

pos.xy += _OutlineFactor * normal.xy;n

嗯。現在的效果有點贊了。

最後再來看看為什麼要打開正面剔除,如果沒有正面剔除我們將看到的是一個顏色錯誤的模型。

就像下面這樣:

好了,到此一個常見而又簡單的效果就實現了。

demo地址:chenjd/Unity-Miscellaneous-Shaders

祝各位早安~

-EOF-

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


推薦閱讀:

【Unity】UGUI系列教程——OSU!Battle!
骨骼與動畫重定向——Unity探索筆記之視覺解決方案(一)
Unity移動端性能優化
Unity3D 正六邊形,環狀擴散,緊密分布,的程序
從零開始學基於ARKit的Unity3d遊戲開發系列11

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