用shader做水波纹效果

1.效果展示:
用shader做水波纹效果
2.代码:
shader代码:

Shader "Unlit/Water"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
	_WaterUV("WaterUV",2D) = "while"{}
	_WaterIntensity("WaterIntensity",float) = 500
	}
		SubShader
	{

		GrabPass{
		Name "BASE"
		Tags{ "Mode" = "Always" }
	}

		Tags{ "Queue" = "Transparent+100" "RenderType" = "Transparent" }


		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

		struct appdata
	{
		float4 vertex : POSITION;
		float2 uv : TEXCOORD0;
		float3 normal:Normal;
	};

	struct v2f
	{
		float2 uv : TEXCOORD0;
		float4 grabuv:TEXCOORD1;
		float4 vertex : SV_POSITION;
		float3 normal:Normal;
	};

	sampler2D _MainTex;
	float4 _MainTex_ST;
	sampler2D _GrabTexture;
	sampler2D _WaterUV;
	float4 _GrabTexture_TexelSize;
	float _WaterIntensity;

	v2f vert(appdata v)
	{
		v2f o;
		o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
		o.uv = TRANSFORM_TEX(v.uv, _MainTex);

		UNITY_TRANSFER_FOG(o,o.vertex);
		o.grabuv = ComputeGrabScreenPos(o.vertex);

		o.normal = v.normal;


		return o;
	}

	fixed4 frag(v2f i) : SV_Target
	{
		fixed4 col = tex2D(_MainTex, i.uv);
	float2 uv = tex2D(_WaterUV,i.uv).xy;

	uv = (uv - 0.5) * 2;

	float2 offset_ = uv * _GrabTexture_TexelSize.xy*_WaterIntensity;

	float4 grabuv = i.grabuv;
	grabuv.xy += sin(offset_);

	fixed4 grabCol = tex2Dproj(_GrabTexture,UNITY_PROJ_COORD(grabuv));


	return col*grabCol;
	}
		ENDCG
	}
	}
}

c#代码:


    using UnityEngine;
using System.Collections;
using System.Threading;

public class Water : MonoBehaviour
{


    public int m_texHeight = 512;

    public int m_texWidth = 512;

    public Texture2D m_waterTexture = null;

    private Material m_waterMatrial;

    private float[,] waveA;
    private float[,] waveB;

    public float decrement = 0.025f;

    public Camera m_waterCam;

    private int time;
    void Start()
    {

        m_waterTexture = new Texture2D(m_texWidth, m_texHeight, TextureFormat.RGBA32, false);

        m_waterMatrial = GetComponent<MeshRenderer>().material;
        Debug.Log("m_waterMatrial==" + m_waterMatrial);
        waveA = new float[m_texWidth, m_texHeight];
        waveB = new float[m_texWidth, m_texHeight];

        m_waterMatrial.SetTexture("_WaterUV", m_waterTexture);

        allColor = new Color[m_texWidth * m_texHeight];

        Thread t = new Thread(new ThreadStart(ThreadWave));
        t.Start();

        //  m_waterMatrial.SetTexture("_MainTex", m_waterTexture);
    }

    public void PopWater(Vector2 pos)
    {
        float x = pos.x;
        float y = pos.y;
        waveA[(int)(m_texWidth * x), (int)(m_texHeight * y)] = 1;
        //waveA[(int)(m_texWidth * x) - 1, (int)(m_texHeight * y) ] = 1;
        //waveA[(int)(m_texWidth * x) + 1, (int)(m_texHeight * y) ] = 1;
        //waveA[(int)(m_texWidth * x) , (int)(m_texHeight * y) - 1] = 1;
        //waveA[(int)(m_texWidth * x), (int)(m_texHeight * y) + 1] = 1;
        //waveA[(int)(m_texWidth * x) - 1, (int)(m_texHeight * y)  - 1] = 1;
        //waveA[(int)(m_texWidth * x) - 1, (int)(m_texHeight * y) + 1] = 1;
        //waveA[(int)(m_texWidth * x)  + 1, (int)(m_texHeight * y) - 1] = 1;
        //waveA[(int)(m_texWidth * x)  + 1, (int)(m_texHeight * y)  + 1] = 1;
    }
    public void PopWater()
    {
        waveA[(int)(m_texWidth / 2), (int)(m_texHeight / 2)] = 1;
        waveA[(int)(m_texWidth / 2) - 1, (int)(m_texHeight / 2)] = 1;
        waveA[(int)(m_texWidth / 2) + 1, (int)(m_texHeight / 2)] = 1;
        waveA[(int)(m_texWidth / 2), (int)(m_texHeight / 2) - 1] = 1;
        waveA[(int)(m_texWidth / 2), (int)(m_texHeight / 2) + 1] = 1;
        waveA[(int)(m_texWidth / 2) - 1, (int)(m_texHeight / 2) - 1] = 1;
        waveA[(int)(m_texWidth / 2) - 1, (int)(m_texHeight / 2) + 1] = 1;
        waveA[(int)(m_texWidth / 2) + 1, (int)(m_texHeight / 2) - 1] = 1;
        waveA[(int)(m_texWidth / 2) + 1, (int)(m_texHeight / 2) + 1] = 1;
    }


    void Update()
    {
        ComputeWave();


        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit rh;
            if (Physics.Raycast(m_waterCam.ScreenPointToRay(Input.mousePosition), out rh))
            {
                Debug.Log("我点击了!!!!");

                //PopWater(rh.textureCoord);
                PopWater();
            }

        }

        time = (int)Time.deltaTime * 1000;

    }

    void OnDestroy()
    {
        f = false;

    }

    bool f = true;
    void ThreadWave()
    {
        while (f)
        {
            Thread.Sleep(time);
            for (int w = 1; w < m_texWidth - 1; w++)
            {

                for (int h = 1; h < m_texHeight - 1; h++)
                {
                    waveB[w, h] =
                       (waveA[w - 1, h] +
                        waveA[w + 1, h] +
                        waveA[w, h - 1] +
                        waveA[w, h + 1] +
                        waveA[w - 1, h - 1] +
                        waveA[w + 1, h - 1] +
                        waveA[w - 1, h + 1] +
                        waveA[w + 1, h + 1]) / 4 - waveB[w, h];


                    float value = waveB[w, h];
                    if (value > 1)
                    {
                        waveB[w, h] = 1;
                    }

                    if (value < -1)
                    {
                        waveB[w, h] = -1;
                    }


                    if (value > -0.0001 && value < 0.0001)
                    {
                        waveB[w, h] = 0;
                    }


                    float offset_u = (waveB[w - 1, h] - waveB[w + 1, h]) / 2;

                    float offset_v = ((waveB[w, h - 1]) - waveB[w, h + 1]) / 2;


                    float r = offset_u / 2 + 0.5f;
                    float g = offset_v / 2 + 0.5f;
                    Color c = new Color(r, g, 0);


                    waveB[w, h] -= waveB[w, h] * decrement;
                    allColor[w + m_texWidth * h] = c;


                }
            }

            float[,] temp;
            temp = waveA;
            waveA = waveB;
            waveB = temp;
        }

    }

    private Color[] allColor;

    void ComputeWave()
    {
        m_waterTexture.SetPixels(allColor);
        m_waterTexture.Apply();



    }

}


3.步骤:
(1)、首先创建一个unity工程,创建一个物体cube,创建两个脚本,一个名为water的c#脚本,一个名为water的shader脚本,把上面的代码分别复制到相应的脚本里。
(2)、把相机改为正交,把C#脚本挂载到cube上
用shader做水波纹效果
water Texture里面拖一张图片,Water Cam里拖上主相机,
(3)、选中shader脚本创建材质,然后,把这个材质也拖拽到cube上,
用shader做水波纹效果
(4)、在材质上添加一个图片。
用shader做水波纹效果
运行,用鼠标不停的点击cube这样就会水波纹的效果了。
哈哈,是不是很简单呢!喜欢博主的加关注哦!你们的阅读,和关注,是我最大的动力呢!
好了,今天小仙女,我就分享到这里咯,明天见。

生命不止,学习不知!

相关文章: