Top > プログラミング関連 > Zバッファのウマい使い方 その2 - 無限に遠いオブジェクトの描画
2008/2/28 記述
Zバッファとは、3D空間内の奥行き情報を保持するバッファ。もう少し詳しい説明については前回の説明を参照。
さて、この記事を書いている時点で、私はFPSと呼ばれる一人称視点のゲームを作っている。プレイヤーは主人公と同一の視点を持つ、そんなゲームだ。
一般にFPSでは武器は視界内に描画される。主人公目線でゲーム世界を表現した結果と言える。武器の描画は、内部処理でも主人公の腕のあたりに3Dメッシュを描画することで行っている。ゲーム世界のオブジェクトと全く同じ処理である。
ここで、主人公は壁に向かって走り、額が接触するぐらいまで可能な限り壁に接近したとしよう。そのとき主人公の視界には迫り来る壁とともに手に持った武器がある(図1)。ところが、よく見ると武器の先端は壁にめり込んでしまっている。本来は図2のようにあるべきだ。というか、市販のFPSでは手に持った武器は壁にめり込まない。
何が起こったのか。ゲーム空間内で武器の3Dメッシュが壁の3Dメッシュにめり込んでいる。3D描画は正しくメッシュ間の前後関係を把握し、あるがままの姿を描き出した。それだけのことである。しかしそれではプレイヤーは納得しない。バグだと言われるか、良くてもクオリティーが低いと言われてしまう。
ではどうすれば武器を壁にめり込まさないことが出来るのか。結論から言う。Zバッファを一旦クリアするのである。クリア後に描画されるオブジェクトは、クリア前に描画されたあらゆるオブジェクトよりも手前にあることになる。
普段はZバッファの恩恵により正しい世界が描画されている。「ゲーム内の建物を描画」→「武器を描画」という手順を取っていれば、武器の描画の直前でZバッファ内には奥行き情報が格納されている。武器を描画する前にZバッファをクリア[全てのピクセルを1.0f(最遠方)で塗りつぶす]してやれば、その時点で全てのオブジェクトが武器よりも遠方にあることになる。こうして武器のめり込み問題は解決した。
この手法で、無限に遠い、すなわちあらゆるオブジェクトよりも奥にあるオブジェクトを描画できるようになった。
実は、前述の画像で武器以外にも同じ手法を用いている箇所がある。あらゆる建物より遠くにある「空(Sky)」である。プログラム内では、主人公目線を中心とした球を描画することで空を表現している。全体の流れは以下のようになる。
ここで、空の描画直後のZバッファクリアを省略するとどうなるのかを図3で示した。意味不明な画像で申し訳ない。簡単に説明すると、空の模様が描かれた直径1メートルのヘルメットの中に頭を突っ込まれたのと同じ状態である。かろうじて"ヘルメット"の中にめり込んできた壁の一部だけが描画されている。