FlowMap采样原理
对FlowMap的原理进行解释,并在Unity Shader中做简单实现
0.前言
FlowMap的关键并不在于使用两个相隔半个周期的采样。FlowMap可以使用任意多次且不低于一次的采样,其关键在于如何构造这些采样结果的权重,使得每个采样在跳变时权重为0。
其实一次采样也行,保证新旧周期切换时uv连续即可。
1.原理
想要让图形在视觉上发生运动,不外乎两种情况:改变顶点位置和改变顶点颜色。让模型(普通mesh或蒙皮mesh)发生运动就属于前者,而神奇的FlowMap就属于后者。

假设现在需要制作一个水面在球体表面循环流动的效果,上图中就是两种典型的实现方式。左边是通过旋转模型实现,右边是通过改变模型UV实现。
FlowMap在时间尺度上通过更改顶点的UV坐标,让顶点上的发生变化,就仿佛上一个帧中颜色相同的顶点移动到当前顶点一样。如果在一片区域内实现这种效果,就可以看到某块区域发生移动的视觉效果,这就是FlowMap的魔法。
2.具体实现
想要在视觉上实现自然运动,那最应该避免的就是防止顶点瞬移,在FlowMap中就是要防止顶点颜色突然跳变,即【顶点颜色需要在时间尺度上连续】
如果让整个贴图的uv在同一方向上移动,只需要保证BaseMap四方连续就好(如上方gif右侧的球体所示)。但是如果只是让贴图某个区域周期性流动呢?
不妨将BaseMap的采样抽象为函数
应用FlowMap的过程抽象为:
但是一般情况下认为顶点是从附近移动过来的而不是无穷远处,因此不会让时间t过大而采样到很远的点。故上式改写为
故使用FlowMap后的顶点颜色为
很明显 是一个周期函数,这是从 这个操作引入进来的。因此顶点色在新旧周期切换时很容易发生突变,除非恰好在切换时uv是连续的(但这通常很难做到,因为BaseMap上有很多像素,而FlowMap上记录的流动方向一般并不是整体一致的)。
因此可以进行多次错开周期的采样,让每次采样颜色的权重在接近周期切换时权重渐变到0,最后将这些采样颜色加权求和作为最终输出颜色。因为每个采样颜色在发生跳变时权重为0,所以并不会导致最终颜色发生跳变。
3.详细证明
这里使用指代时间,指代顶点色,指代采样uv
另外表示采样频率,采样周期为
假设使用两次FlowMap采样,第二次采样比第一次提前个周期,故有:
进一步假设BaseMap的采样函数为:,故有:
和关于时间的变化如下图所示,很明显两者关于时间是不连续的

但是可以通过两者混合加权来实现最终颜色在时间上是连续的,只需要保证和的权重和在新旧周期更换时值为0
本文构造的权重函数为:
关于时间的变化如下图所示

最终颜色在时间上是连续的。【虽然目前一阶不连续,但是可以通过构造更加巧妙的权重函数来实现一阶连续】

4.Unity中实现FlowMap
使用ASE编写了FlowMap采样的Shader,实现一个简陋的流动效果


