Unity Shader序列幀動畫學習筆記
關於無限播放序列幀動畫的一點問題
在學shader的序列幀動畫時,書上寫了這樣一段代碼:
fixed4 frag(v2f i){
// 獲得整數時間
float time = floor(_Time.y * _Speed) % 64;
// 根據時間計算當前行數和列數
float row = floor(time/_HorizontalAmount);
// 對uv坐標進行偏移
half2 uv = float2(i.uv.x/_HorizontalAmount,i.uv.y/_VerticallAmount);
uv.x += column / _HorizontalAmount;
uv.y -= row / _VerticallAmount;
fixed4 c = tex2D(_MainTex,uv);
c.rgb *= _Color; float column = time - row * _HorizontalAmount;
return c;
}
就是依據時間變量_Time來獲得當前要播放的序列幀動畫在整個Texture里是第幾行第幾列,然后在后面根據列數行數繪制當前序列幀動畫,在上面的代碼中,用time/_HorizontalAmount來獲得當前行數,用time % _HorizontalAmount來獲得當前列數,其中_HorizontalAmount表示在Texture中一行中有多少個序列幀動畫。
一開始我看到上面的代碼的時候是蒙蔽的!_Time.y表示從游戲開始到現在經過的時間,而行數和列數跟time變量是成正比例的,我就想。
難道row和column變量不會迅速膨脹嗎??!
但是,使用上述代碼表現出來的shader是不斷的重復播放該動畫,這是為什么呢?
Answer
首先給出肯定,row和column是肯定會隨着time的變大而不停的變大的,那么為什么表現出來的效果不是動畫播放一次之后就結束呢?(因為當row和column變大后,后面根據行數和列數繪制序列幀的代碼就會失效,因為row和column已經超過了整個Texture最大的行數和列數了)
答案是
Texture(貼圖)的Wrap Mode屬性被設置為了Repeat!
當行數和列數急劇增加的時候,在后面的代碼中計算他們的偏移也會急速的增長,見下面的代碼:
// 對uv坐標進行偏移
half2 uv = float2(i.uv.x/_HorizontalAmount,i.uv.y/_VerticallAmount);
uv.x += column / _HorizontalAmount;
uv.y -= row / _VerticallAmount;
其中column/_HorizontalAmount和row/_VerticalAmount會不停的變大,當前uv的偏移坐標大於(1,1)的時候,Repeat屬性就起到了作用!Repeat屬性規定當uv坐標超過(1,1)時,就會不停的重復本身的圖形。
所以上述代碼才會不停的進行播放動畫。
但是,個人認為直接這樣寫還是不妥,實際測試中,當speed超過10^6,圖像就會變得失真,變成一團馬賽克,如下圖所示。
所以,最好的方法是,將題目中的row和column限制在一定范圍,下面是我改動的代碼。
// 獲得整數時間
float time = floor(_Time.y * _Speed) % (_HorizontalAmount*_VerticallAmount);
// 根據時間計算當前行數和列數
float row = floor(time/_HorizontalAmount);
float column = time - row * _HorizontalAmount;