【Siggraph 2010】Water Flow in Por
今天要介绍的是Valve在Siggraph 2010上分享的关于如何使用flow map来控制水体的流动效果的技术,这也是首次用Flow map来控制水体的流动,原文链接在文末给出。
内容主要分为四部分:
![](https://img.haomeiwen.com/i19200103/d8615e0c59d705c1.png)
先来看一下效果图:
![](https://img.haomeiwen.com/i19200103/29d7ff26a5ced38c.png)
![](https://img.haomeiwen.com/i19200103/4769c59b2863fa3b.png)
![](https://img.haomeiwen.com/i19200103/a0056602e236de6f.png)
使用Flow map主要想达成如下三方面的目标:
- 视觉上:
- 解决水纹重复的问题
- 实现水流绕着障碍物流动的效果
- 能够灵活控制水流的速度与bump strength(水纹扰动强度)
- 技术上:
- 能够兼容现有的反射方案
- 能够适配一些低端设备
- 玩法层面
- 破除水体中方向感不明确的困惑,为玩家的探索指引方向
![](https://img.haomeiwen.com/i19200103/200f8e31b3a09a81.png)
![](https://img.haomeiwen.com/i19200103/08a71a049a78510b.png)
在挑选方案的时候,还需要考虑当前的性能压力已经到达极致的困境:
![](https://img.haomeiwen.com/i19200103/175d417e82d1960f.png)
先来看下算法的总体流程:
- 整体的实现逻辑是在PS中完成的,而非在geometric层面或顶点层面
- 继续使用法线贴图来实现水面的涟漪效果
- flow map(每个像素中存储一个对应于地图上某个点的水流方向信息的2D贴图)的制作完全由美术同学负责
- 在PS中会对flow map进行采样,并基于采样的结果来对法线贴图中的数据进行扰动
![](https://img.haomeiwen.com/i19200103/0404869e31e96ef8.png)
一张Flow map覆盖全图:
![](https://img.haomeiwen.com/i19200103/17f326194a470dc5.png)
而法线贴图则是通过tile的方式来覆盖:
![](https://img.haomeiwen.com/i19200103/8e494390b4c49bbd.png)
Flow map是一张覆盖全图的低分辨率贴图(每米4texel),因为中间存储的不是非常直观的数据,因此这里采用houdini来辅助生成:
![](https://img.haomeiwen.com/i19200103/ed1613708a876f31.png)
下面给出了houdini的工作流的大概介绍,仅供参考
![](https://img.haomeiwen.com/i19200103/5178d8e9b90614fe.png)
![](https://img.haomeiwen.com/i19200103/9dd923e9be48e844.png)
![](https://img.haomeiwen.com/i19200103/569b153b7c3e56f7.png)
![](https://img.haomeiwen.com/i19200103/cc9340c9ff708670.png)
看起来,有了flow map之后,法线贴图的样式也得相应调整
![](https://img.haomeiwen.com/i19200103/78f046c1da8cec5b.png)
![](https://img.haomeiwen.com/i19200103/259443154742acd2.png)
很早就有人提出了类似的思路,不过当时是用uv动画来实现流动效果,这里则是将这个思路用在对法线贴图的调制上面
![](https://img.haomeiwen.com/i19200103/1145935e35237ec8.png)
这里尝试将流动逻辑应用在一张噪声贴图上来看看是否能如期看到流动效果:
- 输入:一张flow field贴图跟一张噪声贴图
- 目的是通过对噪声贴图进行扰动以模拟流动效果
- 基本思路是基于flow field的数据来对噪声贴图的采样UV进行偏移,偏移量需要乘以时间t
![](https://img.haomeiwen.com/i19200103/2025dc84f74189b3.png)
输入贴图如下图所示:
![](https://img.haomeiwen.com/i19200103/852ccce0cb87ff2d.png)
按照上面的思路,得到的结果如下图所示,从结果上看貌似并不能很好的满足需要
![](https://img.haomeiwen.com/i19200103/e61e68c272cc1512.png)
经过观察有如下发现:
- 起始位置的扰动效果看起来是符合需要的
- 扰动量幅度稍微优点小
- 扰动效果在前1/3的uv空间中是可用的
![](https://img.haomeiwen.com/i19200103/a06aa5caf7813dc2.png)
基于上述观察,决定用两层扰动来优化表现,这两层的相位存在0.5的差异,并基于如下的混合权重来掩盖后面部分效果较差的问题。
![](https://img.haomeiwen.com/i19200103/2e804d858ad45994.png)
通过上述处理之后,如下图所示,可以得到相对比较正常的流动效果了
![](https://img.haomeiwen.com/i19200103/29dc6e1d85354722.png)
在单张噪声贴图上实验成功,接下来想要将这个方案应用到一个更大的,具有tiling处理逻辑的表面上
![](https://img.haomeiwen.com/i19200103/b5156fe5502a6285.png)
在这个地图上实验之后发现了一些问题
![](https://img.haomeiwen.com/i19200103/640bf1a95921910a.png)
![](https://img.haomeiwen.com/i19200103/5acb06a371913580.png)
Flow map的可视化效果
![](https://img.haomeiwen.com/i19200103/4d27567916e6991d.png)
单层法线扰动后的效果,其实可以看到比较明显的tiling
![](https://img.haomeiwen.com/i19200103/82f6e4cdbd37fff2.png)
双层法线混合扰动,仔细看也能看到重复的纹样(我没看出来。。。)
![](https://img.haomeiwen.com/i19200103/a0234e6abb903f61.png)
总结一下有如下两个问题:
- 纹样重复
- 水面会出现一种重复的pulse(跳动?)效果
![](https://img.haomeiwen.com/i19200103/445a8ffb3f42bd54.png)
为了更具象的指出问题,这里在法线贴图中心加一个红点,可以更明显的观察到重复问题
![](https://img.haomeiwen.com/i19200103/c460b18a9467886a.png)
双层混合的
![](https://img.haomeiwen.com/i19200103/45ebf62e401ed7f8.png)
带(半相?)偏移的双层混合的,可以看到,重复效果就好多了
![](https://img.haomeiwen.com/i19200103/2921fe459a5f83b2.png)
去除红点后的表现
![](https://img.haomeiwen.com/i19200103/a2206f141d672a56.png)
Pulse问题则可以通过噪声贴图来消除,比如叠加一个低分辨率的噪声数据,就可以很好的覆盖住原有的pulse问题(这里不是很直观)
![](https://img.haomeiwen.com/i19200103/c5c69e9dd5ff0856.png)
这里是修复后的效果
![](https://img.haomeiwen.com/i19200103/42a612fb7084b7f0.png)
此外,为了更好的模拟真实水流的效果,这里还用流速来对切线空间中的法线的强度进行了缩放,下图展示了不同流速下的法线扰动效果
![](https://img.haomeiwen.com/i19200103/c8ba42fc72436e96.png)
跟此前的实现方案相比,在性能上,增加了:
- 两个贴图采样:flow + noise
- 21个PS指令
![](https://img.haomeiwen.com/i19200103/4d0030891eea8b16.png)
前面介绍了对法线的扰动,接下来再来看下Portal 2的需求,那就是水面上会有一些浮沫(debris),这里是通过颜色贴图来展现的,因此只通过对法线贴图进行扰动就不够了,还需要支持color map的扰动
![](https://img.haomeiwen.com/i19200103/885004ecd9879e4d.png)
实例图如下
![](https://img.haomeiwen.com/i19200103/10daa72a6e8f574c.png)
flow map大概是这样
![](https://img.haomeiwen.com/i19200103/9fdb95ccef7daeb6.png)
法线扰动结果则按照前面的做法,是这个样子的
![](https://img.haomeiwen.com/i19200103/553b7c2a005d4d50.png)
如果用同样的方法对color map扰动,就会得到如下的效果(好像没看出来有啥问题。。。)
![](https://img.haomeiwen.com/i19200103/8e0cee4cfd083ef3.png)
如下图所示,按照前面法线贴图的扰动算法来看,我们可以得到扰动的幅度跟随时间轴的变化,基于这个我们可以知道,扰动的峰值会以0.5个相位为周期重复出现,即在0.5,1.5,2.5等位置到达峰值
![](https://img.haomeiwen.com/i19200103/90f1e2e48cca012e.png)
而针对基色的扰动,则最好是对这个区间做一个偏移,使得峰值从1.5变成了0.5。
怎么偏移?看图示,峰值出现的位置没有变化,主要是峰值发生了变化,从1.5变成了0.5,原因则是Layer1的扰动原来是从01的,现在则变成了从-0.50.5,基于这个来看的话,可以对扰动的公式做一个调整,从[0, 2*fraction],变成[-fraction, fraction]
![](https://img.haomeiwen.com/i19200103/dae1dcac167f0a30.png)
![](https://img.haomeiwen.com/i19200103/26612eb12bfb2a09.png)
下面是最终的效果,看起来是没有之前的明显扭曲了,但是貌似也不是很能看得出来流动的痕迹(?)
![](https://img.haomeiwen.com/i19200103/90045036d84dd6a4.png)
![](https://img.haomeiwen.com/i19200103/154983c93caaa41e.png)
![](https://img.haomeiwen.com/i19200103/7a911bfc53e739b3.png)
后续工作:略
![](https://img.haomeiwen.com/i19200103/bf341ae98aeddd7a.png)
最后对工作做一个总结:
- 美术同学编辑输出flow map
- 通过两层混合扰动来输出令人满意的法线扰动效果
- 通过噪声贴图来屏蔽pulse问题
- 两层法线的扰动相位使用不同的offset来减少重复
- 对color map来说,需要调整扰动的算法以减低扰动的峰值,从而实现更为真实的流动效果
![](https://img.haomeiwen.com/i19200103/a090ecec9dd351a5.png)