Unityのシェーダで描画する地点の深度を取得する方法です。
Unity2019.2.10
深度を取得する
深度を取得するには、以下のように頂点シェーダでCOMPUTE_EYEDEPTHマクロを使用します。
Shader "Depth" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; half depth : TEXCOORD1; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); // COMPUTE_EYEDEPTHマクロに変数を渡す COMPUTE_EYEDEPTH(o.depth.x); return o; } half4 frag (v2f i) : SV_Target { return i.depth.x; } ENDCG } } }
COMPUTE_EYEDEPTHの中身
COMPUTE_EYEDEPTHはUnityCG.cgincに定義されています。
関連するソースコードだけを抜き出すと以下のようになります。
#define COMPUTE_EYEDEPTH(o) o = -UnityObjectToViewPos( v.vertex ).z inline float3 UnityObjectToViewPos( in float3 pos ) { return mul(UNITY_MATRIX_V, mul(unity_ObjectToWorld, float4(pos, 1.0))).xyz; } inline float3 UnityObjectToViewPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders { return UnityObjectToViewPos(pos.xyz); }
シンプルにビュー空間におけるZ座標を返しているだけです。
座標変換とその用語については以下の記事を参照してください。
0~1の値に変換する
次に深度値を、カメラの位置を0、カメラのFarPlaneを1とする値に変換してみます。
UnityではFarPlaneの位置はProjectionParams.zで取得できます。
また便利なことに、1/FarPlaneの値がProjectionParams.wに格納されています。
そのため、深度値に_ProjectionParams.wを掛けるだけで0~1の値に変換できます。
COMPUTE_EYEDEPTH(o.depth); o.depth *= _ProjectionParams.w;