Unity Shaderの基礎 part 2

# テクスチャを貼ってみる

今回は3Dモデルにテクスチャを貼ってみます。

```
Shader "Custom/surfaceshader003" {
	Properties {
		_MainTex("Base (RGB)",2D) = "white" {}
	}
	SubShader {
		Tags { "RenderType"="Opaque" }

		CGPROGRAM
		#pragma surface surf Lambert

		struct Input {
			float2 uv_MainTex;
		};

		sampler2D _MainTex;

		void surf (Input IN, inout SurfaceOutput o) {
			o.Albedo = tex2D(_MainTex, IN.uv_MainTex);
		}
		ENDCG
	}
	FallBack "Diffuse"
}
```

## 説明

```
Properties {
	_MainTex("Base (RGB)",2D) = "white" {}
}
```
今回は、プロパティにテクスチャを指定しています。
プロパティの書式は、
**変数名("Inspector上の表示名", 変数の種類) = デフォルト値**
でしたね。
今回は、**_MainTex**という、2Dテクスチャの変数を定義しています。
デフォルト値の**"white"**は白ベタのテクスチャを指しています。
試しに**""**にしてみると灰色になりました。

---
```
struct Input {
	float2 uv_MainTex;
};
```
surf関数に渡す構造体の指定です。
今回は、**_MainTex**のUV座標を定義しています。
変数名**_MainTex**の前に**uv**とつけることで、自動的にマテリアルのテクスチャ座標設定(TilingとOffset)が適用されたUV座標が入ってきます。
ちなみに、**float2**というのはfloat型の2要素を持ったベクトルを表しています。
**uv_MainTex.x uv_MainTex.y**という感じでアクセスできます。
他にも**float3**や**float4**などがあります。

---
```
sampler2D _MainTex;
```
プロパティで受け取ったデータをシェーダ内で使うための定義です。
2Dテクスチャの場合は、**sampler2D**です。

---
```
void surf (Input IN, inout SurfaceOutput o) {
	o.Albedo = tex2D(_MainTex, IN.uv_MainTex);
}
```
**tex2D**関数は、**UV座標(uv_MainTex)**から**テクスチャ(_MainTex)上のピクセルの色**を計算して返します。

---
マテリアルに今回作ったシェーダとテクスチャを割り当てます。
![キャプチャ002.PNG](https://qiita-image-store.s3.amazonaws.com/0/22909/423a4642-17f7-d294-dd28-2567c37ce98e.png)
割り当てたテクスチャ
![texture001.png](https://qiita-image-store.s3.amazonaws.com/0/22909/46a9febb-c760-a0b9-9820-419e099942f6.png)


## 実行結果

実行すると下記のようになります。
![キャプチャ001.PNG](https://qiita-image-store.s3.amazonaws.com/0/22909/53fcd9da-8e53-552a-9e42-df10eaf31755.png)

# テクスチャをUVスクロールさせてみる

先ほどのシェーダを改造して、UVスクロールをさせてみます。
テクスチャのUVをX方向とY方向に、時間に比例してずらすようにすればできそうです。

```
Shader "Custom/surfaceshader004" {
	Properties {
		_MainTex("Base (RGB)",2D) = "white" {}
		_ScrollX("Scroll X", float) = 0
		_ScrollY("Scroll Y", float) = 0
	}
	SubShader {
		Tags { "RenderType"="Opaque" }

		CGPROGRAM
		#pragma surface surf Lambert

		struct Input {
			float2 uv_MainTex;
		};

		sampler2D _MainTex;
		float _ScrollX, _ScrollY;

		void surf (Input IN, inout SurfaceOutput o) {
			float2 scroll = float2(_ScrollX, _ScrollY) * _Time.y;
			o.Albedo = tex2D(_MainTex, IN.uv_MainTex + scroll);
		}
		ENDCG
	}
	FallBack "Diffuse"
}
```


## 説明

追加したのは3箇所ですが、要所だけ説明します。

```
Properties {
	_MainTex("Base (RGB)",2D) = "white" {}
	_ScrollX("Scroll X", float) = 0
	_ScrollY("Scroll Y", float) = 0
}
```
**_ScrollX**と**_ScrollY**はUVスクロール用の移動量です。

---
```
void surf (Input IN, inout SurfaceOutput o) {
	float2 scroll = float2(_ScrollX, _ScrollY) * _Time.y;
	o.Albedo = tex2D(_MainTex, IN.uv_MainTex + scroll);
}
```
突然**_Time.y**という変数が出てきましたが、コレは定義済み変数といって、Unity側が自動的に用意している変数の一つです。
**_Time**は、時間に関する変数で、ゲーム中の経過時間が入ってます。
**float4**なので、4要素あるのですが、**x**は1/20、**y**は等倍、**z**は2倍、**w**は3倍の時間が入ってます。
今回は等倍速の時間が欲しかったので**y**を使用しています。
**_ScrollX**と**_ScrollY**をもとにした**float2**の**scroll**に、**_Time.y**を掛けています。
次の行で**UV座標**に**scroll**を足してUVをずらしています。

---
マテリアルにシェーダを割り当て、**ScrollX**と**ScrollY**の値を設定します。
![キャプチャ003.PNG](https://qiita-image-store.s3.amazonaws.com/0/22909/382dc66f-d437-55bf-9248-f77b37583da4.png)
スクロール方向がわかりやすくなるようにテクスチャを変えました。
![frame64x64.png](https://qiita-image-store.s3.amazonaws.com/0/22909/eefcee23-b5cb-e60b-4b06-800c26407f89.png)

## 実行結果
![uvscroll001.gif](https://qiita-image-store.s3.amazonaws.com/0/22909/d9cf329d-301d-2b65-ca3d-4e4a37113b01.gif)



ちなみに、今回使用したテクスチャのインポート設定で、**Wrap Mode**を**Repeat**にしている場合は、上記のようにUVスクロールがループしますが、**Clamp**にしていると、下記のようになります。
![uvscroll002.gif](https://qiita-image-store.s3.amazonaws.com/0/22909/d674d38d-0a59-6e29-a23f-c034694cb32b.gif)

これは、UV座標がテクスチャの端(0～1の間)をはみ出した場合にループせずに端のピクセルを返すようになっているからです。
コレはコレでうまく使えば表現の幅が広がりそうです。

## 参考

http://qiita.com/edo_m18/items/591925d7fc960d843afa
http://docs.unity3d.com/462/Documentation/Manual/SL-BuiltinValues.html