[Omniverse] MDLのlookupを使用してジオメトリの情報をマテリアルに反映

  • by

Omniverse Create 2022.1.1ではMDLの「lookup」が使えるようになりました。
Omniverse Create 2021.3.8ではこれはまだ未実装で動いていませんでした。

MDLでのlookup機能とは ?

マテリアルで使用するMDLでは、MDL内の処理でテクスチャマッピングや色の指定などを行ってマテリアルの表現を行います。
Meshはこのマテリアルを参照する形になります。

実際はMeshのジオメトリも参照されます。また、UV値も参照しています。
これらはMDLを扱う場合は意識しなくても問題ありません。

一方、Meshのプロパティを見ると("Raw USD Properties"にUSDとしてのMeshの生のプロパティが一覧されます)
「primvars:xxx」というのがいくつかあります。

「primvars:st」はUSDではUVとして使用されることが多いです("st"とは限らない)。
"st"はfloat2の配列になります。

「primvars:xxx」の指定はユーザが任意のパラメータを追加することができます。
これをMDLで参照することができる機能が「lookup」になります。

Meshにprimvarを追加 (usdaファイルを編集)

Meshに独自のprimvarを追加するには、テキストファイルであるusdaファイルを直接編集するのが手っ取り早いです。

Omniverse Create上で球のMeshを配置して、usdaファイルで保存しました。
球の部分だけ一部取り出します。

    def Mesh "Sphere"
    {
        int[] faceVertexCounts = [3, 3, 3, 3 ...]
        int[] faceVertexIndices = [0, 1, 2, 0 ...]
        normal3f[] normals = [(0, -50, 0), ...]
        point3f[] points = [(0, -50, 0), ...]
        float2[] primvars:st = [(0.5, 0), ...]
        uniform token subdivisionScheme = "none"
        double3 xformOp:rotateXYZ = (0, 0, 0)
        double3 xformOp:scale = (1, 1, 1)
        double3 xformOp:translate = (0, 0, 0)
        uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"]
    }

「float2[] primvars:st」がUVのfloat2の配列です。

これを参考に以下の行を追加しました。

  color3f primvars:color1 = (0.2, 0.5, 0.0)

「primvars:」は付けるようにしてください。
「primvars:color1」にcolor3fとして情報を与えました。色情報になります。

このusdaファイルをOmniverse Createで新たに開きます。
SphereのPropertyの"Raw USD Properties"を一覧します。

「primvars:color1」を確認できました。

Meshにprimvarを追加 (Pythonスクリプト)

usdaファイルを編集するのは手間ではありますので、これをPython Scriptでプログラムで追加します。

以下は選択されたMeshに対して、"primvar:color1"を追加します。

from pxr import Usd, UsdGeom, UsdPhysics, UsdShade, Sdf, Gf, Tf

# Get stage.
stage = omni.usd.get_context().get_stage()

# Get selection.
selection = omni.usd.get_context().get_selection()
paths = selection.get_selected_prim_paths()

for path in paths:
    # Get prim.
    prim = stage.GetPrimAtPath(path)
    if prim.GetTypeName() != "Mesh": 
        continue

    m = UsdGeom.Mesh(prim)

    # Set primvar (color).
    primvar = m.CreatePrimvar("color1", Sdf.ValueTypeNames.Color3f)
    primvar.Set((0.2, 0.5, 0.0))

    break

MDL Material Graphでlookupを使用

では、マテリアルはMaterial Graphで作成してみましょう。
StageウィンドウでSphereを右クリックし、ポップアップメニューの「Create」-「Matrials」-「Create MDL Graph」を選択します。

Material Graphウィンドウで、MaterialsのPlasticノードをGraphにドロップしました。

plasticのoutから、Material(output)の「mdl:surface」につなぎました。

ノードを「lookup」で検索し「Primvar lookup, color」を探します。
これをGraphにドロップ。

lookup colorノードのoutをPlasticノードのcolorにつなぎました。

これでMDLのコンパイルが行われます。

以下のように球は真っ黒になりました。

lookup colorを選択した状態で、Propertyウィンドウを見ます。
「Inputs」に「inputs:name」「inputs:default_value」があります。
球の黒色は「inputs:default_value」の黒が反映されたようです。

「inputs:name」に球のMeshで指定した「color1」の名前を指定します。

Materialでの「color1」の参照の指定により、ジオメトリ(Mesh)側の「primvars:color1」の値がマテリアルとして反映されました。

このような感じでMDLでlookupを使用することにより、
マテリアルだけでなくジオメトリの情報も参照してくることができるようになります。

「primvars:xxx」の記述は必ず型があります。
この型と、「lookup 型名」は同じである必要があります。

Substance Designerで作成するMDLにて、同様のlookup指定を行うには ?

Substance DesignerでMDL Graphを作成する場合は、
「data_lookup_color」ノードを追加すれば同様のlookup指定ができます。

PROPERTIESウィンドウの「name」で参照する「primvars」の名前を指定します。

lookupとして使用できる型

2022/04/15追記。
Omniverse CreateのMaterial Graphで使用できるlookupのノードを列挙しました。
それぞれ入力値として、ジオメトリでの参照先の識別名を指定します。

ノード名 扱う型/Output
data_lookup_float float
data_lookup_float2 float2
data_lookup_float3 float3
data_lookup_float4 float4
data_lookup_int int
data_lookup_int2 int2
data_lookup_int3 int3
data_lookup_int4 int4
data_lookup_color color
data_lookup_uniform_float float
data_lookup_uniform_float2 float2
data_lookup_uniform_float3 float3
data_lookup_uniform_float4 float4
data_lookup_uniform_int int
data_lookup_uniform_int2 int2
data_lookup_uniform_int3 int3
data_lookup_uniform_int4 int4
data_lookup_uniform_color color

その他、テクスチャファイルを指定したlookupもあるようです(まだ動作は未確認)。

ノード名 扱う型/Output
lookup_float float
lookup_float3 float3
lookup_float4 float4
lookup_color color

このlookupの使用により、
例えば数千の同一テクスチャを貼った木が存在し、葉の色をランダムに乗算合成して変化を与えるといった場合にマテリアルは1つで済むなど利点が出てきそうです。