私たちはAlex Lovett さんと再びチームを組んで、Unity 5のリアルタイムGI機能を活かしたThe Courtyardというデモを作りました。彼は以前建築ビジュアリゼーション向けに Shrine Arch-viz デモを作りましたが、今回のゴールはゲーム開発者が必要とするリアルタイムのフレームレートを実現するデモでした。まずはこのビデオをご覧ください:
Alexさんはアセットストアの追加パッケージなしにUnity 5.2だけを使い、このデモを8週間ですべてゼロから制作しました。
このデモはリアルタイムGIとライティングだけで構成されています。デモには日夜をシミュレートする時刻サイクル、発光するジオメトリ、夜間に点灯する100程度のアニメーション付きスポットライトと、さらにスタンドにあるたくさんのフロアライトとプレイヤーのフラッシュライトが入っています。時刻サイクルは太陽と連動したアニメーション付きスカイボックスを使い、微妙な光の変化を実現しています。私たちがリリースしたプレイアブルデモでは、インゲームでこれらのすべてのライトをコントロールできるUIが追加されています。デモの入手方法等はブログの後半をご覧下さい。こちらに異なる時間帯のスクリーンショットをいくつか掲載しました:
シーンは特にライティングに対して多くの要求をするように作成されました。シーンの大部分はバウンスライトでのみ照らされますが、とくに日没後はシーンのほぼすべてがバウンスライトでライティングされます。
リアルタイムGIシステムはシーンの静的なオブジェクト間を光が通るパスをすべて事前計算しておくことで動作します。この処理を行うことでライトの調整を(例えばレイトレーシングのように)待たされる事なくリアルタイムで出来るようになります。なぜなら、システムはすでにライトの変更によってどのような影響があるかを高速に計算するために必要な全ての情報を持っているからです。しかしながら、これは静的なジオメトリーが変更されない必要がある、ということでもあります。静的ジオメトリーを変更すると再度事前計算が必要となるためです。このため、シーンを作成する時には、まずモデリングと配置を行い、次にライティングを行う、という2つのステージに分けるのが最も合理的な作り方になります(両方終わったら必要に応じて再度この工程をリピートします)。無計画に静的ジオメトリーを動かしながらライトの調整も同時にやろうとすると、ライティングのビルドが沢山発生してしまいます。私たちは将来のUnity 5.xにてよりインタラクティブでプログレッシブなライティングワークフローが実現できるよう取り組んでいますが、それに関する詳細はまた別のブログ記事でお話しします。
このデモはデスクトップPCとコンソールゲーム機に向けて制作したものですが、モバイルプラットフォームでのリアルタイムGIの利用についてはTransporterデモについて書いたUnity 5のGIのブログ記事を参照してください。
Unity 5のリアルタイムGIシステムはGeomerics社のEnlightenを使い、ゲーム用に使えるように設計されています。すべてのライティングの計算はCPUのワーカースレッドで非同期に計算されます。ほとんどのゲームはGPUが先にボトルネックになるので、(別スレッドに分けられている)CPU側での計算処理の追加は、ゲーム全体のフレームレートには影響しにくい存在と言えます。さらに、再計算はライティングの変更があった部分だけに対してされるようになっています。
ゲーム内のライティングのレイテンシーは、選択されたリアルタイム間接ライトマップの解像度に依存します。このデモではAlexさんは応答性を重視して解像度をそこそこ低めに設定しましたが、それでも望むライティング精度と間接照明で照らされたエリアの微妙さを実現しています。
このデモでは、間接ライトマップの解像度は以下のように設定されています:
解像度のバランスを取るために、シーン全体で平均0.25テクセル/ユニットの解像度になるように調整されています。そこからカスタムライトマップパラメーターを使ったマルチプライヤーが追加され、すばらしいライティングと15分程度の事前計算時間を成立させています。
下記のスクリーンショットはシェーディングされたシーンの全体像と、Enlightenによって生成されたさまざまなデータのスクリーンショットです。それぞれ、間接ライトマップの解像度を表すUVチャートビュー、バウンスライトの照明を受け持つクラスター、バウンスライト、 スペキュラと軸外しジオメトリ(off axis geometry)のライティングに使用するライト指向性(lighting directionality) です:
ライトマップ用の良いUVを作るために一手間かけられています。シーン中のいくつかのケースではモデルがライティングの事前計算とラインタイムの両方でよい結果になるよう、注意深くオーサリングされています。このうちの一つのケースは階段のモデルです。
階段は、テクセルサイズを大きくすると1段以上をカバーしてしまうことがあります。こうなると段によってライトの結果に意図しない差が生じてしまうということが起こります。しかしながらたくさんのテクセルを割くとパフォーマンスの観点からは高くついてしまいます。このシーンで使用された階段は縁もついているため、リアルタイムGI用にアンラップ&パッキングすると、不要なチャートができる上にテクセルスペースを多く占有してしまいます。当初、階段のリアルタイムGIのUVレイアウトは以下のようなものでした:
これは70x72テクセルのリアルタイムライトマップを占有しました。このレイアウトには2つの問題があります。まず最初に、一段ごとに4x4テクセルが割り当てられていますが、これは使い過ぎです。次に縁の部分が別のチャートに分けて割り当てられており、これも4x4テクセル使っています。なぜこれらはそれぞれ1テクセルだけを使うようにできないのでしょうか?第一にこれはEnlightenがランタイムでテクスチャーを処理する時に2x2のテクセルブロックを使うよう最適化されているためで、チャートは最低でも2x2テクセル分使用することになります。第二の理由は、Enlightenが球やシリンダーのような形状に対して滑らかな結果を得るためのチャートを縫合するステッチング機能を持っていることにあります。この機能を利用するにはチャートのそれぞれの辺が異なる向き情報を持っている必要があります。向きの情報はブロック毎でのみ保存されるので、ステッチ可能なチャートは最小でも2x2ブロック - つまり4x4テクセルが必要になるわけです。しかし、階段ではステッチングは必要ないので、2x2のテクセルチャートで十分です。
私たちは、ライティングパネルのObjectのプロパティでこの設定を変更可能にしました:
この値は指向性(directionality)を使う設定でもステッチングがうまく機能する4か、よりコンパクトな2が選択できます。チャートの最小サイズを2に設定するオプションはテクセルの密度を大きく削減します。この変更で階段モデルは44x46テクセルのリアルタイムライトマップに収まりました:
よく見ると縁がまだ不要にチャートスペースを埋めています。縁の部分はUVスペースでは階段のステップの一部として創られているので、ちょっと予想外の状態です。下記のイメージはモデルにUVの境界をオーバーレイしたものですが、縁の部分がステップの一部として扱われていることがわかります:
ライトマッピングのUVの2Dビューでは、縁の部分は現れません。これはなぜなら縁はステップの一部としてステップのチャートにまとめられていて、UVスペースでは個別の領域を持っていないためです。これはライティングのシミュレーションが縁の傾斜を処理することを避けるために意図して設定されました。