1 水波特效原理

水面特效 中基于 Shader Graph 实现了模拟水面特效,包含波纹、起伏、折射、泡沫等细节,本文将基于屏幕后处理实现环形水波特效。

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

1)波形方程

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

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

2)振动方程

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

​ 其中,w2 是质点水平振动的角频率(值越大,质点振动越快)。

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

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】水波特效

【Unity3D】水波特效的更多相关文章

  1. inno 实现水波特效

    安装Inno Setup时如果选择了水波效果插件(如下图),将在Inno Setup的安装目录下自带有水波特效的例子,如路径:C:\Program Files (x86)\Inno Setup 5\E ...

  2. matlab练习程序(水波特效)

    还记得原来写过一个对图像进行波纹扭曲操作的博文. 这次实现的是水波特效,其实就是通过正余弦函数表示波纹中心位置慢慢向外扩散,通过叠加衰减因子使振幅不断减小,进而产生水波的效果. 效果如下: 原图: 波 ...

  3. 一款基于jquery实现的鼠标单击出现水波特效

    今天要为大家绍一款由jquery实现的鼠标单击出现水波特效.用鼠标猛点击页面,你可以看到页面不断出面水波纹效果.然后水波纹渐渐消失.效果非常不错.我们一起看下效果图: 在线预览   源码下载 实现的代 ...

  4. Python: PS 滤镜--水波特效

    本文用 Python 实现 PS 滤镜中的 水波特效 import numpy as np from skimage import img_as_float import matplotlib.pyp ...

  5. Unity3d粒子特效:制作火焰效果

    效果 分析 真实的火焰效果,通常包括:火.火光.火星等组成部分,而火焰对周围环境的烘焙,可以通过灯光实现,如点光源. 针对火焰组成部分,我们可以创建对应的粒子系统组件,实现相应的效果,如下图所示: 1 ...

  6. 【Unity3D】基于粒子系统实现烟花特效

    1 需求实现 ​ 粒子系统ParticleSystem 中介绍了粒子初始化.粒子发射.发射器形状.渲染器.碰撞.子发射器.拖尾等粒子系统的基本用法,本节将基于粒子系统实现烟花特效. ​ 实现需求如下( ...

  7. cocos2d-x 动画特效集合

    转自:http://www.cnblogs.com/linux-ios/archive/2013/04/09/3009292.html 备用 bool HelloWorld::init() { /// ...

  8. Android特效专辑(十一)——仿水波纹流量球进度条控制器,实现高端大气的主流特效

    Android特效专辑(十一)--仿水波纹流球进度条控制器,实现高端大气的主流特效 今天看到一个效果挺不错的,就模仿了下来,加上了一些自己想要的效果,感觉还不错的样子,所以就分享出来了,话不多说,上图 ...

  9. WebGL——水波纹特效

    大家好,今天我ccentry要做一个水波纹特效,我们来看看水波纹特效的做法.首先我们来看一下水波纹特效的效果是怎么样的,请看下图. 我们要做的就是类似这种纹理特效,那么我们来看看是如何制作的吧.首先鲫 ...

  10. cocos2dx动画常见特效(转)

    本文转载自:http://www.cnblogs.com/linux-ios/archive/2013/04/09/3009292.html bool HelloWorld::init() { // ...

随机推荐

  1. 永久激活Windows10专业版及其它版本【亲测有效2022-03-16,两种方式】

    前言 小编最近使用公司的电脑,开始出现让你激活的提示,而且每次开机都会弹出来,小编忍住了:但是过不了半个月开始给你在桌面上显示了,一直显示和水印一样.小编忍无可忍,必须找个办法给你消灭掉!!,于是小编 ...

  2. JMS微服务开发示例(九)相同的微服务,按用户所在城市来分配微服务器

    虽然,默认情况下,多个相同的微服务,网关是自动根据微服务的压力情况,把用户请求分配到压力较轻的微服务器上. 但是,在某些业务情景下,我们可能希望人为去控制微服务的请求分配. 举个例子,我在北京.上海. ...

  3. MyBatis02:CRUD操作

    CRUD操作 namespace 这个是命名空间,不可缺少,更不能写错 配置文件中namespace中的名称为对应Mapper接口或者Dao接口的全限定类名,完整包名,必须一致! Select(用于查 ...

  4. Linux-关机重启和注销

  5. [转帖]备份VCSA内置Postgresql数据库

    首先命令行远程登录到VCSA服务器,然后执行如下命令停掉VCSA的核心服务vmware-vpxd: vCenterServerAppliance:~ # service vmware-vpxd sto ...

  6. Oracle 核心列信息查看与处理

    Oracle 核心列信息查看与处理 背景 最近想对数据库表进行跨数据之间的比照 因为有一些自增列或者是时间戳的列不需要进行对比 后者是对比容易导致失真. 所以就准备选用其他方式进行一下处理. 本文主要 ...

  7. [转帖]Linux make: g++: Command not found

    https://www.cnblogs.com/kerrycode/p/4748606.html Linux使用make命令时遇到"make: g++: Command not found& ...

  8. [转帖]12.计算机网络---iptables防火墙管理工具

    文章目录 一.防火墙基础知识 1.1 防火墙是什么? 1.2 iptables基础知识 1.3 netfilter和iptables的关系: 1.4 新型防火墙工具:firewalld 二.iptab ...

  9. 【技术剖析】7. 看看毕昇 JDK 团队是如何解决 JVM 中 CMS 的 Crash

    [技术剖析]7. 看看毕昇 JDK 团队是如何解决 JVM 中 CMS 的 Crashhttps://bbs.huaweicloud.com/forum/thread-168485-1-1.html ...

  10. systemctl 关闭图形界面的办法

    开机以命令模式启动,执行: systemctl set-default multi-user.target   开机以图形界面启动,执行: systemctl set-default graphica ...