[MaterialX] [Omniverse] OpenPBR : マテリアルからジオメトリのパラメータを参照 (primvar)

  • by

確認環境 :
OS : Windows 11
MaterialX 1.39.1
kit-app-template : Omniverse USD Composer (Kit 106.4)

※ 説明で使用したキャプチャした画像は、特に指定がなければOmniverse USD Composerを使用しています。

今回はMaterialX(OpenPBR)を使ってジオメトリのパラメータを見るにはどうノードを組めばいいのか、というのを見ていきます。
UsdPrimvarReaderを使うことになります。
これはUSDのUsdPreviewSurfaceにも存在するノードです。

https://openusd.org/docs/UsdPreviewSurface-Proposal.html#UsdPreviewSurfaceProposal-PrimvarReader

Primvarとは ?

[Omniverse] MDLのlookupを使用してジオメトリの情報をマテリアルに反映
でも説明していますが改めてprimvarについて書いていきます。
primvarはマテリアルなどから参照できるジオメトリが持つパラメータです。

ジオメトリに対してはマテリアルがバインドされています。
マテリアルではbase_colorやmetallic、roughnessまたはテクスチャなどの標準的なパラメータが指定されており、これに対してジオメトリ側のprimvarのパラメータを追加することになります。

USDで定義済みのパラメータとしてMeshのdisplayColorやdisplayOpacity、UV座標配列の"st"(texCoord2f[]で名前は可変)があります。
これらはusdaでは以下のように記述されます。

def Mesh "Sphere"
{
    float3[] extent = [(-50, -50, -50), (50, 50, 50)]
    int[] faceVertexCounts = [...]
    int[] faceVertexIndices = [...]
    normal3f[] normals = [...] (
        interpolation = "faceVarying"
    )
    point3f[] points = [...]
    color3f[] primvars:displayColor = [(1, 0.5, 0.7)]
    texCoord2f[] primvars:st = [...] (
        interpolation = "faceVarying"
    )
    uniform token subdivisionScheme = "none"
    double3 xformOp:rotateXYZ = (0, 0, 0)
    double3 xformOp:scale = (1, 1, 1)
    double3 xformOp:translate = (0, 62, 0)
    uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"]
}
color3f[] primvars:displayColor = [(1, 0.5, 0.7)]

 texCoord2f[] primvars:st = [...]

など"primvars"の後にパラメータ名が指定されているのを確認できます。
"primvars:"はネームスペースと呼ばれます。

マテリアルを割り当ててない状態で"primvars:displayColor = [(1, 0.5, 0.7)]"のように指定すると以下のような表示になります。

次にカスタムパラメータを与えてみます。
以下は球体のMeshに対して、color1という色のパラメータを与えました。

usdaでは以下のように記述します。

def Mesh "Sphere"
{
    color3f primvars:color1 = (1, 1, 1)
    ...
}

このカスタムパラメータをMaterialXのOpenPBRで参照するのが今回のテーマです。

USD Composerでprimvarを追加する

usdのステージに対してprimvarの追加する方法は
usdaファイルに直接追加する、Pythonを使って追加する、が考えられます。
別途、Omniverse USD Composerでも追加できます。

Stageウィンドウでprimvarを追加したいprimを選択し右クリック。
ポップアップメニューの[Add]-[Attribute]を選択します。

Add AttributeウィンドウでNameに"primvars:xxx"のように指定。
Typeで型を指定します。ここでは色を与えたいのでcolor3fを選択しました。
Customはチェックボックスを外していますがどちらでもいいです。
VariabilityはVaryingのままにしました。これはアニメーションのキーフレームで使うかどうかというパラメータになります(Uniformだとキーフレームを持たないことになる)。

MaterialX : primvarで指定できる型

USDのprimvarで使用できる型のうち、いくつかがMaterialXのUsdPrimvarReaderノードで使用できます。
MaterialX Graph Editorでは次のようなノードを選択できました。

  • UsdPrimvarReader_integer
  • UsdPrimvarReader_boolean
  • UsdPrimvarReader_string
  • UsdPrimvarReader_float
  • UsdPrimvarReader_vector2
  • UsdPrimvarReader_vector3
  • UsdPrimvarReader_vector4

MaterialXのusd_preview_surface.mtlxに使用できるUsdPrimvarReaderの一覧があります。
https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/bxdf/usd_preview_surface.mtlx

matrix4dやquatfなどはないようです。
color3(color3f)の場合はvector3で代用することになります。

UsdPrimvarReader_booleanはOmniverse Kit 106.4, 106.5では使えない ?

2024/12/22 追記 :

Omniverse Kit 106.4, 106.5では、UsdPrimvarReader_booleanを使ってもMaterialX側で値が取得できないようでした。
UsdPrimvarReader_integerで整数で代用するのがよさそうです。

MaterialXでprimvarを使用する

ジオメトリに対してcolor3fとして"primvars:color1"を追加した場合、これをマテリアルから参照してみましょう。

MaterialX Graph Editorでmtlxファイルを作成

MaterialX Graph Editor上の作業になります。
はじめにopen_pbr_surfaceノードを以下のように配置しました。

このOpenPBRのためのノード指定については「[Omniverse] MaterialXとOpenPBR」をご参照くださいませ。

"UsdPrimvarReader_vector3"ノードを追加。
パラメータはvarnameに"color1"、fallbackにデフォルト値として(1, 1, 1)を指定しました。

このときのノードのoutはvector3です。
これをcolor3に変換するために"convert_vector3_color3"ノードを追加しました。

"UsdPrimvarReader_vector3"ノードのoutから"convert_vector3_color3"ノードのinにつなぎます。

さらに"convert_vector3_color3"ノードのoutから"open_pbr_surfaceshader"のinであるbase_colorにつなぎます。

これでmtlxファイルとしてファイル保存します。"OpenPBR_primvar_test.mtlx"としました。
これはMaterialX(OpenPBR)としてジオメトリ側の"primvars:color1"をマテリアルのdiffuse_colorとして参照するだけのものになります。

primvarを扱う場合、MaterialX Graph Editor上ではその参照の確認ができません。
そこで、このmtlxファイルをOmniverse USD Composerに持っていきます。

Omniverse USD Composer上で確認

対象のprim(ここではMeshとしてのSphere)のパラメータとして、"primvars:color1"が追加されているのを確認します。

まだ追加されてない場合は、「USD Composerでprimvarを追加する」の手順を参考に追加してくださいませ。
このアトリビュート(属性)は、PropertyウィンドウのRaw USD Propertiesから見ることができます。

"OpenPBR_primvar_test.mtlx"をReferenceとして追加し、PrimPathを"/MaterialX"としました。
これでMaterialXのマテリアルとして認識され、USD Composerでマテリアルとして使用できるようになります。

なお、mtlxファイルをStageウィンドウにドロップしてPayloadのまま扱うこともできました(PrimPathを"/MaterialX"にする指定はいずれにしても必要です)。

SphereのprimにOpenPBR_primvar_testのマテリアルを割り当てます。

Sphereの"primvars:color1"を変更することでSphereの色が変化することを確認できました。

これだけだとdisplayColorを使えば同様のことをできるじゃないか、と思われるかもしれません。
今回説明した内容はprimvarを使う場合の入り口にすぎません。

MaterialXのShaderとして色だけでなくbool値やint(ノードでifの分岐が可能)、個別のパラメータを組み合わせる、などカスタマイズができます。
マテリアルに持たせるパラメータだけだと、バインドしたすべての形状で同じマテリアルを持つことしかできません。
displayColorを使う場合は、metallicやroughness、テクスチャと併用できないという問題もあります(マテリアルを使う場合はdisplayColorは参照されない)。

このときにマテリアルからジオメトリのパラメータにアクセスできる(=primvarを使う)ようにすることで、1つのマテリアルだけで形状ごとに様々な変化を与えることが可能になります。
これらのprimvarを使った応用については後々書いていくようにします。

ということで今回はここまでです。