Unity Shader 水波紋效果

很多遊戲裏的水面場景,大家經常會看到有水波紋的效果,而這種效果是怎麼實現的呢?下面就給大家介紹下實現水波紋效果的shader代碼。

 

效果圖: 

Shader "Custom/shuibowen"{
    Properties{
        _MainTex("Base (RGB)",2D)="white"{}
        _distanceFactor("Distancefactor",float)=1
        _timeFactor("time factor",float)=2
        _totalFactor("total factor",float)=3
        _waveWidth("wave width",float)=4
        _curWaveDis("curwave dis",float)=5
        _startPos("star pos",Vector) = (1,1,1,1)
        _MainTex_TexelSize("Maintex_texelSize",vector)=(1,1,1,1)
    }
    CGINCLUDE
    #include "UnityCG.cginc"
    uniform sampler2D _MainTex;  
    float4 _MainTex_TexelSize;
    uniform float _distanceFactor;  
    uniform float _timeFactor;  
    uniform float _totalFactor;  
    uniform float _waveWidth;  
    uniform float _curWaveDis;  
    uniform float4 _startPos;
    fixed4 frag(v2f_img i) : SV_Target  
    {  
        //DX下紋理座標反向問題  
        #if UNITY_UV_STARTS_AT_TOP  
        if (_MainTex_TexelSize.y < 0)  
            _startPos.y = 1 - _startPos.y;  
        #endif  
        //計算uv到中間點的向量(向外擴,反過來就是向裏縮)  
        float2 dv = _startPos.xy - i.uv;  
        //按照屏幕長寬比進行縮放  
        dv = dv * float2(_ScreenParams.x / _ScreenParams.y, 1);  
        //計算像素點距中點的距離  
        float dis = sqrt(dv.x * dv.x + dv.y * dv.y);  
        //用sin函數計算出波形的偏移值factor  
        //dis在這裏都是小於1的,所以我們需要乘以一個比較大的數,比如60,這樣就有多個波峯波谷  
        //sin函數是(-1,1)的值域,我們希望偏移值很小,所以這裏我們縮小100倍,據說乘法比較快,so...  
        float sinFactor = sin(dis * _distanceFactor + _Time.y * _timeFactor) * _totalFactor * 0.01;  
        //距離當前波紋運動點的距離,如果小於waveWidth才予以保留,否則已經出了波紋範圍,factor通過clamp設置爲0  
        float discardFactor = clamp(_waveWidth - abs(_curWaveDis - dis), 0, 1) / _waveWidth;  
        //歸一化  
        float2 dv1 = normalize(dv);  
        //計算每個像素uv的偏移值  
        float2 offset = dv1  * sinFactor * discardFactor;  
        //像素採樣時偏移offset  
        float2 uv = offset + i.uv;  
        return tex2D(_MainTex, uv);   
    }  
    ENDCG  
    SubShader   
    {  
        Pass  
        {  
            ZTest Always  
            Cull Off  
            ZWrite Off  
            Fog { Mode off }  
            CGPROGRAM  
            #pragma vertex vert_img  
            #pragma fragment frag  
            #pragma fragmentoption ARB_precision_hint_fastest   
            ENDCG  
        }  
    }  
    Fallback off  
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WaterWaveEffect : MonoBehaviour {
    //距離係數  
    public float distanceFactor = 60.0f;
    //時間係數  
    public float timeFactor = -30.0f;
    //sin函數結果係數  
    public float totalFactor = 1.0f;
    //波紋寬度  
    public float waveWidth = 0.3f;
    //波紋擴散的速度  
    public float waveSpeed = 0.3f;
    private float waveStartTime;
    private Vector4 startPos = new Vector4(0.5f, 0.5f, 0, 0);
    public Material _Material;
    void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        //計算波紋移動的距離,根據enable到目前的時間*速度求解  
        float curWaveDistance = (Time.time - waveStartTime) * waveSpeed;
        //設置一系列參數  
        _Material.SetFloat("_distanceFactor", distanceFactor);
        _Material.SetFloat("_timeFactor", timeFactor);
        _Material.SetFloat("_totalFactor", totalFactor);
        _Material.SetFloat("_waveWidth", waveWidth);
        _Material.SetFloat("_curWaveDis", curWaveDistance);
        _Material.SetVector("_startPos", startPos);
        Graphics.Blit(source, destination, _Material);
    }
    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            Vector2 mousePos = Input.mousePosition;
            //將mousePos轉化爲(0,1)區間  
            startPos = new Vector4(mousePos.x / Screen.width, mousePos.y / Screen.height, 0, 0);
            waveStartTime = Time.time;
        }
    }
}

新建一個材質球,選擇此shader,並賦值給這個腳本,點擊屏幕即可看到效果

原文鏈接

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章