Zバッファ
Zバッファ(英: Z-buffer)は画像の奥行き情報を一時的に保持する領域である[1]。深度バッファ(英: depth buffer)とも。
Zバッファ法(ぜっとばっふぁほう、英: Z-buffering)はZバッファを用いた隠面消去法である[1]。
概要
[編集]3次元コンピュータグラフィックスのレンダリング段階では、奥にある物体が手前にある物体で隠れた状態(遮蔽/オクルージョン)を表現するために隠面消去が必要である。
Zバッファ法は各画素の深度情報を保持するバッファを参照して描画の有無を判定し隠面消去を実現する手法である[1]。まず、画面(レンダーターゲット)内において、あるピクセルに物体を描画する際に、物体表面の深度(奥行き)を保存しておく。ここでは例えば視点から最も手前の深度値をゼロと定め、奥に進むにつれて深度値が大きくなるものと定める。次に同じピクセルに物体を描画することになった場合、前回保存した深度の値と今回描画する物体の深度の値の大きさを比較する(深度テスト)。もし今回の深度の方が大きければ、つまり奥にあれば、手前の描画済み物体に隠されて見えないので、新たにピクセルへ描画処理を行なわずに済むことになる。このため、手前に存在する物体から描画して、最後に奥に存在する物体を描画するようにすれば、計算時間を節約することができる。
このとき画面全体の深度をまとめて保存しておく領域はZバッファと呼ばれる。Zバッファは一般に2Dテクスチャの一形態として扱われる。
Zバッファという名前は、Z-coordinate(3次元空間の次元軸を表すXYZのうち、通例奥行きを表すことが多いZ軸の座標値)を保存するバッファ(一時領域)であるところから来ている。Zバッファは通例浮動小数点数を格納できるフォーマットであり、リアルタイムコンピュータグラフィックスでは16ビット、24ビット、32ビットなどがよく使われる。
計算資源の制約が多いリアルタイムグラフィックス用途では特に効果的な技術であり、2015年現在では流通するほぼあらゆるハードウェア(グラフィックスカード/グラフィックスチップ)で使用することができる。
同種として、より描画精度を向上させられるWバッファという技術もある[2][3]が、Zバッファほどの広範なハードウェアサポートはない。
深度テスト
[編集]深度テスト(しんどてすと、英: Depth test)はZバッファ値と入力深度値の大小比較である[4]。Zテスト(英: Z test)とも。
深度テストはピクセル単位で実行される。
深度テストが実行されるタイミング(グラフィックスパイプライン上のステージ)はいくつかありえる。ピクセルシェーダー前に行われる深度テストを Early Z test、後に行われる深度テストを Late Z test と呼ぶ場合もある[5]。
古典的なレンダリングにおいて深度テストは Late Z test として実行される。この場合大半の描画済みピクセルはテストにより捨てられ無駄なピクセルシェーダー処理が走ったように見えるが、ピクセルシェーダーは深度値の上書きが可能なため必要なコストである[6]。特定の条件を満たした場合であれば Early Z test によってピクセルシェーダーをスキップし効率的に描画できる。
更なる最適化を考えると深度テストの実行順序が問題になる。空のZバッファに対して最背面部分の Early Z test をおこなうとバッファが空なのでテストパスし最背面なのに描画されてしまう。また手前寄りの部分を描画したあとに最前面が来ると結局テストパスして再描画されてしまう。つまりフラグメントシェーダーの実行を最小回数に抑えるには最前面から深度テストをしなければならない。これは矛盾していて、最前面が事前に分かっているのなら深度テストせずに最初から最前面だけ描画すればよい。
これを解決するレンダリングテクニックが depth pre-pass である。Early Z test 可能条件であることを前提に、全モデルのジオメトリパス(≒ピクセルシェーダー無し)をまず実行して完全なZバッファを完成させる。この小さなパスが depth pre-pass である[7]。このパスによって最前面で埋まったZバッファが得られる。このZバッファがあるということは「Early Z test をパスしたらすなわち最前面」という状態を意味するため、このZバッファを使ったうえで各モデルのレンダリングパイプラインを通常通り動かすと最前面以外がすべて事前破棄されるピクセルシェーダー最小実行回数が実現できる[8]。
問題点
[編集]半透明の物体をアルファチャンネルによって合成描画(ブレンディング)する際には、単純なZバッファの比較だけでは正しい結果が得られない。ブレンディングの際には奥に存在する物体の情報が必要だが、もし手前から描画してしまうと、合成するために必要な奥に存在する物体の情報が参照できないからである。また、奥に存在する物体の描画自体がZテストによりスキップされてしまう。この問題を緩和するには、まず不透明の物体のみを先に描画しておき、次に半透明の物体だけZソート法で奥から順に描画するなどの手法を用いる必要がある。そのほか、Order-Independent Transparency (OIT、順序非依存の透明度) という解決策も存在する。
また、近接する複数のプリミティブ(ポリゴン)を描画するときに、背面のプリミティブの一部のピクセルが前面のプリミティブ上にレンダリングされたり、その逆になったりする、Zファイティングと呼ばれるアーティファクト(ノイズ)が発生してしまい正しい結果が得られないことがある[9]。特に広大な空間を描画するときに、Zバッファの精度が不足しているとZファイティングが発生しやすくなる。Zファイティングを回避する方法として、Zバッファの精度を上げる、深度バイアスをかける、ステンシルバッファを利用する[10]、などがある。ただしZバッファの精度を上げると、その分メモリを多く消費するようになる。また、画面解像度に比例してZバッファの必要量も増加していく。
ゲームコンソールとZバッファ
[編集]初代PlayStation (PS1) [11]や3DO、セガサターンにはZバッファが搭載されていなかった。そのため、ポリゴン単位で前後関係を判定するZソート法が使用されていた。この方法はZバッファよりも省メモリであるというメリットがあるが、一方で交差するポリゴンを正しく描画できない、ソートのための処理時間を必要とする、などのデメリットもある。
なお、NINTENDO64にはZバッファが搭載されていた。以降、PlayStation 2やドリームキャストなどの後継機種では、Zバッファが搭載されることが標準的になっていった。
脚注
[編集]- ^ a b c "Zバッファ法 画素毎に奥行き判定を行い隠面消去 Zバッファ: 画像の奥行き情報を保存した一時領域 フレームバッファ: 画素毎に色を格納" 以下より引用。藤堂. (2015). 第8回 レンダリング技法1 ~基礎と概要,隠面消去~. 明治大学講義「コンピュータグラフィックス」.
- ^ W-Buffering
- ^ Depth Buffers (Direct3D 9) - Windows applications | Microsoft Docs
- ^ "The depth test compares the framebuffer depth coordinate
Zf
with the depth valueZa
in the depth attachment." Khronos. Vulkan Guide - Using Vulkan - Depth. Vulkan Documentation. 2024-08-17閲覧. - ^ "Early ZS testing ... it happens before any pixels are colored in by fragment shading. ... Late ZS testing happens after all the fragment shading work has been done" 以下より引用。arm. Depth (Z) and stencil (S) testing. arm Developer documentation. 2024-08-17閲覧.
- ^ "For example, if a shader programmatically modifies
gl_FragDepth
, early ZS testing cannot be used, and late ZS testing is forced." 以下より引用。arm. Depth (Z) and stencil (S) testing. arm Developer documentation. 2024-08-17閲覧. - ^ "The depth-prepass renders the geometry without writing colors in the framebuffer." 以下より引用。arm. Use depth pre-pass. Arm Developer Documentation. 2024-08-17閲覧.
- ^ "The depth-prepass ... initializes the depth buffer for each pixel with the depth of the nearest visible object. After this pre-pass the geometry is rendered as usual but using the Early-Z technique, only the objects that contribute to the final scene are actually rendered." 以下より引用。arm. Use depth pre-pass. Arm Developer Documentation. 2024-08-17閲覧.
- ^ Configuring depth-stencil functionality - Windows UWP applications | Microsoft Docs
- ^ Stencil buffers - Windows UWP applications | Microsoft Docs
- ^ [GDC07#36]髪型・半透明・物理音源,20分セッションあれこれ - 4Gamer.net