屏幕水纹特效

效果:

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()
    {
     spreadShader = null;
      if (spreaMaterial != null) DestroyImmediate(spreaMaterial);
      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);
                }
            }

效果:

posted @ 2017-11-21 18:01  BigTreee  阅读(409)  评论(0编辑  收藏  举报