はるのゲーム開発メモ

自分の勉強の成果などをメモ代わりにします

UnityのShader勉強4 テクスチャを貼る

今回はテクスチャを貼ります。

 

まずは貼る画像を用意します。

なんでもいいですが、今回はカラーグリッドを用意しました。

f:id:Haru_android:20171218140751p:plain

これをUnityに取り込み、作ったマテリアルのTextrueにD&Dします。

f:id:Haru_android:20171218141016p:plain

 

前回のコードを書き換えます。

Shader "Unlit/TestShader"
{
	Properties{
		_Texture("Texture",2D)="white"{}
		_Float("float",float) = 1
		_Color("Color",Color) = (1,1,1,1)
		_Range("Range",Range(-10,10))=0.5
		_Vector("ector",Vector)=(0,0,0,0)
	}
	SubShader
	{
		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			sampler2D _Texture;
			fixed _Float;
			fixed4 _Color;
			fixed _Range;
			fixed4 _Vector;
			struct appdata
			{
				float4 vertex : POSITION;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f
			{
				float4 vertex : SV_POSITION;
				float2 uv : TEXCOORD0;
			};

			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord;
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 tex = tex2D(_Texture,i.uv);
				return tex;
			}
			ENDCG
		}
	}
}

結果は

f:id:Haru_android:20171218142235p:plain

無事に表示されました。

ちなみに使うテクスチャをunityちゃんのテクスチャにすればちゃんと表示されます。

f:id:Haru_android:20171218150200p:plain

 

 

今回やったことは、モデルからUV座標を受け取り、それを元にテクスチャの座標から色を受け取り表示しています。

 

順番に見てみます。

struct appdata
{
	float4 vertex : POSITION;
	float2 texcoord : TEXCOORD0;
};

まず取り込むデータにTEXCOORD0を追加します。

TEXCOORD0は1番目のUV座標です。

例のごとく詳しくは

qiita.com

 

次にv2fです。

struct v2f
{
	float4 vertex : SV_POSITION;
	float2 uv : TEXCOORD0;
};

変換後の頂点にデータを入れるわけですが、こちらでもTEXCOORD0を指定します。

前は指定しなくてもよかったらしいのですが、バージョンアップで値を保存したい場合は指定する必要がでました。

uv以外にも自分の好みのデータを保存したい場合も基本的にTEXCOORDを使います。

後ろにつける番号でいくつも保存できます。

UV座標はxとyだけなのでfloat2ですが、

別のデータを使いたいときはfloatやfloat4でも問題ありません。

 

(上限とかあるんですかね...)

 

さて頂点シェーダーです。

 

			
v2f vert (appdata v)
{
	v2f o;
	o.vertex = UnityObjectToClipPos(v.vertex);
	o.uv = v.texcoord;
	return o;
}

こちらでは特に変換せず、受け取った値をそのまま保存します。

 

最後にフラグメントシェーダーです。

fixed4 frag (v2f i) : SV_Target
{
				
	fixed4 tex = tex2D(_Texture,i.uv);
	return tex;
}

ここでUV座標を使ってテクスチャ座標の色を取得します。

 

初めてみたときはfixed4って値は4つしかないのに画像全体の色なんて取得できるのかわからなかったのですが、ピクセルごとにfrag関数が呼ばれると知ったらわかりました。

 

ためしにi.uvのみを使って表示してみます。

frag関数を

fixed4 frag (v2f i) : SV_Target
{
fixed4 color = fixed4(i.uv.x, i.uv.y, 0, 1); return color; }

としてみます。

xとyは0~1の値なので赤と緑に入れてみました。

f:id:Haru_android:20171218150339p:plain

結果はこんな感じです。

どんな値があるのか結果として現れるのがUnityのいいところです。

 

 

 

 

さて次にTillingとOffsetです。

マテリアルのテクスチャにある項目ですね。

f:id:Haru_android:20171218150623p:plain

このコードのままではここを動かしても意味がありません。

テクスチャが動かない予定なら別によいのですが、川の流れを表現したいときなどはこれを動かすのが楽ですのでこれを使えるようにします。

 

以下のようにコードを書き換えます。

Shader "Unlit/TestShader"
{
	Properties{
		_Texture("Texture",2D)="white"{}
		_Float("float",float) = 1
		_Color("Color",Color) = (1,1,1,1)
		_Range("Range",Range(-10,10))=0.5
		_Vector("ector",Vector)=(0,0,0,0)
	}
	SubShader
	{
		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"

			sampler2D _Texture;
			float4 _Texture_ST;

			fixed _Float;
			fixed4 _Color;
			fixed _Range;
			fixed4 _Vector;
			struct appdata
			{
				float4 vertex : POSITION;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f
			{
				float4 vertex : SV_POSITION;
				float2 uv : TEXCOORD0;
			};

			
			v2f vert (appdata v)
			{
				v2f o;
				float4 vec = v.vertex;
				o.vertex = UnityObjectToClipPos(vec);
				//o.uv = v.texcoord;
				o.uv = TRANSFORM_TEX(v.texcoord, _Texture);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				
				fixed4 tex = tex2D(_Texture,i.uv);
				return tex;
			}
			ENDCG
		}
	}
}

変更点はそんなに多くありません。

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"

sampler2D _Texture;
float4 _Texture_ST;

まず#include "UnityCG.cginc"です。

#includeとはC#でいうところの継承のようなものです。

"UnityCG.cginc"とはデフォルトでつける便利なものが色々入っているやつで、C#のMonobehaviourみたいなかんじです。

公式からダウンロードできるシェーダーに入っているので中を確認してみると、なんとなくわかると思います。

 

次にfloat4 _Texture_STです。

これはテクスチャを宣言することで意味が出てきます。テクスチャの変数名の後ろに_STと付け加えます。

使っていないように見えますがちゃんと"UnityCG.cginc"で使っています。

 

 

そして頂点シェーダーです。

v2f vert (appdata v)
{
	v2f o;
	float4 vec = v.vertex;
	o.vertex = UnityObjectToClipPos(vec);
	//o.uv = v.texcoord;
	o.uv = TRANSFORM_TEX(v.texcoord, _Texture);
	return o;
}

 

o.uvにv.texcoordをそのままいれるのでなく

TRANSFORM_TEX(v.texcoord, _Texture)

を入れています。

この関数は"UnityCG.cginc"に記述されていて

#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)

と書かれています。

#defineにはついてはまだ勉強中です。

よくわかりませんが_STを使っているのがわかります。

 

これで使えるようになりました。

TillingとOffsetの値を弄ってみます。

f:id:Haru_android:20171218153859p:plain

できました。

 

 

終わりに

無事にテクスチャを貼ることができました。

texに_Colorをかけてみたりすると色々楽しいので遊んでみると楽しいです。

まだ透過などやっていないことはあるのですが、次回に書きます。

 

次回はtagなどです。