Unity でShaderの勉強 その5

久しぶりにShaderを書いてみたらかなり忘れていました X(

##とりあえず一番シンプルなShaderを書いてみる
失敗した。。。

```lang:失敗しているShader
Shader "Custom/Test1" {
	SubShader {
		Pass {
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			float4 vert(float3 pos : POSITION ) : SV_POSITION  {
				return mul(UNITY_MATRIX_MVP,pos);
			}


			float4 frag() : SV_TARGET {
				return float4(1,1,1,1);
			}

			ENDCG
		}
	}
}

```

Test1マテリアルをCubeにつけてみたけど何も描画されない・・・。
<img width="291" alt="スクリーンショット 2016-12-25 2.12.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/67575/83263aac-fa55-54fe-b5fa-e61c1454093f.png">


どうやら`float4 vert(float3 pos : POSITION ) : SV_POSITION`が間違っているとのこと
`float3 pos`だとだめで`float4 pos`だと正常に描画された。

<img width="268" alt="スクリーンショット 2016-12-25 2.14.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/67575/3c7f695e-4b94-ec3b-749d-353ec0259b47.png">

##色をプロパティで指定できるようにする
Propertiesタグを指定してみた。

```
Shader "Custom/Test1" {
	Properties {
		_Color("Output Color" , COLOR) = (1,1,1,1)
	}
	SubShader {
		Pass {
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			float4 _Color;

			float4 vert(float4 pos : POSITION ) : SV_POSITION  {
				return mul(UNITY_MATRIX_MVP,pos);
			}


			float4 frag() : SV_TARGET {
				return _Color;
			}

			ENDCG
		}
	}
}
```

ちゃんと色が反映されてる :)
<img width="266" alt="スクリーンショット 2016-12-25 2.18.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/67575/d2f31511-396b-9fce-fd7c-3ea58a8a1cc7.png">

##常に手前に描画されるようにする
普通のCubeを用意
<img width="339" alt="スクリーンショット 2016-12-25 2.19.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/67575/70264dcf-ee3f-9846-fae6-f1132aaa4701.png">

常に手前に描画されるようにするためにTest1ShaderのZTestが常に勝つようにする。
ZTestとZWriteの設定をつけた。

```
Shader "Custom/Test1" {
	Properties {
		_Color("Output Color" , COLOR) = (1,1,1,1)
	}
	SubShader {
		ZTest Always
		ZWrite On
		Pass {
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			float4 _Color;

			float4 vert(float4 pos : POSITION ) : SV_POSITION  {
				return mul(UNITY_MATRIX_MVP,pos);
			}


			float4 frag() : SV_TARGET {
				return _Color;
			}

			ENDCG
		}
	}
}
```

うまくいった。
<img width="286" alt="スクリーンショット 2016-12-25 2.25.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/67575/618583a1-a2f2-bacb-d402-604deea420a7.png">

たぶんZTestをAlwaysにしなくても描画順序を遅らせるだけで常に手前に描画されるはず。

QueueをGeometry+1にして普通のCubeよりレンダリングを遅らせる。
```
Shader "Custom/Test1" {
	Properties {
		_Color("Output Color" , COLOR) = (1,1,1,1)
	}
	SubShader {
		Tags { "Queue" = "Geometry+1"}

		Pass {
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			float4 _Color;

			float4 vert(float4 pos : POSITION ) : SV_POSITION  {
				return mul(UNITY_MATRIX_MVP,pos);
			}


			float4 frag() : SV_TARGET {
				return _Color;
			}

			ENDCG
		}
	}
}
```

結果は失敗
<img width="269" alt="スクリーンショット 2016-12-25 2.41.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/67575/83065c49-5634-6bb1-a63d-e9d3d18b7cca.png">
ZTestとZWriteの指定をしなかったのでデフォルト値ZTest LEqual, ZWrite Onが使用され、
ZTestが行われて負けたのでそもそもレンダリングがされず普通のCubeの方が手前に描画された、
のだと思う。


##ZTest処理はQueueで指定した順番で行われるんだっけ？
- ZTest -> レンダリング可能か決まる -> Queueの順番にレンダリングされる
- Queueの順番に各種処理が走る -> ZTest -> レンダリング可能か決まる -> ZBufferに残ったピクセルがレンダリングされる
どっちだったか忘れてしまったので確認。

もし後者ならQueueを小さくしてZTest Alwaysにしたときに普通のCubeの方が手前に描画されるはず。

```
Shader "Custom/Test1" {
	Properties {
		_Color("Output Color" , COLOR) = (1,1,1,1)
	}
	SubShader {
		Tags { "Queue" = "Geometry-1"}
		ZTest Always
		ZWrite On
		Pass {
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			float4 _Color;

			float4 vert(float4 pos : POSITION ) : SV_POSITION  {
				return mul(UNITY_MATRIX_MVP,pos);
			}


			float4 frag() : SV_TARGET {
				return _Color;
			}

			ENDCG
		}
	}
}
```

結果:普通のCubeの方が手前に描画された。
<img width="343" alt="スクリーンショット 2016-12-25 2.51.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/67575/0ef86922-a4d5-db43-a3a1-c9ef0489c3ec.png">

処理の流れはこうだと思う。
- Queue=Geometry-1である赤Cubeの処理が最初に始まる。
- 赤CubeはZTest Alwaysなので常にZTestに勝ち、ZBufferに赤ピクセル情報が書き込まれる。
- Queue=Geometryである普通のCubeの処理が始まる。
- 普通のCubeのZTestはLEqualなので赤Cubeのピクセル情報が入ったZBufferに勝つ。
- ZBufferに普通のCubeのピクセル情報を書き込む。
- 最後にZBufferに残った赤Cubeと普通のCubeのピクセルを画面に映す。


##半透明をやりたい
半透明は確かブレンドするんだったはず・・・！

```
Shader "Custom/Test1" {
	Properties {
		_Color("Output Color" , COLOR) = (1,1,1,1)
	}
	SubShader {
		Tags { "Queue" = "Transparent"}
		ZTest LEqual
		ZWrite Off
		Blend SrcAlpha OneMinusSrcAlpha
		Pass {
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			float4 _Color;

			float4 vert(float4 pos : POSITION ) : SV_POSITION  {
				return mul(UNITY_MATRIX_MVP,pos);
			}


			float4 frag() : SV_TARGET {
				return _Color;
			}

			ENDCG
		}
	}
}
```

結果たぶんOK。透き通った。
<img width="341" alt="スクリーンショット 2016-12-25 2.58.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/67575/3141050c-d154-4a49-b913-c0ce0e6b1975.png">