[Python] Numpy で3D座標変換 その3

[Python] Numpy で3D座標変換 その3

Depth から World Position を復元

3D座標変換その2 で (320. , 33.06740882, 0.9986713, 1.0)という値から、World Position を復元する。
このベクトルの値は SV_POSITION の値として、頂点シェーダーから出力され、ピクセルシェーダーに入ってきた値を float4 の値を想定している。

ここに乗せている Python コードは「3D座標変換その2」に書いているコードの後ろに足せば、動くようにしている。

Depth から World Position を求めるのは以下の通り

  • ピクセルシェーダーに来た座標を NDC 空間に戻す
  • View と Proj の逆行列を求める
  • NDC 空間の座標に、ViewProj の逆行列を掛ける
    • ViewProj 行列の逆行列を求める
    • もしくは View と Proj の逆行列をそれぞれ求めて、InvProj から順番にかけていく。
  • 求めたベクトルの X,Y,Z を W で割る

NDC 空間に戻す

uv = np.array([v1[0,0]/screenWidth, v1[0,1]/screenHeight])
uv = (uv * 2.0) - 1.0
ndc = np.array([uv[0], uv[1], v1[0,2], 1.0])
ndc[1] = ndc[1] * -1.0

SV_Position の XY にはピクセルのスクリーン位置が返ってくる。その値を描画したスクリーンサイズで割ることで、[0,1] 範囲の UV を求めている。そして、NDC の XY 座標は [-1,1] の範囲を取るため、2倍して1引くことで NDC での座標に変換している。

ndc 変数に値をセットしているが、XY は先ほど UV の値から求めた座標を入れて、Z は SV_Position の値をそのまま代入している。(これは、DirectX の NDC の Z が [0,1] のためそのまま使用。[-1,1] の環境では、別途変換が必要)

View Proj の逆行列を掛ける

viewProjInv = np.linalg.inv(view*proj)
wp = np.matmul(ndc, viewProjInv)

#projInv = np.linalg.inv(proj)
#viewInv = np.linalg.inv(view)
#wp = np.matmul(ndc, projInv)
#wp = np.matmul(wp, viewInv)

wp = wp/wp[0,3]

ViewProj の逆行列をかけるか、もしくは、View, Proj の逆行列をそれぞれ求めて、projInv から順番にかけていく。最後に W で割れば、World Position が復元できた。

[[0.  2.5 2.  1. ]]

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA