在之前的文章简单的波动中有介绍波动方程,本文以此为基础学习屏幕后期特效:水波纹
Shader代码如下:
Shader "Hidden/ScreenWave"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_WaveAraneg("WaveArange",float)=0.5
_WaveWidth("WaveWidth",float)=3
_WaveSpeed("WaveSpeed",float)=1
_CenterX("CenterX",float)=0.5
_CenterY("CenterY",float)=0.5
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
//Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
float _WaveAraneg;
float _WaveWidth;
float _WaveSpeed;
float _CenterX;
float _CenterY;
//波动函数实现
float GenWave(float Arange,float x,float w,float timer)
{
float wave=sin(x*w+timer);
wave=(wave+1)*0.5;
wave*=wave*wave;
return Arange*wave;
}
fixed4 frag (v2f i) : SV_Target
{
float2 temUV=i.uv;
float2 temPos=float2((0.5+_CenterX),(0.5-_CenterY));
float2 pos2=temUV-temPos;//屏幕默认原点在左下角,需要调整圆心位置
float len=length(pos2);//获取波动方程中X的值
float timer=-_Time.y*_WaveSpeed;//时间变量
float wave=GenWave(_WaveAraneg,len,_WaveWidth,timer);
float2 pos=normalize(pos2)*wave;//重置位置
fixed4 col = tex2D(_MainTex, temUV+pos);
// just invert the colors
// col.rgb = 1 - col.rgb;
return col;
}
ENDCG
}
}
}
特别注意:
- 屏幕的UV坐标原点在左下角,因此需要设置_CenterX和_CenterY两个参数来实现圆心位置的调整
- _WaveSpeed设置波动频率,
- sin三角函数的范围在-1 ~ 1之间,而屏幕UV坐标的范围在0 ~ 1之间,因为在实现波动函数时需要通过简单的数学计算将结果控制在0 ~ 1之间