UnityShader 用Plane实现简单旗帜飘扬效果

旗帜飘动效果

UnityShader 用Plane实现简单旗帜飘扬效果_第1张图片     UnityShader 用Plane实现简单旗帜飘扬效果_第2张图片

                                                               ===》                                  

实现原理

利用正弦曲线实现平滑的起伏效果:(顶点动画) 
1. 运行时,时间是稳步增加的数值,如果给时间节点加上顶点的位置信息,同一时间不同位置的顶点数据就有了差异性,将时间加上位置偏移量作为sin操作的数据输入,就得到了一串与顶点位置相关的具有差异的正弦运算结果值; 
2. 将(1)中得到的数据作为顶点坐标 Y 方向上的增量,旗帜就具有了平滑起伏波动的飘动效果 
3. 要固定旗帜的一端,就要让一侧的波动值置0,在向另一端方向上波动程度不断增大,我们直接给offset值乘以uv的u值即可(uv坐标是从(0,0)到(1,1)不断增大的二维数组,那么u值就是从0到1稳步增大的一维数组)

UnityShader 用Plane实现简单旗帜飘扬效果_第3张图片

在正弦型函数y=Asin(ωx+φ)+b中:

周期T=2π/ω
波长λ=vT
,其中v是波速。波长是一个周期内波前进的距离,而这段周期内波都是匀速直线前进的,所以直接使用匀速直线运动的位移公式即可。
波长当然不等于周期,波长的单位是m(米),周期的单位是s(秒),单位不同的物理量不能相等。
A表示幅值,表示y=Asin(ωx+φ)偏离x轴距离
b表示原图像y=Asin(ωx+φ)在y轴上移动的距离
ω表示函数在y轴方向的压缩程度,大于为1时,表示被压缩,小于1时表示拉伸
φ表示初相,表示y=Asin(ωx)在x轴方向的移动距离
A为振幅,求法(Ymax-Ymin)/2,(图像中最高点所对的Y轴数,以及最低点所对的Y轴数),意义:A大于1时,纵坐标伸长到原来的A倍,0

ω=2π/ T,求法:先求周期T,(图像中最高点所对的X轴数到最低点所对的X轴数为半个周期)。意义:ω>1图像上个点横坐标缩短为原来的1/ω倍。0<ω<1伸长为原来的1/ω倍。

φ为初相,求法:一般作为未知数,无固定求法。意义:大于0向左,小于0向右移动。

b求法,(Ymax+Ymin)/2,意义:大于0上移,小于0下移。

Unity Shader实现旗帜飘动的代码:

Shader "Demo_Flag/Flag"  // 旗帜飘动
{
    Properties
    {
        _MainTex ("Main Tex", 2D) = "white" {}               	      //主纹理
        _FlagColor("Flag Color", Color) = (1, 1, 1, 1)        	      //旗子颜色
        _Frequency("Frequency", float) = 1                   	      //波动频率
        _AmplitudeStrength("Amplitude Strength", float) = 1           // 振幅强度
        _InvWaveLength("Inverse Wave Length", float) = 1             //波长的倒数(_InvWaveLength越小,波长越大)
        _Fold("Fold", Range(0.0, 2.0)) = 0.5                         //旗帜褶皱程度
    }
    SubShader
    {
        // Need to disable batching because of the vertex animation
        Tags {"DisableBatching" = "True" "RenderType"="Opaque"}

        Pass
        {
       		Tags{"LightMode" = "ForwardBase"}
       
  		    Cull Off

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

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _FlagColor;
            float _Frequency;
            float _AmplitudeStrength;
            float _InvWaveLength;
            float _Fold;

            struct a2v
            {
                float4 vertex : POSITION;
                float4 texcoord : TEXCOORD0;
            };

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

            v2f vert (a2v v)
            {
                v2f o;
                o.uv = v.texcoord.xy;
                float4 offset;
                // 初始化顶点偏移量
				offset.xyzw = float4(0.0, 0.0, 0.0, 0.0);
				// 计算偏移之前的顶点位置
				float4 v_before = mul(_Object2World, v.vertex);
			  // 我们只希望对顶点的 Y 方向进行偏移(正弦型函数y=Asin(ωx+φ)+b)
			   offset.y = _AmplitudeStrength * sin(_Frequency * _Time.y +  (v_before.x + v_before.y* _Fold) * _InvWaveLength) * o.uv.x;

			   //我们只需要把偏移量添加到顶点位置上,再进行正常的顶点变换即可
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex + offset);

				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
            	fixed4 col = tex2D(_MainTex, i.uv);
                col.rgb *= _FlagColor.rgb;
                return col;
            }
            ENDCG
        }
    }
    FallBack "VertexLit"
}
UnityShader 用Plane实现简单旗帜飘扬效果_第4张图片

Tip:

作为sin输入数据的是时间加偏移值,这个偏移值这里选取的是模型空间的顶点坐标信息,此外还可以是uv信息等等,只要是连续的有差异的数据都可以。

源工程下载:UnityShader 用Plane实现旗帜飘扬效果








你可能感兴趣的:(Unity,Shader应用,Unity,Shader,实际应用)