2014年5月26日月曜日

OpenGL: その線形の深度バッファーのダイナミックレンジ、足りてますか?対数深度バッファーのすすめ。

ふつうに深度バッファーをそのまま使っていて満足していていない場合、先ずは以下の参考翻訳記事を拝読しましょう(╹◡╹) ありがたやー。

要点は、
「DirectXにせよOpenGLにせよ、一般に深度バッファーはそれを使おうとするユーザーに対して最近のGPUであれば通常32bits分解能の浮動小数点型を直接そのまま、[0.0f-1.0f]のunorm型に単純で線形に提供しているけど、それじゃあダイナミックレンジが足りないよね!そこで対数トリックだよ!」
ということです。

実装(すごく簡単だよ、興味がある方はぜひ元記事をちゃんと読んでみて!)してみると感動のデプス世界が訪れました。頂点シェーダーに入力される3次元座標値をいわゆる world × view × projection 変換して出力されるスクリーン座標は xy と 深度 z に 倍率 w として出力されるので、 z が線形空間に展開していても対数空間に展開していても、頂点シェーダーの出力への対数空間への展開トリックだけで、仕上がる絵は同じで、うまい具合に深度のダイナミックレンジを飛躍的に向上させる事ができます。感動したよ(╹◡╹)


これは Wonderland.Renderer の実装試験中のデプスバッファーをダンプした図で、左右の違いは深度バッファートリックの有無のみです。左はトリック無し、右はトリック有り。どちらもOpenGLで内部の深度バッファーはGL_DEPTH_COMPONENT32F(=IEEE754/Binary32)です。

わかりやすく比較するために、gimpでそれぞれ最適なレベル補正を行うと以下のようになります。

 先の左側(トリックなし=線形の深度空間)のレベル最適化

先の右側(トリックあり=対数の深度空間)のレベル最適化

レベル補正ダイアログ、また絵の目視でもグラデーションの具合からトリック有りではダイナミックレンジが明らかに向上している事がわかります(╹◡╹)

※このグレースケール画像は簡単なデバッギングのため、本来GPU内部ではIEEE754/Binary32の浮動小数点型のunorm値として24bitsの分解能で保持されている深度バッファーの値を、[0-65535]の16bitsの分解能にキャストしてテキスト画像形式の.pgmで保存し、それをgimpでロードして[0-255]の8bitsの分解能の絵として扱っています。なので、実際のGPU内部の深度バッファーはもっともっと滑らかです(╹◡╹)

0 件のコメント:

コメントを投稿