2007年08月
GPUプログラミング時の基本的な要素として、半透明プリミティブ(または半透明トライアングル、トランスルーセンシ・ポリゴン等)の並び替え処理(ソート処理)が挙げられる。図にあるように、半透明プリミティブは描画順序によってブレンド結果が異なってくるため、より良い見た目を醸し出すためにはプリミティブを視点から見て奥側から描画しなくてはならない。これは単純な様子でいて、割り切れば実際に簡単、正しくやろうとするとキリがない類の処理だ。また、あまりに基本的過ぎて注目されることも少ない点でもある。
ここではゲーム機、ゲームプログラムではどのように半透明ソートを行なっているのか、今後どのような手法が期待されているのか、についてさらっとメモ。
●オブジェクトごとにソート
殆どのタイトルでよく見られる現実的な解決策。
キャラクタ単位、壁単位など適当な単位に描画順序を並べ、半透明プリミティブは奥から描画していく。オブジェクト内での破綻については無視してしまう。なお、同じくソートしたオブジェクト内の不透明プリミティブはHi-Zを有効活用するため手前から描画するのが効率よい。
●ソートしない
アルファソートしない、というのも現実的な、そして潔い選択肢だ。
副作用としては、
・カメラの向き等の描画順序に依存して描画結果が変わる
・深度バッファ更新も一緒にしてしまうと、手前の半透明プリミティブに奥のプリミティブが刈り取られることが結構目立つ。
「ファイナルファンタジーX」ではこの点と、モーション圧縮の誤差が結構目立ち惜しまれる。(この後「ファイナルファンタジーX-2」等のエンジンでは改善されている)
●全プリミティブをソート
半透明プリミティブをいったんバッファリングして、CPUで頑張って全部並び替える。ソートの際には参照点としてプリミティブの重心を使ったり、近傍点を使ったり、いくつかのオプションがある。いずれにしてもプリミティブ同士が交差している場合は破綻する。その際にさらにプリミティブを分割することもオフラインレンダリングなどでは有り得るが、リアルタイム処理ではあまり聞かない。
●AlphaToCoverage
これはもしかすると今後最も有望な解決策だろう。AlphaToCoverageはMSAA/FSAAのカラーバッファに対して、アルファ値に応じたディザパターンを生成してサブピクセルを打ち込む。その結果が描画後段のバッファ・リゾルブ時のブレンド処理され、半透明描画として表示される。サブピクセル毎に深度比較が行なわれるため、(サンプル数が十分であれば)確率的にソートに依存しないプリミティブブレンドが実現できる。サンプル数が少ないとαブレンド階調が少ない、ディザパターンが目立つ、などの副作用が発生してしまう。
4サンプルのMSAA/FSAAではプレステ1相当の4段階でソート不必要なアルファブレンドが実現できる。モダンなGPUでは16サンプル以上のMSAAに対応しており、実用間近だろう。
http://www.humus.ca/index.php?page=3D&ID=61
AlphatoCoverage解説
なお、往年のセガサターンでは50%の半透明プリミティブ(変形スプライト)を実現するのにディザパターン表示を行なっていたが、AlphaToCoverageの原型に近いかもしれない。
●Aバッファ/Rバッファのハードウェア実装
今後のハードウェア実装が一部で示唆されている手法。
カラーバッファと深度バッファをカスケード的に持たせて最上層からN重ね合わせ(nはバッファ数)を実現というもの。
現行のDepth/Stencil処理、ラスタオペレーション処理をより発展させたものと言える。希望としては、ラスタオペレーション処理をもっとプログラマブルに、ラスタオペレーションシェーダ的になると嬉しい。
●その他の人たち
・デプス・ピーリング
マルチパス描画を駆使したややトリッキーなソフトウェア実装。感覚としては、キャラクタ・ジェネレータの合成をソフトウェアで実装しました的アルゴリズムといえる。キャラクタジェネレータの半透明合成では、画面最上層、二層目、n層目といった風にブレンド処理を管理する。
アルファソートだけのためにマルチパス描画を行なうのも大変、ということで実際のタイトルで使用されている例はあまり聞かない。
・タイル描画によるアルファソート
往年のDreamcastのPowerPV等、ImaginationTechnology(http://www.imgtec.com/)GPUで実現されていた夢の機能。
原理としては半透明プリミティブ描画を全てバッファリングしておき、GPU内で一気に処理するもの。全画面分の中間バッファを持つことは困難であるため、画面を小矩形のタイルに分割してレンダリングする。
が、実際にはプリミティブの重ねあわせが増すにしたがってO(n^2)的に描画負荷が高くなり、無制限な半透明描画とはならなかった。またディスプレイリストを完全にローカルメモリに置かねばならない点もレイテンシ増大、メモリ負荷、等のデメリットがある。
・カラーバッファ駆使手法
2007年GDCで発表されていた手法で、下記サイトにプレゼン資料が上げられている。
http://www.houmany.com/htmls/grafx.html
結局のところ同時に描画するNプリミティブは選択する必要があるようで、いまひとつ実用度が不明。
ざっとこのような手法が半透明プリミティブ描画に関する現状と今後だろうか。パーティクル全盛の今日、半透明プリミティブのソートはますます重要性を増していくだろう、多分。
追記:
Hiroyuki OgasawaraさんによるDX10シェーダベースの半透明ソート実装
http://wlog.flatlib.jp/?itemid=1098
手法としては浮動小数点MRTにうまくレイヤを畳み込んでくもの
気になるの点としては、RTとSrcTextureが同一となっているため
レンダリング直後にSrcTextureを参照した場合のコヒーレンシがいじされるのかどうか。 HWによって違いそう?
コメント(4) | トラックバック(0) | ゲーム機の技術






