UMGでXmasイルミネーション

今年も参加させていただきます。コードは一切出てきません。すみません。
RenderTargetについて調べているうちに、CanvasRenderTargetの使い方なるブログを見かけて、ちょっと遊んでいるうちに小ネタを思いつきました。ほとんど参考にならないですが、そこは季節感の演出ということで。

絵素材を３つほど用意します。
１．クリスマス感のある写真とか絵 ： 背景に使います。
２．できれば天使とか★ のようなシンボル ： クリック対象のボタンとして使います。
３．キラキラ用のテクスチャ ： イルミネーション用です。

とりあえずエディタで動けばOKという雑な内容ですみません。

　
####CanvasRenderTarget
コンテンツブラウザ内でアセットとして作ります。
![fig00.png](https://qiita-image-store.s3.amazonaws.com/0/212880/44ba484e-2b8a-21b6-fe46-a28414310b54.png)
![fig02.png](https://qiita-image-store.s3.amazonaws.com/0/212880/5c7b59ab-90e3-2033-58ff-de0cd41b0bcc.png)
テクスチャアセットができたら設定を一部変更します。
![fig05.png](https://qiita-image-store.s3.amazonaws.com/0/212880/fd892dfd-0f33-380c-2ff6-487d276d2636.png)
Size が小さいと低解像度の絵を引き延ばすことになるのでドットが見えてしまいますが、レンダーターゲットテクスチャは非圧縮でメモリを結構占有するのでほどほどに。とりあえず 1920ｘ1080に少し近いアスペクト比で1024ｘ512にしました。今回フォーマットについては色は重要ではないので、R8 を選択。同じ解像度で RGBA8 を選択すると4倍の 2MBになります。（8ｘ4 と 8ｘ1の差ですね）
 
次はマテリアル。
アセットアイコンを右クリックしてコンテキストメニューの一番上、Create Material するとマテリアル作成がちょっとだけラクになります。
![fig01.png](https://qiita-image-store.s3.amazonaws.com/0/212880/930bbd6f-7462-0637-4540-3b8b4e20fde5.png)
![fig03.png](https://qiita-image-store.s3.amazonaws.com/0/212880/436eaff7-b131-d2cd-f7d9-afc1ea480549.png)
このマテリアルを編集してUMGで使えるようにします。
![fig04.png](https://qiita-image-store.s3.amazonaws.com/0/212880/83a69e65-b2f2-e6b2-af00-a0ed1ce86d9f.png)
フォーマットが R8 なので RチャンネルをOpacityにつなぎます。
（Detailsで見るとテクスチャフォーマットが Color になってて、GrayScaleとかにするとErrorになる。謎）

CanvasRenderTargetの準備はひとまずここまで。
次は、Widgetブループリントを作っていきます。

　
　

####Widgetブループリント
![fig06.png](https://qiita-image-store.s3.amazonaws.com/0/212880/12508ba2-34a9-2b05-5e6f-c1b64a685abd.png)
キャンバスに パレットから Image を配置して画面いっぱいに拡げます。
![fig07.png](https://qiita-image-store.s3.amazonaws.com/0/212880/0844d6d8-6d74-4ac1-3e25-68f4965c4124.png)
このImageに、CanvasRenderTargetのマテリアルをセットします。
さらに追加でボタンにする Image を配置します。中央ポジションを維持したいのでAnchorは画面上端中央。
![fig09.png](https://qiita-image-store.s3.amazonaws.com/0/212880/35177f1b-cefa-5db1-304a-fca7c20565f2.png)
★的なテクスチャをセットしておきます。
![tex_Star.png](https://qiita-image-store.s3.amazonaws.com/0/212880/4d6663c9-f7bc-7483-69d5-69e3fd584202.png)


必須ではないけど TextBlock をAlignment XとY それぞれ 0.5 にして一つ配置。
![fig10.png](https://qiita-image-store.s3.amazonaws.com/0/212880/959ccd27-e2c1-52e7-0b0a-413d02070ae3.png)
isVariable を有効にしておきます。

仕上げに、もう 一枚イルミネーションランプ用のキャンバスパネルを重ねておきます。
![fig07.png](https://qiita-image-store.s3.amazonaws.com/0/212880/7f4c5696-5348-1cd1-d164-01ba12b6e8f0.png)

背景は適当なやつを敷きます。ちょっと明度を落としておくとキレイかも。

UMGの構成は以下のようになってます。特に問題は無さそうなので ZOrderは すべて０のまま。
![fig23.png](https://qiita-image-store.s3.amazonaws.com/0/212880/38b65316-e1be-c591-2165-5a781a743f5e.png)


キャンバスは一旦終了。グラフ編集に移ります。

まずは Event Pre Constructから。
![fig08.png](https://qiita-image-store.s3.amazonaws.com/0/212880/783a396a-da44-7d1c-36b1-3d9d97c2123e.png)
Widgetで設定されている解像度を取得しようとしたけど、結局方法が見つけられなくて、初期設定値の1920ｘ1080を定数にして扱うことにしました。いろいろ調べてたら初期値自体を変える方法は見つけられたけど、また別の機会にしてみたいと思うので今回はひとまずこれで進めます。CanvasRenderTargetテクスチャに設定したサイズも後で計算に使うので定数化。これは取得するノードが用意されてますが直値です。

ここでマウスカーソルの座標（1920ｘ1080内）を、CanvasRenderTargetテクスチャ（1024ｘ512内）にマッピングする関数も作っておきます。
![fig17.png](https://qiita-image-store.s3.amazonaws.com/0/212880/86da2201-83fb-10a4-594b-0bbcafedb6bf.png)

　
次は、Event Construct。
ここでは初期化を行っています。
![fig12.png](https://qiita-image-store.s3.amazonaws.com/0/212880/2da2547a-e4b0-3ff6-d26b-58f35644abc8.png)
下段一番左のGetノードは、CanvasRenderTargetテクスチャにアクセスするための **Texture Render Target 2D**型の変数です。
![fig11.png](https://qiita-image-store.s3.amazonaws.com/0/212880/c373dbae-5650-f997-9e7d-7ce8101df5f3.png)
この変数には先に用意してあった CanvasRenderTargetのテクスチャを初期値としてセットしておきます。

　
次は、Event Tick。
ここではマウスカーソルのポジションを拾ってラインを描画します。下図は前半部。
![fig13.png](https://qiita-image-store.s3.amazonaws.com/0/212880/bb7c4889-f482-0ede-2248-7d92723740ed.png)
描き始めの Begin Draw～ノード から 描き終わりの End Draw～ノード へ Contextピンをつなぐ必要があるのですが、Sequenceノードを使ってます。
@tamfoi さんの書かれている記事 [[UE4]ミニマップ的なものを作ってみよう](https://qiita.com/tamfoi/items/0f5534a3ed328828a46e) を参考にさせていただきました。このSequenceノードの使い方気に入ってます。

描画するラインの数をカウントするので、マウスが動いてない場合と、ウィンドウの外にカーソルが出た場合は描画をキャンセルしたくて、チェック用の関数を用意しました。上図の checkMousePosition です。
![fig14.png](https://qiita-image-store.s3.amazonaws.com/0/212880/73c8d473-1770-4539-7d59-9b6d5fdf3399.png)



Begin Draw Canvas to Render Targetノード以降の後半部。
![fig15.png](https://qiita-image-store.s3.amazonaws.com/0/212880/3b3b2e6d-aee1-913b-5002-f37bbdee8c1f.png)

描画数カウンタを増やして描画します。この処理で取得したマウスポジションを保持しておくことで、次に来た時に連続したラインを描くことができます。

今どれだけラインを描画しているかのカウントを上図の showCounter 関数でTextBlockを更新。
![fig16.png](https://qiita-image-store.s3.amazonaws.com/0/212880/cc8896bb-ab03-ad48-2385-c8e4ff4720e2.png)




「マウスのボタンを押したら」というイベントが用意されています。
My Blueprint ＞ Functions から **On Mouse Button Down** 関数をオーバーライドします。
![fig19.png](https://qiita-image-store.s3.amazonaws.com/0/212880/62a25e53-6475-a720-3f0a-6e69ef4789d6.png)

これでマウスのボタンを押している間だけラインが描画されるようになりす。ドラッグして描く感じです。
続けて、マウスボタンを離したときのイベントもオーバーライドして用意します。
**On Mouse Button Up** 関数。
![fig20.png](https://qiita-image-store.s3.amazonaws.com/0/212880/2e5f1258-d5e7-3093-9cdb-01fa40a91288.png)


仕上げのイベント。イルミネーション開始イベント。前半部分。
![fig21.png](https://qiita-image-store.s3.amazonaws.com/0/212880/52603e9e-68fe-6f54-8b43-e566c23a355f.png)
配列に貯めておいたポジションをForEachLoopで利用するのですが、一定の間隔を開けたいので剰余を使って、０の時だけランプを生成するようにします。

後半部分。
![fig22.png](https://qiita-image-store.s3.amazonaws.com/0/212880/9d373ec7-f7c9-9bef-1e89-115ddeacc7dd.png)
Construct Object from Class ノードでUMGのImageを生成して、イルミネーションランプ用のキャンバスに子供として追加しています。


マテリアルをセットしている関数はこんな感じです。
![fig24.png](https://qiita-image-store.s3.amazonaws.com/0/212880/7f74ec98-fa97-f844-568e-f35540501221.png)
引数（Inputs）の型はImage型。
![fig25.png](https://qiita-image-store.s3.amazonaws.com/0/212880/fac07349-9bd3-5d14-dcdb-74f5d782f149.png)

ちょっと作る順番が前後しましたが、イルミネーション用のランプのテクスチャとマテリアルを用意します。
![tex_Lamp.png](https://qiita-image-store.s3.amazonaws.com/0/212880/f746a59a-5189-78b7-0408-f2e91d37608a.png)
↑グレイスケール 128ｘ128
マテリアルはこんな感じ。光り物なので BlendMode は当然 **Additive**（加算）です。
![fig27.png](https://qiita-image-store.s3.amazonaws.com/0/212880/f397fe82-025f-373d-bf1c-2e1938181651.png)
サインカーブを使って -1.0 ～ 1.0 を遷移するうち、 0を境にして 点灯と消灯を繰り返すようにしています。
パラメータは Vector型で受け取ります。 RGBチャンネルがカラー。Aチャンネルが点滅速度の調整用として使っています。
Constantノード（ifノードのBのピンにつながってるやつ）の 値を変えると、点灯時間と消灯時間のバランスを調整することができます。マイナスの値にすると点灯時間が長くなります。


　
####Levelブループリント
これでだいたい用意できたので、テストしてみます。
レベルブループリントでViewportに追加します。
![fig26.png](https://qiita-image-store.s3.amazonaws.com/0/212880/c3f888b2-01c6-6df9-3e83-507634c4724d.png)

いざ。
![draw1.gif](https://qiita-image-store.s3.amazonaws.com/0/212880/dc2d0fcf-6d6a-249e-cc7d-b776071b13dc.gif)
ドラッグのスピードに応じて（結果的にマウスポジション取得の間隔が変わる）、ランプの密度に変化が生まれます。

　

####Widgetブループリント
ここに描き直しの仕様を追加します。
まずイルミネーション用のキャンバスをクリアする関数を用意します。
![fig28.png](https://qiita-image-store.s3.amazonaws.com/0/212880/e11916ed-0bcf-f53d-b4c2-c50b4fbbe1f7.png)
最初の方で書いた初期化のカスタムイベントに、この関数と配列をクリアするノードを追加します。
![fig29.png](https://qiita-image-store.s3.amazonaws.com/0/212880/d5f5a896-5611-0cbb-212b-639c2666941b.png)

もう一つおまけ。
ランプの間隔を変更できるようにします。
![fig30.png](https://qiita-image-store.s3.amazonaws.com/0/212880/eccb3ff6-87b9-475b-5d2f-914bbcfa03ac.png)

　

####Levelブループリント
Widgetの準備は完了です。次はレベルブループリントにInputイベントを置きます。
![fig31.png](https://qiita-image-store.s3.amazonaws.com/0/212880/a34510e7-5a25-5595-1f5b-4d972145da9d.png)

キーボードの［R］キーで、ラインを消して描き直せます。カーソルキーの［←］/［→］でランプの間隔を調整します。

![draw2.gif](https://qiita-image-store.s3.amazonaws.com/0/212880/26940617-9401-535d-ba8b-9cf240fa307f.gif)


　
####マテリアルであそぶ
イルミネーションのパターンをいくつか考えてみました。
![fig32.png](https://qiita-image-store.s3.amazonaws.com/0/212880/c31e8381-ecfb-56b3-3d66-898dc1a89944.png)
最初のは固定カラーでしたがこれは 滑らかにカラーが変化するタイプです。
![draw1.gif](https://qiita-image-store.s3.amazonaws.com/0/212880/2144b205-3380-002b-6c52-33078f3a32ed.gif)
Speed の値をランダムにすることで、キラキラした印象になります。
![ss01.jpg](https://qiita-image-store.s3.amazonaws.com/0/212880/f595c043-648e-5796-12bc-c71319bb83cb.jpeg)


ノイズで瞬く
![fig33.png](https://qiita-image-store.s3.amazonaws.com/0/212880/65062d50-5600-5567-4daa-4dd6b959c053.png)
ノイズを使ってランダムな瞬きを作ります。TexCoord のタイリング設定は小さくします。0.001くらいです。点滅の速度はPannerとノイズのスケールで調整。点滅の間隔というか加減はノイズの座標で。座標をランダムに指定することで一斉に瞬かないようにします。
![draw4.gif](https://qiita-image-store.s3.amazonaws.com/0/212880/2a6c7aab-4811-d013-c722-6a25950bec18.gif)


カラーをUVスクロールで
テクスチャは最初に小さい解像度で作ってノイズを乗せた後、ニアレストネイバーで拡大してます。
![fig34.png](https://qiita-image-store.s3.amazonaws.com/0/212880/722bf932-e9fa-c6b6-9bc2-c47d87d79e56.png)
![fig35.png](https://qiita-image-store.s3.amazonaws.com/0/212880/8412d658-a324-5241-8cdd-ab14da7333f5.png)
UE4にインポートしたあとのフィルタ設定でもNearestを選択すると、キリっとした変化になります。
![draw5.gif](https://qiita-image-store.s3.amazonaws.com/0/212880/a69bc5a9-97b0-a02c-eb9b-ba226fa42a39.gif)


この点滅パターンを切り替えられるようにしてしてもいいかも。
パターンごとの関数を用意したらSwitch on Intで切り替え。
![fig37.png](https://qiita-image-store.s3.amazonaws.com/0/212880/91f525f5-e09c-e505-d5f8-84aa95fddf73.png)
ランプの間隔を変更したのと同じ要領で、カスタムイベント。
![fig38.png](https://qiita-image-store.s3.amazonaws.com/0/212880/31420a04-d7b5-3397-cece-658261e54172.png)
あとは、このカスタムイベントをレベルブループリントから、呼び出してやるだけ。
カスタムイベントを使わず、SwitchノードのIntをランダムにするとミックスにできます。
![fig39.png](https://qiita-image-store.s3.amazonaws.com/0/212880/2c23d96c-f5b8-2ab0-403b-7ff3bfc012d3.png)



####おわりに
雑な記事になってしまって心苦しいですが、いかがでしたでしょうか？
マテリアルアニメーションのネタ開発に教材として使えたらいいなと記事を書きながら考えてました。
サンプルの動画も用意したかったんですけどね・・・。
分からないとこや、おかしいとこなどあればコメントとかTwitterとかでツッコミいただければと思います。
最後まで読んでいただいてありがとうございます。

みなさん良いクリスマスを！

　
明日は @nana_321321 さんの記事です。