前回はOmniverse Unity ConnectorからのUSDエクスポートにおけるマテリアルでUsdPreviewSurfaceに焦点を絞って説明しました。
今回はMDL(OmniPBR/OmniGlass)を使用します。
以下の環境で確認しました。
Unity : 2022.3.6f1
Omniverse Unity Connector : 201.0.0 beta
Omniverse USD Composer : 2023.2.0 beta
USD ComposerにUSDファイルを持って行く場合、MDLを使用するほうが整合性が取れている点が多いです。
MDLを使用する利点
ここでの説明はOmniverse Unity Connectorの機能の説明ではなく、OmniverseでMDLを使う場合の説明になります。
MDLを使用すると、UsdPreviewSurfaceよりもより柔軟にマテリアルを表現できます。
OmniPBRやOmniGlassなどのプリセットのMDLを使用する、もしくは独自でShader的なものを書くことも可能です。
OmniPBRやOmniGlassは、MaterialのPrimに対して1つのShaderのPrimだけでパラメータを与えています。
UsdPreviewSurfaceよりも可読性を持たせたパラメータ指定ができます。
個人的には、プログラム(PythonやC++)としてUSDファイルを作成する場合でもOmniPBRやOmniGlassを使うほうが実装しやすいように思います。
OmniPBRを使用するときのusdaファイルを見ると、以下のようになります。
def Material "OmniPBR_cyawan"
{
token outputs:mdl:displacement.connect = </World/Looks/OmniPBR_cyawan/Shader.outputs:out>
token outputs:mdl:surface.connect = </World/Looks/OmniPBR_cyawan/Shader.outputs:out>
token outputs:mdl:volume.connect = </World/Looks/OmniPBR_cyawan/Shader.outputs:out>
def Shader "Shader"
{
uniform token info:implementationSource = "sourceAsset"
uniform asset info:mdl:sourceAsset = @OmniPBR.mdl@
uniform token info:mdl:sourceAsset:subIdentifier = "OmniPBR"
asset inputs:ao_texture = @../textures/cyawan/cyawan_mat_occlusion.png@ (
colorSpace = "raw"
)
float inputs:ao_to_diffuse = 1
asset inputs:diffuse_texture = @../textures/cyawan/cyawan_mat_albedo.png@ (
colorSpace = "auto"
)
asset inputs:normalmap_texture = @../textures/cyawan/cyawan_mat_normal.png@ (
colorSpace = "raw"
)
float inputs:metallic_constant = 0
float inputs:reflection_roughness_texture_influence = 1
asset inputs:reflectionroughness_texture = @../textures/cyawan/cyawan_mat_roughness.png@ (
colorSpace = "raw"
)
token outputs:out (
renderType = "material"
)
}
}
Materialの中の1つのShaderにマテリアルのパラメータやテクスチャが内包されているのを確認できます。
UsdPreviewSurfaceで同等のパラメータを指定する場合、複数のShaderが互いに接続(connect)されていて複雑でした。
Omniverseでは以下の方法でMDLを作成し、マテリアルとして使用できます。
- OmniPBR/OmniGlass/OmniSurfaceなどのMDLで実装されたプリセットのマテリアル
- mdlファイルをテキストファイルとして作成 ( https://developer.nvidia.com/rendering-technologies/mdl-sdk )
- Substance 3D Designerでmdlファイルを作成 (「[Omniverse] マテリアルの割り当て その7 (MDLを渡す)」もご参照くださいませ)
- Material Graphを使用 (「[Omniverse] マテリアルの割り当て その5 (Material Graph基礎編)」もご参照くださいませ)
OmniPBR
通常のPBRマテリアルを使用する場合はOmniPBRで事足りることも多いです。
Albedoマップに色を乗算するというのも、UsdPreviewSurfaceより分かりやすいです。
この場合は、Albedo MapとColor Tintは乗算合成された表現になります。
usdaファイルでは以下のように記述されます。
def Material "OmniPBR_cyawan"
{
token outputs:mdl:surface.connect = </World/SampleScene/Looks/OmniPBR_cyawan/Shaders0.outputs:out>
def Shader "Shaders0"
{
uniform token info:implementationSource = "sourceAsset"
uniform asset info:mdl:sourceAsset = @OmniPBR.mdl@
uniform token info:mdl:sourceAsset:subIdentifier = "OmniPBR"
asset inputs:diffuse_texture = @./Materials/OmniPBR_cyawan/cyawan_mat_albedo.png@
color3f inputs:diffuse_tint = (0.78378, 0.7102, 0.49932)
}
}
Albedo Mapの識別名は"inputs:diffuse_texture"、Color Tintの識別名は"inputs:diffuse_tint"です。
またOmniPBRのOpacityを使用した場合の半透明表現では、透過部では屈折率の影響を受けません。
アルファ合成のような表現になります。
OmniPBRの屈折率はデフォルトの1.5が与えられています。パラメータとしては存在しません。
これは透過ではなく、金属での反射の表現などで使用される屈折率です。
OmniGlass
ガラスの表現はOmniGlassを使います。
OmniGlassは透過+屈折を行うマテリアルで使用します。
他にも、SSSを含むよりリッチな表現ができるOmniSurfaceなどを使用できます。
Omniverse Unity ConnectorではOmniPBRとOmniGlassの出力を行います。
Omniverse Unity ConnectorでOmniPBRを使用
Omniverse – Settingsを選択し、Settingsウィンドウを表示します。
Material Typeで"MDL"を選択すると、エクスポート時のマテリアルはOmniPBRかOmniGlassを使用して出力されます。
UnityのURPの場合はShaderとして「Universal Render Pipeline/Lit」を使用すると、大部分のパラメータはエクスポート時にOmniPBRとして反映されます。
ただしUsdPreviewSurfaceと違い、「Universal Render Pipeline/Complex Lit」で存在したClearCoatには対応していません。
これは、OmniPBR/OmniGlassではClearCoatのパラメータが存在しないためです。
UsdPreviewSurfaceとOmniPBRの表現の違い
Omniverse Unity ConnectorからUsdPreviewSurface/OmniPBRでエクスポートした場合、表現力の違いはほとんどありません。
以下は、USDエクスポート時のMaterial Typeを"UsdPreviewSurface"と"MDL"を切り替えて比較してみました。
"UsdPreviewSurface"時はOcclusion Mapが反映されていないように見えます。
パラメータとしては存在する/USDViewでは反映されているため、これはUSD Composer 2023.2.0 betaの問題かもしれません。
UsdPreviewSurfaceとMDL(OmniPBR/OmniGlass)のどちらを使うのがいいか?
出力したUSDファイルをOmniverseで使う場合は、マテリアルとしてOmniPBRを使うほうが調整しやすいです。
互換性のため、他のツールやARKitなどでUSDを扱う場合はUsdPreviewSurfaceを使うようにします。
半透明(ガラス表現)を行う場合はOmniGlassを使うほうが調整しやすいため、MDLを使うのがよさそうです。
OmniPBRでの半透明の表現
Unity上で以下のような瓶をUSDエクスポートします。
半透明にするために、マテリアルのパラメータは以下を指定しました。
- Surface Type = Transparent
- Render Face = Both
- Base Mapのアルファ = 0.1098
これをMaterial Typeで"MDL"を指定してUSDエクスポートしました。
USD Composerで読み込むと以下のようになります。
映り込みが分かりやすいように、Environmentsより背景を変更しました。
USD ComposerのRTXレンダラは、デフォルトで両面表示になります。
そのため、ガラス瓶のような両面が必須な表現はそのまま反映されます。
この段階では、透過時の屈折が存在しないためのっぺりしています。
Built-In/URPでは、MDLとしてエクスポートする場合はOmniPBRを使用します。
そのため、半透明は意図した表現が難しいかもしれません。
HDRPの場合
UnityのHDRP時は、USDエクスポート時に特定のパラメータ指定でOmniGlassを使用することができます。
以下のように"HDRP/Lit"のガラス瓶のマテリアルを指定しました。
-
Surface TypeでTransparentを指定。
-
Base Mapのアルファ値を0.0にする
-
Refraction ModelでNone以外を選択
この条件を満たすと、USDエクスポート時にTransparent表現はOmniGlassで出力されます。
このとき、以下のパラメータがOmniGlassに反映されます。
- Metallic
- Smooothhess
- Index Of Refraction
- Transmittance Color
"Transmittance Color"がGlassの色に相当します。
このとき、Base Mapの色は使われていません。
USDエクスポートして、USD Composerにインポートしました。
背景とライトを調整すると、以下のようになりました。
なお、OmniGlassを使用する場合にRoughnessは"RTX-Intaractive(Path Tracing)"でないと反映されません。
"RTX-Intaractive(Path Tracing)"では以下のようになりました。
影もより自然になりました。
Unity(HDRP)でより自然な透過+屈折を行うには?
ここでの指定は、Omniverse Unity ConnectorのUSDエクスポート/インポートには影響しません。
あくまでUnity Editor上の表現の話になります。
Unity 2022(HDRP)の初期状態では、DX11が使用されます。
屈折が絡む場合は、レイトレーシングを行わないと表現で気になる点が出てきます。
以下のような3つのガラスを使った形状を考えてみます。
これは、以下の3つのマテリアルの指定を行ってIORを反映しました。
- Surface TypeでTransparentを指定。
- Base Mapのアルファ値を0.0にする
- Refraction ModelでSphereを選択
しかし、屈折は不自然です。
HDRPでの屈折の場合、メッシュに対してレイトレーシングすると仮定したときに1回のIn+1回のOutとなる形状(球など)とならない表現は難しいようでした。
そのため、HDRPのレイトレを使うようにしました。
これはDX12に切り替える必要があります。
HDRPでレイトレーシングを使用
- Edit – Project Settingsを選択し、Project Settingsウィンドウを表示。
Playerを選択し、Other Settings – Graphics APIs for Windowsに"Direct3D12"を追加します。
"Direct3D12"が先頭になるように順番を入れ替えるようにしてください。 - Window – Rendering – HDRP Wizardを選択。
HDRP + DXRタブを選択し、「Fix」ボタンがある場合はクリックしていきます。
途中でUnity Editorの再起動を促される場合があるため、これは指示に従います。
全部で緑色のチェックが付けばOKです。
なおHDRP + DXRを使用するには、
https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@14.0/manual/Ray-Tracing-Getting-Started.html
より、レイトレーシングが使用できるGPUであるかどうかチェックする必要があります。 - Unity Editorのキャプションで<DX12>が表示されているのを確認。
- Hierarchyウィンドウで右クリックし、Volume – Global Volumeを選択。
GameObject名を"RayTracing"に変更しました。
- "RayTracing"のInspectorウィンドウを表示。
Profileを作成します。これはファイルになり、ここにこのボリュームの設定が保存されます。
一番下の「Add Override」ボタンをクリックし、Ray Tracingの"Ray Tracing Settings"と"Recursive Rendering"を追加します。
それぞれの左上に薄っすらと見える"ALL"をクリックすると、すべての項目がOnになります。
"Recursive Rendering"のStateを"Enabled"に変更します。
これで、シーンでレイトレーシングを使用する準備が整いました。
このときUnityのレンダリングのすべてがレイトレーシングされるわけではなく、機能ごとにレイトレーシングを使うか個別に指定していくことになります。
- ライトの影
- マテリアルの透過処理
などがレイトレーシングの対象です。
今回はマテリアルの透過処理でレイトレーシングを有効にします。
IORを使用しているマテリアルで"Recursive Rendering (Preview)"をOnにします。
これで、以下のように自然な透過+屈折表現になりました。
全ての形状に同じ処理を行いました。
透過の最大数はデフォルト4のため、RayTracing用に作成されたボリュームのパラメータを調整します。
"Recursive Rendering (Preview)"のMax Depthパラメータで調整できます。
4から6に変更しました。
これで、Unity Editorで透過+屈折のガラス表現もいい感じになりました。
USDエクスポートし、USD Composerに持って行く
USDエクスポートを行います。
このとき、Unity Editor側のOmniverse-SettingsでMaterial Typeは"MDL"を選択するようにしてください。
USDファイルのエクスポート後はUSD Composer側の作業になります。
USD Composer側でインポートし、背景(DomeLight)の変更/ライトの調整を行いました。
また、Post ProcessingでTone Mapping OperatorでIrayを選択し、Crash Blacksを0.03に変更しました。
RTX-Real-Timeでは以下のようになりました。
RTX-Interactive (Path-Tracing)ではより自然になりました。
以上で、UnityでOmniverse Unity Connectorを使用してMDL(OmniPBR, OmniGlass)のマテリアルを渡すことを確認できました。