レンダリング最終工程~レンダーバックエンド
ピクセルシェーダの出力は、ずばりいえば「ポリゴンを構成するその画素が、そのシーンではその色に決定されました」ということであり、そのままビデオメモリに書き込んで「1ピクセルの描画処理完了」としたいところなのだが、まだやることがある。
それが[10]のレンダーバックエンド(Render Backend)だ。ちなみにNVIDIAの場合はこの部分をROPユニットと呼んだりしている。ROPユニットはRendering Output Pipeline、あるいはRaster OPerationの略という諸説があるが定かではない。なお、本連載では前者を正解と解釈しておく。
いずれにせよ、ここではピクセルシェーダからの出力を「書き込んでよいものかの検証」、書き込む際には「どう書き込むかの決定」などの、ビデオメモリへの書き込み制御部分になる。ピクセルシェーダ自身はテクスチャを読み出せても、ビデオメモリに書き出せないので、この処理は極めて重要な部分になる。
ところで、DirectX 9/SM2.0世代以前のGPUではピクセルシェーダの個数とROPユニットの個数が常に一致していたので、ピクセルシェーダとROPユニットは"対"のような関係をイメージできていた。しかし、DirectX 9/SM3.0世代以降のGPUでは、ピクセルシェーダプログラムの高度化に伴い、ピクセルシェーダの個数の増強が重点的に行われ、結果、ROPユニットの個数はピクセルシェーダの個数よりも少ないことが一般的となっている。
最近のGPUではピクセルシェーダ>ROPユニットの構成が一般的となった。図はGeForce 7800 GTXのブロックダイアグラム。中段の4×6=24基がピクセルシェーダ。最下段の16基がROPユニット |
「書き込んでよいものかの検証」としては「アルファテスト」「ステンシルテスト」「深度テスト」といったものがある。
アルファテストは出力するピクセル色が完全に透明かどうかのテスト。α要素が0で透明であれば描き込む必要がないのでそのピクセル描画は破棄される。
ステンシルテストは多目的な演算フレームバッファとして利用されるステンシルバッファの内容に従って、アプリケーションが設定した条件にパスできないとそのピクセル描画は破棄される。画面の一部をくりぬいたり、ステンシルシャドウボリューム技法による影生成の影型抜き処理などの際に応用される。
深度テストはこれから描画するピクセルが、視点から見て一番手前になってちゃんと見えるピクセルとなるかどうかを検査するもの。描画するピクセルと1対1に対応するZバッファと呼ばれる奥行き値(Z値、深度値)を格納したバッファをあらかじめ用意しておき、ここから読み出した奥行き値と、これから描画しようとしているピクセルの奥行き値とを比較するのが「深度テストの実態」だ。奥行き値はピクセルシェーダによって算出する。
なお、半透明の3Dオブジェクトを構成する半透明ピクセルの描画などの場合などはこの深度テスト自体を行わない場合もある。
「どう書き込むかの決定」のバリエーションとしては「α合成(αブレンディング)」、「フォグ(霧)」などがある。
α合成は、ただピクセルを上書きで描き込むのではなく、既に書き込まれているピクセル色と半透明合成の計算をして書き戻す、という処理を行うもの。レンダリング対象のフレームバッファからピクセル色を読み出す……すなわちビデオメモリの読み出し処理が介在し、さらにα合成計算までも行う必要があるので意外に負荷の高い処理となる。余談だが、3Dベンチマークソフトなどで、半透明ポリゴンの重ね描きを連続的に行ったりするのは、この性能を評価する狙いがあるためだ。
フォグは、これから描画するピクセルの奥行き値に従って、あらかじめ設定しておいたフォグカラーの混ぜ具合を調整する処理を行うもの。奥に行けば行くほどそのピクセル色を白に近づけるような設定にすれば、奥の方が霞んで見える空気遠近の表現が行える。
もちろん、α合成もフォグ処理も行わない場合は、そのピクセル色をそのままビデオメモリへ書き出す処理を行う。そして書き出す際には、次回以降の別ピクセルの深度テストに備えて、奥行き値も更新しておく。
なお、格子型画素配列の画面描画におけるピクセルのカクカクした感じ(ジャギー)を低減させる、アンチエイリアス処理も、このレンダーバックエンドの部分で行われている。
(トライゼット西川善司)