
Unity上の発光表現とZepeto 3Dアイテムの発光表現について(GI, Particle, Light)
前回。光の表現については今回で最終です。
Global Illumination

中: emission + HDR + bloom
右: emission + Global Illumination
Global Illuminationは壁と床に黄色の光が落ちている
Global Illuminationは光が当たった面から面への照り返しを計算して描画します。光源からの放射された光が他のオブジェクトに影響するのが特徴です。
右のBA-90付近の床や壁は光が落ちてぼんやりと黄色くなっています。左と中のBA-90は光って見えますが、周囲の壁や床が黄色くなっていません。
光が足りないように見えるのであれば、emissionのColorにHDRを使えば、bloomと併用もできます。光量を調整して写実的な絵作りができますね。

中: emission + HDR + bloom
右: emission + HDR + bloom + Global Illumination
GIは壁や床などのオブジェクトに反射する光を事前に計算し、オブジェクトが光っているように見えるテクスチャを貼り付けます。上記の床や壁に移り込む黄色いモヤモヤは、GIが右のBA-90の発光具合を計算して、壁や床に黄色いモヤモヤのテクスチャを貼ってくれた、という理解でよいです。

なお、GIにはBaked GI, Realtime GIがありますが、どちらも事前計算のもと他のオブジェクトへ照り付け具合を生成しています。World内で動くオブジェクトが発光する場合、光源が動いてしまうので光の情報を事前計算で追うことは出来ません。これはParticle(Light)で後述します。
'Baked'に対する'Realtime'だと思っていると、Realtime GIならWorld内で光源となるオブジェクトの動きに合わせて周りの床や壁が照らされる、って表現ができるかも! と思ってしまいがちですが、GIではできません。Emissionで光の強さが動的に変わるなどの表現はRealtime GIで実現可能です。
Baked GI および事前計算リアルタイム GI には、どちらも静的オブジェクトしかベイク/事前計算に含めることができないという制限があります。そのため、動的なオブジェクトは他のオブジェクトへ光をバウンスできません。また、その逆もできません。
Global Illumination設定方法
まずは環境設定から。Window > Rendering > Lighting と進みます。

ここから各項目の設定を一気に説明しますので、下のスクリーンショットを参照しながら読み進めて下さい。
SceneのLighting SettingsがNoneとなっている場合、New Lighting Settingsを選択して新しくSettingを作成してください。これはLightingの設定に名前を付けて管理していると考えてよいです。
Mixed LightningのBaked Global Illuminationをチェックします。Realtimeは光源の情報が動的に変化する場合でもなければとりあえずは不要です。
LightmapperはデフォルトではProgressive CPUになっていますが、Progressive GPUにしても良いです。このあと実施するGIのライトマップの計算処理に時間がかかる場合、良いグラフィックボードを積んでいれば処理の時間が短くなります。
Max Bouncesは1以上にすること。光の反射の回数を表します。値を大きくするほど、複数回の反射を計算してライトマップに反映しますが、そのぶんライトマップの計算処理の時間は長くなります。
Indirect Intencityは1以上にする。反射した光の強さにかかる係数という理解です。1以上ならそのまま、それ未満なら反射で光の強さが減衰するはず…。

Environmentでは、特に設定すべき項目はありませんが、Worldが明るすぎて微妙な反射光を確認しづらい、という場合は下記の値を下げると周囲が暗くなります。

GIで発光させるオブジェクトと、それに紐づくMaterialを設定します。オブジェクトの設定ではContribute Global Illuminationをtrueに設定します。この設定によりオブジェクトがGIの計算対象となります。Materialの設定では、Emissionをtrue > Global IlluminationでBaked(もしくはRealtime)を選択してください。

MaterialではGlobal IlluminationをBakedに設定
さらに、GIでは発光の照り付けを受ける側の設定も必要になります(本記事の例では壁や床)。壁や床のオブジェクトを選択し、それぞれのInspectorで、Contribute Global Illuminationをtrueにします。下は床のInspectorです。

ここまで設定したらLightingウィンドウに戻り、Generate LightingのボタンでGIのライトマップの計算を開始します。Auto Generateを有効にしておくと必要なタイミングで自動的にライトマップの計算を開始してくれますが、それなりに重い処理なので邪魔になりがちです。無効にしておいた方が無難です。

GIの計算処理では、Unityの画面の右下に進捗が表示されます。これが完了すると、GIの結果が画面に反映され、壁や床などに光の照り付けが見られるようになります。Playしてお楽しみ下さい。

ZEPETOでのGI
GIはWorld内に設置したオブジェクトを光らせて、間接照明を使った写実的な画面を作るには向いていますが、3Dアイテムを光らせることは無理です。
仕組みとしてはLightmapStatic(事前計算されたライティング情報をテクスチャとして静的に貼り付けておく)です。3Dアイテムのように、リアルタイムでアバターと一緒に動くオブジェクトに合わせて光が計算し、壁や床を照らしたりするような動作はできません。World側ではアイテムを想定してLightmapを生成できないので、当然、光っている表現になりません。
また、上記で示したGIの設定もWorld側で事前にしておく必要があります。3Dアイテム側がGIで光る事を想定していても、World側でGIを有効にして床や壁、あらゆるオブジェクトに照り返す設定をしていないと、光っているように見えない、という結果になります。
Particle(で光っているように見せる)

この表現方法は光源を使用していません。Particleに一部を透明化したテクスチャを使う事で、周囲にぼやけた色を上塗りして、光っているように見せかけています。
Particleで光っているっぽく見せる設定方法
Particleのテクスチャにアルファチャンネルで透明化した画像を使います。Unityのparticleに含まれているdefault-particleも周囲がアルファで透明化されているため、ひとまずdefault-particleを使用して見た目を確認するのもよいかと思います。
まずはオブジェクトを作成し、適当にMaterialを設定します。私はBA-90を透かし彫りのMaterialを設定しています。

右: オブジェクトを作成し、Materialを設定したBA-90
まずはオブジェクトにParticleを作成します。Hierarchyでオブジェクトを右クリックし、Effects > Particle Systemを選択します。


デフォルトのParticle Systemを選択すると、Scene上でたくさんの白い球が飛んでいく様子が見られると思います。白い球が見られない場合は、Sceneの右下Particle Effect内にある"Play"や"Restart"を押してみてください。このParticle Effectウィンドウは、Partcileを再生したり、再生速度を調整する際に使います。たくさん白い球が飛んでいく効果はデフォルトのParticleの効果ですが、これはInspectorから変更できます。

Inspectorの値を変更します。本note内で例として挙げているBA-90を透かし彫りで光らせるためのパラメータは以下となります。

この設定値では、パーティクルを1個のみ発生させ、周期的に点滅させる効果を設定しています。
Start Color … 色を指定します。
Color over Lifetime > Color … 時間経過による色の変化を設定します。バーの左端(Location: 0.0%)が0秒時点、右端(Location: 100.0%)がDurationで設定した周期の最後でる3秒時点の色やアルファを示します。以下の設定では、開始時のアルファを0としておき、時間経過とともにアルファを255に上昇させ、その後、徐々にアルファを0に戻して開始時点と同じ0に戻しています。このように設定することで、Particle SystemのStart ColorおよびMaterialで設定した色で、定期的に明滅する表現ができます。明滅させる必要がなければ、Location0-100%にAlpha:0を入れておけば良いです。

Renderer > Render Mode … Mesh > Quad を選択すると自然な見え方になって良いかと思います。デフォルトのbillboard他、一部の設定値では、カメラをズームアウトすると、Particleの範囲が相対的に大きくなってしまう値があります。
カメラが引いた時に敢えてParticleを大きくして目立たせる表現もあるかと思いますが、今回はカメラが引いたらParticleのサイズも小さくする、3D空間としては自然な見え方にします。

下: Render Mode: Billboard
Mesh>Quadはカメラ距離に合わせてParticleの描画範囲も小さくなる。
BillboardはParticleの描画範囲がカメラ距離に依存せず、すごい光っているように見えてしまう。さらにUnityが前後を配慮して間違ってくれるので光の放射が変に切れる。
Material … Default-ParticleSystemはUnityのビルトインです。最初から含まれています。中心部から外側にかけて徐々にアルファがかかっており、中心から光が発散しているようにみえるため、シンプルな表現であればこれを使えばよいです。

もちろん、発光する形に合わせてマップを用意すれば、変わった形状で光っているっぽい表現ができます。発光しない部分は画像編集ソフトで透過を指定することを忘れずに。ネオンサインとかによさそう。


これらの値をInspectorで指定し、Particleのサイズが小さければ、
Scaleの値などでサイズを調整すればよいです。

完成です。

ZEPETOでのParticle
環境のLighting設定の影響を受けないため、3Dアイテムにも使用でき、どのWorldでも同様に表現されます。反面、オブジェクト自体を光らせていないことに加え、壁への照り返しなどもないため、Emission+BloomやGIに比べると、表現力はイマイチです。拙作の東京タワーもこの方法で光っているように見せています。(点滅部分はビルトインのdefault-particleに色を設定、タワーの鉄骨部分はEmissionを使用しています)


Particle(Light)

この表現方法は完全な光源を使用します。Lightは光源から発する光の強度、方向、色とオブジェクトの法線の向きで反射を計算し、実際の光が当たっているように画面に描画します。以下のような、GI単体ではできなかった処理も実現できます(realtimeの場合)。その分、描画処理は重く、Lightが画面に入ってきたユーザ端末の負荷は大きくなります。
・アイテム側で設定すればワールド側の設定は不要
・動く物体が床や壁に照り付ける表現が可能

上記はBA-90にLightを設定したParticleをくっつけて、スクリプトで動かしています。BA-90に紐づいた光源が移動すると、床や壁への照り返しも一緒に移動しています。また、ゼペおじの顔や体も光の移動に伴い徐々にテカっていき、光が離れると暗くなっていきます。前回記事で書いた真実の光というやつです。Lightはワールド側の設定等なく、このような光の表現を実現できます。
Lightの注意点として、Lightそのものは画面(カメラ)に映らないということが挙げられます。実際のLightの見え方を下の図でご確認ください。


左: light(SpotLight)のみ設置。光源が存在しないように見えて不自然。
右: light(SpotLight)を設置後、Particle Systemで光の玉を設置。懐中電灯としてはこっちのが自然。
現実では光源を見ることができますが、UnityのLightは周囲のオブジェクトを照らすのみで実体は見えません。懐中電灯やランタン内の光源っぽさを出したいのであれば、Lightを設置しつつ、中心部に先述の Particle(で光っているように見せる)などの方法で、光源があるように見せるのが良いかと思います。勿論、豆電球をモデリングしてParticleを被せるのも、丁寧な仕事で良いと思います。
Particle(Light)設定方法
・参照するLightを設置
・ParticleからLightを参照する設定
上記の段階を踏んで、ParticleのLightを設置します。ちなみにLightのみ設置すればParticleである必要はないのですが、(実際にZEPETOで審査が通るかどうかは別として、)Light単体で使用するよりアイテムに付随して派手に動かしたいケースが多いと思いますので、Particleとして設定する方法を解説します。
まずはLightを設置。Hierarchyの上で右クリックLight > Point LightまたはSpotlightあたりが視認しやすいかと思います。

作成したPoint Light (1)のInstpectorです。Rangeで光の届く距離を設定します。周囲の床や壁まで光が届かせるためにそれなりに大きい値を設定します。値が小さいと光が届かず、光の確認ができません。ColorやIntensityは見易い値で。最初は見易い色、それなりの強さを設定して、具合を見て下げていくと良いかも知れません。
各プロパティの設定が終わったら、上部のチェックを外して無効にします。設置したPoint Light (1)そのものはSceneからは消えますが、あとから(Particleから参照した際)に表示されるので問題ないです。

発光させたいオブジェクト(下図ではCube_particle(light))上で右クリックして、Effects > Particle System を選択し、Particleを付けます。オブジェクトからデフォルトパーティクルの白い球がたくさんでてきます。

オブジェクトの下にParticle Systemがぶら下がります。

発光させたいオブジェクトに作られたParticle Systemを編集していきます。最低限、Emission, Lights, Rendererの3つは有効化してください。それぞれのプロパティは以下です。
開始時点からLightひとつだけ出せばよいので、Start Delayは0、Max Particlesは1で。同じ理由でEmissionのRate over timeは1で良いです。Lightsで、先ほど作成したPoint Light (1)を設定して参照します。RendererはNoneで良いです。

光が表示されない場合は、Particle EffectでRestartしてみてください。


ZEPETOでのParticle(Light)
アイテムにLightを設定するだけで、ワールド側での設定は特に何もしなくても光ります。Lightを設定したアイテムを持ち込めば、行き先がどんなワールドでも、壁や床を照らす豊かな表現ができるはずです。仕組みの上では。
じゃあ、Lightを使えばアイテムを光らせたい問題は全部解決じゃん! 今までの説明した色々な方法はなんだったの? という話ですが、本節の冒頭で述べたクライアント側の負荷の大きさから、ZEPETO公式からは、Lightを使ったアイテムは審査で承認不可とするとの告知が出ています。
従って、提出したアイテムに照明効果が含まれている場合は承認不可の対象となります。
その他、大きすぎる容量や過剰なエフェクトの適用によって他のユーザーのプレイに影響を及ぼしかねないと判断する場合、承認不可 (ex:照明効果を含など)
私はLightを含むアイテム/ワールドを審査に出したことがないので、ZEPETOがLightを設定したアイテムの承認をどう判断するか、実際のところはわかりかねます。
懐中電灯や、(ハロウィン)ランタンなどのアイテムではlightを使った方が絶対に表現がリアルになりますし、夜道をしっとり歩く雰囲気や、闇を手探りで歩くホラー感を出したいのであれば、普通はLightを使うでしょう。ここら辺はZEPETO運営が端末の最低要求スペックをどこら辺に置いているか、という話になります。前回記事でも書きましたが、幅広い層の端末を想定しているので、あまりスペックを上げていく気はなさそうです。
まとめ
これまで3回に分けて、Unity上での光の表現方法とZEPETO内での利用について解説してきました。全体で長くなってしまいましたが、ZEPETO内で利用する際の、それぞれの特徴は以下となります。
$$
\begin{array}{|c|c|c|c|c|} \hline
機能 & 光の表現力 & ワールド^※ & アイテム & 説明 \\ \hline
\text{Emission} & 低 & ○ & ○ & 環境が明るいと光って見えない\\ \hline
\text{Post Processing(Bloom) }& 中 & ○ & × & ワールド側で設定が必要\\ \hline
\text{Global Illumination} & 高 & ○ & × & ワールド側で設定が必要\\ \hline
\text{Particle} & 低 & ○ & ○ & 軽いのでおすすめ。\text{Emission}と併用可\\ \hline
\text{Light} & 最高 & ○ & ? & 機能としては使えるが審査\text{NG}の可能性高 \\ \hline
\end{array}
\\
\\
^{※機能としてワールドでの使用はすべて可能だが、審査の可否は運営次第}
$$