I put an example together for you (see below for the download link).
Here is how it looks:
(sorry for the bad hiccups in the video, my recorder obviously sucks)
The idea is to have a texture that describes how strong the distortion is at a certain pixel (black=full distortion to the left, white=full distortion to the right. In the following example, the Red channel represents horizontal and Green channel the vertical distortion. The Blue channel represents a mask (black=no distortion, white=full distortion). The distortion texture is scrolled using the built-in _Time variable, so you get motion into it.
Old Unity 5 Shader Example, see shader files in the package below for the latest version
[code=CSharp]//
// Created with Unity 5.1
// Example code to help answer the forum post at:
// http://forum.unity3d.com/threads/horizontal-wave-distortion.295769/
//
// This source code is not a full fledged distortion solution.
// It's just an example and hopefully proves useful for someone.
//
Shader "Custom/GrabPass Disortion" {
Properties {
_MainTex ("Texture (R,G=X,Y Distortion; B=Mask; A=Unused)", 2D) = "white" {}
_IntensityAndScrolling ("Intensity (XY); Scrolling (ZW)", Vector) = (0.1,0.1,1,1)
[Toggle(MASK)] _MASK ("Texture Blue channel is Mask", Float) = 0
[Toggle(DEBUGUV)] _DEBUGUV ("Debug Texture Coordinates", Float) = 0
}
SubShader {
Tags {"Queue" = "Transparent" "IgnoreProjector" = "True"}
Lighting Off
Fog { Mode Off }
ZWrite Off
LOD 200
// See http://docs.unity3d.com/Manual/SL-GrabPass.html
GrabPass { "_GrabTexture" }
Pass {
CGPROGRAM
//#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature MASK
#pragma shader_feature DEBUGUV
#include "UnityCG.cginc"
// _MainTex is our distortion texture and
// should use "Bypass sRGB Sampling" import setting.
sampler2D _MainTex;
float4 _MainTex_ST; // texture tiling and offset
// _GrabTexture contains the contents of the screen
// where the object is about to be drawn.
sampler2D _GrabTexture;
// x=horizontal intensity, y=vertical intensity
// z=horizontal scrolling speed, w=vertical scrolling speed
float4 _IntensityAndScrolling;
struct appdata_t {
float4 vertex : POSITION;
half2 texcoord : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
half2 screenuv : TEXCOORD1;
#if MASK
half2 maskuv : TEXCOORD2;
#endif
};
v2f vert (appdata_t v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); // Apply texture tiling and offset.
o.texcoord += _Time.gg * _IntensityAndScrolling.zw; // Apply texture scrolling.
#if MASK
// We don't scroll this texture lookup, because we want the mask to be static.
o.maskuv = v.texcoord;
#endif
half4 screenpos = ComputeGrabScreenPos(o.vertex);
o.screenuv = screenpos.xy / screenpos.w;
return o;
}
fixed4 frag (v2f i) : COLOR
{
half2 distort = tex2D(_MainTex, i.texcoord).xy;
// distort*2-1 transforms range from 0..1 to -1..1.
// negative values move to the left, positive to the right.
half2 offset = (distort.xy * 2 - 1) * _IntensityAndScrolling.xy;
#if MASK
// _MainTex stores in the blue channel the mask.
// The mask intensity represents how strong the distortion should be.
// black=no distortion, white=full distortion
half mask = tex2D(_MainTex, i.maskuv).b;
offset *= mask;
#endif
// get screen space position of current pixel
half2 uv = i.screenuv + offset;
half4 color = tex2D(_GrabTexture, uv);
UNITY_OPAQUE_ALPHA(color.a);
#if DEBUGUV
color.rg = uv;
color.b = 0;
#endif
return color;
}
ENDCG
}
}
}
Old Unity 4 Shader Example
// This source code is NOT a full fledged distortion solution.
// It's just an example and hopefully proves useful for someone.
//
// I'm not sure if Unity Pro is required due to the usage of "GrabPass".
Shader "Custom/DistortionExample" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_IntensityAndScrolling ("Intensity (XY), Scrolling (ZW)", Vector) = (0.1,0.1,1,1)
}
SubShader {
Tags {"Queue" = "Transparent" "IgnoreProjector" = "True"}
Lighting Off
LOD 200
// See http://docs.unity3d.com/Manual/SL-GrabPass.html
GrabPass { "_GrabTexture" }
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
sampler2D _GrabTexture;
// x=horizontal intensity, y=vertical intensity
// z=horizontal scrolling speed, w=vertical scrolling speed
float4 _IntensityAndScrolling;
struct Input
{
float2 uv_MainTex;
float4 screenPos;
};
void surf (Input IN, inout SurfaceOutput o)
{
// get screen space position of current pixel
half2 screenUV = IN.screenPos.xy / IN.screenPos.w;
#if UNITY_UV_STARTS_AT_TOP
screenUV.y = 1-screenUV.y;
#endif
// _MainTex should use "Bypass sRGB Sampling" import setting.
// d.x = horizontal offset 0..1
// d.y = vertical offset 0..1
float4 d = tex2D (_MainTex, IN.uv_MainTex+_Time.gg*_IntensityAndScrolling.zw);
// d.x*2-1 transforms range from 0..1 to -1..1.
// negative values move to the left, positive to the right.
screenUV.x += (d.x*2-1) * _IntensityAndScrolling.x;
screenUV.y += (d.y*2-1) * _IntensityAndScrolling.y;
half4 c = tex2D (_GrabTexture, screenUV);
o.Emission = c.rgb;
o.Alpha = 1;
}
ENDCG
}
FallBack "Diffuse"
}
You can download the Unity project of this example at:
http://www.console-dev.de/bin/UnityGrabPassDistortion.zip
EDIT, April 15th 2017: Package updated to allow to tint distortion areas. Project uses Unity 5.4.
EDIT, September 18th 2015: Package updated with a couple of more features, such as distance fade, culling mode and a particle shader. The package also contains examples that show what causes artifacts/problems with the shaders or perhaps distortion effects in general.