⚡
【ShaderGraph】デプスからワールド座標を復元するカスタムノード
はじめに
シェーダーグラフの標準機能では、シーンのワールド座標を取得することができません。
今回は、シーンのDepthからワールド座標を復元するようなカスタムノードを作ってみました。
参考記事
今回の記事はUnity公式のURPシェーダーを参考にしています。
Reconstruct the world space positions of pixels from the depth texture
環境
Unity 2022.1.0b2.2474
Universal RP 13.1.3
実装の流れ
- SceneDepthノードを利用して、シーンのデプス値を取得
- スクリーン座標、デプス値、View Projection 逆行列から、ワールド座標を作る
シーンのデプス値の取得
SceneDepthノードを使うことで、シーンのデプス情報を取得することができます。
取得できるデプス値は 0~1の値になっています。
このデプス情報ですが、クリップ空間のZ座標に相当します。
デプス値 = 0 なら、カメラのFarClipに位置することを意味し、
デプス値 = 1 なら、カメラのNearClipに位置することを意味します。
ワールド座標の復元
このクリップ座標に View Projection の逆変換を適用することで、ワールド座標を復元することができます。
カスタムシェーダーの作成
HLSLファイルの作成
スクリーン座標からワールド座標を復元するカスタムシェーダー(.hlsl)は以下のようになります。
ReconstructWorldFromDepth.hlsl
// Precision : float
void ReconstructWorldFromDepth_float(float2 ScreenPosition, float Depth, float4x4 unity_MatrixInvVP, out float3 Out)
{
// スクリーン座標とDepthからクリップ座標を作成
float4 positionCS = float4(ScreenPosition * 2.0 - 1.0, Depth, 1.0);
#if UNITY_UV_STARTS_AT_TOP
positionCS.y = -positionCS.y;
#endif
// クリップ座標にView Projection変換を適用し、ワールド座標にする
float4 hpositionWS = mul(unity_MatrixInvVP, positionCS);
// 同次座標系を標準座標系に戻す
Out = hpositionWS.xyz / hpositionWS.w;
}
// Precision : half
void ReconstructWorldFromDepth_float(float2 ScreenPosition, float Depth, float4x4 unity_MatrixInvVP, out half3 Out)
{
// スクリーン座標とDepthからクリップ座標を作成
float4 positionCS = float4(ScreenPosition * 2.0 - 1.0, Depth, 1.0);
#if UNITY_UV_STARTS_AT_TOP
positionCS.y = -positionCS.y;
#endif
// クリップ座標にView Projection変換を適用し、ワールド座標にする
half4 hpositionWS = mul(unity_MatrixInvVP, positionCS);
// 同次座標系を標準座標系に戻す
Out = hpositionWS.xyz / hpositionWS.w;
}
Custom Function ノードの作成
Custom Functionノードを作成し、HLSLファイルを登録します。
ノードを3つ作成し、Custom Functionノードへ接続します。
- Screen Position (Default)
- Scene Depth (Raw)
- Transformation Matrix (Inverse View Projection)
Transformation Matrix ノードは Inverse View Projectionを選択します。
Custom Function ノードを使う
デプス情報からワールド座標が復元できます。
Discussion