一、Flowmap 是什么
半条命2中水的流动
求生之路2中的水的流动
这种方式原理简单,容易实现,运算量少,如今也还在使用
1.flowmap的实质
Flow map(流向图) ,一张记录了2D向量信息的纹理,Flow map上的颜色(通常为RG通道)记录该处向量场的方向,让模型上某一点表现出定量流动的特征。
通过在shader中偏移uv再对纹理进行采样,来模拟流动效果。
右边向量场的方向于中间Flowmap和它的方向是不一致的,这是为什么呢?
2.前置了解:UV映射
UV坐标用于查找纹理的颜色值:
UV贴图(用于理解):使用(R,G)颜色通道表示坐标:
黑色(0,0),绿色处(0,1),红色处(1,0),黄色处(1,1)
如果我们要对一个矩形进行纹理查找的话,我们首先会用到它的UV坐标
左边为unity中的UV坐标 与我们熟知的xy坐标轴相似
用该UV坐标去查找右边这张贴图的颜色值,我们将会得到和原贴图一摸一样的结果
如果让更改UV坐标,让每一列都拥有相同的UV值再去采样,则会得到右图这样的条纹图结果
若使整个采样的时候用的UV值是同一个的话,如图我们将该UV坐标的UV值全都变为黑色,那么结果就会对左下角进行采样
UV贴图上颜色相同的地方就意味着它在采样纹理的时候使用了同一个位置
Flowmap则是通过它上面所带有的向量场的信息对UV进行一个偏移之后,去干扰我们采样纹理时候的过程,如上图
注意在UE4中,UV坐标是不同的,与unity相比是将绿通道反转了。所以使用的Flowmap也会发生变化,要根据引擎进行调整
偏转后的UV坐标去采样右图后得到下面扭曲贴图
2.为什么要使用flowmap?
原因:
类似UV动画,而非顶点动画。换言之,无需对模型顶点进行操作,易实现,运算开销小。
不仅仅是水面,任何和流动相关的效果都可以采用flowmap。
flowmap不仅仅被用于制作一些侵蚀效果或表面的流动效果,还被用于制作流动的天空球中
二、Flowmap shader
1. 借助Shader Graph与desmos理解flowmap
- 采样Flow map获取向量场信息
- 用向量场信息,使采样贴图时的UV随时间变化
- 对同一贴图以半个周期的相位差采集两次,并线性插值,使贴图流动连续
2. 在shader中实现flowmap
- 目标:移。根据flowmap上的值,使纹理随时间偏
- 最简单的随时间偏移:UV - time
- 为什么是相减:
- 先来看看 uv+time 的情况
- (u,v) + (time,0) :模型上某个点: 随着time增加,采样到的像素越远,
- 视觉上可以形容为:更远距离的像素偏移向该点,视觉效果和我们直观认识到的运算法则是相反的。
-
UV值作为向量(u,v),自然也遵循向量的运算法则。但UV偏移时,改变的不是顶点的位置。
-
单方向运动X
由flow map获取流动方向√
-
flow map不能直接使用
将flow map上的色值从[0,1]的范围映射到方向向量的范围[-1,1]即乘2减1
从flowmap获取需要的流动方向,再乘Time就可以让某个点去根据flowmap进行流动
调整采样时的UV为: adjust_uv = uv - flowDir * time
在这里我们用FlowSpeed来控制向量场的强度
但随着时间的增加,扭曲程度会越来越大,所以需要一个Fraction函数把时间变成[0,1]的循环 把它变成一个三角波函数
为了解决这一问题,我们需要构造两层采样相差半个周期的采样,再对他们进行插值混合
随着时间进行,变形越来越夸张,为了把偏移控制在一定范围内:
解决frac产生的跳变,把上面改成:
我们希望的流动:无缝循环
用相位差半个周期的两层采样进行加权混合,使纹理流动一个周期重新开始时的不自然情况被另一层采样覆盖
用flowmap修改法线贴图