GI基礎 アイキャッチ画像

【Unity】グローバルイルミネーション(GI)基礎知識~STYLYへの反映方法

この記事ではUnityでのグローバルイルミネーション(GI)の基礎知識と、それを用いた間接照明のような表現をSTYLYの空間に反映させる方法をご紹介します。

GIで間接光を効かせた部屋

GIで間接光を効かせた部屋

注意事項

本記事のテクニックによる効果は残念ながらWebブラウザ上(STYLY Web Studio、STYLY Gallery)では正しく反映されません。VRで見た場合のみそのまま反映されますので、その点を考慮してご活用ください。

また、今回はSTYLYにシーンごとアップロードする必要があります。

使用したUnityのバージョンは2017.4.15f1です。

サンプル

本記事で作成したサンプルシーンはSTYLY Galleryの以下のページから体験できます。

GI-room

記事で紹介しているUnityプロジェクトのダウンロードはこちらからできます。

STYLY-Unity-Examples

グローバルイルミネーション(GI)とは?

グローバルイルミネーション(以下、GI)とは、CGで光を表現する際に人間が現実を目で見たときのように自然な表現をする技法です。日本語にすると「大域照明」、つまり局所的な直接光の表現だけでなく反射光や環境光などの間接光も含めて大域的(グローバル)に照明効果を表現すると言う意味です。

Unityでのライトの基礎知識と使い方に関しては下記の記事をご参照ください。

閉じられた部屋を作る

GIの効果をわかりやすくするため、今回はコーネルボックスにならい赤と緑の壁のある閉じられた部屋を作ります。

コーネルボックスとは、CGの照明効果が現実同等に描画されるかを検証するためにコーネル大学研究者が発案した有名なモデルです。

MainCameraをSTYLYのStartPositionに合わせる

空間の作成に入る前に、STYLYにシーンをアップロードする前提なのでMainCameraをSTYLYのStartPositionと同じPositionにします。

奥行き(Z座標)を-5、高さ(Y座標)は適当ですが1.5にしました。

MainCameraのPositionをSTYLYに合わせる

MainCameraのPositionをSTYLYに合わせる

Planeを配置する

それではここから部屋を作ります。

今回は床、壁、屋根をすべてUnity基本オブジェクトのPlaneで作ります。

Planeは裏面のメッシュはないため、閉じられた空間にして壁の外の視点から見てもSceneビューなどで確認しやすいからです。

Planeを六面に配置して部屋にします。

壁と天井はScale値はすべて1、壁は高さ(この場合Z座標)を半分の0.5にしました。

Planeで部屋を作る。壁の高さは0.5にした。

Planeで部屋を作る。壁の高さは0.5にした。

自分の場合、各PlaneのTransformは下記表の通りとなりました。

Plane(床)

Position

0 0 0
Rotation 0 0 0
Scale 1 1 1
Plane (1) Position 0 2.5 5
Rotation -90 0 0
Scale 1 1 0.5
Plane (2) Position -5 2.5 0
Rotation -90 0 -90
Scale 1 1 0.5
Plane (3) Position 5 2.5 0
Rotation -90 0 90
Scale 1 1 0.5
Plane (4) Position 0 2.5 -5
Rotation -90 0 180
Scale 1 1 0.5
Plane (5)(天井) Position 0 5 0
Rotation 180 0 0
Scale 1 1 1

壁に色をつける

壁のマテリアルを作成して適用していきます。

まずは赤。ProjectビューのCreateメニューからMaterialを選び、「Red」と名付けます。

ShaderはStandardのまま使います。Albedoカラーを(R:240、G:0、B:0)にします。

壁のマテリアルの設定。RGB=(240,0,0)とした。

壁のマテリアルの設定。RGB=(240,0,0)とした。

同じく「Green」というマテリアルを作り、Albedoカラーを(R:0、G:240、B:0)にします。

これらを左右の壁に各々適用します。(ProjectビューからマテリアルをHierarchyビューの適用したいGameObjectにドラッグアンドドロップします。)

また、その他の壁、床、天井に関しては白にしたいのですが、真っ白ではなく(R:240、G:240、B:240)のマテリアル「White」を作りました。

すべてのPlaneにマテリアルを適用すると以下のようになりました。

コーネルボックスぽいものができた

コーネルボックスぽいものができた

RGB値の240というのは、Unityが提供しているマテリアルチャートを参照しています。これはGI効果をより自然に近い表現にするために必要だということです。

マテリアルチャート(Unityマニュアル)

シーンを保存します。シーン名は何でもよいですがここでは「GI-room」としました。

ここで部屋の中がDirectional Lightのおかげで明るいままですので、Directional Lightを削除しましょう。

DirectionalLightを削除した状態

DirectionalLightを削除した状態

Directional Lightを削除すると部屋の中は真っ暗になるかと思いきや真っ暗にはなりません。

これは、実はすでにGIの効果が有効になっており、部屋の中が照らされているからです。ではこの照明の設定はどこにあるのでしょうか。

Lightingに関する環境設定をする

ここで登場するのがLightingウィンドウです。

UnityにおけるシーンのLightingのセッティングはLightingウィンドウにある程度まとまっています。

Lightingウィンドウは、ファイルメニューの [Window] -> [Lighting] -> [Settings]で開きます。

よく使うので、Inspectorの右にでもレイアウトしましょう。

Lightingウィンドウを表示するメニュー [Window] -> [Lighting] -> [Settings]

Lightingウィンドウを表示するメニュー [Window] -> [Lighting] -> [Settings]

Lightingウィンドウを配置した状態

Lightingウィンドウを配置した状態

さてLightingウィンドウを見ると、まず一番上の所、タブのようなもので「Scene」が選択された状態となっているかと思います。(他に「Global Maps」「Object Maps」というものが並んでいます。)

下記2つの値を共にゼロにします。

  • [Environment] > [Environment Lighting] > [Intensity Multiplier]
  • [Environment] > [Environment Reflections] > [Intensity Multiplier]

そうすると部屋の中は真っ暗になりました。

部屋の中が真っ暗になった

部屋の中が真っ暗になった

[Environment Lighting]、[Environment Reflections]は共に環境光に関する設定項目群であり、[Intensity Multiplier]では明るさの度合いを設定できます。これがデフォルトでは1となっており、閉じた部屋であろうが環境光で照らされた状態となり、シーン内にひとつもライトがなくても明るかったのです。

また、各々[Source]という項目があり、デフォルトではともに「Skybox」となっています。これは環境光の計算のもととなるものがSkyboxに設定されていることを示します。

真っ暗なままだと作業がしにくいため、一旦[Intensity Multiplier]の値をもとの1に戻しましょう。

発光するオブジェクトを置く

今回は光源として発光する(Emissive)オブジェクトを使いたいと思います。

まずはCubeを置き、「Emissive」という名のマテリアルを作成して適用します。これをEmissiveオブジェクトとするには、適用するマテリアルのEmissionを有効にし、値を0以上に設定するだけです。とりあえず3に設定しました。

EmissionをONにしたマテリアルを適用したオブジェクト

EmissionをONにしたマテリアルを適用したオブジェクト

ただこれだけだとまわりのオブジェクトに光の影響を与えません。影響を与えるにはCube自身、そして影響を受けさせたいGameObject(ここでは周りのPlane)のLightmapStaticのチェックをONにする必要があります。

Lightmap StaticをONにする

Lightmap StaticをONにする

PlaneのほうもLightmap StaticをONにする

PlaneのほうもLightmap StaticをONにする

これでやっと発光しているように見えるようになりましたので、薄くして天井に配置しました。

ここでCubeを移動したり、Lightmap Staticをオン/オフしたりするごとに右下に進捗メーターが表示され、なんらかの処理が走ったあとにLighting効果が適用されているようです。

 

Lightingに関する何らかの処理

Lightingに関する何らかの処理

 

(※ちなみにEmissiveオブジェクトは正確にはLightではありませんが、Light同様にGIの効果を得られますし、Lightとは違ってEmissiveオブジェクトそのものが発光する効果を得られますので、蛍光灯やネオンを表現するのに便利です。)

ライティングの事前計算を手動で実行する

ここでまたLightingウィンドウに戻ります。

一番下に「Auto Generate」という項目にチェックが入っています。これをオフにすると、「Generate Lighting」というボタンが有効になりました。

Auto Generateをオフにする

Auto Generateをオフにする

この状態で先程のように、EmissiveにしたCubeを移動したり、Lightmap Staticをオン/オフしたりしてもシーンのライティングに変化はありません。

代わりに、「Generate Lighting」ボタンを押すと処理が実行され、編集した内容によりライティングが変更されました。

Generate Lightingボタンを押した所

Generate Lightingボタンを押した所

また、この処理の実行後にProjectビューに「GI-room」というフォルダと、その中にファイル2つが作成されていました。

Lightingデータができている

Lightingデータができている

この処理はライティングの事前計算と呼ばれるもので、シーンに紐づく事前計算結果データがシーンと同名のフォルダの中に作成されます。

このデータはUnity、もしくはSTYLYの実行時に描画に使用されます。

また、Lightingウィンドウの[Mixed Lighting] > [Baked Global Illumination]のチェックはオフにします。

BakedGIをオフにする

BakedGIをオフにする

そしてGenerate Lightingボタンを押してライティングの事前計算を実行します。(以下、単に「Generate Lightingします」と言います。)

「Auto Generate」、つまり自動生成を無効にしたのでライティングに関わる変更をしてシーンに反映させたい場合には、都度Generateする必要があります。なぜ今回手動生成にしたかというと、どの変更がライティングの効果に影響を与えるかわかりやすくするためです。

[Baked Global Illumination]に関しては今回詳しく説明しませんが、STYLYへのアップロード時に確実に反映させるためオフにしました。

プリミティブを部屋に置く

このままだと蛍光灯のようなものがむき出しで間接照明にはなりませんので、ランプシェードのようなものをCubeで作り、Emissiveオブジェクトの下に置きます。

あとは床に適当にCubeなどのプリミティブを配します。

(ここで床のPlaneのLightmap Staticがオンになっていないことに気づきましたのでオンにしました)

追加したプリミティブはもちろん「Lightmap Static」にし、Whiteマテリアルを適用しました。また、Whiteマテリアルの「Smoothness」を0にします。これは物体表面からの光をよく拡散させるためです。

そしてGenerate Lightingした結果が下の画像です。プリミティブの表面が向かって左に面している側は赤に、右のほうは緑にうっすら色づいています。

これはEmissiveオブジェクトからの光が壁に当たって反射し、プリミティブの表面に届いたものが反映されているからです。GIの効果のひとつとなります。

プリミティブを適当に配置した

プリミティブを適当に配置した

もちろんテクスチャのあるマテリアルであっても同様に反映されます。

テクスチャにも反射光が反映されている

テクスチャにも反射光が反映されている

赤と緑の壁側にもEmissiveオブジェクトを配し、テクスチャの乗せたSphereもEmissiveにしてみました。

もう少し暗がりにしたかったので、Emissionの明るさの値をすべて2に下げました。

また、前述した環境光の明るさの設定値2つをゼロにしました。

  • [Environment] > [Environment Lighting] > [Intensity Multiplier]
  • [Environment] > [Environment Reflections] > [Intensity Multiplier]
全体的に暗くしてみた

全体的に暗くしてみた

これでいい感じに暗くなったのですが、肝心の間接照明(Emissiveオブジェクト)部分から漏れ出る光が薄くなってしまっています。

ここで、Lightingウィンドウの[Light Mapping Settings] > [Indirect Resolution] をデフォルトの2から、4に変更します。[Indirect Resolution]は間接光の解像度を表します。

そしてGenerate Lightingします。

Lightingウィンドウ [Scene] タブ > Light Mapping Settings > Indirect Resolution

Lightingウィンドウ [Scene] タブ > Light Mapping Settings > Indirect Resolution

すると、壁側のEmissiveオブジェクトの光が顕著に明るくなりました。

Indirect Resolutionを倍の4にした

Indirect Resolutionを倍の4にした

 

全体的に明るくなりすぎたので、Generate Lightingボタンのすぐ上にある[Indirect Intensity]で間接光の明るさを調整します。この場合、0.7にしました。

Indirect Intensityを調整

Indirect Intensityを調整

明るさはいいのですが、壁に当たる光の表現の解像度が粗いのが気になりました。

かといって、[Indirect Resolution]を上げすぎてしまうとGenerate Lightingに時間がかかってしまい、作業効率が悪くなってしまいます。実行時のパフォーマンスにも影響を与えそうです。

そこで壁際はPoint Lightに変更してみます。

壁側をPointLightにしてみた

壁側をPointLightにしてみた

Point Lightは球状のため光の形状が変わってしまいましたが、粗さはなくなりました。

また、[Indirect Resolution]を2に戻してみても粗さが気にならない程度になりました。

補足

Unity公式のチュートリアルを参照すると、[Indirect Resolution]が4というのはかなり高い値のようです。屋内の間接光表現が複雑になる空間でも2~3がちょうどよいと書いてありました。

Precomputed Realtime GI (Global Illumination)

※このチュートリアルでいう「Realtime Resolution」(おそらくUnity5.5時)が「Indirect Resolution」に名称変更されたようです。

今回使用したのが上記Precomputed Realtime GIであり、Generate Lightingして事前計算を行いはするものの、それをもとに実行時(リアルタイム)に間接光も含めた光の計算を行う、というものです。

Precomputed Realtime GIを使う場合には「Indirect Resolution」が実行時のパフォーマンスに影響を及ぼしますのでご注意ください。

STYLYにアップロードする

では、できあがった空間をSTYLYにアップロードしましょう。今回はUnityシーンごとアップロードします。

STYLYにUnityシーンをアップロードする方法はこちらを御覧ください。

Cameraを消すのを忘れずに。

Generate Lightingして作成されたLightingの事前計算結果データも含めてアップロードされます。

Webブラウザ上(Web Studio、およびgallery.styly.cc)で見ても反映されませんが、STYLYアプリでVRゴーグルをかけて見ると、Unityで見たままの光が反映されているかと思います。

ただし、PCディスプレイでの見た目よりもVRゴーグルで見たときのほうが明るい気がしました。これは見るVRゴーグルによっても違いが出るかもしれません。

 

今回はUnityのGI、そしてEmissionとPoint Lightを使って間接照明のような表現をしてみました。

UnityのLighting表現に関しては、設定箇所や学ばないといけないことも多岐にわたり、奥が深すぎてまだまだご紹介しきれないのですが、GIを意識してうまく使うことにより、より自然な表現や心地よい空間を作ることができるのではないかと思います。

今回は動かない物体のみで構成された静的な空間でしたが、今後動く物体やライト自体に変化のある空間に関しても書いてみたいと思います。

皆さんもぜひ色々と試してみてください。

参考にした情報

今回以下の記事を主に参考にさせて頂きました。