效果:
Quad和Cube 波纹起始点为啥不一样了,返回都是[-0.5,0.5],坐标中心为模型中心。
原因:估计模型网格数据的UV起始点是不一样的
优化方案说明:由1-3逐渐增加,1和2配套使用
优化方案1:开启单独线程,进行uv水波纹理计算
源代码:
Shader "Sbin/WaveAnimShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_WaveTex ("Texture",2D) = "white"{}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _WaveTex;
struct v2f{
float4 pos:POSITION;
float2 uv:TEXCOORD0;
};
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord.xy;
return o;
}
fixed4 frag (v2f v) : COLOR
{
float2 uv = tex2D(_WaveTex, v.uv);
uv = uv*2-1;//[-1,1]
uv *=0.25;
v.uv +=uv;
fixed4 col = tex2D(_MainTex, v.uv);
return col;
}
ENDCG
}
}
}
using UnityEngine;
using System.Collections;
using System.Threading;
public class WaveAnim : MonoBehaviour
{
public int waveWidth = 128;
public int waveHeight = 128;
float[,] waveA;
float[,] waveB;
bool isRun = true;
float sleepTime;
Color[] colorBuffer;
Texture2D tex_uv;
void Start()
{
waveA = new float[waveWidth, waveHeight];
waveB = new float[waveWidth, waveHeight];
tex_uv = new Texture2D(waveWidth, waveHeight);
colorBuffer = new Color[waveWidth * waveHeight];
GetComponent<Renderer>().material.SetTexture("_WaveTex", tex_uv);
Thread th = new Thread(new ThreadStart(ComputeWave));
th.Start();
}
void Update()
{
sleepTime = Time.deltaTime * 1000;
tex_uv.SetPixels(colorBuffer);
tex_uv.Apply();
if (Input.GetMouseButton(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
Vector3 pos = hit.point;
//获取点击模型的本地坐标
pos = transform.worldToLocalMatrix.MultiplyPoint(pos);
//将本地坐标转成UV坐标
int w = (int)((pos.x + 0.5) * waveWidth);
int h = (int)((pos.y + 0.5) * waveHeight);
PutPop(w, h);
}
}
//ComputeWave();
}
//放置起波点
private void PutPop(int x, int y)
{
int radius = 20;
float dist;
for (int i = -radius; i < radius; i++)
{
for (int j = -radius; j < radius; j++)
{
//控制在uv纹理范围内
if ((x + i >= 0) && (x + i < waveWidth - 1) && (y + j >= 0) && (y + j < waveHeight - 1))
{
dist = Mathf.Sqrt(i * i + j * j);
if (dist < radius)
{
waveA[x + i, y + j] = Mathf.Cos(dist * Mathf.PI / radius);
}
}
}
}
}
/// <summary>
/// 波纹的UV计算
/// </summary>
private void ComputeWave()
{
while (isRun)
{
for (int w = 1; w < waveWidth - 1; w++)
{
for (int h = 1; h < waveHeight - 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];
waveB[w, h] = waveB[w, h] > 1 ? 1 : waveB[w, h];
waveB[w, h] = waveB[w, h] < -1 ? -1 : waveB[w, h];
//控制范围[-1,1]
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_v / 2 + 0.5f;
float g = offset_u / 2 + 0.5f;
//tex_uv.SetPixel(w, h, new Color(r, g, 0));
colorBuffer[w + waveWidth * h] = new Color(r, g, 0);
//进行波纹能量衰减
waveB[w, h] -= waveB[w, h] * 0.025f;
}
}
//tex_uv.Apply();
float[,] temp = waveA;
waveA = waveB;
waveB = temp;
Thread.Sleep((int)sleepTime);
}
}
void OnDestory()
{
isRun = false;
}
}
优化方案2:关闭垂直同步
打开:Edit->Project Setting->Quality,然后选择V Sysnc Count 为Don't Sync
优化方案3:compute Shader 利用GUP才进行计算,GUP计算特点:并行处理效果高
compute Shader 不了解