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


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

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

QQ截圖20170913221207.png

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;

嗯。現在的效果有點贊了。
2b.gif

最后再來看看為什么要打開正面剔除,如果沒有正面剔除我們將看到的是一個顏色錯誤的模型。
就像下面這樣:
QQ截圖20170913224809.png

好了,到此一個常見而又簡單的效果就實現了。
demo地址:chenjd/Unity-Miscellaneous-Shaders

祝各位早安~

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM