UnityShader实例17:屏幕特效之碎屏特效

碎屏特效


概述

       在前公司,由于工作项目的原因,需要在unity实现一个类似狂野飙车8 ,撞车翻车后的碎屏效果(如下图),从图可以看出,该特效除了碎屏的效果外还有个降低饱和度的操作,接下来在下文介绍这个效果实现的代码,完整源码附在本文末尾下载链接。
UnityShader实例17:屏幕特效之碎屏特效_第1张图片


原理

       碎屏的制作相对比较简单,和前面冰块材质的效果类似,可以用一张法线贴图(如下图)存储的值对屏幕UV坐标进行扭曲即可,至于法线怎么做就不多说了,美术都会;至于减低饱和度的操作,则可以用unity内置函数Luminance()来处理。为了方便美术调整,开放了一个调整饱和度的参数。
UnityShader实例17:屏幕特效之碎屏特效_第2张图片


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);

		}


本例效果

       没有合适的场景做测试,就拿了这个色彩比较艳丽的场景做了个展示,这样饱和度的差别看起来比较明显。
UnityShader实例17:屏幕特效之碎屏特效_第3张图片UnityShader实例17:屏幕特效之碎屏特效_第4张图片


总结

       本例屏碎的效果,主要是利用储存在法线贴图的数据对屏幕UV进行相应的偏移,原理是比较简单的,在游戏特效中,这种针对UV扭曲偏移的处理其实很多,在我的博客里面,第一篇关于冰块材质里就有此应用。从优化上角度上说,我们可以不使用法线贴图,而使用计算好的值存在图片的两个通道中来计算UV两个方向的偏移,省掉法线解压缩的计算,这里就不多讲了。至于这个屏碎的法线贴图如何制作,方法很多,合格的美术师制作这个一般不是难事。


下载链接

       屏幕特效之屏碎







你可能感兴趣的:(unity3D,shader实例笔记)