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

前回の実践編ではフィルタを適用したレイヤーの各イメージを法則に従って変換するという、比較的簡単なフィルタの実装を紹介しました。
この手のフィルタはSubstance Designer上でもそのまま使える便利なフィルタですが、今回紹介するのはSubstance Painterのペイント機能を主に利用したちょっと特殊なフィルタの作り方です。
作るものはこんな感じのものです。

f:id:monsho:20180616010721p:plain

ちょっと前にTwitterにも上げましたが、上のレイヤーのペイントが剥げて下のレイヤーが見える、というようなフィルタです。
剥げる部分はSPのペイント機能を使ってペイントして指定します。

このような処理はSPの機能でも実現できるか?というと、可能ではありますが少々面倒です。
下のレイヤーが見えるようにするにはマスクを使えばいいので、ペイントと各フィルタで対応できます。
しかし、剥げた部分の周囲のペイントがめくれ上がる、というのはそれほど簡単ではないと思います。
今回のフィルタはそのようなことが1つのフィルタと1つのレイヤーで実現することができます。

ただ、注意として、あまり出来は良くありません。
実用的なものにするにはもっと詰める必要はあると思いますが、そこはまあ、自分なりに応用してみてください。

今回やること

今回新しく使用している手法は以下のものとなります。

  • User定義マップを使用して他のマップに迷惑をかけないペイントを行う
  • ペイント部分を取り出して効果を適用する
  • 下のレイヤーが見えるように疑似マスクを利用する

実際に作成しながら1つ1つ見ていきましょう。

User定義マップ

User定義マップはSPで使用できるマップの一種ですが、特に用途が決まっていないのでユーザが適当に用途を決めていいマップです。
これらは何らかの情報として出力することもできますし、今回のようにフィルタの起点とすることもできます。
使い方を決めるのはユーザなので、SP上では特に何かが起こったりしないマップチャンネルです。

SPのテクスチャセット設定でチャンネルを追加できますが、ここでUserマップの追加が可能です。

f:id:monsho:20180616011410p:plain

User定義マップは複数種類が使用できますが、今回は "User0" を使用することにしましょう。

SDでフィルタを作成するときは、入力のIDに user0 を指定します。
今回はまず "Painter Filter (specific)" のテンプレートからグラフを作成し、[Input] ノードを1つ追加します。
Attributes の設定は以下のようにします。

f:id:monsho:20180616011829p:plain

Usage の項目には実は User0 という項目がドロップダウンリストには存在しませんが、直入力で設定してください。
SPで User0 チャンネルを追加してそこにペイントしたりするとこの [Input] ノードに情報が入ってくるという寸法です。

ペイント部分を取り出す

SPで User0 のチャンネルにペイントが施されていると想定して話を進めます。
前述の通り、ペイントした結果は SD の [Input] ノードに入ってきますので、これをタネとして処理を作っていきましょう。

しかし、ペイントが剥げたような処理を1から実装するのは面倒なので、以前Substance Shareにアップしたグラフを使用します。

share.allegorithmic.com

このグラフはペイントが剥げた際のペイント部の高さ、ノーマル、ペイントが剥がれている部分のマスクを出力してくれます。
これをダウンロードしたら、作成したフィルタにリンクしてください。
配置しましたら、まず以下のように組んでみましょう。

f:id:monsho:20180616021905p:plain

User0の [Input] ノードをリンクした [Paint Peeling Mask] ノードに接続します。
途中で [Histogram Scan] ノードを経由していますが、[Paint Peeling Mask] が0/1の2値画像を必要としているためです。
2値画像でなくても動作はしますが、結果を保証できないために採用しています。

[Paint Peeling Mask] の出力にあるHeightは元のHeightチャンネルに加算しておきましょう。
このノードにはペイントの基本高さを設定するパラメータがありますが、特に変更する必要は感じませんでした。

下のレイヤーが見えるようにする

SP で下のレイヤーを見えるようにする最も良い手段はマスクを利用することですが、レイヤーのカラーチャンネルに適用されたフィルタからマスクチャンネルを設定する手段はありません。

ではどうすればいいかというと、実はフィルタの出力にはアルファ値を含めることができます。
アルファ値が含まれている [Output] ノードの場合、そのチャンネルのブレンド時にアルファ値が考慮されます。
つまり、同じマスクをすべてのチャンネルに対してアルファ値として出力することで、マスクと同じ結果を生み出すことができるというわけです。

それを考慮した最終結果は以下のようになります。

f:id:monsho:20180616030646p:plain

[Paint Peeling Mask] ノードから出力されるマスクは、ペイントが剥がれている部分が1.0、ペイント部分が0.0で出力されるので、[Invert Grayscale] ノードで反転してからアルファ値として適用します。
Base Color はRGBを出力する必要があるので [Alpha Merge] ノードを利用していますが、Roughness、Metallic、Heightは1チャンネルなので [RGBA Merge] ノードを利用しています。

最後に [Paint Peeling Mask] のパラメータをExposeして終了です。
Exposeしたいパラメータは好きなものを選択しましょう。ただ、今回はノーマルを利用していないので Normal Intensity パラメータは不要でしょう。

ここで1つ注意点を。
SDで設定される入力パラメータは最大値と最小値を設定することができます。
Clamp の項目を True にしない限り、最大・最小値はスライドバーの変動可能範囲を示すだけで、数値の直接入力を行うと最大値を大きく超えて設定することができます。

しかし、SPではこの方法が不可能になっているようです。
SDで設定した最大・最小値の間でスライダーを動かすことができ、数値の直接入力でも最大・最小値の値に収めるためにClampされてしまいます。
現在はまだ回避方法はなさそうなので、十分広い範囲を指定しておく方がよいと思います。

SPでペイントする

SPではまずテクスチャセット設定ウィンドウでUser0のチャンネルを追加しましょう。
そして、ペイントマテリアルのレイヤーを上に、下地のレイヤーを下にして、ペイントマテリアルのレイヤーにフィルタを以下のように設定します。

f:id:monsho:20180616032124p:plain

"Add Paint" でペイントを追加してから "Add Filter" で Paint Peeling Filter を指定します。
あとはこの追加ペイントでUser0のみにペイントすればペイントが剥がれたような結果を確認できるでしょう。
なお、モノクロ画像をUser0に適用すればよかったりするので、ペイントではなく塗りつぶしを使ってもよかったりします。

さて、全3回でSubstance Painter用のフィルタの作成方法を紹介しました。
今回作ったものは実用しようと思うともう少し詰めないと厳しい部分はありますが、作り方はわかったのではないでしょうか。
あまり日本語情報が多くない分野だなと思っていたので、人によっては役に立つ情報なのかなと思います。