碎屏特效
概述
在前公司,由于工作项目的原因,需要在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两个方向的偏移,省掉法线解压缩的计算,这里就不多讲了。至于这个屏碎的法线贴图如何制作,方法很多,合格的美术师制作这个一般不是难事。