tuedaの日記

2011-07-26

[] デプスバッファーを可視化する

何で今更という気がするが、知識としては知っていても自分でやったことがない項目を試している。

ここのところ更新をサボっていたので、生きてますよ〜という事で。

これはglReadPixels()でデプスバッファーを取得してPNG画像として出力したもの。

f:id:tueda_wolf:20110726151154p:image

glReadPixels()はformatにGL_DEPTH_COMPONENTを指定するとフレームバッファーからではなくデプスバッファーから値を読み込む。

基本的に(0, 1)で手前が0で一番奥が1。

デプスバッファーの値からビュー座標のZ値を求める

デプスバッファーの値(0,1)よりビュー座標のZ値(-near, -far)が欲しい時もある(...のか?)。

計算式は明らかなので逆にたどればZ値を計算できる。

  • ビュー座標 --(透視変換行列)--> クリップ座標 --(W除算)--> 正規化デバイス座標 --(0,1化)--> デプスバッファー

ちなみに正規化デバイス座標は(-1,1)だがデプスバッファーに書き込まれる値は(0,1)なのでx0.5+0.5が必要。

上の式では(0,1化)と書いたがもっといい名前を探している。

まずビュー座標からクリップ座標(ゲームプログラミングのための3Dグラフィックス数学のP99を見よう!)

  • Z' = -(f+n)/(f-n)*z - 2nf/(f-n)
  • W' = -z

そしてw除算。

  • Z'/W' = (f+n)/(f-n) + 2nf/(f-n)z

これを(0,1化)したのをdepthとすると、

  • depth = (Z'/W')/2 + 1/2
  • = {(f+n)/(f-n) + 2nf/(f-n)z} / 2 + 1/2

あとは式変形をしてzについて求めれば終わり。

  • z = nf/(depth(f-n)-f)

確かにdepth=0のときz=-nearで、depth=1のときz=-farになっている。

トラックバック - http://d.hatena.ne.jp/tueda_wolf/20110726/p1