しばらく時間があいてしまいました。
実は内々でシーンを管理するツールを作っておりまして、
これはまだお見せできない部分で「VRコンテンツ作るにはこれをツール化したい」的な部分はたくさんあるなぁとわかった次第です。
まだ先になりそうですが、いつか紹介できればと思っております。

さて、今回のテーマは「LOD」です。
LODとは「Level Of Detail」の略で、視点からみて遠くの形状は粗くても目立たないということで
ポリゴン数を抑えて表示速度を上げる方法です。
Shade3DではLODという単語は出てきませんが、リアルタイムではこれがないと大きなシーンではあっという間に重くなってしまいます。

まずはUnityでどこでLODが使われるのかを書いて、次にShade3Dでできることを書いていくようにします。

Unity内で完結できるLOD

Unity内では、Terrainや木/草などがLODを行っています。
Terrainは近くの地面や細かい凹凸が必要な箇所は面の分割が密になり、遠くの面は荒くなっています。
以下はワイヤーフレーム表示したものです。

草も、遠くになると間引きされたり表示されなくなるようになっています。

木はSpeedTree(https://store.speedtree.com/unity/)で作成しますが、この場合自動的にLODが適用されます。
視点から遠くなるほど面数が少なくなり、もっと遠くなるとビルボードになります。
以下の画像は、手前の木と奥の木は同じものです。

手前のほうが面数は多く、奥のものは面数が削減されています。
1つの木に対して4つのメッシュが格納されています。
この木の場合の三角形数は以下のようになります。

「LOD3」はビルボードとなり、視点方向を向く四角形ポリゴンにテクスチャを張り付けた状態になります。
シーンに同じ木を配置して、LODをチェックすると以下のようになりました。

さらに奥に木を配置すると、木は消えます。
これくらいだと、面を削減しているのはばれないですね。
このようにTerrain(地形)要素に対しては、すでにいろいろLODの手段は用意されており、極力面数を削減して最適化できるのが分かります。

では、地形に家などを建てた場合にLOD対応の形状をどう作成するか、というのを次に書いていきます。
モデリングはShade3Dを使います。

建物をLOD対応する

建物は木と同じで、視点から近くに見えるものはポリゴン数を多くし、遠くに行くにしたがってポリゴン数を削減して粗くなっていくようにします。
Shade3DからUnityに渡す流れは以下のように行いました。

  • Shade3D : 建物をモデリング(近接用)
  • Shade3D : 建物をモデリング(粗いポリゴン数)
  • Shade3D : 建物をモデリング(直方体+屋根の三角柱にテクスチャを貼るだけ)
  • Shade3D : 3つの形状をfbx出力
  • Unity : 3つの形状(fbx)をインポート
  • Unity : LODの形状として構築

Shade3DではLOD対応の形状を管理することはできないため、別形状に分けてfbxで出力し、Unity上でLOD対応に構築し直すことにします。

Shade3D : 建物をモデリング(近接用)

木造家屋1軒をモデリングしました。
内々でShade3Dの建物作成プラグイン(自作で非公開にしてます)を使って効率化させています。

これはカメラが一番近い距離にある場合に表示する3D形状になります。
壁は「下見坂張り+ささらご」で凸凹になっており、屋根の骨組みもきっちりとモデリングしています。

VRで見た場合、視点を近づけたり家の中に入ってもそれなりの見栄えになるようにしています。
使用しているマスターサーフェス数は木材用、基礎の石の2つです。
このときのポリゴン数は、5992三角形でした。
これをLOD0とします。
この家を、シーンから見えている箇所に100軒配置した場合は5992 x 100 = 599200三角形消費することになります。
実際は100軒でも少ないでしょうから、
最適化しないとメモリ消費が激しくなるのと、表示が重くなる原因になるのが分かりますね。

Shade3D : 建物をモデリング(粗いポリゴン数)

もっと面数を削減した建物をモデリングします。
1つ前の章でのモデリングと同じサイズで面数だけを抑えていきます。
遠方にあるため、ディテールは無視します。
基礎の石を間引いて横長にして代用、
壁の「下見坂張り+ささらご」を単純な薄い直方体にしてしまう、
屋根の骨組みをモデリングしない、
など、見た目にこだわらずそれらしくモデリングしていきます。
建物の場合は直線的な構成になりますので、
形状をパートに入れて複製後に直方体で表現できるところは大胆に造形してUVマッピング、などと、手作業で進めていくほうが確実かと思います。
以下、同じマスターサーフェスを使用しています。

これで、ポリゴン数は1368三角形になりました。
これをLOD1とします。

Shade3D : 建物をモデリング(直方体+屋根の三角柱にテクスチャを貼るだけ)

もっとも粗いモデリングは直方体と三角柱だけで構成しました。
基礎の石や玄関も省いてみました。

これで、24三角形になりました。
これをLOD2とします。
同じく、同じマスターサーフェスを使用しています。

LOD0/LOD1/LOD2の建物を並べてみます。

これで、Shade3Dでの建物のモデリングができました。
3つの建物をそれぞれ1つのポリゴンメッシュにまとめておき、
wood_house_LOD0、wood_house_LOD1、wood_house_LOD2とします。
基礎の石はフェイスグループでマスターサーフェスを登録しています。
2つのマスターサーフェス、3つのテクスチャで以下のようになりました。

建物はY=0の位置で接地、XZ平面の原点が建物の中心になるようにしておいてください。

Shade3D : 3つの形状をfbx出力

それぞれのポリゴンメッシュを選択した状態で、ファイルの「ファイル」-「エクスポート」-「fbx」を選択します。
FBXエクスポートダイアログボックスで「出力」を「選択された形状」にします。

「形式」タブ内は初期設定のまま、
「ジオメトリ」タブで「面の頂点法線を出力」チェックボックスをオン、
「表面材質」タブで「イメージをFBXファイルに埋め込み」チェックボックスをオフ、
「アニメーション」タブで「出力」を「なし」、
「出力対象」タブのチェックボックスをすべてオフ、とします。
3つの形状をfbxとして出力しました。
Shade3Dでの作業はこれで完了です。

Unity : 3つの形状(fbx)をインポート

Unityを開きます。ここでは、Unity 2017.2.1f1を使用しました。
使用しているAssetの互換性の関係もあり、現在の最新よりも少し古いバージョンを使っています。
以下のようにAssetとしてProjectウィンドウで3つのfbxをインポートし、
マテリアルは別途割り当てました。
また、テクスチャもインポートして割り当て済みです。

Unityへのfbxの読み込みとマテリアルの割り当てについては、チュートリアルの「[Unity] Unityに形状を渡す手順」も参照してくださいませ。

Unity : LODの形状として構築

3つの建物の形状を、1つのLOD対応形状にします。
「wood_house_LOD0」をシーンにドラッグして配置します。
「wood_house_LOD0」を選択した状態でInspectorタブを表示し、一番下の「Add Component」ボタンをクリック。
「LOD Group」を探して追加します。

「LOD Group」コンポーネントが表示され、LOD 0/LOD 1/LOD 2/Culledと表示されたバーが出ています。
ここの「LOD 0」に対してProjectウィンドウより「wood_house_LOD0」をドラッグ&ドロップします。
このときに「Reparent GameObjects」メッセージボックスが表示されるので「Yes」を選択します。

次に、「LOD 1」に対してProjectウィンドウより「wood_house_LOD1」をドラッグ&ドロップします。
同じく、「Reparent GameObjects」メッセージボックスが表示されるので「Yes」を選択します。
「LOD 2」に対してProjectウィンドウより「wood_house_LOD2」をドラッグ&ドロップします。
同じく、「Reparent GameObjects」メッセージボックスが表示されるので「Yes」を選択します。

Hierarchyタブでは以下のように表示されました。

親の「wood_house_LOD0」の「Mesh Filter」は参照させないようするため、Noneにしました。

これで、LODのメッシュのみ反映されることになります。
シーンに建物を追加する際にEmptyのGameObjectを配置して、そこにLOD Groupを追加するほうがいいかもしれません、、、。

InspectorのLOD Groupコンポーネントのカメラのアイコンを左右にドラッグすることで、
以下のように表示が変化します。

Hierarchyの「wood_house_LOD0」をProjectウィンドウにドラッグします。
これで「prefab」という形になりました。

prefab化すると、これをシーンにドラッグすることで
同じ状態のもの(ここではLOD Groupを割り当てたもの)をいくつも配置できます。
これで、建物のLOD対応は完成です。
シーンをファイル保存しておきます。

Unityでたくさん建物を配置して、カメラを動かしてみる

ProjectよりPrefabにした建物をシーンにドラッグして配置します。
そのあと、メインメニューの[Edit]-[Duplicate]を選択して、建物を複製していきます。

カメラを移動させて、形状が距離に合わせて切り替わっていってるのを確認します。

じっくり見ると、左の建物の壁の切り替わりを確認できます。

LODでどれくらい最適化できたか

最後に、LODの効果でどれくらい最適化できるか見てみます。
Playボタンを押し、Gameビューで「Stats」ボタンを押します。

この場合は、Trisは「253.9k」となっています。これは表示されている三角形の総数です。
Set Pass callsは51、Batchesは324となっていました。

では、LODを行わない場合はどうでしょうか ?
Project内のprefabを選択してInspectorの「LOD Group」を表示します。
「LOD 0」の右端をドラッグして、「LOD 1」「LOD 2」が見えない位置まで持ってきます。

これで、シーンで使用しているprefabの情報が一括して反映されました。
これは、LOD 0に固定した状態(=LODが無効の状態)になります。
Playして「Stats」ボタンを押して描画状態を見ると、
Trisは「1.1M」、Set Pass callsは52、Batchesは582となっていました。

LODを使わない状態→使う状態で、以下のように変化したことになります。
Tris : 1.1M → 253.9k、
Verts : 2.1M → 315.6k
SetPass calls : 52 → 51
Batches : 582 → 324
Shadow casters : 245 → 167

三角形数は1/4、頂点数は1/7くらいになっています。かなり最適化できてそうですね。

ということで、LODは最適化に貢献するという話題でした。
Shade3DでもLODの前処理(モデリング)は十分できますので、このへんは制作フローにいれるのがよさそうです。

Shade3DとUnityを行ったり来たりの話題ばかりでしたが、
次回はVRらしいことを予定しています。