1. 程式人生 > >Unity Shader 紋理取樣UV動畫 幀動畫

Unity Shader 紋理取樣UV動畫 幀動畫

在Shader紋理取樣的運用中,靈活的對UV進行操作可以達到很多種很棒的效果,今天就來介紹一種簡單的動畫效果幀動畫。

效果圖:


用到的示例圖:


關鍵點就是對紋理取樣中的縮放(Tiling)與偏移(Offset)的理解,如圖:


正常情況下的取樣效果:

幀動畫要求每次只顯示一小張圖,然後練習跳轉顯示後續的圖,所以每次UV的範圍就不能在預設的0-1的範圍。

如給定的這張圖,寬為2,高為3,u的範圍(Tiling的X屬性)為 1/寬, v的範圍(Tiling的Y屬性)為1/高,設定看效果:


能取樣到小圖了,接下來就是通過程式碼控制偏移量,使每次的取樣結果都是按照我們想要的順序取樣下去就ok了,至於是通過C#程式碼去動態修改偏移量還是Shader中去修改,都是一個目的就是隨時間推移改變偏移量Offset。我這裡採用C#來修改Offset值:

using System.Collections;
using UnityEngine;

public class TextureUVST : MonoBehaviour
{
    public int width;
    public int height;
    public int fps;

    int _index = 0;
    int _totalCount;
    float _uInterval;//u方向上偏移的單位間隔
    float _vInterval;//v方向上偏移的單位間隔
    Material _mat;

	void Start ()
    {
        _totalCount = width * height;
        _uInterval = 1f / width;
        _vInterval = 1f / height;
        _mat = GetComponent<MeshRenderer>().material;
        _mat.SetTextureScale("_MainTex", new Vector2(_uInterval, _vInterval));//固定的 所以設定一次就行了
        StartCoroutine(Play());
    }
	
    IEnumerator Play()
    {
        while (true)
        {
            yield return new WaitForSeconds(1f / fps);//等待設定的一幀時間

            //使用
            //_mat.SetTextureOffset("_MainTex", new Vector2(_index % width * _uInterval, 1 - _index / width * _vInterval - _vInterval));//362514  正常的左上開始, 左到右,上到下
            _mat.SetTextureOffset("_MainTex", new Vector2(_index / height * _uInterval, _index % height * _vInterval));//123456
            //_mat.SetTextureOffset("_MainTex", new Vector2(_index % width * _uInterval, _index / width * _vInterval));//142536
            //_mat.SetTextureOffset("_MainTex", new Vector2(_index / height * _uInterval, 1 - _index % height * _vInterval - _vInterval));//321654

            //累加
            _index++;
            _index %= _totalCount;
        }
    }
}

Shader簡單的紋理取樣程式碼:

// Upgrade NOTE: replaced tex2D unity_Lightmap with UNITY_SAMPLE_TEX2D

Shader "Custom/UVFrame2" {

	Properties{
		_MainTex("MainTex",2d) = ""{}
	}

	SubShader{
		pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "unitycg.cginc"

			sampler2D _MainTex;
			float4 _MainTex_ST;

			struct v2f
			{
				float4 pos : POSITION;
				float2 uv : TEXCOORD0;
			};

			v2f vert(appdata_full v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
				//o.uv = TRANSFORM_TEX(float4(_TilingX,_TilingY,_OffsetX,_OffsetY), _MainTex);
				return o;
			}

			fixed4 frag(v2f IN) :COLOR
			{
				fixed4 color = tex2D(_MainTex, IN.uv);

				return color;
			}

			ENDCG
		}
	}
}