言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

Croquet でのポータル描画の仕組み

忘れないようにメモ。

先に書いたように、ポータルは他の世界へと繋がるどこでもドアで、描画も今いる世界に穴を開けて、向こう側に別の世界が見えるようにしないといけない。これを実現するためにステンシルが使われる。ここで注意すべき事は、

1) ネスト。つまり、ポータルの向こうにもポータルが見えて、さらに奥が見える可能性がある。
2) 同じ視野から複数のポータルが見える可能性がある。

の2点だ。まず 1) から。ステンシルには数字を付けることが出来るから、これは単純にポータルの重なり順に応じた番号を記録してやれば良い。つまり、今の世界から直接見えるポータルを 1 番。ポータルを通してさらに向こうに見える遠くのポータルを 2 番という風にする。そして 2 番のステンシルに穴を開ける時は、1番 の穴より外に広がらないようにする。

ただ、こうすると 2) の時に困る。同じ世界に複数のポータルが見えている場合、それぞれステンシルに穴を開けるのだが、これが混ざってしまう。番号は階層を表現するのに使ってしまうから、ここでは使えない。まあ、ポータルの中身を表示するたびに穴を塞いでしまえば良い話だが、ポータル表示コードにそういう部分が含まれていないのでどうやっているんだろうと思っていた。ここの鍵は z バッファだ。

z バッファは物体の後ろにあるべき画像が表に出てこないように、物の距離を覚えておく時に使う特別なメモリだ。ポータルの奥の世界を描画した後に、この部分のz バッファを強制的にポータル自身位置の z バッファに書き換えてやる。そうすると、奥の世界は見た目上は奥なんだけど、openGL はポータルの位置にノッペリと存在しているかのように扱う。このようにすると他のポータルの為に同じ番号のステンシルの穴をあけ、そこに別の世界を描画しても混ざり合うことは無い。それぞれの世界は別の平面上にあるから、openGL はきちんと描き分ける。

さすがアンドレアス。あったま良いな。