FlowMap:流动效果实现

什么是Flowmap

flowmap的实质是张记录了2D向量信息的纹理,Flow map上的颜色( 通常为RG通道)记录该处向量场的方向,让模型上某一点表现出定量流动的特征。通过在shader中偏移uv再对纹理进行采样,来模拟流动效果。Flowmap的特征是周期性变化。

UV映射:UV坐标用于查找纹理的颜色值。UV贴图(用于理解) :使用(R, G)颜色通道表示坐标:黑色(0,0) ,绿色处(0,1),红色处(1,0),黄色处(1,1)。UV贴图上颜色相同处: 意味着采样纹理时使用了同一位置。

为什么使用Flowmap

类似UV动画,而非顶点动画。换言之,无需对模型顶点进行操作,易实现,运算开销小。不仅仅是水面,任何和流动相关的效果都可以采用flowmap。

Flowmap Shader

1.采样Flow map获取向量场信息
2.用向量场信息,使采样贴图时的UV随时间变化
3.对同一贴图以半个周期的相位差采集两次,并线性插值,使贴图流动连续

最简单的随时间偏移? UV - time
先来看看uv+time的情况:(u,v) + (time,0) ,模型上某个点:随着time增加,采样到的像素越远,视觉上可以形容为:更远距离的像素偏移向该点,视觉效果和我们直观认识到的运算法则是相反的。

UV值作为向量(u,v) ,自然也遵循向的运算法则。但UV偏移时,改变的不是顶点的位置。

flow map不能直接使用,要将flow map.上的色值从[0,1 ]的范围映射到方向向量的范围[-1,1]。

//从flowmap获取流向
float3 flowDir = tex2D(_FlowMap, i.uv) * 2.0 - 1.0;

随着时间的进行,UV偏移会越来越夸张,为了把偏移控制在一定范围内,需要构造两个周期相同,相位相差半个周期的波形函数。

//构造周期相同,相位相差半个周期的波形函数
float phase0 = frac( Time * 0.1 * TimeSpeed ) ;
float phasel = frac( Time * 0. 1 * TimeSpeed + 0. 5) ;

为了得到无缝循环的流动,利用相位差半个周期的两层采样进行加权混合,使纹理流动一个周期重新开始时的不自然情况被另一层采样覆盖。

//平铺贴图用的uv
float2 tiling_ _uv = i. uV * MainTex_ ST. xy +_ MainTex ST. zw;
//用波形函数周期化向量场方向,用偏移后的uv对材质进行偏移采样
half3 tex0 = tex2D( MainTex, tiling_uv - flowDir. xy * phase0) ;
half3 tex1 = tex2D( MainTex, tiling_uv - flowDir. xy * phase1) ;

//构造函数计算随波形函数变化的权值,使得MainTex采样值在接近最大偏移时有权值为0,并因此消隐,构造较平滑的循环
float flowLerp = abs((0.5 - phase0) / 0.5);
half3 fina1Color = lerp(tex0, tex1, flowLerp) ;

Shader "FX/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 { "RenderType"="Opaque"
                "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
            {
                //0~1 *2-1 得到 -1~1 方向
                fixed4 flowDir = tex2D(_FlowMap, i.uv) * 2.0 - 1.0;
                //强度修正
                flowDir *= _FlowSpeed;
                //正负修正
                #ifdef _REVERSE_FLOW_ON
                    flowDir *= -1;
                #endif

                //两个0~1循环 计时
                float phase0 = frac(_Time * 0.1 * _TimeSpeed);
                float phase1 = frac(_Time * 0.1 * _TimeSpeed + 0.5);

                float2 tiling_uv = i.uv * _MainTex_ST.xy +   _MainTex_ST.zw;

                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
        }
    }
}

Flowmap的制作

1.        Flowmap Painter

unity制作的绘制Flowmap的工具,用该工具得到的flowmap为线性空间下的颜色,不需要gamma矫正,Unity中请取消勾选 “SRGB”。

flowmap贴图设置:

1.无压缩或高质量
2.确认色彩空间

导出时注意gamma校正选项、UV匹配:用Labs UV transfer节点来匹配高模和低模的UV

2.        Houdini Labs

Houdini Labs是内置在houdini中的一组游戏开发相关的节点,可以在github中搜索sidefx Labs或着直接在houdini中安装得到。在较早版本的houdini中无法在shelf内找到该工具,你只能通过github下载。在这些未被内置到houdini的版本中, 这组工具的名称为gamedev。

参考链接:【技术美术百人计划】图形 2.8 flowmap的实现——流动效果实现

猜你喜欢

转载自blog.csdn.net/weixin_51327051/article/details/123577801