屏幕水纹特效
效果:
shader:
Shader "Unlit/Spread" { Properties { _MainTex ("Texture", 2D) = "white" {} _R("Radius", Range(0,2)) = 0.2 _Width("Width", Range(0,1)) = 0.2 _Intension("Intension", Range(0,1)) = 0.025 } SubShader { Tags { "RenderType"="Opaque" "IgnoreProjector" = "Opaque" } LOD 100 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; }; sampler2D _MainTex; float4 _MainTex_ST; half _R; half _Width; half _Intension; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture half2 coords = i.uv; coords = (coords - 0.5) * 2; float r = coords.x * coords.x + coords.y* coords.y; if (r < _R*_R && r >(_R - _Width)*(_R - _Width)) { half2 offsets = _Intension * coords;//光波越外越明显(偏移越大) return tex2D(_MainTex, i.uv - offsets); } else { return tex2D(_MainTex, i.uv); } } ENDCG } } }
挂Camera的脚本:
using UnityEngine; using System.Collections; public class Spread : MonoBehaviour { public AnimationCurve V_Curve; public float V_SpreadSeconds = 2f; public float V_SpreadMaxRadius = 2f; float m_Radius = 0f; float m_CurveTime = 0f; Material spreaMaterial; Shader spreadShader; // Use this for initialization void Start () { spreadShader = Shader.Find("Unlit/Spread"); spreaMaterial = new Material(spreadShader); } private void OnDestroy() {if (spreaMaterial != null) DestroyImmediate(spreaMaterial);
spreadShader = null;
spreaMaterial = null;
} private void OnEnable() { m_CurveTime = 0; } // Update is called once per frame void Update () { if (m_CurveTime <= V_SpreadSeconds) { float rate = m_CurveTime / V_SpreadSeconds; m_Radius = V_Curve.Evaluate(rate)* V_SpreadMaxRadius; m_CurveTime += Time.deltaTime; }
else enabled = false; } private void OnRenderImage(RenderTexture source, RenderTexture destination) { spreaMaterial.SetFloat("_R", m_Radius); Graphics.Blit(source, destination, spreaMaterial); } }
脚本没什么可说的,shader主要思想是向内采样。
改进版:
因为上面水波的光环很明显,所以下面虚化内环并加一些注释:
fixed4 frag (v2f i) : SV_Target { // sample the texture half2 coords = i.uv; coords = (coords - 0.5) * 2; float r = coords.x * coords.x + coords.y* coords.y; //水波外环半径是_R,内环半径是_R-_Width,环内向里面采样(即偏移采样),这样水波过后还是正常采样 if (r < _R*_R && r >(_R - _Width)*(_R - _Width)) { //外环保持,越向内环coef越小 half coef = r / _R / _R; //乘coords是水波越外越明显(偏移越大),乘多个coef是为了更弱化内环 half2 offsets = coef * coef * coef * _Intension * coords; return tex2D(_MainTex, i.uv - offsets); } else { return tex2D(_MainTex, i.uv); } }
效果: