找回密码
 立即注册
查看: 226|回复: 0

【Unity3D】水波特效

[复制链接]
发表于 2023-3-14 10:06 | 显示全部楼层 |阅读模式
1 水波特效原理


水波特效属于 Unity3D 后处理特效,其原理是:对渲染后的纹理进行局部挤压和拉升变换,即对局部 uv 坐标进行周期性的偏移运动,实现波纹效果。

1)波形方程

为简化水波模型,我们假设水波以机械波(正弦或余弦)传播,并且 0 时刻的水面波形函数为:

其中,r 是质点距离水波中心的半径长度,w1 是波形角频率(值越大,波纹越密),A 是质点水平振动的振幅,offset 是质点的水平偏移量。

本文代码资源见:Unity3D水波特效。

2)振动方程

t 时刻,半径为 r 的质点水平偏移量为:

其中,w2 是质点水平振动的角频率(值越大,质点振动越快)。
2 代码实现


WaterWaveEffect.cs
using UnityEngine;   [RequireComponent(typeof(Camera))]  // 屏幕后处理特效一般都需要绑定在像机上 public class WaterWaveEffect : MonoBehaviour {     public float A = 0.01f; // 水面质点水平波动振幅     public float w1 = 60; // 水波截面波形角频率(值越大, 波纹越密)     public float w2 = 30; // 水面质点水平波动角频率(值越大, 水波质点振动越快)     public float waveWidth = 0.3f; // 水波宽度(水波在扩散时, 后波会消失)     public float waveSpeed = 0.3f; // 水波传播的速度     private float waveTime; // 水波传播时间     private Vector4 waveCenter; // 水波中心     private Material waveMaterial; // 水波材质     private bool enabledWave = false; // 水波开关       private void Awake() {         waveMaterial = new Material(Shader.Find("Custom/WaterWave"));         waveMaterial.hideFlags = HideFlags.DontSave;     }      private void Update() {         if (Input.GetMouseButton(0)) {             waveCenter = new Vector2(Input.mousePosition.x / Screen.width, Input.mousePosition.y / Screen.height); // 屏幕坐标归一化             enabledWave = true;             waveTime = 0;         }     }      void OnRenderImage (RenderTexture source, RenderTexture destination) {         if (enabledWave) {             SetWaveMaterialParams();             Graphics.Blit (source, destination, waveMaterial);             waveTime += Time.deltaTime;             if (waveTime > 2 / waveSpeed) { // 水波传播到屏幕外面, 结束水波特效                 enabledWave = false;             }         } else {             Graphics.Blit (source, destination);         }     }      private void SetWaveMaterialParams() { // 设置水波材质参数         waveMaterial.SetFloat("_A", A); // 水面质点水平波动振幅         waveMaterial.SetFloat("_w1", w1); // 水波截面波形角频率(值越大, 波纹越密)         waveMaterial.SetFloat("_w2", w2); // 水面质点水平波动角频率(值越大, 水波质点振动越快)         waveMaterial.SetFloat("_t", waveTime); // 水波传播时间         waveMaterial.SetVector("_o", waveCenter); // 水波中心         waveMaterial.SetFloat("_waveDist", waveTime * waveSpeed); // 水波传播距离         waveMaterial.SetFloat("_waveWidth", waveWidth); // 水波宽度(水波在传播时, 后波会消失)     } }
说明:WaterWaveEffect 脚本组件需要挂在相机下。

WaveShader.shader
Shader "Custom/WaterWave"  {     Properties      {         _MainTex ("mainTex", 2D) = "white" {}     }       SubShader      {         Pass         {             ZTest Always             Cull Off             ZWrite Off             Fog { Mode off }               CGPROGRAM              #pragma vertex vert_img // UnityCG.cginc中定义了vert_img方法, 对vertex和texcoord进行了处理, 输出v2f_img中的pos和uv             #pragma fragment frag             #pragma fragmentoption ARB_precision_hint_fastest              #include "UnityCG.cginc"              sampler2D _MainTex;             float _A; // 水面质点水平波动振幅             float _w1; // 水波截面波形角频率(值越大, 波纹越密)             float _w2; // 水面质点水平波动角频率(值越大, 水波质点振动越快)             float _t; // 水波传播时间             float2 _o; // 水波中心坐标             float _waveDist; // 水波传播距离             float _waveWidth; // 水波宽度(水波在传播时, 后波会消失)              fixed4 frag(v2f_img i) : SV_Target // 水波uv坐标的计算不能在顶点着色器中进行, 因为屏后处理的顶点只有屏幕的4个角顶点             {                 float2 vec = i.uv - _o.xy;                 vec.x *= _ScreenParams.x / _ScreenParams.y; // 按照屏幕长宽比进行缩放                 float radius = length(vec); // 距离波中心的半径长度                 float leng = abs(radius - _waveDist);                 float offset = 0;                 if (leng < _waveWidth)                 {                     offset = _A * sin(_w1 * radius - _w2 * _t) * (1 - leng / _waveWidth);                 }                 return tex2D(_MainTex, i.uv + offset * 0.707); // offset是一维的, uv是二维的, 需要除以根号2, 即乘以0.707             }              ENDCG         }     }      Fallback off } 3 运行效果


点击屏幕任意位置,出现水波如下,注意观察地面和天空交界的直线,可以明显看到正弦波形。

4 推荐阅读

    渲染管线 固定管线着色器一 固定管线着色器二 表面着色器 顶点和片元着色器 选中物体描边特效 基于模板测试和顶点膨胀的描边方法 半球卷屏特效 卷轴特效 激光灯、碰撞特效

声明:本文转自【Unity3D】水波特效

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-6-3 04:11 , Processed in 0.104172 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表