[Shade3D] Shade3Dからリアルタイム環境に形状を渡す

  • by

2021年1月に、「DOKI for Shade3D」( http://www.ft-lab.ne.jp/shade3d/DOKI/ )と、
glTF Converter ( https://github.com/ft-lab/Shade3D_GLTFConverter ) をアップデートしました。
Shade3D側でリファレンスとしてレンダリングして確認できる環境を作り、
そのままの形状/マテリアルで他のツール(ゲームエンジンなど)に渡す、というのが個人的に設定している目標になります。

そのためかかせないのが表面材質(マテリアル)を「PBRマテリアル」として統一することになります。
昨今のリアルタイム環境/ゲームエンジンは、マテリアルについてはPBRマテリアルをベースとしています。
同じパラメータ/テクスチャを渡すとほぼ同じ材質表現になります。
裏面を表示するかしないかのDoubleSided(Two Sidedとも呼ばれる)、複数のUVレイヤを使えるかどうか、など細かい違いはあります。
が、これらもゲームエンジン側でShaderを記載することで解決できる場合が多いです。
ただし、その渡す手段がまだ統一されているといえない状態ではあります。

ここでは、Shade3D ver.17 Standardと
その上で動作するプラグインとして
DOKI for Shade3D ver.1.1.1.2、glTF Converter ver.0.2.5.0を使用しています。
レンダリング環境は以下になります。

OS : Windows 10
Mem : 16 GB
CPU : 4 x Intel(R) Core(TM) i5-2500 CPU @ 3.30GHz
Shade3D : Shade3D Standard ver.17.1.0

今制作中(というよりも開始したばかり)の個人プロジェクトを例に説明していきます。

今回は、WebGL環境を出力先とします。

今の構想はこんな感じ。

なお、UnityにglTFファイルを渡す手段として、UniVRM ( https://github.com/vrm-c/UniVRM )などのアセットを別途使う方法もあります。
v0.63.0で確認したところ、URPやHDRP環境ではダイレクトにマテリアルが生成できていない?ような挙動のため、もう少し待つ必要がありそうでした。
また、Unity Asset Storeでアセットを公開/販売したい場合はfbxかobjといったUnityが標準でサポートしているファイルフォーマットを使用する必要があるため、
現状はfbx形式でUnityに渡してテクスチャのみ入れ替えるのが無難ではありそうです。

(参考)アセットストアへの出品 : http://assetstore.info/guide/

Unigineの場合は、標準でglTF形式のインポートに対応しています。
ただし、ver.2.13段階ではマテリアル情報でRoughness-Metallicテクスチャが渡らなかったり、KHR_texture_transformの情報が渡らないようです。
Unigineの場合は、glTFファイルを渡した後、別途テクスチャも渡してマテリアルを再調整する必要があります。

WebGLの場合は、WebGLフレームワークの実装に左右されます。
有名どころのBabylon.js / Cesium / three.js / FilamentではほとんどはglTFファイルを渡すだけでOKです。
また、PBRマテリアルの再現性もかなり高いです。

上図の「リファレンス」とは、オフラインレンダリングを行ったお手本です。
これは、正確な光の回り込みなどを確認するためのものです。
リアルタイム環境だけで調整していると、気づかないうちに「リアルじゃない」結果に突き進んでしまう場合があります。
他の方に指摘してもらうか、自身で数日置いてから見る、などしないと気づかないというのもざらです。
経験的なものもありますが、リファレンスと照らし合わせることであらぬ方向に行ってしまうのを防ぐというストッパーにもなります。

なお、各ゲームエンジンではShaderに合わせたテクスチャを割り当てる必要がある箇所があります(特に、Metallic-Roughnessは1つのテクスチャにパックされていることが多い)。
glTF Converter ver.0.2.5.0では、各ゲームエンジン別のテクスチャを別途出力する機能を追加しています。
これはブログで別途解説予定です。
WebGL環境ではglTFで統一されているため、このテクスチャの置き換え処理は不要です。

Shade3DでのPBRマテリアル

Shade3D ver.20 Professional版以降では、標準でPBRマテリアルを選択できます。
実用的な実装になったのはver.21から。
glTF Converterのver.21 Pro付属のものを使うと、Shade3D標準のPBRマテリアルをglTFエクスポートできます。
ただし、Basic/Standardでは使えないのとver.19以前では使えません。

このため、ここでは「DOKI for Shade3D」プラグインで説明していくことになります。
この場合は、DOKI自身はShade3D ver.14 Standard/Prodessional版以降で動作します。
glTF Converterは「不透明マスク」を使用するため、ver.16のStandard/Prodessional版以降での動作になります。
DOKI for Shade3D(OSPRay)はレンダリングが高速で品質もよいため、リファレンスとしてのチェックがしやすいと思われます。
DOKIを使用する場合は、Shade3Dの標準レンダリングを使わないという選択肢が有効かもしれません(レンダリングとglTFエクスポートにより内外で一元化できるようにしているため)。
そうなるのを目指しているプロジェクトでもあります。

FBXファイルだけではリアルタイム環境に渡せないの ?

FBXファイルのエクスポートは、FBX SDKを使用することになります。
これはどのDCCツールも同じだと思われます(クローズドフォーマットなので、、)。
FBX SDK 2020で確認しましたが、PBRマテリアルについての記述は見当たりませんでした。

前述のように、昨今のリアルタイム環境はマテリアルについてはPBRマテリアルをベースにしています。
それをサポートしたファイルフォーマットでないと、結局はマテリアル/テクスチャを渡した先のリアルタイム環境で調整する手間が発生します。
また、FBX SDKは毎年バージョンアップされており、バージョンによっては互換性が保たれていません。
DCCツールも常に最新のFBX SDKについていく必要があります(そして、大抵はバージョンを上げたがらない)。
そのため、個人的にはFBXファイルの使用は場所を選ぶかなという気がしてます。

オフラインやリアルタイムとは ?

一応、単語として出す「オフライン」や「リアルタイム」について。線引きしておきます。
Shade3DやBlender/Maya/Maxなどの「DCCツール」で「レンダリングを伴う画像の作成」は「オフラインレンダリング」のように呼ばれます。
ゲーム界隈の方は「プリレンダリング」という呼び方も多いかと思います。
これは、シーンを作成してレンダリングを実行すると少し待った後に1枚画像や動画が生成される手順になります。
シーンが複雑になればなるほどレンダリング時間がかかります。かつては、1枚のレンダリングに数日かかる場合もありました。
昨今は、レンダラのアルゴリズムの改善やAIの普及(主にDenoise、高周波ノイズをいい感じに滑らかにする)、GPUレンダラが出てきたことにより、
レンダリング時間はかなり短縮されています。
※ 分かりやすい単語なので「AI」と書いてますが、「Deep Learning」のことです。

「DOKI for Shade3D」はレンダリングエンジンとしてIntel社のOSPRay( https://www.ospray.org/ )を使用しており、これはアルゴリズムが強力なのとDenoise処理でAIを使用するため、
レンダリングはかなり速くなっています。

一方、「リアルタイムレンダリング」は、WebGLやUnity/Unreal Engine/Unigineなどのリアルタイムエンジンで行う描画です。
GPUを使用し、ハードウェアの力を借りて描画をガンガン回していきます。
オフラインレンダリングほど正確ではありませんが、ライトマップやライトプローブなどのリアルタイム専用のノウハウを使用して、1秒間に30-60フレーム分、VRだと1秒間に90フレームなど、高速に描画を行います。
絵作りとしては、プラスアルファの知識もいるため少し難易度が上がります。
昨今では、「レイトレーシング」もリアルタイムで行えるようになってきつつあるため、「反射」や「透過/屈折」もオフラインレンダラと変わらないくらいの品質で詰めることもできるようになってきています。

この「オフライン」と「リアルタイム」は作法に違いがあり、最適化もそれぞれ異なります。
この「オフライン」から「リアルタイム」向けに形状を渡す、というのが今回のテーマになります。

Shade3Dでの形状としての最適化

また、モデリングにおいて無駄なポリゴンを省いたりマテリアル(Shade3Dでのマスターサーフェス)をまとめたり、といった最適化はいずれの場合も必要です。
これについては、Shade3Dチュートリアルの「リアルタイム環境に渡すための最適化」でもまとめていますので、参考になるかと思います。
また、本ブログの「[Shade3D] 古いテレビをモデリング」がリアルタイム環境に渡すためのモデリングを目指してるため参考になるかもしれません。

リアルタイムに表示する必要があるため、最適化は必須です。
できるだけポリゴン数を抑えて軽くし、シンプルな構成にしておく必要があります。

形状の管理

形状はよく「アセット」と呼ばれます。
ここではキャビネットを例に説明します。

形状は原点を中心に配置しています。
マテリアルはマスターサーフェス(マスターマテリアル)で管理します。
この場合は、木の部分とガラス部の2つのみ。

[DOKI : PBR]のラベルは、DOKI for Shade3DでのPBRマテリアルの指定です。
こうすることで、表面材質ウィンドウの指定はそのままDOKI(OSPRay)に渡されて、PBRマテリアルとしてレンダリングに反映されます。

以下の赤で囲った部分がそのままPBRマテリアルのパラメータとして割り当てられています。

パラメータ名 テクスチャ指定 PBRマテリアルでのパラメータ名 説明
拡散反射 o BaseColor RGB : 基本色情報
A : 不透明度
反射 o Metallic グレイスケール指定
映り込み
透明 o Opacity グレイスケール指定
glTFのOpacityに「1.0 - 透明」が渡される
荒さ o Roughness グレイスケール指定
ざらつき具合
発光 o Emissive RGB : 発光色

glTFでは、屈折(IOR)は常に1.5として扱われます。
「透明」はBaseColorのAlpha値と合成されます。
このほか、マッピング要素として「法線マップ」「不透明マスク」「オクルージョン」を渡すことができます。
「不透明マスク」はBaseColorのAlpha値と合成されます。
DOKI for Shade3Dでは「発光」表現は表面材質ウィンドウでは指定できず、別途マテリアルの種類を「Luminous」にする必要があります。

UV

木のマテリアル/ガラスのマテリアルに分けており、テクスチャにすべての要素を押し込んでいます。
以下は木のマテリアルが参照するUV。

金属の取っ手や蝶番も、木のマテリアルの中に入れています。
上のUV図面では右下に金属部を入れています(灰色の箇所)。
不透明のマテリアル表現については、一般的な拡散反射のみの場合や金属などの反射する場合などでも、1つのマテリアル内でまとめることができます。
透明(不透明)が入る場合/両面指定が必要な場合などはリアルタイム環境ではShaderを変えることになるため、マテリアルを分けるほうがいいです。

テクスチャの作成と割り当て

テクスチャは、Substance PainterもしくはSubstance Designerで作成しています。
これはテクスチャ生成の専用ツールで、PBRマテリアルに対応しています。

ここで作成したテクスチャをglTF形式でエクスポートし、テクスチャをShade3Dに読み込んできています。
[Shade3D] DOKI for Shade3DとPBRマテリアルの指定」もご参照くださいませ。

表面材質のマッピングで以下のように指定しています。

5つのマッピングレイヤを指定。

マッピングの種類 合成 チャンネル合成 説明
拡散反射 乗算 アルファ乗算済み Aチャンネルを使用しない場合は、アルファ乗算済みにする
法線 通常 アルファ乗算済み 「適用率」で法線の強さを指定
荒さ 乗算 グレイスケール(G) 効果設定の「荒さ」を1.0にしておくこと
反射 乗算 グレイスケール(B) 基本設定の「反射」を1.0にしておくこと
Occlusion(glTF) 乗算 グレイスケール(R) glTF Converterの追加オプション

「荒さ」「反射」「Occlusion」については、Substance PainterでglTFとして出力されたテクスチャのRGBをそれぞれ分解して使用します。
基本はこの5つのマッピングと、発光する場合は発光のテクスチャを指定することになります。
DOKI for Shade3Dの「PBRマテリアル」の場合は、一般的なPBRマテリアルと互換性があるためこの情報がそのままレンダリングに渡ることになります。

レンダリング

DOKI for Shade3Dでレンダリングすると以下のようになりました。

1つのアセットの管理はこれで完結します。

DOKI for Shade3Dを持っていない場合

DOKI for Shade3Dがない場合、「PBRマテリアル」のレンダリングはできません。
Shade3D ver.20 Pro版以降の場合は、Shade3D標準でPBRマテリアルの指定はできます。

ここでのDOKIを使用した想定での表面材質のパラメータの指定自身は、DOKIがなくても使えますのでそれで割り当て、
glTFエクスポートしてWebGL側で確認する、という手段もあります。

glTF Converterは、エクスポートのデフォルトではShade3Dでの表面材質の設定をPBRマテリアルに似せるように加工して出力します。
それに頼るのも手ではあります(標準のレンダリング結果にある程度似せてglTFファイルを出力)。
ですが、可能な限りDCCツール(Shade3D)側と出力先の環境(WebGL/Unity/Unigineなど)はPBRマテリアルで統一させたほうが調整しやすいかと思います。

Shade3D上で複数アセットを使ったシーンをレンダリング

個別にモデリングしたアセットを「外部参照」としてシーンに読み込み、リンクを使って形状を配置していきます。

ブラウザでは「マスターオブジェクト」として読み込まれています。

レンダリングすると以下のようになりました。
DOKI for Shade3D(OSPRay)のレンダリングで、800x600ピクセルで26秒。

Shade3D側でレンダリング作品を作る場合は、

  • (大量の)アセットをあらかじめ用意
  • 別途シーンを作成し、アセットを外部参照で読み込んで並べる

という流れが管理しやすいかと思います。

アセットをglTFエクスポートして、WebGL環境に持って行く

再びキャビネットの形状に戻ります。
glTFエクスポートする場合は、基本的に1アセットで1glTF、のほうが管理しやすくなります。
メインメニューの「ファイル」-「エクスポート」-「glTF(glb) Shade3D Material」を選択します。

glTF Exportダイアログボックスで「テクスチャを加工せずにベイク」チェックボックスをオンにすることで、
DOKI for Shade3Dでマテリアルを「PBRマテリアル」として割り当てた状態でglTFファイルとしてエクスポートされます(DOKI for Shade3Dがなくても動作します)。
この場合は、テクスチャの加工処理(拡散反射と反射を考慮してピクセル単位で近似するなど)は行われず同一のテクスチャマッピングが複数ある場合にそれらがベイクされる動作のみ行われます。

出力されたglbファイルをglTF Viewer ( https://gltf-viewer.donmccurdy.com/ )に持って行きます。

glTF Viewerはthree.jsを使っているため、WebGLプログラムでもまったく同じように形状を再現できます。
このように、Shade3DでのDOKI(OSPRay)のレンダリングと同じマテリアルを保ったままリアルタイムに持っていけました。
ただし、WebGLフレームワークにより、微妙に挙動が変わる部分もあります。
three.jsの場合は、ガラスの半透明の表現はやや弱いようです。
いくつか比較してみます。

VS Code上でglTF Toolsを使って確認しました。

Three.js

Babylon.js

Cesium

Filament

DOKI for Shade3D(OSPRay)のレンダリング結果とFilamentは近く、半透明の映り込みがよりリアルに見えます。

半透明の補正

Adobe Aero(AR用アプリ)の場合は、three.jsの表示に近いです。
そのため、ターゲットによっては半透明(不透明マスク)を0.5あたりに底上げして出力したほうがそれらしくなります。
この場合はガラスのマテリアルで、「不透明マスク」の適用率を0.5に下げてglTF出力。

three.jsでは以下のようになりました。

この状態でFilamentに持って行くと、不透明が強いことになってしまいます。

WebGLフレームワークによっては表現が異なる場合があるので(特にOpacityの半透明表現)、その点は注意する必要があります。

なお、キャビネットの形状はglTFのサンプルとして以下に置いてますので、よろしければご参考までに。
https://ft-lab.github.io/gltf.html

今回はここまでです。
Shade3Dのレンダリング結果をもとに、glTFエクスポートしてWebGL環境で見る流れでした。
Unity/Unigineに渡す流れは別途ブログで説明していきます。