UE4のマテリアルを使って、原神の武器出現を再現してみる

今更ながら最近原神を触っていて、武器の出現の仕方が良い感じなので
UE4のマテリアルを使って、再現してみるまとめです
（大まかな流れのみの記載となるので、要所要所の手順は検索などで補間いただければ）

まずは動画から
<iframe width="560" height="315" src="https://www.youtube.com/embed/BTziFKpLA64" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

良い感じですよね～
この演出から実装を分解して、以下のように実装していきたいと思います。
UEのバージョンはUE5.0.0 Early Access 2を利用しています

## 実装工程
[1.武器が高さに沿って出現する](#1-武器が高さに沿って出現する)
[2.出現するキワの部分が光ってる](#2-出現するキワの部分が光ってる)
[3.キワに沿って光が移動している](#3-キワに沿って光が移動している)
[4.全体に別のテクスチャが乗っかってフェードアウトする](#4-全体に別のテクスチャが乗っかってフェードアウトする)

以上、４つに工程に分解しました。さっそく実装を始めていきましょう。

### 1.武器が高さに沿って出現する
武器のモデルが最初からすべて描画されているわけではなく、武器の高さにそって徐々に出てきています。
武器は自由に回転するので、武器の軸に沿って出現させるようにします。

まず、描画をクリッピングするために、マテリアルをMaskedに変更します。

https://docs.unrealengine.com/4.27/ja/RenderingAndGraphics/Materials/MaterialProperties/BlendModes/

これにより、OpacityMaskのパラメータが使えるようになり、OpacityMaskを設定することで、描画のON/OFF（クリッピング）が出来るようになります。

https://docs.unrealengine.com/4.27/ja/Resources/ContentExamples/MaterialNodes/1_8/

次に、武器の出現率のパラメータを用意して、0～1を取り、その出現率を元にマテリアルで描画するか否かを決めるようにします。

モデルの各頂点は頂点座標を持っているので、武器の高さのデータがあれば、単純に
頂点座標＜武器の高さ×出現率
の場合のみ描画を行う、といったような形で処理が出来そうです。

上記の内容に基づいたマテリアルが以下になります。
このノード群から出力されるパラメータをOpacityMaskへつなぎます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12340/f007b30e-11f6-55ec-74c0-8e6de563466a.png)

・LocalPositionは頂点の座標を取得してこれるマテリアル関数です。
・WeaponHeightは武器の高さ情報です。
・AppearLineが0～1の武器の出現率です。（0.015の引き算は後述）

武器の高さ情報は、UE4側でソケット「Top」「Base」を追加して、そのソケットの差分を高さとしています。

https://docs.unrealengine.com/4.27/ja/WorkingWithContent/Types/SkeletalMeshes/Sockets/

本来は別データとして持つか、頂点情報から高さを計算したほうが良いと思いますが、主題と外れるので割愛。
また、座標のオフセットはモデルの頂点座標を計算しやすくするために、高さを0～とするために行っています。
今回は直入力です。

以下のような感じでモデルが出てきます

<iframe width="560" height="315" src="https://www.youtube.com/embed/mMSgKSu_prk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

OKですね。次へ進みましょう。

###  2.出現するキワの部分が光ってる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12340/a13ab36d-07a1-e3bd-fcfb-0b250211634d.png)

上の画像で見る通り、武器の出現のキワの部分が明るく光っています。

UE4で物体を光らせたい時はマテリアルのEmissiveColorに値を入れてあげると、光らせることが出来ます
問題は、EmissiveColorを適用するべき描画領域の算出です。

「1.武器が高さに沿って出現する」で対応した描画領域の大きさより、少し大きいもの（AppearLineが少し進んだもの）を用意します。
そこから1.で用意した描画範囲を引き算してあげれば、キワの描画範囲を取りだせます。

その描画範囲を元に、EmissiveColorを入れてあげれば良い感じになりそうですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12340/fdbf15cb-7378-8730-1679-cf9c23b4f155.png)

上記のノードで、以下の画像の用にエミッシブ範囲をクリッピング出来ます
なお、計算した頂点座標は色々な箇所で利用されるので、Named Reroutes機能を機能を使って
紫ノードの「CalculatedVertex」にまとめる形にしています。

https://historia.co.jp/archives/24717/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12340/9e9ecfa9-ed94-98f6-e7b2-9c49957fde3e.png)

あとはこの描画範囲に、EmissiveColorを入れてあげればOKです
明るくさせるために適当に10倍しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12340/b3b29931-d223-d6e1-0cfc-6ccb8b6a0c9d.png)

この出力を、EmissiveColorにつないでやります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12340/1f29e067-3bc1-d55f-a22a-86f213781cfd.png)

また、1で指定したOpacityMaskは、実際に見える範囲とエミッシブを含む範囲とするため
下のStep関数から出力された値をつなげてあげます。
あとは、Bloomのポストエフェクトをかけてあげて（手順割愛）光をぼんやりさせて、より光ってる感を出します。

<iframe width="560" height="315" src="https://www.youtube.com/embed/uyTI7RnWgHg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

### 3.キワに沿って光が移動している
つづけて観察すると、よく見たら武器が出るキワの近くの方がより黄色く光ってます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12340/90b1b24e-0957-d304-a57a-64c4cb0a9fa2.png)

この光の部分をEmissiveColorに追加してあげます。
まず、光り方の具合を制御するために、マテリアル用にカーブデータを用意します。

普通にパラメータとして渡してもよいのですが、今回は以下の機能を利用してテクスチャとして渡してみます。便利。
使い方は以下の記事がわかりやすいので参照してください。

https://historia.co.jp/archives/10594/

カーブのデータは、シンプルに0～1のTimeで0～1のValueを取るようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12340/7ed1ac81-a04c-e624-6305-61985c033093.png)

このカーブの数値を武器の出現率を元に新しくエミッシブとして追加してあげます。
上記の内容に基づいたマテリアルが以下になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12340/41b5aa82-ab6c-de66-389a-9539de63574b.png)

GlowCurveでカーブの情報を取り出すことが出来ます。
一番右から出ているのが今回追加するEmissiveColorです。
2.で追加したEmissiveColorにAddして、それを新たなEmissiveColorとします

挙動としては以下のようになりました。さて、ラストです。
<iframe width="560" height="315" src="https://www.youtube.com/embed/9I67Oy9KBo8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

### 4.全体に別のテクスチャが乗っかってフェードアウトする
動画を見ると、模様のようなものが武器にのって、全体がぼんやりしているように見えます。
この部分を実装していきます...と行きたい所なのですが、ここは良い感じのリソースが必要なので、ちゃんとした再現は断念。

それっぽいマテリアルだけ実装していきます。

適当に輝度が高い所を光らせて、時間とともに消えるようにします。
良い感じの模様は乗らないですが、適当に出している輝度が高い所を＝模様として、模様のテクスチャに置き換えれば良い感じになると思います。

上記手順を実現したマテリアルはこちら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12340/6f7c198c-82a6-4c6a-e9b2-85924e6d1e51.png)

左上からはDiffuseカラーを受け取ってます。
適当に輝度計算して明るいところを光らせるようにします

GlowTimeLineはBP上で値を渡します。
上記のようなタイムラインとなっていて、武器が出現しきった当たりから消え始めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12340/cfcd3899-310b-e59e-0a0d-ba9c6857bf27.png)

出力されるEmissiveをさらに追加してあげると、結果として...こうなりました。
<iframe width="560" height="315" src="https://www.youtube.com/embed/oy2C5yc8CnE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

まあまあ良い感じではないでしょうか？

プロジェクトは以下に置いておきますので、ご参考にどうぞ。
（アセットはマケプレのものなので、入れておりません）
https://github.com/CreaterShiba/GenWeapon

以上！