近年、「レイトレーシング」というワードはゲーマーならば一度は聴いたことがあるほど馴染み深いものとなっている。
実際にPS5といえばレイトレーシングと返されるほどプロモーションの段階でも繰り返しアピールがなされてきたし、一度ゲーム内でその効果を味わったために、過去のゲームのグラフィックスでは物足りなく感じるようになったプレイヤーも数しれないはずだ。一方で、レイトレーシングが内部的にどういった処理を経て動作しているのかについて知る人はそう多くないのではないだろうか。
「レイトレーシング ~ 基礎とPS5™における枠組み ~」では、技術者向けにレイトレーシングの概要について解説が行われた。本稿では、その講演を踏まえて筆者が面白いと感じた点をなるべくわかりやすい形でまとめてみようと思う。なお、細かい内容については大部分を割愛した上で可能な限り甘口な内容に落とし込んでいるため、細かい詳細を理解したい場合には講演のタイムシフト録画を確認することをおすすめする。
レイトレーシングってなんだろう?
少し詳しい人ならばレイトレーシングと聞けば、描画したいスクリーンからレイ(Ray)という光線を飛ばし、レイが物体と衝突(交叉)したところで物理的に反射をさせることで、さらにその先まで追いかけてグラフィックをレンダリングする手法のことをイメージするだろう。平たく言えば、水面やガラスの反射を精細に描画するアレのことだ。
しかし実際のところ、レイトレーシングという言葉の意味するものは応用分野や文脈によって大きく異なるようだ。ただしどの場面においても「レイをトレース(追跡)して何らかの形状との交叉判定を行う」という点では共通しているという。交叉(交差)判定とは、レイが物体と衝突しているかどうかを判定するための手法であるが、最も純粋な意味での「レイトレーシング」とは、この交叉判定をそのものを指すようだ。
他にも「レイトレーシング」の指す言葉の意味は物理シミュレーションからサウンドの分野に至るまで様々あるが、本講演では先に上げた交叉判定そのものと定義する。というのも、交叉判定は古典的レイトレーシングを含めたすべての手法の基礎となるもので、PS5で提供されているライブラリについても交叉判定自体が実装されているからだ。つまり、このライブラリを用いればあらゆる場面に対応することができるというわけだ。
PS5内でリアルタイムでレイトレーシングを行うことの本質的な強みとして、周辺環境を正確に把握することが挙げられる。レンダリングの分野で言えば正確な反射表現やアンビエントオクルージョン(影の生成)、間接光の表現などが可能になるということだ。さらにいえばグラフィック改善にとどまらず、リアルタイムで計算を行えるために、より自由な破壊表現を行うことなども期待されている。PS5で既に発売されたタイトルでもレンダリング以外に様々な応用がなされてきたようだ。
PS5で行われる効率的なレイトレーシング
実用的な内容について話そう。レイと物体を交叉判定する際、最も単純な方法をとるならばレイが全物体と交叉しているかどうかを判定すればよい。ただし、仮に画面上に100万個の物体があった場合、総当たりで判定を行うと100万回に及ぶ途方も無い時間がかかることになる。そのため、PS5では効率的に交叉判定を行うための高速化機構が構築されている。
ここからは、高速化機構の中でも典型的なもののひとつで、PS5でもライブラリとして実装されているBounding Volume Hierarchy(BVH)の解説を行う形でレイトレーシングの流れを追ってみよう。どうか、以下の画像に目を通しながら読み進めてみてほしい。
はじめに、レイトレーシングを行いたい画面上の物体のまとまりがあるとしよう。ゲーム画面を単純化したものと考えればいい。問題は、あるレイがどの物体に対して交叉しているかを調べることで、それさえわかってしまえば、そこから先の状態は理屈上は同じ処理の繰り返しですべて計算をし、描画などをすることができる。
そのための準備処理として、まず物体のまとまりを矩形で囲み(画像では赤い枠線による0番の四角形)、さらに矩形内部の物体を分割して、再度囲い込んでいく。下の画像では大雑把に二分割をすることで、0番の内部の物体が1と2の番号が付けられた矩形に分けられたことがわかるだろう。
同時にこの情報をもとに木構造を構築していく。木構造とは誤解を恐れずにざっくりと説明すると、効率的に各要素にアクセスするためのグループ分けのようなものだ。上記画像右側では、物体の集合全体を表す赤い0の矩形を基準にして、グループ分けされた1と2の矩形が二股に分かれて配置されていることがわかるだろう。
この物体の分割と木構造の構築を繰り返していくと、最終的に以下のような状態となる。すべての三角形がどこかのグループに配置されていることがわかるだろうか。この木構造をもとに効率的に判定を行うことで、最終的な判定回数を総当たりよりも少なくすることができる。
例えば画像のようにレイが7番の三角形と交叉していることを判定することを目標としよう。まず木構造の親となる0番の矩形からチェックを行うと、この矩形とレイは交差していることがわかる。そのため、判定範囲を更新し、次は1番と2番の矩形と判定を行う。先に判定を行うのは番号順の関係から1番となるわけだが、1番と矩形は交叉しているため、2番はいったん候補(スタック)に入れておきながら3番と4番の判定に移る。
3番は交叉していないため、次の候補になっている4番の判定を行う。すると4番はレイと交差する。これを繰り返すと7番の矩形とレイが交叉していることがわかるだろう。ところで、2番の矩形も判定すべき候補に入っていたわけだが、既にレイは7番の矩形と交叉していることが知られているため、2番の矩形は判定する必要がないとして候補から捨てるわけだ。
今回は物体の数が6個しか無いために分岐の数は3回となり、あまり判定回数を削減できた気がしないが、この物体が仮に100万個あった場合にはこの方法を取れば理論上は20回程度の分岐で済むことになる。つまり、数が多ければ多いほど圧倒的な差になるということだ。この考え方はアルゴリズムを学ぶ上で計算量(オーダー)と呼ばれるため、興味のある人は調べてみてほしい。
もちろん表示されている物体は常に変形・移動を繰り返すことになるために、この矩形による分割を更新していく必要がある。更新方法は単純に考えれば、先程の工程を繰り返して構造を1から作り直すことと、移動したことを判定して少しずつ修正していく事が考えられる。無論、後者のほうが負担は少ないため、変化があまり大きくないのであれば修正していく形で更新を行いたい。
ここでも、先ほど作成した木構造を利用していくことになる。更新には木構造の末端からチェックを行っていき、それぞれの矩形の移動地点とのズレを補完していくことで、段階的に修正をする。ただし、大きく物体が変化している場合は修正しきれなくなってしまうため、正確な交叉判定が行えなくなってしまう。その時は先程のようにもう一度構造を作り直す必要が出てくるわけだ。
さらに、より効率的に判定を行うため、ここまでで説明した木構造自体を子として二重に木構造を作成する。それぞれの木構造は画面上の一部を担っている。これにより、画面の中で一部の物体のみが動いた場合なら、その一部の木構造のみを更新すればよいわけだ。この構造を宇宙で例えるなら、恒星や惑星(物体)の集まりが銀河(木構造)を形成し、さらにその銀河が更に複数集まることで銀河団(二段階AS)を形成しているといったようなことだろう。
また、上で解説した高速化処理を行うための問題として、本来十分なメモリ容量が必要になることが挙げられるが、PS5では使用したメモリを別のメモリに圧縮してコピー(コンパクション)することで、最終的なメモリ使用量を削減する工夫が凝らされている。他にもリアルタイムレンダリングにおけるレイトレーシングには様々な問題があるが、その多くにはこれといった正解もなく、様々な工夫をこらしてみるしかないということが現状のようだ。
PS5でのレイトレーシングライブラリでは上で行われた高速化処理や、先程触れた様々な問題点に対して可能な限り良い形で対応された実装が提供されているため、クリエイターは複雑な実装をすることなくすぐにレイトレーシングを使い始めることができる。それだけでなく、必要に応じて高速化処理などのチューニングも行うことができることが強調された。
いかがだっただろうか。今回は講演をもとに、非プログラマでも理解がしやすそうな箇所をとりあげてより詳細に解説を行ってみたが、もしこれを読んでレイトレーシングに興味が湧いてみたら趣味で実装に挑戦してみるのもよいだろう。もしかしたらあなたも将来、PS5を支えるグラフィックエンジニアとして活躍しているかもしれない。
からの記事と詳細 ( PS5の内部処理をわかった気になってみよう ~素人でもわかる レイトレーシング編 ~【CEDEC2021】 - IGN Japan )
https://ift.tt/3jgZoG4
No comments:
Post a Comment