unity实现透明水波纹扭曲///
Shader "Unlit/Water"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_WaterUV("WaterUV",2D)="while"{}
_WaterIntensity("WaterIntensity",float)=500
}
SubShader
{
GrabPass{
Name "BASE"
Tags { "Mode" = "Always" }
}
Tags { "Queue"="Transparent+100" "RenderType"="Transparent" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal:Normal;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 grabuv:TEXCOORD1;
float4 vertex : SV_POSITION;
float3 normal:Normal;
};
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _GrabTexture;
sampler2D _WaterUV;
float4 _GrabTexture_TexelSize;
float _WaterIntensity;
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
o.grabuv=ComputeGrabScreenPos(o.vertex);
o.normal=v.normal;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
float2 uv=tex2D(_WaterUV,i.uv).xy;
uv= (uv-0.5)*2;
float2 offset_ =uv * _GrabTexture_TexelSize.xy*_WaterIntensity;
float4 grabuv=i.grabuv;
grabuv.xy+=sin(offset_);
fixed4 grabCol=tex2Dproj(_GrabTexture,UNITY_PROJ_COORD(grabuv));
return col*grabCol;
}
ENDCG
}
}
}
using UnityEngine;
using System.Collections;
using System.Threading;
public class Water : MonoBehaviour
{
public int m_texHeight = 512;
public int m_texWidth = 512;
public Texture2D m_waterTexture = null;
private Material m_waterMatrial;
private float[,] waveA;
private float[,] waveB;
public float decrement=0.025f;
public Camera m_waterCam;
private int time;
void Start()
{
m_waterTexture = new Texture2D(m_texWidth, m_texHeight, TextureFormat.RGBA32, false);
m_waterMatrial = GetComponent<MeshRenderer>().material;
waveA = new float[m_texWidth, m_texHeight];
waveB = new float[m_texWidth, m_texHeight];
m_waterMatrial.SetTexture("_WaterUV", m_waterTexture);
allColor = new Color[m_texWidth* m_texHeight];
Thread t = new Thread(new ThreadStart(ThreadWave));
t.Start();
// m_waterMatrial.SetTexture("_MainTex", m_waterTexture);
}
public void PopWater(Vector2 pos)
{
float x=pos.x;
float y=pos.y;
waveA[(int)(m_texWidth * x) , (int)(m_texHeight * y)] = 1;
//waveA[(int)(m_texWidth * x) - 1, (int)(m_texHeight * y) ] = 1;
//waveA[(int)(m_texWidth * x) + 1, (int)(m_texHeight * y) ] = 1;
//waveA[(int)(m_texWidth * x) , (int)(m_texHeight * y) - 1] = 1;
//waveA[(int)(m_texWidth * x), (int)(m_texHeight * y) + 1] = 1;
//waveA[(int)(m_texWidth * x) - 1, (int)(m_texHeight * y) - 1] = 1;
//waveA[(int)(m_texWidth * x) - 1, (int)(m_texHeight * y) + 1] = 1;
//waveA[(int)(m_texWidth * x) + 1, (int)(m_texHeight * y) - 1] = 1;
//waveA[(int)(m_texWidth * x) + 1, (int)(m_texHeight * y) + 1] = 1;
}
public void PopWater()
{
waveA[(int)(m_texWidth / 2), (int)(m_texHeight / 2)] = 1;
waveA[(int)(m_texWidth / 2) - 1, (int)(m_texHeight / 2)] = 1;
waveA[(int)(m_texWidth / 2) + 1, (int)(m_texHeight / 2)] = 1;
waveA[(int)(m_texWidth / 2), (int)(m_texHeight / 2) - 1] = 1;
waveA[(int)(m_texWidth / 2), (int)(m_texHeight / 2) + 1] = 1;
waveA[(int)(m_texWidth / 2) - 1, (int)(m_texHeight / 2) - 1] = 1;
waveA[(int)(m_texWidth / 2) - 1, (int)(m_texHeight / 2) + 1] = 1;
waveA[(int)(m_texWidth / 2) + 1, (int)(m_texHeight / 2) - 1] = 1;
waveA[(int)(m_texWidth / 2) + 1, (int)(m_texHeight / 2) + 1] = 1;
}
void Update()
{
ComputeWave();
if (Input.GetMouseButtonDown(0))
{
RaycastHit rh;
if (Physics.Raycast(m_waterCam.ScreenPointToRay(Input.mousePosition), out rh))
{
PopWater(rh.textureCoord);
}
}
time = (int)Time.deltaTime * 1000;
}
void OnDestroy()
{
f = false;
}
bool f = true;
void ThreadWave()
{
while (f)
{
Thread.Sleep(time);
for (int w = 1; w < m_texWidth - 1; w++)
{
for (int h = 1; h < m_texHeight - 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];
float value = waveB[w, h];
if (value > 1)
{
waveB[w, h] = 1;
}
if (value < -1)
{
waveB[w, h] = -1;
}
if (value > -0.0001 && value < 0.0001)
{
waveB[w, h] = 0;
}
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;
Color c = new Color(r, g, 0);
waveB[w, h] -= waveB[w, h] * decrement;
allColor[w + m_texWidth * h] = c;
}
}
float[,] temp;
temp = waveA;
waveA = waveB;
waveB = temp;
}
}
private Color[] allColor;
void ComputeWave()
{
m_waterTexture.SetPixels(allColor);
m_waterTexture.Apply();
}
}
//Unity3D Shader实现镜子效果//
Shader "Custom/FanShe" {
Properties{
_MainTex("Albedo",2D) = "white"{}
_MainTint("Diffuse Color",Color)=(1,1,1,1)
_Cubemap("Cubemap",CUBE) = ""{}
_ReflAmount("Reflection Amount",Range(0.1,1.0))=0.5
}
SubShader{
Tags{"RenderType"="Opaque"}
LOD 200
CGPROGRAM
#pragma surface surf Lambert
#pragma target 3.0
struct Input {
float2 uv_MainTex;
float3 worldRefl;
};
sampler2D _MainTex;
samplerCUBE _Cubemap;
fixed4 _MainTint;
half _ReflAmount;
void surf(Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex)*_MainTint;
o.Albedo = c.rgb;
o.Emission = texCUBE(_Cubemap, IN.worldRefl)*_ReflAmount;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Shader_FanShe : MonoBehaviour {
public Cubemap cubeMap;
public Camera cam;
Material curmat;
// Use this for initialization
void Start () {
InvokeRepeating("change", 1, 0.1f);
curmat = gameObject.GetComponent<Renderer>().material;
if (curmat == null)
{
Debug.Log("cw");
}
}
// Update is called once per frame
void Update () {
}
void change()
{
cam.transform.rotation = Quaternion.identity;
cam.RenderToCubemap(cubeMap);
curmat.SetTexture("_Cubemap",cubeMap);
}
}
/Unity shader实现移动端模拟深度水效果///
Shader "Game_XXX/whater"
{
Properties
{
_WaterTex ("Normal Map (RGB), Foam (A)", 2D) = "white" {}
_AlphaTex("AlphaTex", 2D) = "black" {}
_shadowLight ("shadowLight",range(0,1)) = 0
_Tiling ("Wave Scale", Range(0.00025, 0.007)) = 0.25
_WaveSpeed("Wave Speed", Float) = 0.4
_SpecularRatio ("Specular Ratio", Range(10,500)) = 200
_outSideColor("outSideColor",Color) = (0,0,0,0)
_outSideLight("outSideLight",Range(0,10))=1
_inSideColor("inSideColor",Color) = (0,0,0,0)
_inSideLight("intSideLight",Range(0,10))=1
_Alpha("Alpha",Range(0,1)) = 1
//模拟灯光颜色
_LightColorSelf ("LightColorSelf",Color) = (1,1,1,1)
//模拟灯光方向
_LightDir ("LightDir",vector) = (0,1,0,0)
//高光强度
_specularLight("specularLight",range(0.1,2)) =1
}
SubShader {
Tags {
"Queue"="Transparent-200"
"RenderType"="Transparent"
"IgnoreProjector" = "True"
"LightMode" = "ForwardBase"
}
LOD 250
Pass
{
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#include "UnityCG.cginc"
float _Tiling;
float _WaveSpeed;
float _SpecularRatio;
sampler2D _WaterTex;
sampler2D _AlphaTex;
float4 _LightColorSelf;
float4 _LightDir;
float4 _outSideColor;
float _outSideLight;
float4 _inSideColor;
float _inSideLight;
float _shadowLight;
float _specularLight;
float _Alpha;
struct v2f
{
float4 position : POSITION;
float3 worldView : TEXCOORD0;
float3 tilingAndOffset:TEXCOORD2;
float3x3 tangentTransform:TEXCOORD4;
float2 alphaUV :TEXCOORD7;
};
v2f Vert(appdata_full v)
{
v2f o;
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
//视向量(世界空间)
o.worldView = -normalize(worldPos - _WorldSpaceCameraPos);
o.position = UnityObjectToClipPos(v.vertex);
//uv动画
o.tilingAndOffset.z =frac( _Time.x * _WaveSpeed);//frac :返回标量或矢量的小数
o.tilingAndOffset.xy = worldPos.xz*_Tiling;
o.alphaUV = v.texcoord;
//求世界法线三件套
float3 normal =normalize( UnityObjectToWorldNormal(v.normal));
float3 tangentDir = normalize( mul( unity_ObjectToWorld, float4( v.tangent.xyz, 0.0 ) ).xyz );//切线空间转化为世界空间
float3 bitangentDir = normalize(cross(normal, tangentDir) * v.tangent.w);//切线 法线 计算副切线
o.tangentTransform = float3x3( tangentDir, bitangentDir, normal);
return o;
}
float4 Frag(v2f i):COLOR
{
//法线采样
fixed3 BumpMap01 = UnpackNormal(tex2D(_WaterTex,i.tilingAndOffset.xy + i.tilingAndOffset.z ));
fixed3 BumpMap02 = UnpackNormal(tex2D(_WaterTex,i.tilingAndOffset.xy*1.1 - i.tilingAndOffset.z));
//两张法线相混合
//fixed3 N1 =saturate( normalize(mul( BumpMap01.rgb, i.tangentTransform )));
//fixed3 N2 =saturate( normalize(mul( BumpMap02.rgb, i.tangentTransform )));
//fixed3 worldNormal = N1 - float3(N2.x,0,N2.z);
fixed3 N1 = normalize(mul( BumpMap01.rgb, i.tangentTransform ));
fixed3 N2 = normalize(mul( BumpMap02.rgb, i.tangentTransform ));
fixed3 worldNormal = N1*0.5 +N2*0.5;
float LdotN = dot(worldNormal, _LightDir.xyz); //_LightDir为模拟灯光
//高光
float dotSpecular = dot(worldNormal, normalize( i.worldView+_LightDir.xyz));
fixed3 specularReflection = pow(saturate(dotSpecular), _SpecularRatio)*_specularLight;
//通道贴图采样
fixed4 alphaTex = tex2D (_AlphaTex,i.alphaUV);
//模拟灯光的颜色 * 漫反射系数= 基础水的颜色
fixed4 col =_LightColorSelf*2 * saturate (LdotN) ;
//用alpha贴图的r通道来模拟水的深浅的颜色,白色为深色,黑色为浅色 ,同时乘以想要的颜色
col.rgb = col.rgb * alphaTex.r *_inSideColor * _inSideLight + col.rgb * (1-alphaTex.r) * _outSideColor *_outSideLight + specularReflection;
//控制透明度,根据alpha的r通道 来控制深浅的透明度,深色的透明度小 浅色的透明度大
col.a = _Alpha * alphaTex.r;
//手动绘制阴影 用alpha贴图的g通道 跟col相乘 来模拟阴影
alphaTex.g = saturate(alphaTex.g + _shadowLight);
col.rgb *= alphaTex.g;
return col;
}
ENDCG
}
}
FallBack "Diffuse"
}
/Unity Shader模拟玻璃效果//
Shader "Glass Refraction" {
Properties {
_MainTex ("Main Tex", 2D) = "white" {}
_BumpMap ("Normal Map", 2D) = "bump" {}
_Cubemap ("Environment Cubemap", Cube) = "_Skybox" {}
_Distortion ("Distortion", Range(0, 100)) = 10
_RefractAmount ("Refract Amount", Range(0.0, 1.0)) = 1.0
}
SubShader {
// 1.队列设置成透明的可以保证渲染该物体的时候,其他所有不透明的物体都已经被渲染到屏幕上了
// 这样GrabPass保存屏幕图像的时候才能完整
// 2.渲染类型设置为不透明是为了使用着色器替换的时候,物体可以在被需要时正确的渲染
Tags { "Queue"="Transparent" "RenderType"="Opaque" }
// 抓取屏幕图像并保存到纹理 _RefractionTex 中
GrabPass { "_RefractionTex" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _BumpMap;
float4 _BumpMap_ST;
samplerCUBE _Cubemap;
float _Distortion;
fixed _RefractAmount;
sampler2D _RefractionTex;
// 可以得到系统保存的纹素的尺寸大小 1/256,1/512
// 对屏幕图像坐标采样进行偏移的时候需要使用该变量
float4 _RefractionTex_TexelSize;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float2 texcoord: TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float4 scrPos : TEXCOORD0;
float4 uv : TEXCOORD1;
float4 TtoW0 : TEXCOORD2;
float4 TtoW1 : TEXCOORD3;
float4 TtoW2 : TEXCOORD4;
};
v2f vert (a2v v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
// 得到对应被抓取的屏幕图像的采样坐标
o.scrPos = ComputeGrabScreenPos(o.pos);
// 原图和法线贴图公用同一套UV坐标,进行纹理偏移缩放设置
o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
o.uv.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);
// 世界方向
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
// 法线世界方向
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
// 切线世界方向
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
// 世界副切线方向
fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
// 定义:切线空间到世界空间的变换矩阵
// 所有的TBN都从切线空间转换到了世界空间
o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
return o;
}
fixed4 frag (v2f i) : SV_Target {
// 世界空间
float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
// 世界空间下的观察方向
fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
// 对法线贴图进行采样,并使用UnpackNormal解压*2-1,但实际上法线贴图在切线空间下
// 所以需要将bump从切线空间转换到世界空间
fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
// 对采样坐标进行偏移
float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;
i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;
// 对屏幕纹理进行采样
fixed3 refrCol = tex2D(_RefractionTex, i.scrPos.xy/i.scrPos.w).rgb;
// 将bump从切线空间转换到世界空间
// TtoW0的xyz:T的X,B的X,N的X
// 用点积得到一个常量
bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
// 用法线贴图求反射方向
fixed3 reflDir = reflect(-worldViewDir, bump);
// 主纹理采样
fixed4 texColor = tex2D(_MainTex, i.uv.xy);
// 对_Cubemap进行纹理采样,使用反射方向
fixed3 reflCol = texCUBE(_Cubemap, reflDir).rgb * texColor.rgb;
// 反射颜色+折射颜色
fixed3 finalColor = reflCol * (1 - _RefractAmount) + refrCol * _RefractAmount;
return fixed4(finalColor, 1);
}
ENDCG
}
}
FallBack "Diffuse"
}
//Unity shader实现多光源漫反射以及阴影/
Shader "Unlit/MulLight"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
//一盏主灯
Pass
{
//Always: 总是渲染;没有光照模式。
//ForwardBase: 适用于前渲染、环境、主要方向灯、光/sh光和烘焙图。
//ForwardAdd: 适用于前渲染, 叠加每一盏灯,每一盏灯就多一个pass。
//Deferred: 延迟渲染,渲染g缓冲区 。
//ShadowCaster:将物体深度渲染到阴影贴图或者深度纹理上 。
//PrepassBase: 用于传统的延迟光照,渲染法线和高光效果。
//PrepassFinal:用于传统的延迟光照,通过结合文理、灯光、和法线来渲染最终的结果。
//Vertex:当对象不是光映射时,用于遗留顶点的渲染,所有顶点灯都被利用。
//VertexLMRGBM: 当对象被光映射时,在遗留的顶点上使用渲染,在LightMap是RGBM编码的平台上(pc和控制台)。
//VertexLM: 当对象被光映射时,在遗留的顶点上使用渲染,在LightMap是双idr编码的(移动平台)平台上。
Tags { "RenderType"="Opaque" "LightMode" = "ForwardBase"}//
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#pragma target 3.0
//衰减与阴影的实现
#include "AutoLight.cginc"//
//fwdadd:ForwardBase的阴影显示,在下面的ForwardAdd里得用fwdadd; 必须结合fallback,两者缺一不可
#pragma multi_compile_fwdadd_fullshadows//
sampler2D _MainTex;
float4 _MainTex_ST;
//定义一个灯光,名字为固定格式,会自动取场景中灯光
float4 _LightColor0;//
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 normal:NORMAL;//
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos: SV_POSITION;
float3 normal :TEXCOORD1;//
//点光源需要的衰减
LIGHTING_COORDS(3,4)//#include "AutoLight.cginc"
};
v2f vert (appdata v)
{
v2f o;
//这里一般用 o.pos,用o.vertex有时候会报错
o.pos= UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.normal = v.normal;//
//点光源需要的衰减
TRANSFER_VERTEX_TO_FRAGMENT(o)//#include "AutoLight.cginc"
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//物体法向量转化为世界法向量
float3 N = normalize(UnityObjectToWorldNormal(i.normal));//
//世界光向量:unity封装好的光向量,会自动调用场景里面的存在的灯光
float3 L =normalize( _WorldSpaceLightPos0.xyz);//
//点光源需要的衰减系数
float atten = LIGHT_ATTENUATION(i);//#include "AutoLight.cginc"
fixed4 col = tex2D(_MainTex, i.uv);
//最终颜色 = 主颜色 x( 灯光颜色 x 漫反射系数 x衰减系数 + 环境光)
col.rgb = col.rgb * (_LightColor0.rgb* saturate(dot(N,L)) *atten + UNITY_LIGHTMODEL_AMBIENT);//
return col;
}
ENDCG
}
//多盏灯叠加
Pass//
{
Tags { "RenderType"="Opaque" "LightMode" = "ForwardAdd"} //ForwardAdd :多灯混合//
Blend One One//
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#pragma target 3.0
//衰减与阴影的实现
#include "AutoLight.cginc"//
//fwdadd:ForwardAdd的阴影显示,在上面的ForwardBase里得用fwdbase; 必须结合fallback,两者缺一不可
#pragma multi_compile_fwdadd_fullshadows//
sampler2D _MainTex;
float4 _MainTex_ST;
//定义一个灯光,名字为固定格式,会自动取场景中灯光
float4 _LightColor0;//
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 normal:NORMAL;//
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos: SV_POSITION;
float3 normal :TEXCOORD1;//
float4 wPos :TEXCOORD2;//
//点光源需要的衰减
LIGHTING_COORDS(3,4)//#include "AutoLight.cginc"
};
v2f vert (appdata v)
{
v2f o;
//这里一般用 o.pos,用o.vertex有时候会报错
o.pos= UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.wPos= mul(unity_ObjectToWorld, v.vertex);//
o.normal = v.normal;//
//点光源需要的衰减
TRANSFER_VERTEX_TO_FRAGMENT(o)//#include "AutoLight.cginc"
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//物体法向量转化为世界法向量
float3 N = normalize(UnityObjectToWorldNormal(i.normal));//
//世界光向量:这里计算的是点光源,按照灯光的距离来算衰减,第一个pass不需要
float3 L = normalize (lerp(_WorldSpaceLightPos0.xyz , _WorldSpaceLightPos0.xyz - i.wPos.xyz , _WorldSpaceLightPos0.w));//
//点光源需要的衰减
float atten = LIGHT_ATTENUATION(i);//#include "AutoLight.cginc"
fixed4 col = tex2D(_MainTex, i.uv);
//最终颜色 = 主颜色 x 灯光颜色 x 漫反射系数 x 衰减系数 第一个pass已经有了环境色 这里就不能加了
col.rgb = col.rgb * _LightColor0.rgb * saturate(dot(N,L))*atten;//
return col;
}
ENDCG
}
}
//需要产生阴影
FallBack "Diffuse"
}
/Unity Shader实现水波纹效果//
Shader "Custom/shuibowen"{
Properties{
_MainTex("Base (RGB)",2D)="white"{}
_distanceFactor("Distancefactor",float)=1
_timeFactor("time factor",float)=2
_totalFactor("total factor",float)=3
_waveWidth("wave width",float)=4
_curWaveDis("curwave dis",float)=5
_startPos("star pos",Vector) = (1,1,1,1)
_MainTex_TexelSize("Maintex_texelSize",vector)=(1,1,1,1)
}
CGINCLUDE
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
float4 _MainTex_TexelSize;
uniform float _distanceFactor;
uniform float _timeFactor;
uniform float _totalFactor;
uniform float _waveWidth;
uniform float _curWaveDis;
uniform float4 _startPos;
fixed4 frag(v2f_img i) : SV_Target
{
//DX下纹理坐标反向问题
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
_startPos.y = 1 - _startPos.y;
#endif
//计算uv到中间点的向量(向外扩,反过来就是向里缩)
float2 dv = _startPos.xy - i.uv;
//按照屏幕长宽比进行缩放
dv = dv * float2(_ScreenParams.x / _ScreenParams.y, 1);
//计算像素点距中点的距离
float dis = sqrt(dv.x * dv.x + dv.y * dv.y);
//用sin函数计算出波形的偏移值factor
//dis在这里都是小于1的,所以我们需要乘以一个比较大的数,比如60,这样就有多个波峰波谷
//sin函数是(-1,1)的值域,我们希望偏移值很小,所以这里我们缩小100倍,据说乘法比较快,so...
float sinFactor = sin(dis * _distanceFactor + _Time.y * _timeFactor) * _totalFactor * 0.01;
//距离当前波纹运动点的距离,如果小于waveWidth才予以保留,否则已经出了波纹范围,factor通过clamp设置为0
float discardFactor = clamp(_waveWidth - abs(_curWaveDis - dis), 0, 1) / _waveWidth;
//归一化
float2 dv1 = normalize(dv);
//计算每个像素uv的偏移值
float2 offset = dv1 * sinFactor * discardFactor;
//像素采样时偏移offset
float2 uv = offset + i.uv;
return tex2D(_MainTex, uv);
}
ENDCG
SubShader
{
Pass
{
ZTest Always
Cull Off
ZWrite Off
Fog { Mode off }
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
ENDCG
}
}
Fallback off
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WaterWaveEffect : PostEffectsBase {
//距离系数
public float distanceFactor = 60.0f;
//时间系数
public float timeFactor = -30.0f;
//sin函数结果系数
public float totalFactor = 1.0f;
//波纹宽度
public float waveWidth = 0.3f;
//波纹扩散的速度
public float waveSpeed = 0.3f;
private float waveStartTime;
private Vector4 startPos = new Vector4(0.5f, 0.5f, 0, 0);
public Material _Material;
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
//计算波纹移动的距离,根据enable到目前的时间*速度求解
float curWaveDistance = (Time.time - waveStartTime) * waveSpeed;
//设置一系列参数
_Material.SetFloat("_distanceFactor", distanceFactor);
_Material.SetFloat("_timeFactor", timeFactor);
_Material.SetFloat("_totalFactor", totalFactor);
_Material.SetFloat("_waveWidth", waveWidth);
_Material.SetFloat("_curWaveDis", curWaveDistance);
_Material.SetVector("_startPos", startPos);
Graphics.Blit(source, destination, _Material);
}
void Update()
{
if (Input.GetMouseButton(0))
{
Vector2 mousePos = Input.mousePosition;
//将mousePos转化为(0,1)区间
startPos = new Vector4(mousePos.x / Screen.width, mousePos.y / Screen.height, 0, 0);
waveStartTime = Time.time;
}
}
}
///