什么是Flow Map?
Flow Map的实质是一张记录了2D向量信息的纹理。Flow map上的颜色(通常为RG通道)记录该处向量场的方向,让模型上某一点表现出定量流动的特征。通过在shader中偏移uv再对纹理进行采样,来模拟流动效果。
在UE4相对与unity中uv坐标翻转了绿通道,所以制作flowmap的时候需要注意
Unity中的FlowMap
UE4中的FlowMap
为什么要使用FlowMap?
类似UV动画,而非顶点动画,无需对模型顶点进行操作,易实现,运算开销小。和流动有关的都可以使用flowmap
如何使用FlowMap
首先flowmap不能直接使用,因为flowmap上的色值映射到方向向量的范围是[-1,1],所以要经过一个重新映射
//*2-1 得到 -1~1 方向
fixed4 flowDir = tex2D(_FlowMap, i.uv) * 2.0 - 1.0;
得到流动方向后,用时间作为参数,根据时间增加进行流动,这时候需要Fraction函数把时间变成0-1的一个循环,它会变成一个三角波函数
但是这样做的话产生的效果是从0到最大扭曲,再从最大扭曲跳变回0,会有断层的效果
这时候需要需要构造两层采样相差半个周期的采样,再对他们进行一个差值混合
float phase0 = frac(_Time * 0.5 * _TimeSpeed);
float phase1 = frac(_Time * 0.5 * _TimeSpeed + 0.5);
实现代码shader部分:
Shader "Unlit/FlowMap"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_Color("Tint", Color) = (1,1,1,1)
_FlowMap("FlowMap", 2D) = "white" {}
_FlowSpeed("intensity", float) = 0.1
_TimeSpeed("speed", float) = 1
[Toggle]_reverse_flow("reverse", Int) = 0
}
SubShader
{
Tags {
"IgnoreProjector" = "True"
"RenderType" = "Opaque"
}
Cull Off
Lighting Off
ZWrite On
//LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature _REVERSE_FLOW_ON
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
fixed4 _Color;
sampler2D _MainTex;
sampler2D _FlowMap;
float4 _MainTex_ST;
float _FlowSpeed;
float _TimeSpeed;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
//UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//先根据uv采样flowmap上的方向向量,进行一个映射
//再将向量乘以流动速度
fixed4 flowDir = tex2D(_FlowMap, i.uv) * 2.0 - 1.0;
flowDir *= _FlowSpeed;
//若勾选则反向流动
#ifdef _REVERSE_FLOW_ON
flowDir *= -1;
#endif
//周期相同,相位相差半个周期的波形函数
float phase0 = frac(_Time * 0.5 * _TimeSpeed);
float phase1 = frac(_Time * 0.5 * _TimeSpeed + 0.5);
//float2 tiling_uv = i.uv * _MainTex_ST.xy + _MainTex_ST.zw;
float2 tiling_uv = TRANSFORM_TEX(i.uv, _MainTex);
//再用flowDir.xy与波形函数进行相乘,对tiling_uv坐标偏移,再对MainTex进行纹理采样
half3 tex0 = tex2D(_MainTex, tiling_uv + flowDir.xy * phase0);
half3 tex1 = tex2D(_MainTex, tiling_uv + flowDir.xy * phase1);
//此操作为了使两层采样有一个平滑过渡
float flowLerp = abs((0.5 - phase0) / 0.5);
half3 finalColor = lerp(tex0, tex1, flowLerp);
return float4(finalColor, 1.0) * _Color;
}
ENDCG
}
}
}
其中使用到了FlowMapPainter
使用FlowMapPainter导入图片时会出现翻转现象,可以在PS中进行翻转再导入
导入flowmap进u3d时注意不要勾选sRGB,同时将压缩改为none
最后效果: