一个鼠标点击水波纹理shader
2017-01-06 22:40
99 查看
一张图片,通过鼠标点击产生水波纹理,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~1
uv *= 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 initialization
void 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 frame
void 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.5
int w = (int)((pos.x + 0.5) * waveWidth);
int h = (int)((pos.y + 0.5) * waveHeight);
PutDrop (w, h);
}
}
//ComputeWave ();
}
void Putpop()
{
//能量置1
waveA [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创建一个材质,创建一个面片或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~1
uv *= 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 initialization
void 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 frame
void 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.5
int w = (int)((pos.x + 0.5) * waveWidth);
int h = (int)((pos.y + 0.5) * waveHeight);
PutDrop (w, h);
}
}
//ComputeWave ();
}
void Putpop()
{
//能量置1
waveA [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;
}
}
相关文章推荐
- 点击button按钮后,启动一个实现鼠标拖动另一个button的线程 (JFrame/C# WinForm)
- eclipse在新版本GTK(2.18) 上的一个bug--鼠标点击按钮无响应的解决办法
- jQuery 二级菜单,一次显示一个小类 鼠标点击显示小类
- 不用鼠标点击就可以触发一个函数的单击事件
- 每天一个JavaScript实例-点击图片显示大图添加鼠标操作
- 用户控件包含一个搜索功能,但是在调用页面中按回车时无法直接提交这个表单,只有鼠标点击才提交,如何解决?
- js 鼠标点击一个按钮显示div的浮动框,点击页面其他任何地方后,隐藏浮动框
- [原]界面上有几个球队名字的列表,将鼠标放到球队名字上就变为红色背景,其他球队背景颜色为白色,点击一个球队的时候就将点击的球队变为fontSize=30字体(fontSize=‘’回到默认)。
- appearance格式化表单元素的边框,在chrome和FF下鼠标点击时会多出一个蓝色边框
- 用iTween实现一个鼠标点击一个地方平面中间出现一个向上抛然后下落的球
- eclipse在新版本GTK(2.18) 上的一个bug--鼠标点击按钮无响应的解决办法
- Aspx中为flash生成一个鼠标点击事件
- 还是一个鼠标点击td变成input,失去焦点更新数据库
- 界面上有几个球队名字的列表,将鼠标放到球队名字上就变为红色背景,其他球队背景颜色为白色,点击一个球队的时候就将点击的球队变为fontSize=30字体(fontSize=‘’回到默认)。
- 使用鼠标左键点击绘制一个矩形 右键清屏 源代码
- 去掉鼠标点击一个链接时在其四周出现的虚线框
- 还是一个鼠标点击td变成input,失去焦点更新数据库
- C# winform datagridview中如何实现鼠标右键点击一行数据出现一个带有删除的菜单,并能执行删除操作?
- 一个仿dota,点击鼠标让人物行走的简易demo
- 计划:写一个统计鼠标点击次数,滑动距离,键盘按键次数的软件