admin 管理员组

文章数量: 887006

一个鼠标点击水波纹理shader

一张图片,通过鼠标点击产生水波纹理,shader比较简单,算法主要在C#那边,多线程优化计算

用下面shader创建一个材质,创建一个面片或Cube并挂上下面C#脚本,设置图片像素,默认是256*256,赋值材质图片纹理,运行,点击鼠标即可看到效果


shader

Shader "Zon/WaveTexture" {Properties {_MainTex ("水波纹理", 2D) = "" {}}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_full v){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);o.uv = v.texcoord.xy;return o;}fixed4 frag (v2f IN) : COLOR{float2 uv = tex2D(_WaveTex, IN.uv).xy;uv = uv * 2 - 1; //把0~1转成-1~1uv *= 0.025;IN.uv += uv;fixed4 color = tex2D(_MainTex, IN.uv);return color;}ENDCG}}
}

C#脚本


using UnityEngine;
using System.Collections;
using System.Threading;public class WaveTexture : MonoBehaviour {public int waveWidth;public int waveHeight;float[,] waveA;float[,] waveB;Color[] colorBuffer;Texture2D tex_uv;bool isRun = true;int sleepTime;// Use this for initializationvoid Start () {waveA = new float[waveWidth, waveHeight];waveB = new float[waveWidth, waveHeight];colorBuffer = new Color[waveWidth * waveHeight];tex_uv = new Texture2D (waveWidth, waveHeight);GetComponent<Renderer> ().material.SetTexture ("_WaveTex", tex_uv);Thread th = new Thread (new ThreadStart(ComputeWave));th.Start ();//Putpop ();//PutDrop(64,64);}// Update is called once per framevoid Update () {sleepTime = (int)(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 = transform.worldToLocalMatrix.MultiplyPoint(hit.point);//把世界坐标转换成图片像素坐标//Debug.Log(pos);//pos = -0.5 ~ 0.5int w = (int)((pos.x + 0.5) * waveWidth);int h = (int)((pos.y + 0.5) * waveHeight);PutDrop (w, h);}}//ComputeWave ();}void Putpop(){//能量置1waveA [waveWidth / 2, waveHeight / 2] = 1;//中间点waveA [waveWidth / 2 - 1, waveHeight / 2] = 1;//左waveA [waveWidth / 2 + 1, waveHeight / 2] = 1;//右waveA [waveWidth / 2, waveHeight / 2 - 1] = 1;//下waveA [waveWidth / 2, waveHeight / 2 + 1] = 1;//上waveA [waveWidth / 2 - 1, waveHeight / 2 - 1] = 1;//左下waveA [waveWidth / 2 - 1, waveHeight / 2 + 1] = 1;//左上waveA [waveWidth / 2 + 1, waveHeight / 2 - 1] = 1;//右下waveA [waveWidth / 2 + 1, waveHeight / 2 + 1] = 1;//右上}void PutDrop(int x, int y){int radius = 20;float dist;for (int i = -radius; i <= radius; i++) {for (int j = -radius; j <= radius; j++) {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);}}}}void ComputeWave(){while (isRun) {for (int w = 1; w < waveWidth - 1; w++) {for (int h = 1; h < waveHeight - 1; h++) {//8个方向计算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;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;//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.0025f;//能量衰减计算}}//tex_uv.Apply ();float[,] temp = waveA;waveA = waveB;waveB = temp;Thread.Sleep (sleepTime);}}void OnDestroy(){isRun = false;}
}


本文标签: 一个鼠标点击水波纹理shader