1. 程式人生 > >UnityShader例項17:螢幕特效之碎屏特效

UnityShader例項17:螢幕特效之碎屏特效

碎屏特效

概述

       在前公司,由於工作專案的原因,需要在unity實現一個類似狂野飆車8 ,撞車翻車後的碎屏效果(如下圖),從圖可以看出,該特效除了碎屏的效果外還有個降低飽和度的操作,接下來在下文介紹這個效果實現的程式碼,完整原始碼附在本文末尾下載連結。

原理

       碎屏的製作相對比較簡單,和前面冰塊材質的效果類似,可以用一張法線貼圖(如下圖)儲存的值對螢幕UV座標進行扭曲即可,至於法線怎麼做就不多說了,美術都會;至於減低飽和度的操作,則可以用unity內建函式Luminance()來處理。為了方便美術調整,開放了一個調整飽和度的引數。

shader實現

       碎屏特效需要扭曲uv座標,是針對畫素的操作,因此關鍵程式碼主要是針對frag函式進行操作,在frag函式之前我們先需要引入幾個從C#指令碼傳過來的引數,一張法線貼圖_BumpTex,控制最終飽和度的引數_satCount,考慮到所使用的法線貼圖是一個正方形的貼圖,而螢幕的長寬比是不固定的,為防止法線貼圖拉伸引入兩個長寬比的引數_scaleX,_scaleY;

		uniform sampler2D _BumpTex;
		uniform float _satCount;
		uniform float _scaleX,_scaleY;

       Frag函式部分如下:bumpUV做了居中以及對應螢幕長寬比的拉伸處理;_scaleX,_scaleY值在C#指令碼中完成計算並傳過來。
		fixed4 frag (v2f i) : COLOR
		{
			half2 bumpUV = i.texcoord -0.5;
			bumpUV *= float2(_scaleX, _scaleY);
			bumpUV += 0.5;
			half2 bump = UnpackNormal(tex2D( _BumpTex, bumpUV)).rg;
			i.texcoord = bump * 0.5  + i.texcoord.xy;
			fixed4 col = tex2D(_MainTex , i.texcoord);
			fixed4 lum = Luminance(col);
			col = lerp(col, lum, _satCount);
			return col;
		}

C#指令碼

       C#指令碼比較簡單,計算了螢幕的長寬比引數,關鍵程式碼如下:
	void OnRenderImage (RenderTexture sourceTexture, RenderTexture destTexture)
	{	
		#if UNITY_EDITOR
			FindShaders ();
			CheckSupport ();
			CreateMaterials ();	
		#endif

		float scaleX , scaleY ;

		if(sourceTexture.width > sourceTexture.height)
		{	
			scaleX = 1.0f;
			scaleY = (float) sourceTexture.height / (float) sourceTexture.width;			
		}		
		else
		{
			scaleX = (float) sourceTexture.width / (float) sourceTexture.height;
			scaleY = 1.0f;	
		}
		

	//	print("scaleX:-------" + scaleX + " 	" + "scaleY:-------" + scaleY);

		if(BumpMap != null){
			
	        BrokenScreenMaterial.SetFloat ("_satCount", satCount);
	        BrokenScreenMaterial.SetFloat ("_scaleX", scaleX);
	        BrokenScreenMaterial.SetFloat ("_scaleY", scaleY);
	 		BrokenScreenMaterial.SetTexture ("_BumpTex", BumpMap);
	   		Graphics.Blit (sourceTexture, destTexture, BrokenScreenMaterial,0);

		}
		else {

			Graphics.Blit (sourceTexture, destTexture);

		}


本例效果

       沒有合適的場景做測試,就拿了這個色彩比較豔麗的場景做了個展示,這樣飽和度的差別看起來比較明顯。

總結

       本例屏碎的效果,主要是利用儲存在法線貼圖的資料對螢幕UV進行相應的偏移,原理是比較簡單的,在遊戲特效中,這種針對UV扭曲偏移的處理其實很多,在我的部落格裡面,第一篇關於冰塊材質裡就有此應用。從優化上角度上說,我們可以不使用法線貼圖,而使用計算好的值存在圖片的兩個通道中來計算UV兩個方向的偏移,省掉法線解壓縮的計算,這裡就不多講了。至於這個屏碎的法線貼圖如何製作,方法很多,合格的美術師製作這個一般不是難事。

下載連結