久しぶりにShaderを書いてみたらかなり忘れていました X(
##とりあえず一番シンプルな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につけてみたけど何も描画されない・・・。
どうやらfloat4 vert(float3 pos : POSITION ) : SV_POSITION
が間違っているとのこと
float3 pos
だとだめでfloat4 pos
だと正常に描画された。
##色をプロパティで指定できるようにする
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
}
}
}
常に手前に描画されるようにするために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
}
}
}
たぶん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
}
}
}
結果は失敗
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
}
}
}
処理の流れはこうだと思う。
- 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
}
}
}