顶点动画-河流的效果

目标是让一个矩形网格面片,通过顶点动画,实现出河流的效果。(如下图)所谓的河流效果,就是呈现出波浪感,而想要呈现出波浪感,我们必须了解 波长、波动频率、波动幅度 这些关键因素

1、波浪感的关键因素

  • 波长:指两个相邻波峰或波谷之间的距离。波长越大,波动越缓慢,波形周期越长。
  • 波长的倒数:1/波长,倒数越大,表示波动越频繁,波形周期越短
  • 波动频率:指波动在单位时间内发生的次数(相当于波浪变化的频率)
  • 波动幅度:指波峰或波谷相对于中线(静止位置)的最大偏移位置

我们需要在我们的Shader代码中,声明这三个关键因素变量,用于控制顶点的偏移
从而实现流动的2D河流效果

2、基本原理

基本原理:让我们的顶点在对应的轴向产生偏移。
主要运用的就是Shader中的内置函数 sin,以及内置时间变量 _Time.y
sin 是正弦函数,正弦函数是一个周期性函数,常用与表示波动和震荡效果,它的返回值是 -1~1
_Time.y 是切换到当前场景后所经过的时间,参与到计算中,可以让我们的波浪周期性变化
再结合 波长的倒数、波动评率、波动幅度 等可变参数,参与到计算中,便可以实现效果

关键步骤一:让顶点上下动起来

我们可以利用sin函数让顶点在希望移动的轴向上产生偏移,并且为了能够周期性变化,可以让时间参与到计算中: sin( _Time.y )
该函数随着时间的变化,会不停地返回 -1~1 之间的数
为了控制波动评率,我们可以声明波动评率变量参与计算:sin( _Time.y * 波动频率)
用得到的返回值,作为顶点在某一轴向的偏移值,便可以让顶点动起来

但这样有一个问题:所有顶点偏移的会一样,会呈现出整体移动的效果

关键步骤二:让顶点有差异性的动起来

为了让顶点之间偏移位置有差异,我们可以在计算 sin 时利用每个顶点的不同点制造差异性
对于顶点来说,不同点主要来自坐标,我们可以利用他们变化某个轴的坐标制造差异性
sin( _Time.y * 波动频率 + 顶点某轴坐标)
用得到的返回值,作为顶点在某一轴向的偏移值,便可以让顶点有差异性的动起来

但是这样还是没办法体现波长和波动幅度

关键步骤三:体现波长和波动幅度

sin( _Time.y * 波动频率 + 顶点某轴坐标) 已经可以帮助我们实现波动变化了
想要体现出波长和波动幅度,我们只需要将这两个变量参与计算即可

波长的体现: sin( _Time.y * 波动频率 + 顶点某轴坐标 * 波长的倒数)
倒数越大,波形周期越短
波动幅度体现: sin( _Time.y * 波动频率 + 顶点某轴坐标 * 波长的倒数) * 波动幅度
相当于将 -1~1 范围扩大了

总结后就是:

流动的2D河流基本原理,就是利用下面这个公式,对顶点位置进行偏移计算
某轴位置偏移量 = sin( _Time.y * 波动频率 + 顶点某轴坐标 * 波长的倒数) * 波动幅度
其中具体轴向根据模型空间决定波动频率、波长倒数、波动幅度为自定义变量,可以外部调节

3、实现

在这里需要一个渲染标签:"DisableBatching" = "True"

主要作用:是否对SubShader关闭批处理
在制作顶点动画时,有时需要关闭该Shader的批处理,因为在制作顶点动画时,有时需要使用模型空间下的数据,而批处理会合并所有相关的模型,这些模型各自的模型空间会丢失,导致我们无法正确使用模型空间下相关数据。在实现流程的2D河流效果时,我们就需要让顶点在模型空间下进行偏移,因此我们需要使用该标签,为该Shader关闭批处理、

Shader "ShaderProj/8/2DWate"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        // 波动的幅度、频率、波长的倒数
        _WaveAmplitude("WaveAmplitude", Float) = 1
        _WaveFrequency("WaveFrequency", Float) = 1
        _InvWaveLength("InvWaveLength", Float) = 1

        // 纹理变化速度
        _Speed("Speed", Float) = 1
    }
    SubShader
    {
        //透明Shader相关渲染标签 + 关闭批处理标签
        Tags { "RenderType"="Tranparent" "Queue"="Transparent" "IgnoreProjector" = "True" "DisableBatching" ="True"}

        Pass
        {
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _Color;
            float _WaveAmplitude;
            float _WaveFrequency;
            float _InvWaveLength;
            float _Speed;

            v2f vert (appdata_base v)
            {
                v2f o;
                // 模型空间下的偏移位置
                float4 offset;
                // 在模型空间的 x 轴进行偏移
                offset.x = sin(_Time.y * _WaveFrequency + v.vertex.z * _InvWaveLength) * _WaveAmplitude;
                offset.yzw = float3(0, 0, 0);
                o.vertex = UnityObjectToClipPos(v.vertex + offset);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

                o.uv += float2(0, _Time.y * _Speed);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 color = tex2D(_MainTex, i.uv);
                color.rgb *= _Color.rgb;
                return color;
            }
            ENDCG
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值