【ShaderGraph】デプスからワールド座標を復元するカスタムノード

2022/01/01に公開

はじめに

シェーダーグラフの標準機能では、シーンのワールド座標を取得することができません。
今回は、シーンのDepthからワールド座標を復元するようなカスタムノードを作ってみました。

参考記事

今回の記事はUnity公式のURPシェーダーを参考にしています。
Reconstruct the world space positions of pixels from the depth texture

環境

Unity 2022.1.0b2.2474
Universal RP 13.1.3

実装の流れ

  1. SceneDepthノードを利用して、シーンのデプス値を取得
  2. スクリーン座標、デプス値、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ノードへ接続します。

  1. Screen Position (Default)
  2. Scene Depth (Raw)
  3. Transformation Matrix (Inverse View Projection)

Transformation Matrix ノードは Inverse View Projectionを選択します。

Custom Function ノードを使う

デプス情報からワールド座標が復元できます。

Discussion