【UE4】マテリアルのUV座標によるグラデーションをイジってみたメモ

[historia]:https://historia.co.jp/archives/13908/
[ue4customnode]:https://docs.unrealengine.com/4.27/ja/RenderingAndGraphics/Materials/ExpressionReference/Custom/

特にUMGでマテリアルのUV座標ノードを使ってグラデーションをつけるのは常套手段である。
ドット・バイ・ドットでのきれいなグラデーションを付けられるし(語弊アリ)、いろいろなサイズのグラデーションテクスチャを作らずに済む。

ここに、ただリニアに変化するだけのグラデーションだけでなく、色の変化の割合などを操作する方法をメモしておく。

:::note info
要するに、すぐ忘れてしまう自分向けのメモです。
:::

# 参考サイト

- [［UE4］UMGで使えるシンプルなグラデーションのつくり方あれこれ - ヒストリアブログ][historia]

# シンプルなグラデーション

良くあるパターン。
TexCoordのRチャンネル(U方向)かGチャンネル(V方向)をAlphaにして、２色をLerpする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/a36b62dc-9de2-3e6c-9f2f-c5d386d70c2f.png)

こういう絵になる。
※V方向のグラデーションはComponent MaskをGチャンネルに変えればOK。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/50786757-6459-24f0-ceb5-c788ab896a23.png)

# Powerでコントラストをつける

Epic公式サンプルのマテリアルでもPowerノード(べき乗ノード)を使ってコントラストをつけるパターンは多い。
ここでもPowerノードを使ってお手軽にコントラストをつけてみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/af0157fd-2910-8238-a7de-20123000b404.png)

パラメータContrastが1の時、リニアなグラデーションと同じになり、1より小さければグラデーション開始側に寄り、1より大きければ逆側に寄る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/8938bd7a-7966-f169-a951-09e5a57c1e9c.png)

# Easeでコントラストをつける

そもそもPowerによる式はEase Inの式と同じ。であれば、Ease OutやEase In/Outも用意すればグラデーションにバリエーションを出せるであろう、という考え。
結果は下の図のような感じ。
Ease InはExpが大きくなるにつれ水色が強くなっていく。Ease Outはその逆。
Ease In/Outはそもそも0.5を境にEase InとEase Outを切り替える仕組みなので、中央(0.5)に寄っていく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/bc51cb7d-8664-7a6c-ca35-e2ec12743106.png)

マテリアルでのEaseは、BlueprintのEaseノードのC++コードを参考にして(目コピして)、マテリアル関数を用意した。

## マテリアル関数 MF_EaseIn

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/271c4b9c-7346-ef9b-436a-1baaf9fe23ae.png)

## マテリアル関数 MF_EaseOut

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/7b116f83-8d5c-382f-d6d2-34b4dccd7b27.png)

## マテリアル関数 MF_EaseInOut

Ease In/Outはアルファ値0.5でEase InとOutを切り替える必要があり、ノードグラフで組むよりHLSLのほうが書き易かったので、[Customノード][ue4customnode]を使用した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/06769894-2b96-b12d-6c64-be5024ac545e.png)

Customノード「[HLSL] Ease In Out」の中身はこちら：

```hlsl
float Alpha = saturate(InAlpha);
return (Alpha < 0.5)
? lerp(0.0, 1.0, pow(Alpha * 2.0, InExp)) * 0.5
: lerp(0.0, 1.0, 1.0 - pow(1.0 - (Alpha * 2.0 - 1.0), InExp)) * 0.5 + 0.5;
```

# グラデーションの回転

グラデーションの回転は、ヒストリアさんの[UMGで使えるシンプルなグラデーションのつくり方あれこれ][historia]を参考にさせていただきました。

例えば、グラデーションを45度回転させると、グラデの端(水色と青)がウィジット矩形の端に来ず、グラデーションしていない面積が増えてしまう。
上記の[ヒストリアブログ][historia]には、これを対処するための、傾きによってグラデーションをスケールさせてやる方法が載っている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/d72e5031-a1cc-a19e-5f51-882e690f503d.png)

- 【左: Default】シンプルにUVを45度回転させただけのもの。
    - 黒い矩形が元のUV(0,0)-(1,1)に相当する。
    - 黒い矩形の外側はアルファ値が負の値(0側)や1より大きい値(1側)になってしまう。
    - ※上の図はアルファ値を0と1の間にクランプしてある。
- 【右: Normalized】[ヒストリアさんの方法][historia]でウィジットの矩形の端が必ずアルファ0, 1になるように元のUV(0,0)-(1,1)をスケールさせたもの。
    - ざっくり sinθ+cosθ 倍すればよい。

動画で見ると挙動が分かりやすい：

![20211216_01_NomalizedGradients.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/9d532be6-0831-fcb1-8a87-231881795a11.gif)

## マテリアルグラフ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/50b6ef00-ecac-4d5e-be83-b39dd890a27c.png)

## マテリアル関数 MF_RotateGradients_Normalized

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/bbeb7352-9bb0-55fe-6607-3e7c89c47a36.png)

# おまけ

![20211216_02_FontGradients.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/612cf323-b50d-4d2f-bddc-464c2bf6d75e.gif)

(おわり)