「[Omniverse] MaterialXを使う – その3」の続きです。
以下についてメモ書きです。
- Noiseテクスチャを使用
Omniverse Create 2022.3.1を使用しました。
fractal3d
ノイズは"fractal3d"のNodeGraphが使用できそうです。
"standard_surface_marble_solid.mtlx"が参考になりそうでした。
https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/resources/Materials/Examples/StandardSurface/standard_surface_marble_solid.mtlx
以下は、Omniverse Createで配置した球(半径 50cm)で見栄えが良くなるように調整したmtlxファイルです。
standard_surface_marble_solid.zip
zipを解凍すると、mtlxファイルに展開されます。
Omniverse Create(RTX-Real-Time)では以下のように表示されました。
シンプルな例
"standard_surface_marble_solid.mtlx"はいくつかの要素が組み合わさっているため、もっとシンプルな実装から見ていきます。
"UseNoise.mtlx"というファイル名にしました。
<?xml version="1.0"?>
<materialx version="1.38" colorspace="lin_rec709">
<nodegraph name="NG_noise">
<input name="noise_scale" type="float" value="0.1" />
<position name="obj_pos" type="vector3" space="object" />
<multiply name="scale_pos" type="vector3">
<input name="in1" type="vector3" nodename="obj_pos" />
<input name="in2" type="float" interfacename="noise_scale" />
</multiply>
<fractal3d name="noise" type="float">
<input name="octaves" type="integer" value="3" />
<input name="lacunarity" type="float" value="0.5" />
<input name="position" type="vector3" nodename="scale_pos" />
</fractal3d>
<combine3 name="combine_color" type="color3">
<input name="in1" type="float" nodename="noise" />
<input name="in2" type="float" nodename="noise" />
<input name="in3" type="float" nodename="noise" />
</combine3>
<output name="out_color" type="color3" nodename="combine_color" />
</nodegraph>
<standard_surface name="SR_NoiseTest" type="surfaceshader">
<input name="base" type="float" value="1" />
<input name="base_color" type="color3" nodegraph="NG_noise" output="out_color" />
<input name="specular_roughness" type="float" value="0.5" />
</standard_surface>
<surfacematerial name="NoiseTest" type="material">
<input name="surfaceshader" type="surfaceshader" nodename="SR_NoiseTest" />
</surfacematerial>
</materialx>
NodeGraphの"NG_noise"はノイズを使ったcolor3を作成します。
図で表すと以下のような感じになるでしょうか。
Omniverse Create 2022.3.1に"UseNoise.mtlx"を読み込みました。
これは単純な黒と白のみのノイズを描画しています。
nodegraphのinput
nodegraphでinputを使用します。
<nodegraph name="NG_noise">
<input name="noise_scale" type="float" value="0.1" />
</nodegraph>
ここでは"noise_scale"というfloat値を与えました。
これを使用する場合、以下の"in2"の指定のように"interfacename"で参照する必要がありました(この場合は"nodename"ではありません)。
<multiply name="scale_pos" type="vector3">
<input name="in1" type="vector3" nodename="obj_pos" />
<input name="in2" type="float" interfacename="noise_scale" />
</multiply>
position : オブジェクト座標の位置(vector3)を取得
"positon"ノードを使用することで、オブジェクト座標での位置を取得します。
<position name="obj_pos" type="vector3" space="object" />
書式は https://materialx.org/assets/MaterialX.v1.38.Spec.pdf で確認できます。
36ページ目の"Geometric Nodes"を参照。
space="world"指定でワールド座標位置の参照になるようですが、Omniverse Create 2022.3.1では反映されませんでした。
fractal3d : 3Dフラクタルノイズ
ノイズの作成は"fractal3d"ノードを使用します。
これは3Dフラクタルノイズになります。
<fractal3d name="noise" type="float">
<input name="octaves" type="integer" value="3" />
<input name="lacunarity" type="float" value="0.5" />
<input name="position" type="vector3" nodename="scale_pos" />
</fractal3d>
書式は https://materialx.org/assets/MaterialX.v1.38.Spec.pdf で確認できます。
27ページ目の"Standard Procedural nodes"を参照。
"octaves"でオクターブを整数値で指定(デフォルト3)。
"lacunarity"は、octaveの間の指数関数的なスケール値の指定(デフォルト2.0)。
"position"は位置をvector3で指定。
outputはfloat値になります。
PerlinNoiseを使用する場合は、"noise2d"や"noise3d"を使用できます。
combine3 : 複数のチャンネルを1つに結合
"combine3"は、前回の「[Omniverse] MaterialXを使う – その3 : separate」で解説した"separate"の逆の操作を行います。
<combine3 name="combine_color" type="color3">
<input name="in1" type="float" nodename="noise" />
<input name="in2" type="float" nodename="noise" />
<input name="in3" type="float" nodename="noise" />
</combine3>
書式は https://materialx.org/assets/MaterialX.v1.38.Spec.pdf で確認できます。
40ページ目の"Channel Nodes"を参照。
"combine3"はoutputとして"color3"または"vector3"を返します。
この場合、inputとして"in1","in2","in3"を指定でき、それぞれにfloat値を渡します。
ここでは、"fractal3d"からのfloat値を渡しています。
これでグレイスケールのカラーがノイズとして取得できました。
後は、今までと同じ流れになります。
"fractal3d"の値を加工していくと、冒頭であった"standard_surface_marble_solid.mtlx"の大理石のような表現になります。
乗算(multiply)、加算(add)、べき乗(power)、sin、合成(mix)の組み合わせで大理石模様にしています。
multiplyは説明済みなので、addとpower、sin、mixについてノード構成だけ書いておきます。
add
"in1"と"in2"の値を加算します。
<add name="add1" type="float">
<input name="in1" type="float" value="0.1" />
<input name="in2" type="float" value="0.3" />
</add>
power
"in1"の"in2"乗の値を加算します。
<power name="power" type="float">
<input name="in1" type="float" value="2.0" />
<input name="in2" type="float" value="3.0" />
</power>
sin
三角関数のsinの値を計算します。
"in"はラジアンで指定します。
1.5707の場合は、π/2で90度相当。
<sin name="sin" type="float">
<input name="in" type="float" value="1.5707" />
</sin>
mix
2値を合成します(lerp)。
"bg x (1.0-mix) + fg x mix"の計算になります。
<mix name="color_mix" type="color3">
<input name="bg" type="color3" value="0.8, 0.8, 0.8" />
<input name="fg" type="color3" value="0.5, 0.3, 0.9" />
<input name="mix" type="float" nodename="0.2" />
</mix>
"UseNoise.mtlx"でmixを使う
例として前述の"UseNoise.mtlx"にて、"combine3"を"mix"に置き換えてみます。
nodegraphのコードだけ記載します。
<nodegraph name="NG_noise">
<input name="noise_scale" type="float" value="0.1" />
<position name="obj_pos" type="vector3" space="object" />
<multiply name="scale_pos" type="vector3">
<input name="in1" type="vector3" nodename="obj_pos" />
<input name="in2" type="float" interfacename="noise_scale" />
</multiply>
<fractal3d name="noise" type="float">
<input name="octaves" type="integer" value="3" />
<input name="lacunarity" type="float" value="0.5" />
<input name="position" type="vector3" nodename="scale_pos" />
</fractal3d>
<mix name="color_mix" type="color3">
<input name="bg" type="color3" value="1.0, 0.1, 0.0" />
<input name="fg" type="color3" value="0.0, 0.1, 0.2" />
<input name="mix" type="float" nodename="noise" />
</mix>
<output name="out_color" type="color3" nodename="color_mix" />
</nodegraph>
mixは以下のように記載しました。
<mix name="color_mix" type="color3">
<input name="bg" type="color3" value="1.0, 0.1, 0.0" />
<input name="fg" type="color3" value="0.0, 0.1, 0.2" />
<input name="mix" type="float" nodename="noise" />
</mix>
fractal3dのfloat値を"mix"に指定しています。
なお、色についてはUSDやOmniverseのMDLと同じくLinear(raw)で指定します。
Omniverse Createでこのmtlxファイルを使用すると以下のようになりました。
ここで疑問点が出て来ると思います。
mixで2つの色を指定したのに黒が見えてますね。
fractal3dの値をクランプする
"RTX-interactive(Path Tracing)"に切り替えてみました。
黒は見えません。
どうやらこれは、fractal3dを使用するにあたって0.0-1.0の範囲にclampができていないのが原因のようです。
具体的にはfractal3dはマイナス値も返します。
これを修正してみます。
<multiply name="scale_v" type="float">
<input name="in1" type="float" nodename="noise" />
<input name="in2" type="float" value="1.0" />
</multiply>
<clamp name="clamp_v" type="float">
<input name="in" type="float" nodename="scale_v" />
<input name="low" type="float" value="0.0" />
<input name="high" type="float" value="1.0" />
</clamp>
<mix name="color_mix" type="color3">
<input name="bg" type="color3" value="1.0, 0.1, 0.0" />
<input name="fg" type="color3" value="0.0, 0.1, 0.2" />
<input name="mix" type="float" nodename="clamp_v" />
</mix>
まず"multiply"でfractal3dのfloat値の倍率を変えることができるようにしました。
ただ、ここでは倍率は1.0で値は変更していません。
"clamp"で"low"と"high"を指定することで、0.0-1.0の範囲に収まるようにしました。
これをOmniverse Createに読み込みました。
"RTX-Real-Time"
"RTX-interactive(Path Tracing)"
これで同じになりました。
"scale_v"の"in2"を4.0にしてみました。
Omniverseに読み込まれた段階でmtlxはMDLに変換されるため、パラメータはOmniverseで変更して確認できます。
fractal3dの値が0.0以下の場合は黒にしたい
上記の"UseNoise.mtlx"では、fractal3dの値が0.0以下の場合に黒にした方がカッコいい感じだったので、
"RTX-interactive(Path Tracing)"でもあえてそうしてみましょう。
"noise"はfractal3dのoutput値(float)、これはマイナス値も含みます。
"color_mix"にクランプされた色(color3)が入っているとします。
<multiply name="scale_v2" type="float">
<input name="in1" type="float" nodename="noise" />
<input name="in2" type="float" value="10.0" />
</multiply>
<clamp name="clamp_v2" type="float">
<input name="in" type="float" nodename="scale_v2" />
<input name="low" type="float" value="0.0" />
<input name="high" type="float" value="1.0" />
</clamp>
<multiply name="m_color" type="color3">
<input name="in1" type="color3" nodename="color_mix" />
<input name="in2" type="float" nodename="clamp_v2" />
</multiply>
<output name="out_color" type="color3" nodename="m_color" />
"scale_v2"で"noise"の値を10倍と大きくすることで、値を大きくしてます(0.0付近の値を飛ばしている)。
"clamp_v2"でこの値をクランプします。結果的に、0.0か1.0に近い値が入ることになります。
その間は緩やかにグラデーションします。
これを"color_mix"に乗算することで、"noise"がマイナスになる場合は黒になるようにしています。
Omniverse Createで見てみました。
上が"RTX-Real-Time"、下が"RTX-interactive(Path Tracing)"。
これで同じ結果になりました。
最終的なmtlxファイルです。 UseNoiseMix2.zip
今回はここまでです。