首先,要扭曲,就肯定要动,这个shader还是得需要Time系列的变量进行驱动。不过这只是其中一个条件,由于shader是高度并行化的计算,我们没有办法区分每个像素到底需要偏移多少。在屏幕水波纹效果中,我们是通过计算当前像素点到屏幕中心位置的距离作为偏移值的,对于后处理这样做可能比较方便,但是对于普通物体上使用的shader就没有那么简单了。比如,我们同样是让采样坐标按照sin值进行偏移:
fixed4 frag(v2f i) : SV_Target	{	i.grabPos.x += _DistortStrength * sin(_Time.y * 10);	i.grabPos.y += _DistortStrength * sin(_Time.y);	fixed4 color = tex2Dproj(_GrabTempTex, i.grabPos);	return 1 - color;	}那么所有的顶点就都会按照一致的方向进行偏移:
为了让偏移变得随机,我们就要引入一个能够随机化输出的东东,也就是噪声图。比如我们找到了一张这个样子的噪声图:
然后,只需要用一个连续变化的值去采这个噪声图,就可以得到不连续的随机输出偏移值。下面附上扭曲效果的实现:
//Distort shader //by: puppet_master //2017.4.24 Shader "ApcShader/Distort" {	Properties	{	_DistortStrength("DistortStrength", Range(0,1)) = 0.2	_DistortTimeFactor("DistortTimeFactor", Range(0,1)) = 1	_NoiseTex("NoiseTexture", 2D) = "white" {}	}	SubShader	{	ZWrite Off	Cull Off	//GrabPass	GrabPass	{	//此处给出一个抓屏贴图的名称,抓屏的贴图就可以通过这张贴图来获取,而且每一帧不管有多个物体使用了该shader,只会有一个进行抓屏操作	//如果此处为空,则默认抓屏到_GrabTexture中,但是据说每个用了这个shader的都会进行一次抓屏!	"_GrabTempTex"	}	Pass	{	Tags	{	"RenderType" = "Transparent"	"Queue" = "Transparent + 100"	}	CGPROGRAM	sampler2D _GrabTempTex;	float4 _GrabTempTex_ST;	sampler2D _NoiseTex;	float4 _NoiseTex_ST;	float _DistortStrength;	float _DistortTimeFactor;	#include "UnityCG.cginc"	struct v2f	{	float4 pos : SV_POSITION;	float2 uv : TEXCOORD0;	float4 grabPos : TEXCOORD1;	};	v2f vert(appdata_base v)	{	v2f o;	o.pos = mul(UNITY_MATRIX_MVP, v.vertex);	o.grabPos = ComputeGrabScreenPos(o.pos);	o.uv = TRANSFORM_TEX(v.texcoord, _NoiseTex);	return o;	}	fixed4 frag(v2f i) : SV_Target	{	//首先采样噪声图,采样的uv值随着时间连续变换,而输出一个噪声图中的随机值,乘以一个扭曲快慢系数	float4 offset = tex2D(_NoiseTex, i.uv - _Time.xy * _DistortTimeFactor);	//用采样的噪声图输出作为下次采样Grab图的偏移值,此处乘以一个扭曲力度的系数	i.grabPos.xy -= offset.xy * _DistortStrength;	//uv偏移后去采样贴图即可得到扭曲的效果	fixed4 color = tex2Dproj(_GrabTempTex, i.grabPos);	return color;	}	#pragma vertex vert	#pragma fragment frag	ENDCG	}	} }