1. 程式人生 > >Unity&Shader案例篇—旋轉、平移和縮放

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、其實還差一個貼圖的縮放,有興趣的朋友可以自己去實現一下,跟旋轉操作的變數是一致的