[Omniverse] MaterialXを使う – その2

  • by

[Omniverse] MaterialXを使う」ではOmniverse上でMaterialXのmtlxファイルを扱うところまで進みました。
今回はmtlxファイルの中身をいじっていきます。
ここではOmniverse Create 2022.3.1を使用しました。
確認はOmniverse Create上で行っていますが、"MaterialX Viewer"も試してみます。

MaterialX Viewer

mtlxファイルを見るビュワーとして"MaterialX Viewer"が用意されています。
ここではWindows版で確認しました。

MaterialXのGitHub( https://github.com/AcademySoftwareFoundation/MaterialX )より、Releasesより"MaterialX_Windows_VS2019_x64_Python38.zip"をダウンロードして解凍しました。
解凍後の"bin/MaterialXView.exe"をダブルクリックして起動します。

マウス右ドラッグでパン、左ドラッグで回転。ホイールでズーム調整できます。
"Load Material"ボタンをクリックすると、mtlxファイルを読み込みます。
テクスチャを割り当てるmtlxファイルを指定してみました(mtlxの内容については後述します)。

"Load Mesh"ボタンをクリックすると、objまたはglTF(glbも含む)ファイルを読み込めます。
リファレンスとしてのmtlxファイルの確認に使用できそうです。

mtlxファイルの構成を確認

前回書いた以下の内容を見ていきます。"standard_surface_plastic.mtlx"というファイル名にしています。
XML形式になります。

<?xml version="1.0"?>
<materialx version="1.38" colorspace="lin_rec709">
  <standard_surface name="SR_plastic" type="surfaceshader">
    <input name="base" type="float" value="1" />
    <input name="base_color" type="color3" value="0.10470402, 0.24188282, 0.81800002" />
    <input name="specular_roughness" type="float" value="0.32467532157897949" />
  </standard_surface>
  <surfacematerial name="Plastic" type="material">
    <input name="surfaceshader" type="surfaceshader" nodename="SR_plastic" />
  </surfacematerial>
</materialx>

コメントを書くには ?

XMLと同じです。

<!-- 何かコメント -->

のように記載します。

構成

ノードの接続の表現にすると以下のようになるでしょうか。

"SR_plastic"(standard_surfaceタグで指定される)のoutputを
"Plastic"(surfacematerialタグで指定される)につないでいます。
タグのくくりが1つのノードに相当します。
standard_surfaceタグでは属性としてname="SR_plastic"とtype="surfaceshader"の2つがあります。
これにより、ノード名(name)と型(type)を指定しています。

inputタグは、ノードのピンに相当します。入力要素として、名前(name)と型(type)、値が指定されています。

<input name="base" type="float" value="1" />

surfacematerialタグの入力要素は以下のように記載されています。

<input name="surfaceshader" type="surfaceshader" nodename="SR_plastic" />

型(type)として、入力するノードのtypeと同じものを指定。
ノード名(nodename)として、入力するノードの名前と同じものを指定しています。

ノードの種類と使用できるinputは ?

では、どのようなノードの種類があり、ノード別のinputはどのようなものがあるのでしょうか?
仕様の確認は、MaterialX公式のPDFファイルで確認できます。

MaterialX公式 : https://materialx.org/

MaterialX Spec PDF (v1.38) :
https://materialx.org/assets/MaterialX.v1.38.Spec.pdf

このPDFの"Material Nodes"のページ(61ページ目)に説明がありました。
"standard_surface"のパラメータをまとめてみます。
"standard_surface"はこれ以外にもパラメータがありますが、このSpecのPDFでは記載がありませんでした。

パラメータ名(name) 型(type) デフォルト値 説明
base float 1.0 ベースカラー値(0.0 – 1.0)
base_color color3 (0.8, 0.8, 0.8) ベースカラー(Albedo)
specular float 1.0 スペキュラー値(0.0 – 1.0)。
これはラフネスなどにも影響する。
specular_color color3 (1, 1, 1) スペキュラー色
specular_roughness float 0.2 ラフネス値(0.0 – 1.0)
metalness float 0.0 メタリック値(0.0 – 1.0)

standard_surfaceのパラメータ一覧とデフォルト値

GitHubの以下のmtlxファイルに、standard_surfaceのすべてのパラメータとデフォルト値が記載されています。

https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/resources/Materials/Examples/StandardSurface/standard_surface_default.mtlx

Standard Surfaceってそもそも何 ?

Autodesk Standard Surface
https://autodesk.github.io/standard-surface/

これがベースになってそうです。
OmniverseではOmniSurfaceのベースとしてAutodesk Standard Surfaceが考慮されているため、
パラメータはおなじみのものとなりますね。

Glass表現で使用するパラメータ

たとえばGlass表現で使用するのは以下のパラメータが使用できます。

パラメータ名(name) 型(type) デフォルト値 説明
specular_IOR float 1.5 屈折率
transmission float 0.0 透過値(0.0で非透過、1.0で完全透過)
transmission_color color3 (1, 1, 1) 透過時の色
transmission_depth float 0 透過時のdepth (*1)
transmission_scatter color3 (0, 0, 0) 透過時のscatter (*1)
transmission_scatter_anisotropy float 0 透過時のscatter_anisotropy (*1)
transmission_dispersion float 0 透過時のdispersion (*1)
transmission_extra_roughness float 0 透過時のラフネス値
opacity color3 (1, 1, 1) 不透明度

*1 : これは未調査。

"standard_surface_glass.mtlx"も参考になりそうです。
https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/resources/Materials/Examples/StandardSurface/standard_surface_glass.mtlx

<?xml version="1.0"?>
<materialx version="1.38" colorspace="lin_rec709">
  <standard_surface name="SR_glass" type="surfaceshader">
    <input name="base" type="float" value="0.0" />
    <input name="specular" type="float" value="1" />
    <input name="specular_color" type="color3" value="1, 1, 1" />
    <input name="specular_roughness" type="float" value="0.01" />
    <input name="specular_IOR" type="float" value="1.52" />
    <input name="transmission" type="float" value="1" />
    <input name="transmission_color" type="color3" value="1, 1, 1" />
    <input name="transmission_depth" type="float" value="0" />
    <input name="transmission_scatter" type="color3" value="0, 0, 0" />
    <input name="transmission_scatter_anisotropy" type="float" value="0" />
    <input name="transmission_dispersion" type="float" value="0" />
    <input name="transmission_extra_roughness" type="float" value="0" />
    <input name="opacity" type="color3" value="1, 1, 1" colorspace="lin_rec709" />
  </standard_surface>
  <surfacematerial name="Glass" type="material">
    <input name="surfaceshader" type="surfaceshader" nodename="SR_glass" />
  </surfacematerial>
</materialx>

Glass表現では"transmission"を1.0にしているのが大きな違いでしょうか。
その他は"specular_IOR"以外はデフォルト値が割り当てられています。
Omniverse Createでは以下のように表示されました。

※ RTX-Interactive(Path-Tracing)である必要があります。

もう少しノードの接続が増えてくると、ノードの意味が分かりやすくなると思います。
次に、base_colorにテクスチャを接続してみます。

テクスチャの接続

mtlxファイルを配置するフォルダ構成を以下のようにしました。

[images]
  tile_image.png
[UseTexture]
  UseTexture.mtlx

"UseTexture.mtlx"がMaterialXのドキュメントファイルです。
ここを基準にすると、テクスチャは"../images/tile_image.png"に存在することになります。

UseTexture.mtlx

<?xml version="1.0"?>
<materialx version="1.38" colorspace="lin_rec709">
  <nodegraph name="NG_test1" fileprefix="../images/">
    <tiledimage name="image_color" type="color3">
      <input name="file" type="filename" value="tile_image.png" colorspace="srgb_texture" />
      <input name="uvtiling" type="vector2" value="1.0, 1.0" />
    </tiledimage>
    <output name="out_color" type="color3" nodename="image_color" />
  </nodegraph>

  <standard_surface name="SR_test1" type="surfaceshader">
    <input name="base" type="float" value="1" />
    <input name="base_color" type="color3" nodegraph="NG_test1" output="out_color" />
    <input name="specular_roughness" type="float" value="0.5" />
  </standard_surface>

  <surfacematerial name="TextureTest" type="material">
    <input name="surfaceshader" type="surfaceshader" nodename="SR_test1" />
  </surfacematerial>
</materialx>

この場合は、以下の3つのノードが存在します。

  • "NG_test1"(nodegraph)内の"image_color"(tiledimage)
  • "SR_test1"(standard_surface)
  • "TextureTest"(surfacematerial)

2つめと3つめは今までと同じノードになります。
"nodegraph"タグを新たに追加しました。
図で表すと以下のようになるでしょうか。

"SR_test1"の"base_color"に対して、テクスチャの色(color3)を渡しています。

"nodegraph"タグ内は複数のノードを格納できます。

<nodegraph name="NG_test1" fileprefix="../images/">
</nodegraph>

としたときに、fileprefixはファイルを指定する場合の相対パスを与えています。

    <tiledimage name="image_color" type="color3">
      <input name="file" type="filename" value="tile_image.png" colorspace="srgb_texture" />
      <input name="uvtiling" type="vector2" value="1.0, 1.0" />
    </tiledimage>
    <output name="out_color" type="color3" nodename="image_color" />

"tiledimage"の"file"でファイル名の指定、テクスチャのスケール値を"uvtiling"として指定しました。
"output"タグでどのノード(ここではnodename="image_color")を出力するかを指定しました。

"standard_surface"タグの"base_color"にて、nodegraphにノードグラフ名、outputにノードグラフ内のoutputを与えることで、ここに定数の色ではなくテクスチャからのピクセル色をつなげています。

    <input name="base_color" type="color3" nodegraph="NG_test1" output="out_color" />

Omniverse CreateでこのUseTexture.mtlxを適用すると以下のようになりました。

テクスチャに指定の色を乗算

UseTexture.mtlxを発展させて、テクスチャに指定の色を乗算します。

UseTextureMultiply.mtlx

<?xml version="1.0"?>
<materialx version="1.38" colorspace="lin_rec709">
  <nodegraph name="NG_test1" fileprefix="../images/">
    <tiledimage name="image_color" type="color3">
      <input name="file" type="filename" value="tile_image.png" colorspace="srgb_texture" />
      <input name="uvtiling" type="vector2" value="1.0, 1.0" />
    </tiledimage>
    <output name="out_color" type="color3" nodename="image_color" />
  </nodegraph>

  <nodegraph name="multiply_color3">
    <multiply name="multiply_texColor" type="color3">
      <input name="in1" type="color3" nodegraph="NG_test1" output="out_color" />
      <input name="in2" type="color3" value="1, 0.1, 0.1" />
    </multiply>
    <output name="out_multiply" type="color3" nodename="multiply_texColor" />
  </nodegraph>

  <standard_surface name="SR_test1" type="surfaceshader">
    <input name="base" type="float" value="1" />
    <input name="base_color" type="color3" nodegraph="multiply_color3" output="out_multiply" />
    <input name="specular_roughness" type="float" value="0.5" />
  </standard_surface>

  <surfacematerial name="TextureTest" type="material">
    <input name="surfaceshader" type="surfaceshader" nodename="SR_test1" />
  </surfacematerial>
</materialx>

色の乗算は、nodegraphのmultiplyタグで行います。
テクスチャから取得した色(nodegraph="NG_test1" output="out_color")を1つめの色、
定数として(1, 0.1, 0.1)を2つ目の色として乗算しています。
ここでは別のnodegraphに分けてそれに対してmultiplyタグを指定しました。

  <nodegraph name="multiply_color3">
    <multiply name="multiply_texColor" type="color3">
      <input name="in1" type="color3" nodegraph="NG_test1" output="out_color" />
      <input name="in2" type="color3" value="1, 0.1, 0.1" />
    </multiply>
    <output name="out_multiply" type="color3" nodename="multiply_texColor" />
  </nodegraph>

図で表すと以下のようになるでしょうか。

Omniverse CreateでこのUseTextureMultiply.mtlxを適用すると以下のようになりました。

どのようなノードがあるか探す

"tiledimage"は、以下に記載がありました。

MaterialX: Supplemental Notes (v1.38) :
https://materialx.org/assets/MaterialX.v1.38.Supplement.pdf

"multiply"は以下に記載がありました。

MaterialX Spec PDF (v1.38) :
https://materialx.org/assets/MaterialX.v1.38.Spec.pdf

実践的なノードの書き方は、GitHubを見るほうが参考になりそうです。
https://github.com/AcademySoftwareFoundation/MaterialX/tree/main/resources/Materials/TestSuite

以上で、MaterialXのノードと接続の動きが見えてきました。
後はドキュメントやGitHubを見ていけば全体が見わたせそうですね。