Unity-Shader——用UV动画模拟模型在水下的场景

时间:2022-06-12 04:30:12

先放一个效果图
Unity-Shader——用UV动画模拟模型在水下的场景

参数为:

Unity-Shader——用UV动画模拟模型在水下的场景

Shader代码:

Shader "Custom/UnderWater" {
    Properties {
        _MainTex ("基础贴图 (RGB)", 2D) = "white" {}
        _FlushTex ("水波贴图 (RGB)", 2D) = "white" {}
        _FlowColor("水波颜色", Color) = (1,1,1,1)
        _FlowSpeed("扫光速度", Range(0,1)) = 0.01
        _TexSpeedX("UV流动速度X", Range(-1,1)) = 0.01
        _TexSpeedY("UV流动速度Y", Range(-1,1)) = 0.01
        _FlushLight("水波亮度", Range(0,10)) = 2
    }

    SubShader {


        Pass
        {

        Tags {   "Queue" = "Geometry" }

        CGPROGRAM

        #include "UnityCG.cginc"
        #pragma vertex vert
        #pragma fragment frag


        struct v2f
        {
            float4 vertex:POSITION;
            float2 uv:TEXCOORD0;
            float nr:TEXCOORD1;
        };

        sampler2D _MainTex;
        sampler2D _FlushTex;
        float4 _FlowColor;
        float _FlowRange;
        float _FlowSpeed;
        float _TexSpeedX;
        float _TexSpeedY;
        float _FlushLight;
        v2f vert(appdata_base  v)
        {

            v2f o;
            o.uv = v.texcoord;
            o.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
            float3 dir = normalize(float3(cos(_Time.x * _FlowSpeed),sin(_Time.y * _FlowSpeed),sin(_Time.z * _FlowSpeed)));
            o.nr = dot(dir,v.normal); 
            return o;
        }

        fixed4 frag (v2f IN):COLOR
        {
            fixed fac = saturate(IN.nr * IN.nr );
            fixed2 offset = float2(_Time.x * _TexSpeedX , _Time.x * _TexSpeedY);
            half4 fluc = tex2D(_FlushTex,IN.uv  + offset)  * _FlowColor * _FlushLight ;
            half4 c= fac*tex2D(_MainTex, IN.uv) * (1 - fac)*fluc;
            return c;
        }
        ENDCG
        }


    }
    FallBack "Diffuse"
}

在这个Shader中,主要是使用一张水波贴图来和模型原本贴图颜色进行叠加,来模拟模型在水下的颜色。

再读取水波贴图时,进行UV动画偏移,模拟水波在身上流动的效果。

最后,最重要的是水波流动时会在模型身上产生随机的阴影。该阴影需要随机、连续,并且有一定的周期性。

我们用三角函数生成了一个周期向量,为了体现差异性,每个向量使用的 _Time 尺度不同。
其中:
_Time.x = 1/20 t
_Time.y = t
_Time.z = 2t
_Time.w = 3t
然后我们用这个周期向量与模型空间下的法线的点乘,得到的结果用来当做水波阴影的系数。

   float3 dir = normalize(float3(cos(_Time.x * _FlowSpeed),sin(_Time.y * _FlowSpeed),sin(_Time.z * _FlowSpeed)));
   o.nr = dot(dir,v.normal);   

为了增加差异性,这个系数在偏远着色器取了平方值。

fixed fac = saturate(IN.nr * IN.nr );

接下来取水波颜色

fixed2 offset = float2(_Time.x * _TexSpeedX , _Time.x * _TexSpeedY);
half4 fluc = tex2D(_FlushTex,IN.uv  + offset)  * _FlowColor * _FlushLight ;

这里使用了简单的UV动画,体现水波在模型身上的流动性。

关于UV动画,这里有介绍。

最后将模型原色和水波颜色进行叠加。

half4 c= fac*tex2D(_MainTex, IN.uv) * (1 - fac)*fluc;