FlowMap简单应用
1.让纹理动起来
我们应用一张水的纹理在面片上,假设这是水流,但水流应该是会动的,我们可以手动修改matetial的offset来让纹理“流动”。
要想在playmode中让纹理自动“流动”,我们可以加入时间变量来扰动UV:
1 float4 frag (v2f i) : SV_Target 2 { 3 //获取unity内置时间变量 4 float offset=_Time.x; 5 //控制x y两个方向的移动 6 float4 finalCol=tex2D(_MainTex,i.uv+float2(offset,offset)*_FlowSpeed); 7 8 return finalCol; 9 }
这样“河流”就自己“流动”起来了。
但是这样横平竖直地流动有点单调了,这时候我们引用flowmap来丰富效果。
flowmap如下所示:
乍眼一看我们无法理解flowmap到底是什么,有什么作用。实际上flowmap是用纹理的RG两个通道的记录该处向量场的方向,让纹理上某一点出现定向流动的效果。简单理解,flowmap给上面水纹理指出:你接下来要“流动”的方向。我们将flowmap采样的结果放到原uv上进行扰动便有了向不同方向流动的结果。
我们还缺少点东西。如果我们在DCC工具上做了一张flowmap是0~255,到了shader里面计算会normalized成0~1,实际上我们向量表示范围应该是-1到1之间,因此我们需要把flowmap采样结果从0~1映射到-1~1:
1 float4 frag (v2f i) : SV_Target 2 { 3 4 //获取unity内置时间变量 5 float offset = _Time.x; 6 float2 flowmap = tex2D(_FlowpMap,i.uv).xy; 7 flowmap=flowmap * 2 - 1 ; 8 //控制x y两个方向的移动 9 float4 finalCol = tex2D(_MainTex,i.uv + flowmap * _FlowSpeed * float2(0,offset); 10 11 return finalCol; 12 }
如此一来就有了还不错的效果。
2.advanced in flowmap
我们会发现flowmap一开始的几秒效果不错,然而随着时间推移效果逐渐变得离谱,我们希望只要开头几秒的效果。
我们使用了时间变量来让其流动,时间是不断增长的,可以简单看是是f(x)=x这样一个函数:
ps:我们通过desmos这个网站帮我们可视化一下,但是desmos中数学公式与unity shaderlab中写法有所不同,不过表达的意思是一样的。
当我们在shader中使用frac函数后会返回数值的小数部分,这样就能不断重复0~0.99:
这样我们就能只放出flowmap开头的效果。
但是这样每次0.99突然跳回0太突兀了,这个过渡能否柔和一点不被玩家察觉呢?我们可以构造一个锯齿波,让其值在区间内来回波动:
其实跟sin cos很像。
实际上当我们看久了依然会感觉比较单调,毕竟是遵循周期规律变化,因此我们可以构造两个一样的函数周期频率一样,但是周期会错开
这种技术源自valve在GDC 2010上的分享,当时被应用在了求生之路2和传送门2中。
思路是这样的:我们构造两个这样的周期函数A和B,A与B的周期频率一样,但是他们一开始的位置,或者说值是不同的,比如大家从0秒开始,一个值为1,一个为0,通过lerp函数进行线性插值来进行平滑过渡。
为了更好理解,我们称之为“层”,即本质上我们希望有两层一样的效果,错开周期,并把效果lerp到一起。