Substance Painter用フィルタの作り方(基礎編)

今回の記事はSubstance Painter用のフィルタをSubstance Designerで作成する基礎的はお話です。
ちょっと前にTwitterで流したやつの作り方をやる前に、まず基本的な部分を押さえておきましょう、ということです。
チュートリアルは Allegorithmic 公式からも出ていますし、難しいものではないのですが、とりあえず作ったことがない人向けなのでかなり初歩からの解説となります。

Substance Designer編

まずはSubstance Designerで簡単なフィルタを作成します。
新しいグラフを作成しますが、テンプレートとしては以下の3つのどれかを選択します。

f:id:monsho:20180614004327p:plain

(generic) は特に指定のない[Input]ノードと[Output]ノードが1つ置かれているだけの簡単なものです。
(specific) は入力ノードと出力ノードが4つずつ置かれています。Base Color / Roughness / Metallic / Heightですね。
(specific w/ additional maps) は (specific) と同様の入力と出力を持ち、加えてメッシュからベイクされたワールド法線、ポジションなどのマップも参照できるようになっています。
今回は (specific) を選択しましょう。
グラフ名はなんでもいいですが、今回は FilterTutorial という名前にしました。

グラフが表示されたら [Input] ノード、および [Output] ノードの Base Color以外を削除してしまいましょう。
今回は使いません。
次に以下のようにノードを組みます。

f:id:monsho:20180614005217p:plain

[HSL] ノードの [Saturation] パラメータは 1.0 にしておきます。
このグラフを一旦保存して、それから .sbsar を生成します。
生成するには、生成したグラフを選択してから以下のボタンを押してください。

f:id:monsho:20180614005504p:plain

保存フォルダとファイル名を決定し、保存をします。
保存する際に以下のようなダイアログが出てきますが、[Pixel size] のパラメータは不要なのでチェックを外しておきましょう。

f:id:monsho:20180614005638p:plain

これでSD側の作業は終了です。

Substance Painter

次にSubstance Painterを起動し、適当なプロジェクトを作成するか読み込みます。
とりあえず PreviewSphere をサンプルから読み込んだ方がテストするにも簡単でしょう。

プロジェクトを開いたらSDで保存した .sbsar ファイルをドラッグ&ドロップしましょう。
すると以下のダイアログが出てきますので2つのパラメータを変更します。

f:id:monsho:20180614011433p:plain

上の方はインポートするリソースのカテゴリーで、今回は "filter" にします。
下の方はこのリソースの寿命で、"project '~'" を選択するとこのプロジェクトを編集中にのみ有効になります。
つまり、このプロジェクトを閉じるとインポートしたリソースも消えます。
今回はテストなので永続的に置かれても困りますのでこのようにしました。

ではテストです。
適当なマテリアルをFillレイヤーに追加し、ここに Add Filter でフィルタを設定、追加したテストフィルタを設定してみましょう。
Base Colorの色が鮮やかになるのがわかるでしょう。
フィルタをON/OFFすれば色が変わるのを確認できるはずです。

何をしたのか?

SDで作成したフィルタは極めて簡単です。
入力として、フィルタが設定されたレイヤーの Base Color を取得します。
この Base Color はそのレイヤーのみの結果です。それまでのレイヤーのすべてを合成した結果ではないので注意してください。
そのため、ペイントしたレイヤーにフィルタをかけるとペイント部のみに効果がかかります。

で、この入力した Base Color に [HSL] ノードを使ってサチらせます。
そしてこのノードから最後の出力ノードに出力します。
出力先は Base Color なので、入力してきた Base Color を鮮やかな色合いにするだけし直しています。

なお、[Input] / [Output] ノードで特定の情報を入出力として扱いたい場合は、Identifier もしくは Usage に適切なものを選択します。
どのようなIDが有効かは以下のドキュメントから確認できます。

Channel specific filter - Substance Painter - Allegorithmic Documentation

フィルタを修正してみる

ちょっとフィルタを修正してみましょう。
SD に戻って [HSL] ノードのすべてのパラメータを Expose してください。
これを保存し、再度 .sbsar ファイルに出力します。

今度は SP に戻って、シェルフから今回作ったフィルタを選択、右クリックしてみてください。

f:id:monsho:20180614013615p:plain

このようなダイアログが表示されるので、[Reload] を選択しましょう。
リロード後、先ほどフィルタを設定した部分に新しいフィルタをD&Dしましょう。
すると [HSL] ノードの3つのパラメータをいじれるようになっているはずです。

とまあ、こんなところです。
次回は応用編です。

3Dノイズに疑似的なポジションを提供する

Twitterでも呟いてたネタをもう少し詳しく。
以前のブログ記事にも書きましたが、Substance Designer/Painterに3Dノイズが存在します。
3Dノイズは3次元空間の座標に対して連続的なノイズを生成してくれる代物ですが、逆を言えば3次元空間の座標が存在しなければノイズを生成してくれません。

Substance Painterは必ずメッシュを読み込まなければならないため、3次元空間の座標は簡単に取得できますが、Substance Designerでは必ずしもメッシュが読み込まれるとは限りません。
では、SDでメッシュが読み込まれていなければ使い道がないのか?というと、実はそんなこともなかったりします。
ポジションマップに相当する画像があれば使えるのです。
というわけで、今回はハイトマップを元に疑似的なポジションマップを作成し、そこから3Dノイズを使うというのをやってみます。

まず、[Pixel Processor]を用意しましょう。
次に[Pixel Processor]内部に入り、こんな感じにノードを組んでみます。

f:id:monsho:20180523230741p:plain

[Get Float2]で $pos を取得すると、0~1までのUV値を取得できます。
つまり、この[Pixel Processor]はRGチャンネルにUV値が、Bチャンネルに0が、Aチャンネルに1が入った状態になります。
この物体が3次元空間中に存在するとすれば、縦横の幅が1で、XY平面に水平な板ということになります。
では、この出力結果を適当な3Dノイズに接続してみましょう。

f:id:monsho:20180523231319p:plain

このようにちゃんとしたノイズが生成されているのがわかります。
ただ、2D Viewを見ているとわかると思いますが、ちょっとジャギジャギしてます。
理由は簡単で、[Pixel Processor]の出力が8ビットなので、3D座標の精度が低くなってしまっているのです。
なので、[Pixel Processor]のフォーマットを変更しましょう。とりあえず16ビットでOKです。

f:id:monsho:20180523231802p:plain

一目瞭然ですね。

次に、グラフのパラメータにFloatパラメータを追加しましょう。IDはheightとしておきます。
そして、[Pixel Processor]を以下のように変更します。

f:id:monsho:20180523232227p:plain

Bチャンネルに入る値が0ではなくheightというパラメータに変わりました。
あとはheightパラメータをいじってみましょう。ノイズが連続的に変化していくのがわかると思います。

では最後に、[Pixel Processor]を以下のように変更しましょう。

f:id:monsho:20180523232414p:plain

入力されたグレースケール画像を高さ(Z方向)とみなして疑似的なポジションを生成します。
結果はこんな感じになります。

f:id:monsho:20180523233000p:plain

使い物になるのか?というとなかなか難しい部分はあるかもしれませんが、今までにないようなノイズの生成が可能になるかもしれません。
興味がある方は実際に作ってみて、いろんなハイトマップを入力してみましょう!

.sbsファイルをコピーする際の注意点

Substance Designerゆるゆる会にて、こんな感じのエラーが出るというハプニングが。

f:id:monsho:20180423013344p:plain

とある. sbs ファイルを開いたときに出てきたエラーなのですが、エラーメッセージを見ての通り、開いた.sbsファイル内で使用されている. sbs ファイル(このエラーメッセージの場合は grunge_map_010_bitmap.sbs)が見つからないというものです。

このようなエラーは .sbs ファイルをよその環境などにコピーした際に発生します。
自身のライブラリに存在するノードを使用したが、コピーした先の環境にはその .sbs が存在しないとか、存在はしてもパスが通ってないとかの理由からファイルを見つけることができず失敗します。

新しい環境にもそのファイルが存在するのであれば、上の画像のダイアログで [Yes] を選択したあと、ファイル選択ダイアログが表示されるので、そこから対象となる .sbs ファイルを設定すればいいのです。

しかし、コピーするたびにパスを変更しなければならず、同じ環境しか使わないならともかく複数環境を行ったり来たりする場合には大変面倒です。

そこで今回紹介するのが .sbs ファイルを依存ノードを含んでエクスポートする方法です。
勉強会などに参加する場合には参考にしてください。

やり方はとっても簡単。
エクスポートしたい .sbs をSubstance Designerに読み込ませ、エクスポートしたい .sbs を右クリック、[Export with dependency] を選択しましょう。

f:id:monsho:20180423014727p:plain

以下のようなウィンドウが出てきたらエクスポートするフォルダを選択してOKをクリックするだけです。

f:id:monsho:20180423020952p:plain

最終的にはこのように、エクスポート対象と .sbs ファイルと、dependencies フォルダに依存するファイルがエクスポートされます。

f:id:monsho:20180423021137p:plain

以上です。

Subsntace Designerでカラーを設定するパラメータあれこれ

Substance Designerでマテリアルを作成した場合、ベースカラーを変更したいと考えることが多いと思います。
例えばタイルの色を白や黒、赤や青に変えたい場合が多くあるでしょう。
このような場合のカラーを変更する手段を3つほど紹介します。

HSL

HSLノードはHSL色空間を利用して色を変化させるときに使用します。
HSL色空間はHSV色空間と似たものですが、ちょっと計算式が違っています。
色相を360度の角度で表すため、赤→青と変化させる際に彩度と輝度は変更したくない場合、色相は変えずに彩度や輝度だけを変更したい場合に使いやすいです。
使い方も簡単で、出力するベースカラーに挟むだけでOKです。

f:id:monsho:20180326164818p:plain

上の画像では色相のみを変更して紫色にしていますので、彩度と輝度は維持されます。
パラメータはHue(色相)、Saturate(彩度)、Lightness(輝度)の3つがあり、パラメータをExposeする場合はすべてのパラメータをそのままExposeするだけでOKなので簡単です。

Replace Color

ある特定の色を別の色に変化させる場合に必要なHSLの変化量を自動計算してくれるノードです。
パラメータはSource ColorとTarget Colorの2つがあり、ユーザはSource Colorに代表色を設定しておきます。

f:id:monsho:20180326165941p:plain

変更したい色を出力するノードのすぐ後ろに接続し、以下の手順でパラメータを設定します。

f:id:monsho:20180326170242p:plain f:id:monsho:20180326170421p:plain

この後、Target ColorをExposeすればOKです。

若干面倒な部分としては、出力したいカラーのデフォルトが変更した場合にSource ColorとExpose済みのTarget Colorの両方を変更しなければならないという点です。
Source Colorは問題ないのですが、Expose済みのTarget Colorのデフォルト値を変更するのは上記の手段ではできません。
Source ColorをコピーしてTarget Colorに設定するか、Exposeしたパラメータを削除してもう一度同じ手順を踏むかのどちらかとなります。

Gradient (Dynamic)

上記2つの手法は全体の色を変化させることはできますが、Gradient Mapノードで作成したグラデーションの変化量などは変更できません。
これらを変更させたい場合も多分にあるのではないかと思うのですが、Gradient Mapのグラデーションは残念ながらExpose可能なパラメータではありません。
Gradient (Dynamic)ノードを用いると入力マップとしてGradient Mapの結果を入力することができます。

f:id:monsho:20180326171913p:plain

このノードの組み方はデフォルトのグラデーションが存在し、それとは別のグラデーションを使いたい場合の設定も可能にしたバージョンです。
もし、必ずユーザにグラデーションを設定させるのであれば、下のGradient (Dynamic)の出力を用いればOKです。
上記の組み方の場合は設定項目が多めになりますので注意してください。
手順はこのようになります。

f:id:monsho:20180326172532p:plain f:id:monsho:20180326172752p:plain f:id:monsho:20180326173653p:plain f:id:monsho:20180326173515p:plain f:id:monsho:20180326174015p:plain

画像がないとないとわかりにくかったので説明も画像に入れちゃいましたが、検索性が悪くなるんだよなぁ…

とりあえず自分がよく使う手法は以上ですが、他にこの方法いいよ!ってのがあったら教えてください。

Substance 2018の3Dノイズについて

Spring has come!

は~るで~すよ~(弾幕
というわけで暖かくなって花粉が飛びかう春が来ましたね。

春といえば!
Substance Designer/Painterのアップデートです!
というわけで双方とも2018.1が来ていますので、サクッとアップデートしちゃいましょう。
まあ、不具合はあるかもしれませんがね。

今回のアップデートではパフォーマンス向上が結構重要です。
特にSubstance Painterではシェルフのアイテム読み込みが驚くほどに速くなってます。
さすがに一瞬ということはありませんが、今までのように下手すると数分待たされるということはなくなりました。
特にSPで作業をする人にとっては朗報じゃないでしょうか。
また、UIもかなり変わっていますね。

Substance DesignerはUDIMのベイクに対応しています。
パフォーマンス向上はランダムシードの変更時にわかりやすいと思います。

さて、双方に共通しているアップデート内容として3Dノイズの追加が挙げられます。
この3Dノイズはかなりの可能性を秘めていると個人的には思うので、少し詳しく書きます。

プロシージャルにおけるノイズ

ノイズという単語は音楽の中に入ってくるプツプツといったもの、雨音のようなものなどを指す言葉として使われるのが一般じゃないかと思います。
映像系であれば8mmフィルム特有の線が入ったりとか、写真の場合はISO感度を高くしすぎた場合のざらつきなどでしょうか。

プロシージャルにおけるノイズは非常に重要で、SDならプロシージャルマテリアルの起点、ディテール作成など様々な分野で活躍します。
これらのノイズは完全に不規則なものではなく、ある程度の規則性を持ったランダムな画像になります。
ランダムなのに規則性とはこれいかに?という疑問もあるかもしれませんが、Perlin Noiseなどは特にわかりやすいのではないかと思います。

f:id:monsho:20180317010737p:plain

白と黒を凹凸と考えると、凹凸の場所自体に規則性はないものの、凹凸への変化は滑らかです。
SDのノイズのほとんどは規則性を持ったランダムノイズなので、タイリングも正しく行われますし、それらを如何様にブレンドしてもタイリングの原則は確保されるという便利な代物です。

しかし、これらのノイズ画像は2Dの画像ですので、平面ではその恩恵を受けられますが、3Dモデルに適用しようとすると問題が出てきてしまうのです。

3D空間で2Dノイズを使用する

手始めに球を出してみます。UV展開は以下のようになっています。

f:id:monsho:20180317011408p:plain

これに通常のノイズ代表として、[Cells 1]を貼りつけてみましょう。

f:id:monsho:20180317011553p:plain

2Dビューポートを見ると規則性のあるランダムになっていることがわかりますね。
しかし3Dビューポートは一律にランダムが適用されているように見えません。
中心部の胴体部分はノイズが横に伸びているように見えますし、球の頭頂部などはひどい有様です。

f:id:monsho:20180317011835p:plain

これを避ける方法として Tri-planar で貼りつける方法もあります。
Fill Layer のプロパティで Projection の項目を Tri-planar projection を選びます。

f:id:monsho:20180317012438p:plain

結果はこのようになります。

f:id:monsho:20180317012605p:plain

一見するとうまくいっているように見えますが、中心付近からY字型にラインが入っているように見えませんか?
これは Tri-planar の特徴です。

UVマップでのテクスチャ貼りつけは、1枚のテクスチャで球を包み込むような形になりますが、Tri-planar はXYZそれぞれの軸に垂直に6枚のテクスチャを貼りつけるようにします。
それぞれの軸に向いた面に対しては正しく貼りつけられるのですが、中間部分(斜め45度向き)では複数軸から貼りつけた内容をブレンドすることになります。
上の画像のY字型のラインはまさにこのブレンドされている部分です。
Tri-planar はある程度のクオリティは確保してくれるので使い物にならないわけではないのですが、連続性が微妙な部分が出てきてしまうのは避けられません。

3Dノイズを使用する

3Dノイズは2D空間にしか適用されなかったノイズを3D空間に拡張したものです。
つまり、奥行き方向にも連続性を持ったランダムが適用されるというわけです。

SPではシェルフ内の [Procedurals] カテゴリにまとめられています。

f:id:monsho:20180317015022p:plain

これをFill Layerに適用してみましょう。

f:id:monsho:20180317015115p:plain

Tri-planar の時と同じ場所をスクリーンショット撮影しているのですが、Y字のラインは見当たりませんね。
これは3Dノイズが3次元的な連続性を持っているからであり、連続性を持った面に対して連続性持ったノイズを提供してくれているのです。

ただし1点だけ注意を。
3Dノイズを使用する場合、ノイズの参照データとして Position Map が必要になります。
こいつはちゃんとベイクするようにしましょう。
SDで使う場合もメッシュを読み込んでその Position Map を生成しないと役に立ちません。

より自由にハイトマップを作成する

Substance Designerでは最初にハイトマップを作成するのが基本的なアプローチになります。
しかし、何も考えずにハイトマップを作っていくと数値が飽和してノーマルが残念なことになったりします。

f:id:monsho:20180309001758p:plain

[Blend]ノードでは加算(Add)を使っています。
この場合、[Shape]ノードの段階で数値が 1.0 のピクセル、つまり画像中心のピクセルは2倍されるので2.0になるはずです。
そしてそこからすそ野に向かって徐々に数値を減らしていくはずなので、生成されるノーマルマップは山なりになっているべきなのですが、上の画像のように途中から平べったくなってしまいます。

なぜこのようになるのかというと、基本的なフォーマットでは数値が1.0までで飽和してしまい、それより大きな値は1.0にクランプされてしまうからです。
実際に3DViewで高さとノーマルに上の画像のノードを割り当てるとこのようになります。

f:id:monsho:20180309002803p:plain

高さが途中でクランプされてしまっているのが一目瞭然です。

これを避けるため、通常は高さが1.0を超えない範囲でうまくやるものなのですが、[Blend]ノードによる加算や Add Sub などを使ってしまうと意図せず1.0を超えてしまうこともあります。
1.0を超えてしまった部分はノーマルマップが平坦になってしまうため、大変見苦しい結果となってしまいます。

f:id:monsho:20180309003326p:plain

このような画像になるのは意図していない場合がほとんどですが、ユーザが変更可能なパラメータが多くなってくると、パラメータの組み合わせによってはこのような結果となってしまうことが多々あります。

これを避ける方法の1つが浮動小数点フォーマットを使用する方法です。

f:id:monsho:20180309003942p:plain

浮動小数点フォーマットを利用すると、ノードの数値は 1.0 より大きな値を取り扱うことが可能になります。
そのため、最初の画像は以下のような結果となります。

f:id:monsho:20180309004156p:plain

中心部分の高さがクランプされず、滑らかな形状ができていることが確認できますね。

ただし、どこの段階で浮動小数点マップを使用するか、どの段階で16ビットフォーマットに変換するかは難しい判断となります。

例えば、[Gradient Map]ノードのように、入力されて入ってくる数値が 0.0~1.0 の範囲になっていることを前提としているノードでは、1.0を超えた値は1.0と同じ結果となります。

また、[Slope Blur]などのノードに浮動小数点フォーマットのノードを使うと、意図しないノイズが出てしまったりします。

f:id:monsho:20180309005821p:plain

左の画像は[Slope Blur]を使用する段階で浮動小数点フォーマットに変換した場合ですが、細かなノイズが表面に出てしまっているのがわかります。
それに対して、ハイトをノーマル生成ノードに渡す部分で浮動小数点フォーマットに変換した場合は滑らかな表面になっています。
浮動小数点フォーマットは速度面にも問題が出る可能性が高いので、ハイトをブレンドする場所で主に使うようにし、そこを超えた段階で [Auto Levels] ノードを使って 0.0~1.0 の範囲に収めるようにするのが良いのではないかと思います。

Substance Designerのノード構成覚書

これから少しずつですが、Substance Designerでこういうノード構成するとこういうのが作れます、というのを覚書的に書いていこうと思います。

内臓的な形状

内臓のような有機的な形状を作るノード構成です。
これはTwitterでも呟きましたが、ここにも再掲。
基本は[Perlin Noise]と[Slope Blur Grayscale]を用います。

f:id:monsho:20180226224932p:plain

[Slope Blur Grayscale]の Grayscale 入力と Slope 入力の両方に[Perlin Noise]を繋ぎます。
後者のように Slope に繋ぐ前にブラーをかけても良いですね。
後者の場合はより滑らかな感じになります。

[Slope Blur Grayscale]の Mode パラメータは Blur か Max にしましょう。Min だとうまくいきません。
Samples パラメータは基本最大、Intensity は Slope に繋げているノードによってうまいパラメータは変化しますので調整してみてください。
なお、後者のパラメータはこんな感じ。

パラメータ名 数値
[Blur HQ Grayscale]のIntensity 14
[Slope Blur Grayscale]のIntensity 4

ノイズは他のノイズでも使えるものがありますが、どんなノイズでもうまくいくわけではないので注意してください。
とは言え、いろいろなノイズで試してみると面白いと思います。
一例として、[Grunge Map 002]、[Crystal 2]、[Liquid]、[Moisture Noise]で試したものを掲載します。

f:id:monsho:20180226231416p:plain

物によっては布っぽい形状も作れますね。

直線と曲線を織り交ぜた形状

石畳のようなマテリアルを作る際、スタイライズドなマテリアルの場合は形状が結構難しかったりしませんか?
直線と曲線を織り交ぜたような、単純に歪んでるだけじゃない、手書きにあるような意図的な飛び出し部分などが欲しい場合があるかと思います。

石畳の基本形状は [Tile Random] と [Distance] を使うことが自分は多いですが(クラックの作成とかでも使う)、この方法では形状が直線的になりすぎます。
そこで、そのあとに [Perlin Noise] と [Warp] で歪ませたりするのですが、これだと歪みが曲線的過ぎてイメージが何となく違います。

そこで考えたのが以下の2種類の方法です。

[Crystal 1] と [Directional Warp] を使う方法

f:id:monsho:20180227000702p:plain

[Distance] の後に [Directional Warp] と [Crystal 1] を使って、尖った歪みを作成する方法です。
[Perlin Noise] で歪ませるよりは直線的な歪みができます。
しかし、あまり曲線的な部分は出てこないので、[Perlin Noise] の歪みと併用の方がいいかもしれません。
結果は以下のようになりました。

f:id:monsho:20180227001754p:plain

[Distance] の前に歪ませる方法

つい最近、適当に接続したノードが割といい感じになっていたので、それをもとに作ってみたものです。
[Tile Random] から [Distance] に繋げる前に [Warp] と [Perlin Noise] で歪ませます。

f:id:monsho:20180227001931p:plain

歪ませた後に [Edge Detect] でエッジ抽出し、それを [Blend] の Subtract で減算します。
これは [Warp] 後にエッジ部分にアンチエイリアス的に幾分滑らかになってしまうためです。
この状態で [Distance] に通すとうまく形状に合わせて広がってくれません。
後半部は前述の方法と同じなので割愛。
そして結果は以下。

f:id:monsho:20180227002243p:plain

どちらがいいかと言われると好みの問題かな、とも思います。