今回はUnityでよりリアルになるように詰めていく部分になります。
なお、VRコンテンツとして納得がいく形で詰めていきたいのもあり
スケジュールを仕切り直ししまして、VRコンテンツ作成プロジェクトは来年も持ち越すことにしました。

さて、今回の流れに関連する知識として
チュートリアルサイトの「Unityに形状を渡す」に、Shade3DからUnityに形状を渡した際のライティング処理も含めたシーンの作り方に関係する内容を記載しています。
「作り方」についてはチュートリアルに任せるとして、その外枠の大雑把な部分でこのように使ってるよ、ということを「VRコンテンツへの道」のこちらで書いていくことにします。

リアルタイムで必要な要素

Shade3Dのようなオフラインレンダリングと違い、リアルタイムの場合はリアルタイム向けのライティング要素が必要になります。
チュートリアルの「[Unity] 室内シーンのライティング調整」から細かく書いていますが、ここでは導入だけ書きます。
ざくっと以下のような要素に分かれます。

  • 形状をDynamic/Staticに分ける
  • Staticな形状でライトマップ計算、ベイク
  • Staticな形状の映り込みを「Reflection Probe」でキャッシュ
  • 「Light Probe」でシーンの光の情報をキャッシュ
  • イメージエフェクトとしての「Post Processing Stack」の使用

形状をDynamic/Staticに分ける

地形(Terrain)や建物などの動かない形状は「静的」(Static)と明示することで、Staticな形状はライトマップ対象となり、「Reflection Probe」の反射の映り込みや「Light Probe」の光のキャッシュにも反映されます。
動くキャラクタや、動かせる小物類は「動的」 (Dynamic)となります。

下画像の場合は、建物はStatic、それ以外のタンスや籠などはDynamicになります。

これは次に説明する「ライトマップ」の割り当てがすでに行われたものです。

Staticな形状でライトマップ計算、ベイク

Staticな形状のテクスチャとして、「ライトマップ」というものを割り当てます。
これは、形状の表面にライティングの情報を「焼き付け」(ベイク)したものです。
下画像はライトマップとしてベイクされたテクスチャです。

Static形状の場合は、ライティングがテクスチャとしてベイクされるためベイクされた後はかなりきれいです。
ただ、ライトマップの対象となる形状が増えれば増えるほど計算時間とメモリ消費が多くなります。
もし、ライトマップ処理を行わない場合は以下のようになり、遮蔽や間接照明などが反映されない状態になります。

Staticな形状の映り込みを「Reflection Probe」でキャッシュ

リアルタイムで反射がある表現は、
「Reflection Probe」で反映するパターンと、
ポストエフェクトとしての「SSR(Screen Space Reflection)」の2つの手法が主にあります。
「Reflection Probe」は、指定位置から球状に周りの映り込みをキャプチャし、それを周囲の形状の反射として利用する仕組みです。
下画像は、室内に「Reflection Probe」の形状が存在し、周囲が映り込んでいます。

「Reflection Probe」での映り込みとしてキャプチャされるのは、Staticな形状のみになります。
Dynamic形状で映り込みがある場合は、この「Reflection Probe」の映り込みを参照します。

「SSR(Screen Space Reflection)」はレンダリング後のポストエフェクトの反射の映り込みになります。

「Light Probe」でシーンの光の情報をキャッシュ

Staticな形状がシーンに存在する場合に、指定の位置の光の情報をキャッシュして、Dynamicな形状は二次的に間接的な光を反映することができます。
この光の情報を「Light Probe」というので蓄えていきます。
下画像の黄色の球が「Light Probe」の位置となります。

これを使用することで、
室外にあるDynamic形状は空の影響で明るくなり、
室内にDynamic形状を移動させると暗くなる、といった動的なライティングを反映することができるようになります。

この「Reflection Probe」「Light Probe」を使用することで、Dynamicな形状でも間接照明が行われたかのようなライティングをリアルタイムに行えるわけですね。

「Post Processing Stack」の使用

シーンのリアルタイムレンダリングが完了後、ポストエフェクトを加えます。
これは「Post Processing Stack」(https://www.assetstore.unity3d.com/jp/#!/content/83912)というUnity製のアセットを使用しました。
このアセットは品質の底上げにかなり貢献します。

下画像は、左が「Post Processing Stack」をかける前、右がかけた後です。

ぜんぜん違いますね。

複数の効果をかけることができるのですが、リアルな表現として重要なSSAO(Screen Space Ambient Occlusion)について。
下画像の左がSSAOをかける前、右がかけた後です。

タンスの後ろや部屋の角部分がうっすらと暗くなってます。
AOは、遮蔽される部分を暗くして疑似的に間接照明的な陰影ができる効果を出します。
「Screen Space」なので、これはレンダリングのスクリーンに対して行われるAO計算、ということになります。
Static/Dynamicに関係なく行われる遮蔽計算で、ライトマップなどの前処理計算は不要です。
その代わり、スクリーンから見えないカメラの後ろなどの情報は反映できないのと、レンダリング解像度に依存します。

ざくっとですが、以上の流れでリアルなシーンをUnityで作成するようにしています。
詳しくはチュートリアルの「[Unity] 室内シーンのライティング調整」をご参照くださいませ。

AOマップの使用箇所

話が変わって、その他の補足です。
第4回「プラグインでモデリングを効率化」
で、Shade3Dの「AOUtil」プラグインを使用したAOマップの作成とUnityへの反映についてちらっと説明してます。

ライトマップでのベイク対象ではないDynamicな形状に対して、必要な場合はAOマップを与えるようにしました。
以下は井戸の表現でAOマップを与えてます。

左からSSAOなし、SSAO有効、SSAO + AOマップ有効、としたときの結果です。
AOマップのサイズは1024 x 1024ピクセルとしました。
SSAOがない場合は間接照明がされていないような表現ですが、SSAOを有効にするとうっすら間接照明が入る感じになります。
さらにAOマップが入ると、それっぽい間接照明が入ったかのような表現になっています。
なお、SSAOもAOマップもフェイクな遮蔽ですので実際の陰影とは異なります。
SSAOの場合は、AO計算を行う適応半径をパラメータで調整できます。
下画像はSSAOだけを反映したものです。
左は木材が交差する部分の陰影が出ていますが、屋根の下の陰影が弱いです。
右は木材が交差する部分の陰影が薄くなっており、代わりに屋根の下の陰影が明確になっています。

実際は井戸だけでなく、シーン上のすべてに対してSSAOはかかることになるため、どちらの表現も必要になりますよね。
SSAOはいろいろな手法があり、それぞれの欠点を補った表現ができます。
上画像のような両極端をハイブリットに表現するSSAOもあります。

代わってAOマップを使用する場合、これはあらかじめテクスチャに陰影をベイクするため、ライトマップよりも正確さは落ちますがSSAOよりもそれらしい表現が可能になります。

なぜStatic形状にしてライトマップのベイク対象にしないかというと、
ライトマップは形状が増えれば増えるほど計算時間がかかり、ライトマップ用のベイクテクスチャも増えることになります。
これを抑えるのと、ライトマップするほど重要な形状ではない場合は、複数配置しても同じAOマップの陰影の遮蔽具合で間に合いそう、という理由からです。
ただ、SSAO表現も進化していってますので、このAOマップのベイクという方法はいずれはいらなくなるかもしれませんね。
今のところ、まだ必要な箇所があるかなというのが個人的な感想です。

草の表現

草の表現について、前回からのバージョンアップです。
草は「DirectX 11 Grass Shader」(https://www.assetstore.unity3d.com/jp/#!/content/36335)というアセットを使用していますが、草のテクスチャを入れ替えることができます。

前回は以下のように、単色で草を表現してました。

草のテクスチャを与えて、以下のようにしました。

ただ、草でテクスチャを使用した場合は速度低下にもつながりますので、パラメータを調整してカメラ位置から離れると草を短くしたり密度を粗くしたりと最適化してます。
調整するとVRでもなんとか使える感じです。

今回詰めた内容を総動員して、下画像のようになりました。

後はひたすらShade3DにモデリングしてUnityに持っていく、という作業が延々と続きます。

さて、ようやくここまで来ました。
次回は、本記事のテーマであるVRに戻る予定ですが、
Shade3Dのプラグインでツールを拡張したりしてましたので、それも紹介できればと思います。