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用來渲染正常的模型
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
經過這次繪制,屏幕上出現了正常的模型。
OK,下面第二個pass要來了。
由於這次我們需要使用法線信息,所以我們可以直接使用Unity內建的appdata_base作為vs的輸入,它包含了頂點的法線信息。而由於這次vs和fs之間並沒有數據的傳遞,因此vs只需要輸出位置到SV_POSITION,而fs只需要輸出純色到SV_Target即可。
float4 vert(appdata_base v) : SV_POSITION
{
...
}
fixed4 frag() : SV_Target {
return _OutlineColor;
}
除此之外,在vs中我們不能直接使用在model空間的法線信息,因此還要將頂點的法線信息從model空間轉換到clip空間。
float3 normal = mul((float3x3) UNITY_MATRIX_MVP, v.normal);
然后將頂點沿着法線方向膨脹一定距離:
pos.xy += _OutlineFactor * normal.xy;
嗯。現在的效果有點贊了。
最后再來看看為什么要打開正面剔除,如果沒有正面剔除我們將看到的是一個顏色錯誤的模型。
就像下面這樣:
好了,到此一個常見而又簡單的效果就實現了。
demo地址:chenjd/Unity-Miscellaneous-Shaders
祝各位早安~
-EOF-
最后打個廣告,歡迎支持我的書《Unity 3D腳本編程》
歡迎大家關注我的公眾號慕容的游戲編程:chenjd01