【UE4】今さら Material Layer を試す

[1]:https://docs.unrealengine.com/ja/Engine/Rendering/Materials/MaterialLayers/index.html
[2]:https://youtu.be/7ieuiaZNwII
[3]:https://youtu.be/7ieuiaZNwII?t=750
[4]:https://historia.co.jp/archives/955/
[5]:https://3d.nicovideo.jp/alicia/
[6]:https://www.unrealengine.com/marketplace/ja/product/fabric-materials-56-pack
[7]:https://store.steampowered.com/app/401090/MODO_indie/?l=japanese
[8]:http://modogroup.jp/
[9]:http://modogroup.jp/tipsblog/


UE4.19 から追加された Material Layer と Material Layer Blend、以前から気になりつつ、やっと試す機会を得た。
ちなみに、UE4 初期からある、Material Attribute を返すマテリアル関数群を MatLayerBlend_Standard などでブレンドするアレの話ではない。UE4.19 から新しく追加された Material Layer アセットや Material Layer Blend アセットなどを使うヤツの話である。

# 参考URL

- [マテリアルレイヤー - Unreal Engine 4 ドキュメント][1]
    - このドキュメント、なにやら分かりやすそうで良く分からない…のだが、[このドキュメントの最後の方の動画][2] が分かりやすい。英語だが。前置きをすっ飛ばして、グラフを組んでいるところを見たい方は、[12分30秒あたり][3]から見ればよいかもしれない。
- [［UE4］Layered Material の基本的な使い方 - ヒストリアブログ][4]
    - 昔ながらの Material Attribute を返す関数を MatLayerBlend_Standard などでブレンドする方法を復習したい方はどうぞ。

# やりたいこと

肌や髪、布地など、いろいろな質感を部分ごとに切り替えてマテリアルを作りたい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/1fe58d14-0331-279b-7616-12f66bc71b67.png)

- 左側は Base Color にテクスチャをつないだだけのもの。
- 右側は あれこれ頑張ったマテリアルを、マテリアルレイヤーを利用してパーツごとにレイヤーブレンドしたもの。（この左右比較はズルいか？）

> ご存じ、無料・表記不要・改変可で使えるニコニ立体の[アリシア・ソリッド][5]を使わせていただいています。

## ざっくりやったことを並べると：

- 布地は２種類。ジャージ生地（タイツ）とレイヨン生地（その他の布地）。パーツによって UV のスケールを変えて、布目の密度感を変えている部分もある。 
    - 布地のマテリアルやテクスチャは、Marketplace の [Fabric Materials - 56 Pack][6] を使用。（2019年3月の無料コンテンツ）
- 肌・髪や布地など、ほとんどのパーツは Subsurface。Preintegrated Skin でも Subsurface Profile でもなくSubsurface（単なる好み）。Default Lit のパーツは少数で、髪留めのアクセサリや歯など。

## あらかじめ DCCツールでやったこと：

> 私は [MODO indie][7] を使っています（月額 1500 円ほど）
> Blender ほど Web に記事はないですが、知り合いに教えてくれる人がいるのでなんとなく採用。
> （あと、[MODO JAPAN GROUP][8]の[Tips動画][9]が分かりやすい）

- オリジナルデータはパーツごとにマテリアルが設定されているため、マテリアルが大量にある。これをテクスチャ１枚につきマテリアル１個になるようにまとめた。
    - とはいえ、できるようになったはずの Shading Model のレイヤーブレンドが機能しなかったので、結局、テクスチャ１枚につき、Subsurface 用・Opacity Mask用・Default Lit用に分けることになってしまった。(UE4.25 のバグか？ anisotropic BRDF との併用でおかしくなったのか？　…要調査）
- マテリアルのUVマップからマスクテクスチャを作成。
- オリジナルデータでは目のハイライトなどをポリゴンで用意してあったが、これを削除。また、テクスチャの頬などにもハイライトが描きこんであったが、これも周囲の肌の色で塗りつぶすなどして削除。
- 普通にポリゴン性状に基づいたシェーディングをしたかったため、オリジナルデータに付いていた頂点法線などを削除。おそらくトゥーンシェード用に調整されていると思われる。
    - その結果、あちらこちらでポリゴンのエッジが立って、頂点一個一個を手動でチマチマ調整する事態に陥ったので、よいこは気軽にマネしないでください。

# Material Layer の使い方

## まずは、Project Settings で機能を有効化

Project Settings > Engine > Rendering の Support Material Layers を True にする。
エディタの再起動が必要なので注意。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/f5a57ce7-3475-722a-e40c-90af4775b33d.png)

> 画像では、UE4.25 新機能(Beta版)の異方性反射 (anisotropic BRDf)も ON になっているが気にしないでください。ただ単に別で試していたもので Material Layer とは関係ありません。

## マスターマテリアルを作る

普通に新規にマテリアルを作り、以下のようなノードグラフにする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/f2450c00-be99-051a-3783-0d76866cbfbd.png)

マテリアル本体は、詳細パネルで「Use Material Attributes」にチェックを付けておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/d43b2ce9-b3b7-5e24-0e6a-1d5e28f53ebc.png)

左側のノードは「Materal Attribute Layers」で検索すれば出てくる。
その詳細パネルに Layers という項目があり、「＋」ボタンを押すとレイヤーが追加されるのだが、いったん気にしないでおく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/9df2d0f6-4b1c-3992-e380-8e9d450db775.png)

## マテリアルインスタンスを作る

次に、このマスターマテリアルから、マテリアルインスタンスをつくる。
いつも通り、マスターマテリアルを右クリックして「Create Material Instance」を選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/e08a1b47-7dc5-e227-685a-ee65d74f79b2.png)

ここでは衣装のマテリアルを作るとして「MI_AliciaSolid_WearSubsurface」と命名。
例えば Subsurface のレイヤーと Default Lit のレイヤーをブレンドするといった、Shading Model のレイヤーブレンドが、なぜか機能しなかったので、今回は明示的に Subsurface 用のマテリアルを用意している。(UE4.25.0 のバグ？)
とは言え、マスターマテリアル本体で Shading Model を Subsurface に設定していないのがミソ。

### 詳細パネルの設定

マテリアルインスタンスを開くと「Layer Parameters」というタブが開くが、いったんそれは置いておいて、「Details (詳細)」パネルを開く。
ここで「Material Property Overrides」の中の Shading Model を Subsurface に変更する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/becd1671-1e49-aef9-1bae-83cb9979213c.png)

いつの間にかマスターマテリアルの Shading Model すら上書き(override)できるようになっていた。(UE4.25から？)
この機能のおかげで、一つのマスターマテリアルから、種々の Shading Model のマテリアルインスタンスが作成できるようになった！ ほかにも、Blend Mode や Two Sided も上書きできる。ありがたい。

### Layer Parameters の設定

Layer Parameters は、マスターマテリアルで追加した「Material Attribute Layers」ノードに対応している。
現時点では何も設定していないので、中身は空っぽ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/bbe22b2d-7976-c5f7-ab20-c66a10040f41.png)

- Background として Layer Asset を作って入れればいいらしいことが分かる。
- 「Layers ＋」とあることから、どんどんレイヤーを追加できることが分かる。

## Material Layer アセットを作成する

コンテントブラウザの右クリックメニューから「Materials & Textures > Material Layer」を選択すると「Material Layer Asset」なるアセットが生成される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/2b49e3ce-d388-987b-7af3-83798f32e36a.png)

これが、上記の Layer Parameters の Background や Layers に追加するアセットになる。
色々試行錯誤した結果、この Material Layer Asset の役割は：

- Skin(肌)、Rayon(レイヨン生地)、Jersey(ジャージ生地) といった、素材ごとの特性を組むと良いっぽい。
- Scalar Parameter, Vector Parameter といった、マテリアルパラメータを用意すれば、上記のマテリアルインスタンスの Layer Parameters の中で任意に値を設定できる。
    - マテリアル関数を使ってブレンドしていた時代では、関数側は引数にしておいて、マスターマテリアル側でその引数にマテリアルパラメータを接続していたが、手間が一気に省けてありがたい。

### Material Layer アセットのノードグラフ

ダブルクリックして開くと以下のようなグラフが現れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/68e70357-0c71-f140-415c-83e3460afdbe.png)

どこに何を組めばいいのか全くぴんと来ないのだが、どうやら Set Material Attributes のところにグラフを組んでいけばよいようだ。
Set Material Attributes ノードを選択すると、詳細パネルは以下のようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/c736989d-f187-0c4b-424c-f56432a656dd.png)

「Attribute Set Types」の横の「＋」をクリックすると、アトリビュートがどんどん増えていくので、これを自分の設定したいマテリアル属性だけ並べればよい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/0e3be3dc-7941-89e5-7b2a-1a4cc14a65ff.png)

この時、ノードグラフ中の Set Material Attribute ノードは以下のようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/0f3d59cf-e973-6e36-a547-9b6c9eba45eb.png)

あとはノードグラフを組むだけである。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/0a999888-a185-c4ec-5a6d-0ad7ef02daf7.png)

ここでマテリアルパラメータにした箇所がマテリアルインスタンス側で任意に変更できるようになる。

> なお、利用したマテリアルアセット(Marketplace の [Fabric Materials - 56 Pack][6])のマテリアルグラフやその一部を私が公開するのはマズかろうということで、単純化したり、マテリアル関数に隠ぺいするなどして誤魔化していある。悪しからずご了承ください。

## 再びマテリアルインスタンスに戻る

まずは、Background に先ほど作った Material Layer Asset を追加する。
これから上にのせるレイヤーがない部分には、このバックグラウンドレイヤーが表示されることになる。
ここでは、タイツの部分向けに Jersey(ジャージ生地)のレイヤーをセットした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/a72469b7-e304-3173-970d-58d5f8296b4b.png)

さらに、「Layers ＋」の＋ボタンを押して、新規レイヤーを追加。
ここに２つ目の Material Layer Asset を追加し、パラメータをセットする。
ここでは、衣装の白いシャツの部分用に Rayon(レイヨン生地)のレイヤーをセットした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/37255298-01dd-f8a1-33e2-b90a7e8e0415.png)

現時点では、プレビュー画面には Background レイヤーのマテリアルしか表示されていない。
これは、上記スクリーンショットに赤枠で囲った「Blend Asset」がないからである。

### Material Layer Blend Asset の作成

コンテントブラウザの右クリックから「Materials & Textures > Material Layer Blend」を選択すると、Material Layer Blend Asset が生成される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/b096fca4-e9df-9561-edad-362cfb4364ee.png)

ダブルクリックして開くと、以下のようなノードグラフが現れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/7995ced4-3890-5bf2-388d-bf958c19bf58.png)

見ての通り、Bottom Layer と Top Layer をブレンドするよ、というグラフだが、「Alpha」に何もつながっていない。これは以下のようにしておけば、当面は困らない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/67e2c5bc-843e-dfaf-0959-5ec1f82ee20b.png)

- Texture Parameter としてマスクテクスチャを指定できるようにする。
- Append Vector ノードで RGB と A を合体させているのは、つづく Channel ノードが float4 を受け取るから。
- Channel ノードの正式名称は「Channel Mask Parameter」。Channel で検索すれば見つかる。

なお、Material Layer Blend アセットは、プロジェクトに１個あれば十分。普通はこの形式のブレンドしかしないだろう。
もちろん、Base Color は Top Layer のものしか使わない、といった特殊なブレンドが必要ならば、それ用の Material Layer Blend アセットが必要になる。

### Material Layer Blend Asset をレイヤーに組み込む

再びマテリアルインスタンスに戻って、Material Layer Blend Asset を指定したら、こうなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/527a18dd-b4b4-7e6c-cc1c-35687963c9d3.png)

マスクテクスチャの Red チャンネルの部分だけ Rayon にしている。
左隣の 3D Viewport で、（見づらいが）青や薄い紫の部分は Jersey 素材、白の部分が Rayon 素材である。

あとは、新たにスカート用のレイヤーを追加。
それぞれのレイヤーをたたむとこんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/3be662e9-f5ce-f030-fc11-73a503ebb61a.png)

ちなみに、各レイヤーは名前が変更できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/56597799-8f00-0a9d-d3ce-9f6e8b769b0e.png)

残念ながら、バックグラウンドレイヤの名前は変更できない。

# まとめ

- マスターマテリアル
    - Material Attribute Layer を繋げるだけ。
    - このマテリアルを直接使うよりは、マテリアルインスタンスを作成して使う。
    - マテリアルインスタンスで Shading Model, Blend Mode, Two Sided などをオーバーライドできるので、マスターマテリアルでそれ用のものを用意しないでよい。
- マテリアルインスタンス
    - Material Layer Asset と Material Layer Blend Asset を積み重ねてゆく。
    - レイヤーごとにパラメータを変更できる。例えば、同じレイヨン素材でも色味やアレコレ何でも部位に合わせて弄ることができる。
- マテリアルレイヤーアセット
    - 肌、髪、布地など、素材ごとのグラフを記述する。
    - 部位に応じた細かい設定はマテリアルパラメータに出して、レイヤーアセットを量産しないようにする。
- マテリアルレイヤーブレンドアセット
    - 上に重ねるレイヤーのマスクを指定するのが主。
    - 通常は、Top Attribute と Bottom Attribute をマスクテクスチャに応じてブレンドするもの１つで十分。