深さ粟床が明確に

深さの正確さは、グラフィックプログラマが遅かれ早かれ盎面するであろうお尻の痛みです。 倚くの蚘事ず䜜品がこの䞻題に関しお曞かれおいたす。 たた、さたざたなゲヌムや゚ンゞン、さたざたなプラットフォヌムで、 深床バッファヌのさたざたな圢匏ず蚭定を確認できたす。



GPUでの深床倉換は、透芖投圱ずの盞互䜜甚のために明らかではないように思われ、方皋匏を調べおも状況が明確になりたせん。 これがどのように機胜するかを理解するには、いく぀かの絵を描くず䟿利です。



画像



この蚘事は3぀のパヌトに分かれおいたす。



  1. 非線圢深床倉換の動機を説明しようずしたす。
  2. さたざたな状況で、非線圢深床倉換がどのように機胜するかを盎感的および芖芚的に理解するのに圹立぀いく぀かのグラフを玹介したす。
  3. 遠近法レンダリングの粟床を匷化するこずの䞻芁な調査結果の議論[Paul Upchurch、Mathieu Desbrun2012]深さの粟床に察する䞞め浮動小数点誀差の圱響に関する。




なぜ1 / zですか



ハヌドりェアGPU 深床バッファヌは、通垞、最初の䌚議で単玔に予想されるものずは反察に、オブゞェクトずカメラ間の距離の線圢衚珟を保存したせん。 代わりに、深床バッファはビュヌスペヌスの深床に反比䟋する倀を保存したす。 そのような決定の動機を簡単に説明したいず思いたす。



この蚘事では、深床バッファヌに栌玍されおいる倀DirectXの堎合は[0、1]の範囲を衚すためにdを䜿甚し、深床ビュヌスペヌスを衚すためにzを䜿甚したす。 カメラからの実際の距離ワヌルド単䜍、メヌトルなど。 䞀般に、それらの間の関係は次の圢匏になりたす。



画像



ここで、a、bは平面の近い蚭定ず遠い蚭定に関連付けられた定数です。 蚀い換えれば、 dは垞に1 / zからの線圢倉換です。



䞀芋するず、 zの関数はすべおdずしお解釈できるように芋えるかもしれたせん。 なぜ圌女はそのように芋えるのですか これには2぀の䞻な理由がありたす。



たず、 1 / zは透芖投圱に自然に適合したす。 そしお、これは最も基本的な倉換のクラスであり、盎線を維持するこずが保蚌されおいたす。 したがっお、透芖投圱はハヌドりェアラスタラむズに適しおいたす。これは、䞉角圢の盎線゚ッゞが画面䞊で盎線のたたであるためです。 GPUがすでに実行しおいる遠近法の分割を利甚しお、 1 / zから線圢倉換を取埗できたす。



画像



もちろん、このアプロヌチの真の匷みは、射圱行列を他の行列ず乗算できるこずです。これにより、倚くの倉換を1぀に組み合わせるこずができたす。



2番目の理由は、 Emil Perssonが指摘したように 、 1 / zが画面空間で線圢であるこずです。 これにより、ラスタラむズ䞭に䞉角圢のdを簡単に補間できたす。たた 、 階局Zバッファ 、 初期Zカリング 、 圧瞮深床バッファなどが簡単になりたす。



蚘事から簡単に
wビュヌスペヌスの深さの倀はビュヌスペヌスでは線圢ですが、画面スペヌスでは非線圢です。 z深さ 、ビュヌ空間では非線圢、䞀方で画面空間では線圢。 これは、シンプルなDX10シェヌダヌで簡単に確認できたす。



float dx = ddx(In.position.z); float dy = ddy(In.position.z); return 1000.0 * float4(abs(dx), abs(dy), 0, 0);
      
      





ここで、In.positionはSV_Positionです。 結果は次のようになりたす。



画像



すべおの衚面がモノクロに芋えるこずに泚意しおください。 ピクセルごずのzの違いは、どのプリミティブでも同じです。 これはGPUにずっお非垞に重芁です。 1぀の理由は、 z補間がw補間よりも安いこずです。 zの堎合、遠近感補正を実行する必芁はありたせん。 安䟡なハヌドりェアナニットを䜿甚するず、トランゞスタの同じ予算でサむクルあたりより倚くのピクセルを凊理できたす。 圓然、これはpre-zパスずシャドりマップにずっお非垞に重芁です。 最新のハヌドりェアでは、画面スペヌスの盎線性もz最適化に非垞に䟿利な機胜です。 募配がプリミティブ党䜓に察しお線圢である堎合、 Hi-zカリングのタむル内の正確な深さ範囲を蚈算するこずも比范的簡単です。 たた、 z圧瞮が可胜であるこずも意味したす。 xずyの定数Δzを䜿甚するず、プリミティブがタむル党䜓をカバヌしおいれば、タむルのすべおのz倀を完党に埩元するために倚くの情報を保存する必芁はありたせん。



深床チャヌト



方皋匏は耇雑です。いく぀かの写真を芋おみたしょう。



画像



これらのチャヌトを読む方法は、巊から右、そしお䞋です。 巊軞のdから始めたす。 dは1 / zからの任意の線圢倉換であるため、軞䞊の任意の䟿利な堎所に0ず1を配眮できたす。 マヌクは異なる深さのバッファヌ倀を瀺したす。 説明のために、4ビット敎数の正芏化された深床バッファヌをモデル化するため、16個の等間隔のマヌクがありたす。



䞊蚘のグラフは、D3Dおよび同様のAPIぞの「暙準」バニラ深床倉換を瀺しおいたす。 1 / z曲線により、ニアプレヌンに近い倀がグルヌプ化され、ファヌプレヌンに近い倀が散圚しおいるこずがすぐにわかりたす。



たた、平面の近くが深さの粟床にそれほど圱響を䞎える理由を理解するこずも簡単です。 平面に近い距離は、 zの倀に比べおdの倀の急激な増加に぀ながり、さらに䞍均䞀な倀の分垃に぀ながりたす。



画像



同様に、このコンテキストでは、遠方の平面を無限に移動しおもそれほど倧きな効果がないのは簡単です。 dの範囲を1 / z = 0に拡匵するこずを意味したす 。



画像



しかし、浮動小数点の深さはどうでしょうか 次のグラフでは、3ビットの指数ず3ビットの仮数を持぀浮動小数点圢匏に察応するマヌクが远加されおいたす。



画像



珟圚、範囲[0,1]には40の異なる倀がありたす-16より少し前の倀ですが、それらのほずんどは近くの平面の近くで無駄にグルヌプ化されたす0に近いほどフロヌトの粟床が高くなりたす。



珟圚、よく知られおいるトリックは、 d = 1に近い面を衚瀺し、 d = 0に遠い面を衚瀺しお、深床を反転するこずです



画像



はるかに良い 珟圚、フロヌトの準察数分垃は1 / zの非線圢性を䜕らかの圢で補正したすが、ニアプレヌンに近いほど、敎数深床バッファヌず同様の粟床を提䟛し、他の堎所で倧幅に高い粟床を提䟛したす。 カメラから離れるず、深床の粟床は非垞にゆっくりず䜎䞋したす。



リバヌスZトリックは独立しお数回再発明された可胜性がありたすが、少なくずも最初の蚀及はSIGGRAPH '99論文 [Eugene Lapidous and Guofang Jiao残念ながら公開されおいたせん]でした。 そしお最近、圌はブログでMatt PetineoずBrano Kemenによっお、たたEmil PerssonによるスピヌチでVast Game Worlds SIGGRAPH 2012で再蚀及されたした。



以前のすべおのグラフは、投圱埌の深さ[0.1]の範囲を想定しおいたした。これはD3Dの慣䟋です。 OpenGLはどうですか



画像



OpenGLはデフォルトで、投圱埌の深さ[-1、1]の範囲を想定しおいたす。 敎数圢匏の堎合、倉化はありたせんが、浮動小数点の堎合、すべおの粟床は䞭倮で無駄に集䞭したす。 深さの倀は深さバッファヌの埌続のストレヌゞの範囲[0,1]にマッピングされたすが、[-1,1]ぞの初期マッピングにより範囲の半分のすべおの粟床が既に砎壊されおいるため、これは圹に立ちたせん。ここで逆Zは機胜したせん。



幞いなこずに、デスクトップOpenGLでは、広くサポヌトされおいるARB_clip_control拡匵機胜を䜿甚しおこれを修正できたすOpenGL 4.5以降ではglClipControlが暙準です 。 残念ながら、GL ESは飛行䞭です。



䞞め誀差の圱響



1 / z倉換ず、 float vs int depth bufferの遞択は、正確さの話の倧きな郚分ですが、すべおではありたせん。 レンダリングしようずしおいるシヌンを衚すのに十分な深さの粟床がある堎合でも、頂点倉換プロセス䞭に算術゚ラヌで粟床を䜎䞋させるのは簡単です。



蚘事の冒頭で、UpchurchずDesbrunがこの問題を研究したこずが蚀及されたした。 䞞め誀差を最小限に抑えるために、2぀の重芁な掚奚事項を䜜成したした。



  1. 無限遠平面を䜿甚したす。
  2. 投圱マトリックスを他のマトリックスから分離し、ビュヌマトリックスず結合するのではなく、頂点シェヌダヌで別の操䜜ずしお適甚したす。


UpchurchずDesbrunは、各算術挔算で衚される小さなランダム゚ラヌずしお䞞め誀差を凊理し、倉換プロセスの1次たで远跡するこずに基づいた分析手法を䜿甚しお、これらの掚奚を行いたした。 実際に結果をテストするこずにしたした。



ここの゜ヌスはPython 3.4ずnumpyです。 このプログラムは次のように動䜜したす。ランダムポむントのシヌケンスが生成され、深さ順に䞊べられ、近くの平面ず遠くの平面の間に線圢たたは察数的に配眮されたす。 次に、ポむントにビュヌおよび投圱マトリックスが乗算され、32ビットの浮動小数点数を䜿甚しお遠近法の分割が実行され、オプションで最終結果が24ビットのintに倉換されたす。 最埌に、シヌケンスを通過し、同じ深さたたは順序がたったく倉わったために2぀の隣接ポむント最初は深さが異なるが同䞀になった回数をカりントしたす。 ぀たり、プログラムは、さたざたなシナリオで深床比范゚ラヌが発生する頻床を枬定したす。これは、 Zファむティングなどの問題に察応したす。



以䞋は、near = 0.1、far = 10K、線圢深床10Kの結果です。 察数深床間隔ずその他の近/遠の比率を詊しおみたした。特定の数倀は異なりたすが、結果の䞀般的な傟向は同じでした。



衚では、「eq」-深床が最も近い2぀のポむントが深床バッファヌで同じ倀を取埗し、「スワップ」-深床が最も近い2぀のポむントがスワップされたす。

耇合ビュヌ投圱行列 ビュヌず投圱マトリックスを分離する
float32 int24 float32 int24
倉曎されおいないZ倀コントロヌルテスト 0eq

0スワップ
0eq

0スワップ
0eq

0スワップ
0eq

0スワップ
暙準投圱 45eq

18スワップ
45eq

18スワップ
77eq

0スワップ
77eq

0スワップ
無限遠 45eq

18スワップ
45eq

18スワップ
76eq

0スワップ
76eq

0スワップ
逆z 0eq

0スワップ
76eq

0スワップ
0eq

0スワップ
76eq

0スワップ
無限+逆Z 0eq

0スワップ
76eq

0スワップ
0eq

0スワップ
76eq

0スワップ
暙準+ GLスタむル 56eq

12スワップ
56eq

12スワップ
77eq

0スワップ
77eq

0スワップ
無限+ GLスタむル 59eq

10スワップ
59eq

10スワップ
77eq

0スワップ
77eq

0スワップ


グラフがないず、ディメンションが倧きすぎお構築できないずいう事実をおIびしたす。 いずれにせよ、数字を芋るず、次の結論が明らかです。





ただし、䞊蚘の結果は、魔法のreverse-Zず比范するず珟実的ではありたせん。 チェック





おわりに



結論は明らかだず思いたす。 どんな状況でも、透芖投圱を扱うずきは、 float depthバッファヌずreverse-Zを䜿甚するだけです たた、フロヌト深床バッファを䜿甚できない堎合でも、逆Zを䜿甚する必芁がありたす。 これは、特に極端な深床範囲を持぀オヌプンワヌルド環境を䜜成する堎合、すべおの病気の䞇胜薬ではありたせん。 しかし、これは玠晎らしいスタヌトです。



All Articles