Unity&Shader案例篇—旋轉、平移和縮放
一、前言
在Unity中通過控制物體的Transform可以很容易的對物體進行旋轉、平移和縮放,得到一些簡單的動畫效果。但是有個不好的地方是,一旦這個物體上有碰撞體的話,會跟環境發生碰撞。我就就想能不能在不麻煩特效動畫那邊的情況下,自己用Shader去處理一些基於模型頂點或貼圖的dong動畫效果。如圖所示是我完全使用Shader處理處理的頂點的xuan旋轉、平移和縮放,另外還有兩個是貼圖的旋轉和平移。Unity的版本為2017.3.1
頂點的移動 頂點的旋轉 頂點的縮放 貼圖的移動 貼圖的旋轉上面五個型別的操作,其中旋轉是比較難的,其他的頂點操作都比較簡單。
二、實現
1、頂點的移動:在Shader程式碼裡設定三個方向的變數_SpeedX、_SpeedY和_SpeedZ,然後再頂點變換的時候fen分別加上這個變數就可以來對頂點進行位移操作,如果乘以shi'時間就可以得到自動位移的效果了,所以頂點Shader程式碼為:
v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.vertex += float4(_SpeedX, _SpeedY, 0, _SpeedZ)*_Time.y; o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; }
2、貼圖的移動:關鍵是對UV進行操作,關鍵的片段Shader部分的程式碼為
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed2 UV = i.uv;
fixed xV = _XSpeed * _Time.x;
fixed yV = _YSpeed * _Time.y;
UV += fixed2(xV, yV);
fixed4 col = tex2D(_MainTex, UV);
return col;
}
3、頂點的縮放:上面的位移是對頂點ji進行加操作,而縮放是對頂點的值進行乘操作就可以了,關鍵的頂點Shader部分程式碼為
v2f vert (appdata v)
{
v2f o;
v.vertex.xz *= clamp((_SinTime.w + 3.0)*0.5, 1.0, 2.0);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
4、頂點的旋轉:旋轉相比上面的操作會比較難,思路是先計算要旋轉的角度,然後得到旋轉矩陣,最後直接講頂點的 位置向量和旋轉矩陣相乘得到新的頂點值,關鍵的計算函式為:
float4 CalculateRotation(float4 pos)
{
float rotation=_RotationSpeed*_Time.y;
float s,c;
sincos(radians(rotation), s, c);
float2x2 rotMatrix=float2x2(c,-s,s,c);
pos.xy=mul(pos.xy,rotMatrix);
return pos;
}
新的頂點的計算並不是每個方向都計算,我這裡只處理了x和z方向的,將新得到的頂點位置賦值給輸出頂點的時候要注意原來的z就是新頂點的y頂點Shader的程式碼為:
v2f vert (appdata v)
{
v2f o;
float4 k=float4(v.vertex.x,v.vertex.z,1.0,1.0);
k=CalculateRotation(k);
o.vertex = UnityObjectToClipPos(float4(k.x,v.vertex.y,k.y,v.vertex.w));
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
5、貼圖的旋轉:這裡要用到一個變數“_MainTex_ST”(如果貼圖的名稱為“_MainTex”),其實只要涉及到對模型貼圖的UV進行位移和偏移操作都要用到這個變數,還必須先宣告一下,如下所示:它是一個四維向量,其中xy是貼圖的Scale,zw是貼圖的offset
sampler2D _MainTex;
uniform float _RotationSpeed;
float4 _MainTex_ST;
先計算當前貼圖的縮放比例和偏移相對原點的值div,然後對當前貼圖的頂點進行旋轉,最後加上div得到正在旋轉之後的貼圖的值,關鍵程式碼如下:
float4 CalculateRotation(float4 pos)
{
//先計算距離位置點距離原點的值
float2 div= (_MainTex_ST.xy / 2.0) + _MainTex_ST.zw;
float rot = _RotationSpeed * _Time.y;
pos.xy -= div;
float s, c;
sincos(radians(rot), s, c);
float2x2 rotMatrix = float2x2(c, -s, s, c);
pos.xy = mul(pos.xy, rotMatrix);
pos.xy += div;
return pos;
}
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv.xy = CalculateRotation(v.uv);
return o;
}
三、總結
1、由物體的transform的旋轉、平移和縮放嘗試著實現了Shader對模型頂點或貼圖的旋轉、平移和縮放
2、其實還差一個貼圖的縮放,有興趣的朋友可以自己去實現一下,跟旋轉操作的變數是一致的