Search Unity

私たちはAlex Lovett さんと再びチームを組んで、Unity 5のリアルタイムGI機能を活かしたThe Courtyardというデモを作りました。彼は以前建築ビジュアリゼーション向けに Shrine Arch-viz デモを作りましたが、今回のゴールはゲーム開発者が必要とするリアルタイムのフレームレートを実現するデモでした。まずはこのビデオをご覧ください:

Alexさんはアセットストアの追加パッケージなしにUnity 5.2だけを使い、このデモを8週間ですべてゼロから制作しました。

このシーンに一切のベイク済みライトなし

このデモはリアルタイムGIとライティングだけで構成されています。デモには日夜をシミュレートする時刻サイクル、発光するジオメトリ、夜間に点灯する100程度のアニメーション付きスポットライトと、さらにスタンドにあるたくさんのフロアライトとプレイヤーのフラッシュライトが入っています。時刻サイクルは太陽と連動したアニメーション付きスカイボックスを使い、微妙な光の変化を実現しています。私たちがリリースしたプレイアブルデモでは、インゲームでこれらのすべてのライトをコントロールできるUIが追加されています。デモの入手方法等はブログの後半をご覧下さい。こちらに異なる時間帯のスクリーンショットをいくつか掲載しました:

シーンは特にライティングに対して多くの要求をするように作成されました。シーンの大部分はバウンスライトでのみ照らされますが、とくに日没後はシーンのほぼすべてがバウンスライトでライティングされます。

リアルタイムGIシステムはシーンの静的なオブジェクト間を光が通るパスをすべて事前計算しておくことで動作します。この処理を行うことでライトの調整を(例えばレイトレーシングのように)待たされる事なくリアルタイムで出来るようになります。なぜなら、システムはすでにライトの変更によってどのような影響があるかを高速に計算するために必要な全ての情報を持っているからです。しかしながら、これは静的なジオメトリーが変更されない必要がある、ということでもあります。静的ジオメトリーを変更すると再度事前計算が必要となるためです。このため、シーンを作成する時には、まずモデリングと配置を行い、次にライティングを行う、という2つのステージに分けるのが最も合理的な作り方になります(両方終わったら必要に応じて再度この工程をリピートします)。無計画に静的ジオメトリーを動かしながらライトの調整も同時にやろうとすると、ライティングのビルドが沢山発生してしまいます。私たちは将来のUnity 5.xにてよりインタラクティブでプログレッシブなライティングワークフローが実現できるよう取り組んでいますが、それに関する詳細はまた別のブログ記事でお話しします。

リアルタイムGIに向けたオーサリング

このデモはデスクトップPCとコンソールゲーム機に向けて制作したものですが、モバイルプラットフォームでのリアルタイムGIの利用についてはTransporterデモについて書いたUnity 5のGIのブログ記事を参照してください。

Unity 5のリアルタイムGIシステムはGeomerics社のEnlightenを使い、ゲーム用に使えるように設計されています。すべてのライティングの計算はCPUのワーカースレッドで非同期に計算されます。ほとんどのゲームはGPUが先にボトルネックになるので、(別スレッドに分けられている)CPU側での計算処理の追加は、ゲーム全体のフレームレートには影響しにくい存在と言えます。さらに、再計算はライティングの変更があった部分だけに対してされるようになっています。

ゲーム内のライティングのレイテンシーは、選択されたリアルタイム間接ライトマップの解像度に依存します。このデモではAlexさんは応答性を重視して解像度をそこそこ低めに設定しましたが、それでも望むライティング精度と間接照明で照らされたエリアの微妙さを実現しています。

このデモでは、間接ライトマップの解像度は以下のように設定されています:

  • 中央のエリアは 2ユニット毎に1テクセル (例: 0.5テクセル/ユニット)。
  • 中央のエリアに近い砂丘は、10ユニット毎に1テクセル。
  • 外側のエリアは32ユニット毎に1テクセル。

解像度のバランスを取るために、シーン全体で平均0.25テクセル/ユニットの解像度になるように調整されています。そこからカスタムライトマップパラメーターを使ったマルチプライヤーが追加され、すばらしいライティングと15分程度の事前計算時間を成立させています。

下記のスクリーンショットはシェーディングされたシーンの全体像と、Enlightenによって生成されたさまざまなデータのスクリーンショットです。それぞれ、間接ライトマップの解像度を表すUVチャートビュー、バウンスライトの照明を受け持つクラスター、バウンスライト、 スペキュラと軸外しジオメトリ(off axis geometry)のライティングに使用するライト指向性(lighting directionality) です:

ライトマップ用の良いUVを作るために一手間かけられています。シーン中のいくつかのケースではモデルがライティングの事前計算とラインタイムの両方でよい結果になるよう、注意深くオーサリングされています。このうちの一つのケースは階段のモデルです。

階段は、テクセルサイズを大きくすると1段以上をカバーしてしまうことがあります。こうなると段によってライトの結果に意図しない差が生じてしまうということが起こります。しかしながらたくさんのテクセルを割くとパフォーマンスの観点からは高くついてしまいます。このシーンで使用された階段は縁もついているため、リアルタイムGI用にアンラップ&パッキングすると、不要なチャートができる上にテクセルスペースを多く占有してしまいます。当初、階段のリアルタイムGIのUVレイアウトは以下のようなものでした:

use_normals_4_texels_ptx

これは70×72テクセルのリアルタイムライトマップを占有しました。このレイアウトには2つの問題があります。まず最初に、一段ごとに4×4テクセルが割り当てられていますが、これは使い過ぎです。次に縁の部分が別のチャートに分けて割り当てられており、これも4×4テクセル使っています。なぜこれらはそれぞれ1テクセルだけを使うようにできないのでしょうか?第一にこれはEnlightenがランタイムでテクスチャーを処理する時に2×2のテクセルブロックを使うよう最適化されているためで、チャートは最低でも2×2テクセル分使用することになります。第二の理由は、Enlightenが球やシリンダーのような形状に対して滑らかな結果を得るためのチャートを縫合するステッチング機能を持っていることにあります。この機能を利用するにはチャートのそれぞれの辺が異なる向き情報を持っている必要があります。向きの情報はブロック毎でのみ保存されるので、ステッチ可能なチャートは最小でも2×2ブロック – つまり4×4テクセルが必要になるわけです。しかし、階段ではステッチングは必要ないので、2×2のテクセルチャートで十分です。

私たちは、ライティングパネルのObjectのプロパティでこの設定を変更可能にしました:

params - Copy

この値は指向性(directionality)を使う設定でもステッチングがうまく機能する4か、よりコンパクトな2が選択できます。チャートの最小サイズを2に設定するオプションはテクセルの密度を大きく削減します。この変更で階段モデルは44×46テクセルのリアルタイムライトマップに収まりました:

use_normals

よく見ると縁がまだ不要にチャートスペースを埋めています。縁の部分はUVスペースでは階段のステップの一部として創られているので、ちょっと予想外の状態です。下記のイメージはモデルにUVの境界をオーバーレイしたものですが、縁の部分がステップの一部として扱われていることがわかります:

stairs_uv

ライトマッピングのUVの2Dビューでは、縁の部分は現れません。これはなぜなら縁はステップの一部としてステップのチャートにまとめられていて、UVスペースでは個別の領域を持っていないためです。これはライティングのシミュレーションが縁の傾斜を処理することを避けるために意図して設定されました。

stairs_uv4

ステップと縁が別々のチャートに分けられてしまっている理由は、リアルタイムGIで使用されるUVはインスタンス毎の実際の解像度にあわせて再パックされる必要があるためです。パッキングのアルゴリズムは、隣の領域の内容が漏れ出ることを避けるためにチャートの周りに半テクセルの境界があることを保証します。これはインスタンス毎のUVでマージンをパッキングしなくてよく、テクスチャーアトラスをうまく使えるように保証してくれます。

問題は、今回の例ではステップと縁の間にあるエッジのような、ハードエッジがある場合です。ハードエッジではそれぞれの面が別の法線を持たなければならないので、モデルインポーターはインポート時にすでにハードエッジにある頂点を複製しています。そのため、チャートははじめから分けられていて、これを再パッキングすると縁の部分が別のチャートになってしまうわけです。これはチャート検出がデフォルトで法線を見て処理するようになっているからです。要するに、アンラッパーが同一の頂点座標と同一のUVながら異なる法線のエッジを検出すると、チャート的にはエッジにそって分けるようにするわけです。

今回のモデルでは、こうした振る舞いは望ましくありません。ライティングに重要な影響を与える部分ではないので、縁の部分もステップの一部として扱われてほしいと思います。そのような状態を実現するためにパッキング処理時のチャートの検出で法線を無視するオプションを設定可能にしました。この設定を有効にすることで、UVが同じならば法線が違ってもハードエッジを無視して同じチャートに割り当てます:

params

パッキングのオプションを変更することで、テクセルの密度をさらに減らすことができます。縁とステップは同じチャートに統合され、ライトマップのサイズは最終的に22×24になりました:

final

2015-10-26_1555

これらの新しいオプションを適切に使うことで、リアルタイムGIの事前計算時間を1時間30分から15分に減らすことができました。

パフォーマンス的にはどうなのか?

リアルタイムGIは目指したランタイムパフォーマンス/メモリー消費量に到達させるまで、大した調整は必要ありませんでした。しかし、ポストエフェクトのスタックはかなり深く、映画風ヴィネット(Filmic Vignette)、ブルーム(Bloom)、トーンマッピング(Tonemapping)、レンズゆがみ(Lens Distort)、SSAO(Screen Space Ambient Occlusion)、カラーコレクション(Color Correction Curves)、ノイズと粒子(Noise And Grain) 、カラーグレーディング(Color Grading Properties)とアンチエイリアス(Antialiasing)を適用しています。このぐらいポストエフェクトを入れても、まともなGPUを積んだ高速なデスクトップPCならば60fpsで動作します。

また、リアルタイムGIについてはいくつかの調整を行っています。

高速な環境ライティング

リアルタイムGIシステムは環境のライティング入力をスカイボックスから直接採ることができます。しかしながら、この機能を使用するには、CPUで稼働しているリアルタイムGIシステムをアップデートするためにスカイボックスのテクスチャーをGPUからダウンロードする必要があります。これは昼夜変化のシミュレーションを行うこのデモのようにな、環境ライティングが毎フレーム変わる場合理想的ではありません。かわりに、現在時刻からライティングのグラデーションとアンビエント強度を計算して、それをリアルタイムGIシステムが使うようにしました。これらはグラデーションベースのアンビエント入力の計算に使われたLightingパネルの設定です:

env_panel2グラデーションのアンビエントソースはすべてCPUから処理できます。これは非常にパフォーマンスに優れた方法で、またスカイボックスを使った方法とほとんど見分けがつかない結果をもたらします。

tod_1sec

環境ライティングを更新するコードの骨組みはこんな感じです:

[csharp]
using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

[ExecuteInEditMode]
public class EnvironmentUpdater : MonoBehaviour {

public Gradient groundGradient, equatorGradient, skyGradient;
private TimeOfDayManager m_TimeOfDayManager;

void OnEnable () {
m_TimeOfDayManager = FindObjectOfType<timeofdaymanager> ();
}

void Update () {
float currentTime = m_TimeOfDayManager.time;
RenderSettings.ambientGroundColor = groundGradient.Evaluate(currentTime);
RenderSettings.ambientEquatorColor = equatorGradient.Evaluate(currentTime);
RenderSettings.ambientSkyColor = skyGradient.Evaluate(currentTime);
}
}
[/csharp]

このコードはマネージャーが現在時刻を管理することを前提としています。このデモではそのようなマネージャーがあり、さらにUIから現在時刻をインタラクティブに変更することができるようになっています。

高速な自己発光ライティング

リアルタイムGIシステムは、環境ライティングと同じように自己発光(エミッシブ)するオブジェクトを直接シェーダーの発光プロパティで実現することができます。リアルタイムGIシステムはデフォルトでマテリアルのemissionプロパティを使ってリアルタイムライトマップ空間のエミッシブマップに出力するか、もしくはカスタマイズしたシェーダーであればそのためのメタパスを追加して処理できます。しかし、これはデータがリアルタイムGIシステムに処理される前にGPUからのテクスチャーのダウンロードを必要とします。このダウンロードを回避するために、オブジェクトの発光プロパティを直接固定カラーとして設定するスクリプトAPI(DynamicGI.SetEmissive)が利用でき、これを使うことでリアルタイムGIシステムがGIシミュレーションの処理にエミッションを直接適用することができるようになります。これはGPUを完全にバイパスしてシーンのライティングをほとんどコストなしで行う方法を提供します。下記にこの機能を使ったスクリーンショットを何枚か用意しました:

emissive

より大きな世界でスケールするには?

このデモで一つ明確なことは、これは大きなシーンではないということです。では、リアルタイムGIはどのようにスケールするのでしょうか?メモリーの使用量を小さく抑えながらもライティングの応答性を高く保つには、大きな世界をさいの目に切ってプレイヤーが世界を旅する間にその一部をストリーミングして読み込んだり解放したりといった処理をすることになるでしょう。リアルタイムGIシステムは LoadLevelAdditiveUnloadLevel と合わせて利用できます。もちろん、シーンをアンロードするには気をつけるべきことはあります。たとえばアンロード時に不可視状態したオブジェクトでも、バウンスライトには大きな影響を与えてしまいます。これについては、シーンをアンロードする際にバウンスライトのフェードを実現するためのスクリプト・コールバックを追加することを検討しています。これが入ればライトが突然ポンと変わってしまうのを避けられ、よりアグレッシブにストリーミングができるようになるでしょう。その他にもレベル単位のストリーミングよりも細かい制御を可能にするために、レベル内のインスタンスの更新頻度のプライオリティコントロールをスクリプトから制御可能にすることを検討しています。

加算ローディングを使ったり、12月8日のUnity5.3 で予定されているマルチシーン編集機能を使用すれば、美しいリアルタイムGIを使ったスケーラブルな世界を作成することが可能になるでしょう。

このデモを入手するには?

ビルド済みのデモアプリケーションを OSXWin64、そしてLinux 向けに作成しましたので、こちらからダウンロードできます。さらにプロジェクトデータはアセットストアからダウンロード出来ます。プロジェクトはUnity 5.2.2p2 以降のUnityで動作します。デモの操作方法についてはzipファイルの中に含まれるテキストファイルで説明しています。

このデモはデスクトップPCでもっとも良く動作します。このブログ記事での数値は3.6GHzのIntel i7-4790 CPUと16GBのメモリー、NVIDIA GeForce GTX 780 GPU を搭載したWindows 10 のマシンで計測しました。

クレジット

Alex Lovett (aka @heliosdoublesix): クリエイティブディレクション、アートディレクション、ビルド、ライティング、アニメーション、オーディオディレクション、そしてUnityのGI機能に絶え間ないストレステストを行いつつ、このデモをリリース
Thomas Pasieka and Plamen ‘Paco’ Tamnev: 小道具モデリング
Music Marks: 音楽、プレビュー動画制作
Dave Dexter: リアルタイムデモのオーディオ制作
Silvia Rasheva: プロデューサー
Morgan McGuire: リフレクションの問題の修正

Jesper MortensenKuba Cupisz and Kasper Storm Engelstoft: 開発中のAlexさんのサポート、およびすべてのアーティストのためのライティングシステムの改善

Plamen ‘Paco’ Tamnev: スペシャルサンクス – 最後の最後で発見した問題の修正

48 replies on “デスクトップとコンソールのすごいリアルタイムGI”

So you needed 4 Level Designers/Artists and 3 Programmers (graphics engineers of Unity) to create this rather small scene (visually) that has no meaningful gameplay?
That doesn’t sound like Enlighten is a viable solution for small indie teams and mobile development.

Is my computer or is this blog entry incorrect? I can’t see anything except for a repeating screen capture.

[…] แหล่งที่มา http://blogs.unity3d.com/2015/11/05/awesome-realtime-gi-on-desktops-and-consoles/ […]

I’m facing a problem with the Win x64 download. I’ve redownloaded it three times and always face the same error – the .zip is invalid, or empty. I’ve tried with both Windows and 7zip. Neither can extract them.

Was having the same issue, the archive was corrupted and after repairing the game ran with geometry, ui and gi correct – though materials all had strange artifacts. Anyway, alternative download worked for me.

[…] สำหรับบท 2 นี้ก็หมดเพียงเท่านี้แล้วละจ้า หากใครไม่เข้าใจ หรือสงสัยตรงไหนสามารถเข้าไปอ่านเพิ่มเติมได้ที่นี่นะจ๊ะ (T^T) […]

The desktop pc demo crashes for me a few seconds after the “Made with Unity” logo disappears. This is on a Windows7-64 Ultimate system with 6Gb RAM with GeForce GTS 250 and nVidia driver 341.92 . Let me know if you need more details.

For me this demo doesn’t work. I see only a lot of pink color on the screen which I presume is a missing shader?

Hi,

I can’t find “Ignore Normals” and “Min Chart Size” in Object properties of the lighting panel in 5.2x. Is this a feature of 5.3 to be released?

[…] [31] Mortensen, J., “Awesome Realtime GI on Desktops and Consoles”, Unity Technologies featuring Geomerics Enlighten. Available Online. […]

Nice demo and cool to see a realtime version of it as well. However I found some issues. There are a few stairs where you can walk under the structure into a small room. One of the room illustrates some lighting leaks, where a blue light is cast in the room, while there is no source of light. Also the hotkey ‘K’ should make a screenshot. While Unity hangs to create one, there is not actual .png created as all.
Also I saw that there are props all over the place, but they do not appear in the reflection of the water.

Would be cool to have these issues being fixed.

Thanks for the info! I’ll go check it out. Although I do think you’re comparing apples and oranges here.

Any ETA on mixed mode lighting working in U5 ? Full realtime or full precomp is pretty limited.

Fixes for mixed mode lighting are ready and in the queue, which mean they will go into the Unity 5.4 alpha. If no issues are found, we can backport the fixes to 5.3.

On my machine (iMac running OS X 10.10), the demo takes a while to load, performs like crap for about 3 frames, and then crashes. I’ll be honest, this does not inspire confidence.

How can we precompute lighting in a scene that requires both static GI and precomputed GI?

It’s not the lighting that is precomputed. It’s information about how light *would* bounce from one surface to another, from all possible angles, throughout all the static objects in the scene.

The scene would still be pitch black if there were no realtime lights present, because there’s no actual light data baked.

However when you introduce a realtime light into the scene at runtime, at any position or rotation, it automatically knows from the pre-computed data where the bounced light would end up. And if you move it, rotate it, or change the colour or intensity of the light, the indirect illumination automatically matches. And as demonstrated, it’s fast enough to have a lot of animated lights running at the same time.

By definition, precomputation of lighting is not “realtime” lighting….

“The realtime GI system works by precomputing all of the paths that light takes….” from your own description.

In the Editor it does say Precomputed Realtime GI though, maybe the spelling was not perfect that time… Anyway, I hope you didn’t expect realtime GI ‘by definition’ ;)

The lighting is not precomputed. The paths the light could take are, but the actual lighting itself is not.

Comments are closed.