[UI特效]程序水波纹理

        音之国度的进入界面想搞点事情,想来想去,觉得点击滑动屏幕造成界面产生一个水波的效果还是非常理想的。

        首先想想屏幕动画的原理,来自与纹理的偏移。简单的来说,屏幕任意一点的像素uv发生了偏移,导致取得颜色在逐帧更新。

        其次我们再来想想如何做出水波的动画,比如我们如果要让运动物理做一个小鱼的移动动画,我们可以让他的轨迹满足正弦函数,显然,我们要做出屏幕水波特效,我们需要让屏幕像素的uv偏移量按照某种规律逐帧发生变化。

        那么应该满足怎么的规律呢?我们想到了实际物理学中波的传递,也就是说,鼠标点击所在就是水波能量的源点,然后这个能量慢慢向四周传递,并且传递的过程中能量也逐渐递减。

       接着我们再来说说程序实现的具体思路。

       首先我们维护一个二维数组,这个数组保存着屏幕像素点当前帧的uv偏移量,初始为0。

        一旦用户鼠标产生一个点击事件,我们就投入一个圆形区域的能量源,也就是给这个区域内的像素空间uv偏移量赋上值。

       接着我们开一个用户线程,这个线程用于传递能量,也就是让二维数组中的每一个值,都等于以他为中心的正方形模板的偏移量的一个加权平均,接着再对这个值做一个衰减函数的操作。(当然这个过程中有一些数据的归一处理之类的)。

          代码如下:

      

using UnityEngine;
using System.Collections;
using System.Threading;
public class wavetexture : MonoBehaviour {
	public int wave_height;
	public int wave_width;
	public float xoffset;
	public float yoffset;
	float[,] Wave_last;
	float[,] Wave_next;
	Texture2D tex_uv;
	bool isRun=true;
	int sleeptime;
	Color[] colorbuffer;
	public Camera cam;
	void Start () 
	{
		Wave_last = new float[wave_width, wave_height];
		Wave_next = new float[wave_width, wave_height];
		tex_uv = new Texture2D (wave_width, wave_height);
		colorbuffer = new Color[wave_width * wave_height];
		GetComponent<Renderer> ().material.SetTexture ("_wavetex", tex_uv);
		Thread th = new Thread (new ThreadStart (ComputeWave));
		th.Start ();
	}

	void Update ()
	{
		sleeptime = (int)(Time.deltaTime * 1000);
		tex_uv.SetPixels (colorbuffer);
		tex_uv.Apply ();
		if(Input.GetMouseButton(0))
		{
			RaycastHit hit;
			Ray ray = cam.ScreenPointToRay (Input.mousePosition);
			if(Physics.Raycast(ray,out hit,200.0f))
			{
				if(hit.collider.transform.name=="sky")
				{
					Debug.Log ("flags");
					Vector3 hitpoint=this.transform.worldToLocalMatrix.MultiplyPoint (hit.point);
					Debug.Log (hitpoint.x+"   "+hitpoint.y);
					int xforu = (int)((hitpoint.x+xoffset) * wave_width);
					int yforv = (int)((hitpoint.y+yoffset) * wave_height);
					put (xforu, yforv);
				}
			}
		}
	}
	void put(int x,int y)
	{
		int riaus=8;
		float dist;
		for(int i=-riaus;i<=riaus;i++)
		{
			for (int j = -riaus; j <= riaus; j++)
			{
				if(x+i>=0&&x+i<=wave_width-1&&y+j>=0&&y+j<=wave_height-1)
				{
					dist = Mathf.Sqrt (i*i+j*j);
					if (dist < riaus)
					{
						Wave_last [x + i, y + j] = Mathf.Cos (dist * Mathf.PI / riaus);
					}
				}
			}
		}

	}
	void ComputeWave()
	{
		while (isRun) 
		{
			for (int w = 1; w < wave_width - 1; w++) 
			{
				for (int h = 1; h < wave_height - 1; h++) 
				{
					Wave_next [w, h] = (Wave_last [w - 1, h] + Wave_last [w + 1, h] + Wave_last [w, h - 1] + Wave_last [w, h + 1] +
					Wave_last [w - 1, h - 1] + Wave_last [w + 1, h - 1] + Wave_last [w - 1, h + 1] + Wave_last [w + 1, h + 1]) / 4 - Wave_next [w, h];
					if (Wave_next [w, h] >= 1) 
					{
						Wave_next [w, h] = 1.0f;
					}
					if (Wave_next [w, h] <= -1)
					{
						Wave_next [w, h] = -1.0f;
					}
					float offset_u = (Wave_next [w - 1, h] - Wave_next [w + 1, h]) / 2;
					float offset_v = (Wave_next [w, h - 1] - Wave_next [w, h + 1]) / 2;
					float r = offset_u / 2 + 0.5f;
					float g = offset_v / 2 + 0.5f;
					colorbuffer [w + wave_width * h]=new Color(r,g,0);
					Wave_next [w, h] -= Wave_next [w, h] * 0.001f;
				}
			}
			float[,] Wave_l;
			Wave_l = Wave_next;
			Wave_next = Wave_last;
			Wave_last = Wave_l;
			Thread.Sleep (sleeptime);
		}
	}
	void OnDestroy()
	{
		isRun = false;
	}
}

具体用于渲染的shader:

扫描二维码关注公众号,回复: 168829 查看本文章

Shader "Custom/texure_animation" {
	Properties
	 {
		_MainTex ("Main", 2D) = "white" {}
		_SecondTex ("Second", 2D) = "white" {}
		_F("F",Range(0,12))=1
	}
	SubShader {
		pass
		{		
			CGPROGRAM
			#pragma vertex ver
			#pragma fragment frag
			#pragma target 3.0
			#include "UnityCG.cginc"
			sampler2D _MainTex;
			sampler2D _SecondTex;
			sampler2D _wavetex;
			float _F;
			struct v2f
			{
				float4 pos:POSITION;
				float2 uv:TEXCOORD0;
			};
			v2f ver(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=IN.uv;
				float2 uv_wave=tex2D(_wavetex,IN.uv).xy;
				uv_wave=uv_wave*2-1;
				uv_wave*=0.03f;
				IN.uv+=uv_wave;
				fixed4 Maincoloroftex=tex2D(_MainTex,IN.uv);
				float2 offset_uv=float2(0.01*_Time.y,0);
				uv=IN.uv+offset_uv;
				fixed4 color_1=tex2D(_SecondTex,uv);
				Maincoloroftex*=color_1.b;
				Maincoloroftex*=3.5f;
				
				//Maincoloroftex.rgb+=color_1.rgb;
				/*uv=IN.uv-offset_uv;
				fixed4 color_2=tex2D(_SecondTex,uv);
				Maincoloroftex.rgb*=color_2.rgb;
				Maincoloroftex.rgb*=2;*/
				return Maincoloroftex;
			}
			ENDCG
		}
	}
	FallBack "Diffuse"
}



猜你喜欢

转载自blog.csdn.net/qq_33999892/article/details/73385619
今日推荐