V-Ray to Unity 建築パースを1時間でウォークスルーVR化する1

久しぶりの更新です。
先週、コンテンツ東京2018へ行ってきました。
色んな面白いコンテンツを出展している企業やクリエイターさんがいて良い刺激になりました。

今日は、建築パース用に作ったシーンファイル(3dsMAX+V-Ray)をそのままUnityへ持っていく方法について書きます。

VRを使った空間設計のプレゼン案件は大規模である事が多く、たとえば2000㎡程度のウォークスルーVRを外注するとパースの3Dデータを提供してから早くても2週間、遅い所だと1ヶ月以上の納期が掛かります。僕はこれを1時間でやりたいのです!

パースのデータを短時間でVR化する為に

パース作成時の留意点

  • パースは3dsMAX+V-Rayで作成する
  • ポリゴン数は1000万ポリゴン以下に抑える(最終的には300万ポリゴン以下に削減)
  • マッピングはRWSではなくUVWを使う
  • Unityへそのまま持っていけるマテリアルは、VrayMtl、VrayLightMtl、VrayBlendMtl、VrayMtlWrapper、標準マテリアル、マルチサブオブジェクトマテリアル

VR化工程

  1. 【自動】MAXScriptで、VR用にシーン最適化する(ポリゴン数削減と、オブジェクトの統合)
  2. 【自動】MAXScriptで、FBXファイル+独自形式のマテリアルファイルを出力
  3. 【自動】Unityで、独自形式のマテリアルファイルを読み込む
  4. 【手動】Unityで、VR用アセットテンプレートを読み込み、基本設定等を行う。
  5. 【手動】ビルドして完成。

2000㎡の空間CGを2K60fbs以上で動かすために、テクスチャベイクやGI、SSRは使いません。ベースライティングは、指向性ライトの3点照明で形を出します。メインライティングは、必要な場所にスポットを配置します。どうしてもリアルに見せたい所だけライトマップをベイクします。シーンが軽ければ、GIかSSAOを使っても良いかもしれません。

 

VR作成で時間がかかる「作業」を自動化する

パース用で作成した3dsMAXシーンをUnityへ持っていくにはポリゴンのリダクションやアタッチなどのシーン最適化やマテリアルの移行が必要になります。パースのVR化を依頼された制作会社は、MaterialConverterなどのフリースクリプトを使ったり、手作業ゴリ押しでやっている所がほとんどだと思います。これらを自動化する事で、大幅に納期を削減する事ができます。

必要なスキル

スクリプトを使ってV-Ray→Unityへデータをそのまま持っていける様にしていきます。パース作成の他に、MAXScript、C#、V-Rayの知識、Unityシェーダーの理解が必要です。

MAXScript

3dsMAX+V-Rayで作成されたシーンの解析、ポリゴンのリダクション、オブジェクトの最適化、マテリアルの最適化と変換、マテリアルファイルをCSV出力するのに使います。

C#

Unity側で、マテリアルのCSVファイルを読み込むのに使います。

V-Ray

マテリアル変換ロジックを考えるのに必要です。V-RayとUnityではマテリアル構造が違うので、何をどういう計算式で変換すればいいか考えなければいけません。

Unityシェーダー

基本シェーダーで再現できないマテリアルは新たにシェーダーを作成しなければいけません。Unityは簡単にシェーダーを書ける様に作られています。

 

スクリプトの中身

最初に書いておきますが、競合他社にそのまま使われると困るのでソースコードは一部だけ公開します…ご了承くださいm(_ _)m

3dsMAX側のスクリプトツール(MAXScript)

1.リダクション

まず、シーン全体のバウンディングボックスサイズを取得します。
床、壁、天井、家具、その他(建具と造作)を分けて取り出し、シーン全体に対する面積比から適切なポリゴン数になるようにプロオプティマイザーを掛けます。オブジェクトを種類ごとに取り出す方法は、命名規則を設定するのが最も簡単で確実です。自動判別したい場合は、名前、位置、サイズ、親子ツリーからある程度推測できます。

GeForce GTX1080を使う想定だと、300万ポリゴン以下にしなければ60fpsを確保するのが難しくなるので、逆算して300万ポリゴン以下になる様にシーンを最適化します。

2.アタッチ

パースのデータをVR化するには、ポリゴン数よりもオブジェクト数の方に気をつけるべきかもしれません。オブジェクトは、マテリアル毎にアタッチすればOKです。SceneMaterialsでマテリアルの配列を取得できます。マテリアル毎にアタッチすると、オブジェクト数は100以下になるはずです。100以上になる場合は、パース作成の時点でマテリアルが最適化できていないかもしれません。

3.マテリアルの変換

マテリアルプロパティをUnity用に変換して、CSVファイルで出力します。
この変換ロジックが最も重要です!
V-RayとUnity両方のマテリアルを理解して変換式を考える必要があるのでハードルが高くなります。

ヒント

たとえば、反射強度に関わる設定はV-RayだとColor値ですが、UnityはFloat値です。Color値をUnityのFloat値へ変換するには「(R/255+G/255+B/255)/3」でRGB値の平均を取るのが最もシンプルな方法ですが、これだけでは不具合が生じます。V-RayマテリアルのRGB平均値と、UnityのFloat値はリニアな相関グラフにならないからです。とはいえ複雑な曲線グラフの式を書くのは難しいので、RGB平均値のレンジテーブルを作って段階的に処理するのが良いと思います。

あとは、V-RayマテリアルはMapが設定されている場合に設定値が無視される仕様になっていますが、UnityはMapに対して設定値が加算されてしまいます。Mapがある場合はRGB値を固定にするなどの工夫も必要です。

4.マテリアルのCSV出力

Unity用に変換したマテリアルプロパティは、ユーザー定義プロパティとしてFBX内に埋め込む事ができます。
埋め込まれたプロパティは、UnityでFBXファイルインポート機能にフックさせて取得できますが、インポート後にユーザー定義プロパティを取得する方法はありません。

パースデータの修正が入る事を想定して、マテリアルはFBX埋め込みではなくCSVで出力します。Color値をCSVで出力するなら、区切り文字は「カンマ」以外にします。

Unity側のスクリプトツール(C#)

FBXとマテリアルCSVを読み込んでから、Unity側で用意しておいたエディタ拡張スクリプトを実行します。

Unity側のスクリプト内容はシンプルです。Resourcesフォルダ内にMaterialsとTexturesフォルダを作ってそれぞれのアセットを収集します。あとはCSVを文字列で読み込み、1行ずつ、区切り文字でスプリットして対応するプロパティに割り当てるだけです。

もう少し詳しく書いた方が良いのかもしれませんが、長くなりそうなので今日はここまで。ソースコードはまた次回にします。