Fluid Flux2.0海浪原理拆解

文摘   2024-10-08 18:30   澳大利亚  

【USparkle专栏】如果你深怀绝技,爱“搞点研究”,乐于分享也博采众长,我们期待你的加入,让智慧的火花碰撞交织,让知识的传递生生不息!

这是侑虎科技第1689篇文章,感谢作者杨超wantnon供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)

作者主页:
https://www.zhihu.com/people/wantnon


大概一年前,在油管上看到这个视频:

Fluid Flux 2.0 - Coastline [Unreal Engine 5] 

https://www.youtube.com/watch?v=zLmiqJJI5ZQ


除了效果很好,更重要的是看到简介中写着:“并非实时模拟”、“预烘焙”:

这意味着不会有太大性能开销,于是顿觉价值大大的。


但当时事情多,就只收藏了一下,没细研究。后来还看到有人移植《戴子玲:Fluid Flux 2.0 的近岸海浪》


虽然我们本来就是UE项目,移植更方便,但是想仔细看下原理。


通过删除次要内容,拆出来核心逻辑如下:


其中WorldCoastlineMap用于生成海岸线,WavePofileMap用于单个海浪动画和置换,WaveProfileDistance控制海浪离岸的距离,WaveProfileTime为动画时间。


效果:(将区域范围缩小到了100,手动拖动WaveProfileTime)

可以看到海浪的翻滚效果。


下面来分析原理,主要是搞懂:

1. WorldCoastlineMap和WavePofileMap这两个图的含义。

2. 由WorldCoastlineMap生成海岸线的原理。

3. 由WavePofileMap生成单个动画的原理。


一、WorldCoastlineMap含义


WorldCoastlineMap:

R通道明显是SDF,表示“到水的距离”,在材质中,R先被0.5减,然后连到Distance,所以Distance含义为“到岸的距离”。


再看G、B通道,在材质中,它们也是先被0.5减,然后连到Direction:


即Direction=(0.5,0.5)-(G,B),我们看它表示哪个方向,如下图:

(因为G通道看起来像从左往右打光,所以我们用左亮右暗的球代表它,因为B通道看起来像从上往下打光,所以我们用上亮下暗的球代表它)

即当我们把岛看成球时,得到的Direction呈放射状(图中是(G,B)-(0.5,0.5),箭头向外,如果是Direction=(0.5,0.5)-(G,B),则箭头向里),所以Direction表示的是“指向海岸的方向”。


至此Distance和Direction的含义都清楚了,一个是(从陆地)“到海岸的距离”,一个是(从陆地)“指向海岸的方向”。


二、海岸线UV计算


由Distance和Direction计算海岸线UV,虽然连线摆在那儿,但默认的WorldCoastlineMap较复杂,难看清所以然。于是有必要自己弄一个简单的WorldCoastlineMap,就一个如图所示左高右低的简单斜面,Distance值左大右小,Direction=(-1,0,0):

则只需将材质中的Distance和Direction输入一下:

结果:

可见,和预期是一致的。这样就有了一个更简单的例子可以观察。


为了方便做各种试验,在Houdini中复现了一下(为了代码简洁,参数随手写死的,与UE中的并不一致):


注意几点:
1. 用Colormap采样出来的贴图(我用的TGA格式)颜色要做Gamma矫正Pow 0.45。

2. UE中WaveProfileMap的Wrap模式U是设置为Wrap,V设置为Clamp:


但Houdini中Colormap的Wrap模式不能U和B分开控制:

所以只能把UV都设置成Clamp(Houdini中叫Streak),然后通过对U加Frac,人为实现U向的Tiling。也就是如下图所示,将代码从左边改成右边:

这样改是不影响最终结果的,而且由于U不再超出0到1,所以更便于可视化。

U这样改写以后,V就可以直接写成:

v=u-dis+offset;

其中offset就相当于UE里的WaveProfileDistance,用于控制浪到海岸的距离。


这样一来,公式比UE里连的更简洁了,下面就基于此来理解原理。


V可视化长这样:


以下为其演变过程:

可见:
1. 加P.y是为让条纹倾斜。

2. 加noise有两个效应:

  • 效应1:条纹产生扭曲。

  • 效应2:条纹V方向上渐变产生交错。


最右一行是将WaveProfileMap换成了如下自定义贴图(为了观察UV):


当time变化时,效果如下:


如果不加noise,则如下:


至此海岸线UV计算原理已看清楚。


三、海浪翻滚动画实现


从上面自定义贴图的视频中可以看到,如果不加noise的话,看起来就是贴图在沿着条纹平移。把自定义贴图换回WaveProfileMap,并加上Vector Disp,加noise与不加noise效果对比如下:


可见,浪前沿的不规则形状是靠noise的效应1“条纹产生扭曲”实现的,浪前沿顿锐交错是靠noise的效应2“条纹V方向上渐变产生交错”实现的。在未加noise之前,浪只感觉是在沿着条纹走,丝毫感觉不到垂直于条纹向前推的感觉,但加上noise之后,浪沿条纹走的感觉就削弱了,开始有了垂直于条纹推进的错觉。


在浪垂直于条纹向前推进的过程中,还会有翻滚效果,拉近可以看得比较清楚:

所以最后一个问题就是:浪的翻滚是靠什么实现的。


这涉及到WaveProfileMap的含义。


打开UE工程的WaveProfileMap关卡,可以看到制作WaveProfileMap的方式,是用一排样条线做出了一个卷曲的海浪形状:


这可以理解为一个完整的3D海浪,也可以理解为一套2D序列(每个切片为一帧2D剪影)。


后一种理解更符合此方法的本意。


在Houdini用一个移动立面进行截取,可以直观看到2D海浪动画的样子:

所以它就是在条纹上每个点处播放这个2D动画:
由于条纹V方向上有均匀渐变(不加noise的情况下),所以V方向上各处2D动画存在均匀的相位差,整体看上去就像一个完整3D海浪在沿着条纹平移一样。然后通过加noise使条纹扭曲,并在V方向上产生相位产生交错,从而打破平移感。


四、不规则海岸


上面通过构造最简的直线形海岸,大致看清了原理。依此原理,容易生成其它形状海岸,比如(为了方便,仍然在Houdini里验证)


(1)圆形:



(2)自定义形状:



五、不足(个人观点)


我觉得海岸线UV计算的方法很巧妙,但也有不足,最主要的不足是公式不对称,从而不同方向得到的UV品质不一致,导致某些方向上海浪的形不够好,比如:拉伸过于严重、移动速度沿条纹方向过快等。


是否可以考虑不用通过DIS和DIR简单的数学运算生成UV,而是用离线方法生成更好的UV,从而得到更好的效果,或许是一个改进方向。


文末,再次感谢杨超wantnon的分享,作者主页:https://www.zhihu.com/people/wantnon如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)。


 

Frame Capture模式-网格查看器


近期精彩回顾

【学堂上新】MMORPG全栈式网络游戏开发之旅

【学堂上新】UWA DAY 2024精选推荐(一)

【万象更新】GPM 2.0 重新定义性能监测与优化

【万象更新】UWA Gears:Frame Capture模式 - 纹理查看器


侑虎科技
UWA,专业的游戏和VR应用性能优化平台。www.uwa4d.com
 最新文章