1. 程式人生 > >Shader水漣漪效果

Shader水漣漪效果

using UnityEngine;
using System.Collections;
using System;
using UnityEngine.UI;


public class WaterRipper : MonoBehaviour
{
    public Texture2D ww;
    public Material xxx;
    public Color32[] ALLColor;
    public float[] buf1;
    public float[] buf2;
    public Color32 CC;
    public float DowenPower;//波能衰減力度
    public int Width_Tex;
    public int Hight_Tex;
    public float Times;
    //TODO
    //137行被註釋程式碼
    //public Text textpois;//這個用來檢測畫素值
    //62行被註釋程式碼
    //public RawImage P;//這個用來簡版的描繪波紋


    // Use this for initialization
    void Start()
    {


        Width_Tex = Screen.width / 10;
        Hight_Tex = Screen.height / 10;


        ww = new Texture2D(Width_Tex, Hight_Tex, TextureFormat.ARGB32, false);


        xxx.SetTexture("_BumpMap", ww);


        ALLColor = new Color32[Width_Tex * Hight_Tex];


        buf1 = new float[Width_Tex * Hight_Tex];//儲存上一幀的波幅
        buf2 = new float[Width_Tex * Hight_Tex];//這一幀的波幅


        Debug.Log(ALLColor.Length);
    }


    // Update is called once per frame
    void Update()
    {
        if (Times < 0.01f)
        {
            Times += Time.deltaTime;
        }
        else {
            RippleSpread();
            BufToColor();
            Change();
            Times = 0;
        }


        OnClickWater();
        //if (Input.GetMouseButton(0))
        //{
        //}
        //if (Input.touchCount > 0) {
        //    OnClickWater();
        //}
        //P.texture = ww;
    }
    //*******************************************************//計算波能資料緩衝區//*******************************************************
    public void RippleSpread()
    {
        float X1;
        float X2;
        float X3;
        float X4;


        for (int i = 0; i < buf1.Length; i++)
        {        //波能擴散 


            //水波邊界反彈
            if ((i % Width_Tex - 1) >= 0)
            {
                X1 = buf1[i - 1];
            }
            else {
                X1 = buf1[i + 1];
            }
            if ((i % Width_Tex + 1) < Width_Tex)
            {
                X2 = buf1[i + 1];
            }
            else {
                X2 = buf1[i - 1];
            }
            if ((i - Width_Tex) >= 0)
            {
                X3 = buf1[i - Width_Tex];
            }
            else {
                X3 = buf1[i + Width_Tex];
            }
            if ((i + Width_Tex) < buf1.Length)
            {
                X4 = buf1[i + Width_Tex];
            }
            else {
                X4 = buf1[i - Width_Tex];
            }


            //波能擴散
            buf2[i] = (X1 + X2 + X3 + X4) / 2f - buf1[i];
            //波能衰減
            buf2[i] -= buf2[i] / 32f;
            if (buf2[i] < 1)
            {
                buf2[i] = 0;
            }
        }
        buf1 = buf2;
    }


    /// <summary>
    /// 將波幅度轉換成圖片顏色
    /// </summary>
    public void BufToColor()
    {
        for (int i = 0; i < buf1.Length; i++)
        {
            ALLColor[i].g = (byte)(buf1[i] - 128f);
            ALLColor[i].a = (byte)(buf1[i] - 128f);
            //ALLColor[i].r = (byte)(buf1[i] + 128f);
            //ALLColor[i].b = (byte)(buf1[i] + 128f);


        }
    }
    //*****************************************************//增加波源//*****************************************************
    public void OnClickWater()
    {
        Vector3 V3 = Input.mousePosition;
        //Vector3 V3 = Input.GetTouch(0).position;
            DropStone(((int)V3.x), (int)V3.y, 100, 255);
        //textpois.text = V3.ToString();
    }
    public void DropStone(int x, int y, int stoneSize, int stoneweight)
    {   //根據傳入的座標,在對應的波幅中新增波


        int X1 = x / 10;
        int y1 = y / 10;
        //為了不報越界錯誤錯,在這裡加入限制條件,這些數的計算結果沒有超過陣列的大小
        if (Width_Tex * y1 + X1 < buf2.Length)
        {
            for (int posx = X1 - stoneSize; posx < X1 + stoneSize; ++posx)
            {
                for (int posy = y1 - stoneSize; posy < y1 + stoneSize; ++posy)
                {
                    if ((posx - X1) * (posx - X1) + (posy - y1) * (posy - y1) < stoneSize * stoneSize)
                    {
                        buf2[Width_Tex * y1 + X1] = stoneweight;
                    }
                }
            }
        }
    }
    public void Change()
    {
        ww.SetPixels32(ALLColor);
        ww.Apply();
    }
}