Unity Shader实现水波纹效果
CSharp代码
using System.Threading;
using UnityEngine;
public class WaveTexture : MonoBehaviour
{
public Vector2Int SiezVe2;
float[,] WaveA;
float[,] WaveB;
Texture2D texture2;
bool isRun = true;
private int dateTime;
private Color[] colors;
private bool isHavePlayer;
void Start()
{
WaveA = new float[SiezVe2.x, SiezVe2.y];
WaveB = new float[SiezVe2.x, SiezVe2.y];
texture2 = new Texture2D(SiezVe2.x, SiezVe2.y);
colors = new Color[SiezVe2.x* SiezVe2.y];
GetComponent<MeshRenderer>().material.SetTexture("_WaveTex", texture2);
Thread th = new Thread(new ThreadStart(CompleteWave));
th.Start();
}
void Update()
{
if (!isHavePlayer) return;
dateTime = (int)(Time.deltaTime * 1000);
texture2.SetPixels(colors);
texture2.Apply();
}
void Pop(int x, int y)
{
int r = 5;
float dist;
for (int i = -r; i < r; i++)
{
for (int j = -r; j < r; j++)
{
if ((x + i >= 0 && (x + i < SiezVe2.x - 1)) && ((y + j >= 0) && (SiezVe2.y - 1 > y + j)))
{
dist = Mathf.Sqrt(i * i + j * j);
if (dist < r)
{
WaveA[x + i, y + j] = Mathf.Cos(dist * Mathf.PI / r);
}
}
}
}
}
void CompleteWave()
{
while (isRun)
{
for (int i = 1; i < SiezVe2.x - 1; i++)
{
for (int j = 1; j < SiezVe2.y - 1; j++)
{
WaveB[i, j] = (WaveA[i, j + 1] + WaveA[i, j - 1] + WaveA[i + 1, j] + WaveA[i - 1, j] + WaveA[i + 1, j + 1] + WaveA[i + 1, j - 1] + WaveA[i - 1, j + 1] + WaveA[i - 1, j - 1]) / 4 - WaveB[i, j];
float value = WaveB[i, j];
if (value > 1)
{
WaveB[i, j] = 1;
}
if (value < -1)
{
WaveB[i, j] = -1;
}
float offset_U = (WaveB[i - 1, j] - WaveB[i + 1, j]) / 2;
float offset_V = (WaveB[i, j - 1] - WaveB[i, j + 1]) / 2;
float r = offset_U * 0.5f + 0.5f;
float g = offset_V * 0.5f + 0.5f;
colors[i + j*SiezVe2.y] = new Color(r,g,0);
WaveB[i, j] -= WaveB[i, j] * 0.025f;
}
}
float[,] tmp = WaveA;
WaveA = WaveB;
WaveB = tmp;
Thread.Sleep(dateTime);
}
}
private void OnDestroy()
{
isRun = false;
}
private void OnTriggerEnter(Collider other)
{
isHavePlayer = true;
}
private void OnTriggerStay(Collider other)
{
Vector3 v = transform.InverseTransformPoint(other.transform.position);
int w = (int)(((v.x / -5) * 0.5 + 0.5f) * SiezVe2.x);
int h = (int)(((v.z / -5) * 0.5 + 0.5f) * SiezVe2.y);
Pop(w, h);
}
private void OnTriggerExit(Collider other)
{
isHavePlayer = false;
}
}
Shader 代码
Shader "Texture/v2f_9_10"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
uniform sampler2D _WaveTex;
v2f vert (appdata_base v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
fixed4 frag (v2f i) : COLOR
{
float2 uv = tex2D(_WaveTex, i.uv);
uv = uv * 2 -1;
uv *= 0.025;
i.uv += uv;
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}