-
今天我们使用shader来实现一个这样的动画
先说下思路,如下图宽是X轴,高是Z轴。我们以X轴作为sin() 函数的参数,随着X的变大,即可出现曲线。
然后Z再加上这个值,这样就能在Z上看出曲线。 即 z = z + sin(x);
接着我们再在sin()里加上time的变化,既可出现动画。
准备工作,创建一个普通Plane面片,然后创建一个Unilt Shader,在新创建出来的shader上直接右键,创建一个材质球(材质球会自动使用这个Shader),接着把材质球丢给这个Plane。这样准备工作就完成了。
接下来增加下参数
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Speed("Speed",float) = 1 //控制速度
_XScale("XScale",float) = 1 // 控制波的宽度
_Amplitude("_Amplitude",float) = 1 //控制幅度
}
- 修改顶点函数
v2f vert (appdata v)
{
v2f o;
//核心代码
v.vertex.z = v.vertex.z + _Amplitude * sin(v.vertex.x * _XScale + _Time.y * _Speed);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
- 这样就大功告成了
可以看到核心代码和思路是一样的,只是加了几个参数增加调控度。
这里_Speed主要控制动画速度。 _Amplitude 主要控制动画的幅度。 XScale控制一个波的宽度。 - 最后贴下全部代码
Shader "Unlit/VertexAnim"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Speed("Speed",float) = 1 //控制速度
_XScale("XScale",float) = 1 //控制波的宽度
_Amplitude("_Amplitude",float) = 1 //控制幅度
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _XScale;
float _Speed;
float _Amplitude;
v2f vert (appdata v)
{
v2f o;
v.vertex.z = v.vertex.z + _Amplitude * sin(v.vertex.x * _XScale + _Time.y * _Speed);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
-
注意点
如果你的XScale按默认的1.那么你可能会得到像下图这样不太平滑的波
这是因为Plane的顶点相聚得比较远。并不是连续的,所以就会出现不平滑。可以切换到Wireframe视角,如下图,可以看到顶点离得还是蛮远的。
这时候XScale参数就发挥作用了,把XScale调小到0.5。那么相当于顶点就离得更密集了,也就越平滑了! - OK,就这样了!