【Unity Shader】搖擺的小草——頂點動畫
阿新 • • 發佈:2019-01-01
Shader 動畫的主要點在座標變換,程式碼:
Shader中設定渲染佇列為 Transparent, 如果需要batch場景中模型的話需要在 Tags 中加上 “DisableBatching=True”, 不允許批處理。Shader "Custom/Grass" { Properties { _MainTex ("Grass Texture", 2D) = "white" {} _TimeScale ("Time Scale", float) = 1 } SubShader{ Tags{"Queue"="Transparent" "RenderType"="Opaque" "IgnoreProject"="True"} Pass{ Tags{"LightMode"="ForwardBase"} ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Cull Off CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _MainTex; half _TimeScale; struct a2v { float4 vertex : POSITION; float4 texcoord : TEXCOORD0; }; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; }; v2f vert(a2v v){ v2f o; float4 offset = float4(0,0,0,0); offset.x = sin(3.1416 * _Time.y * clamp(v.texcoord.y-0.5, 0, 1)) * _TimeScale; o.pos = mul(UNITY_MATRIX_MVP, v.vertex + offset); o.uv = v.texcoord.xy; return o; } fixed4 frag(v2f i) : SV_Target{ return tex2D(_MainTex, i.uv); } ENDCG } } FallBack Off }
關閉深度寫入 Zwrite off。 關閉剔除,渲染雙面Cull Off。開啟混合為了顯示透明 Blend SrcAlpha OneMinusSrcAlpha。
vertex函式中, 必須把座標轉換成視覺空間, 所以我們把操作就集中在這裡,我的想法是:
草是延 Y 軸生長的, 而且根不能動。所以,在判斷當前的座標有兩種情況:
1, 如果 y 座標靠近 0 時,我們認為他是根部,根部不需要改變。
2, 其他高度, y 需要沿著某個方向做來回的搖擺pingpong運動。
當把根部看做原點,草的運動可以當成正弦函式, 取座標距離底部的距離做一個限制,使底部擺動小clamp(v.texcoord.y-0.5, 0, 1)。 clamp(x, a, b) 的作用時當 x< a時 x=a, 當x > b 時 x=b。
我們做一個x方向的偏移(也可以z),sin(3.1416 * _Time.y * clamp(v.texcoord.y-0.5, 0, 1)), _Time是一個時間變化量,最後在乘上一個我們偏移的最大距離 _TimeScale即可。
最後,把SV_POSITION暫存器中的座標設定為原本的座標vertex 加上便宜座標offset 後的轉換。