鶏がシステム汚染のエフェクトを再現してみた




##はじめに
この記事は[Unreal Engine 4 (UE4) Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ue4)の17日目の記事です。

色々あってアドカレを書くことになった鶏です。
本記事ではそんな鶏が某有名タイトルのPエンドで発生しているシステム汚染エフェクトを再現しようと頑張った話になります。
マテリアルについては最近勉強し始めたばかりの初心者なので、
もし何かお気づきの点があればコメントか上谷のTwitterに優しくDM等お願いします。
UE4.23.1 で動作確認してます。


##やること
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">どーが <a href="https://t.co/8H6LEYFHWS">pic.twitter.com/8H6LEYFHWS</a></p>&mdash; 上谷🍖 (@kamitani_08) <a href="https://twitter.com/kamitani_08/status/1206535683638063104?ref_src=twsrc%5Etfw">December 16, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
こんな感じのをやります。※上のTwitterが見れない人は[こちら](https://twitter.com/kamitani_08/status/1206535683638063104?s=20)
本記事では上の動画で使用している３つのマテリアルを以下のフォーマットに沿って紹介していきます。
１、概要 ： その章で作りたいマテリアルの概要です。大体こんなのがやりたいんだなーと感じてくれたらと思います。
２、作ったマテリアル ： 実際に作ったマテリアルの全容です。
３、やっている事 ： ２のマテリアルの説明です。１を見て大体の構想が解る人は見なくても大丈夫ですはい。


では始めまーす



##モザイク
某有名タイトルのエフェクトを見ていると通常のUVを分割してその範囲をサンプリングした色で塗り潰すようなモザイク表現とは少し違い、下記のように横に分割はされていますが縦の分割はされず、画像が引き延ばされているような表現をされてました。
それを真似てこんな感じのやつ作りました
![キャプチャ0018.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/06b599db-660a-9d0c-ad68-43970fc8581b.png)






####・作ったマテリアル
作成したマテリアルが以下になります。
![グリッジ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/e6371951-4d78-0706-cd3a-2d605c455fca.png)








####・やっている事

まず横の分割数を取得するのにNoise関数とLerpで一定の範囲の乱数を算出
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/f8b36083-4a20-99d9-de7a-2552d5e095ee.png)


取得した乱数を使用して分割することでその範囲で画像が横に伸びるようにする
![キャプチャ0001.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/a069a14c-ef35-454f-f58b-3bf666f03f6f.png)


計算結果とVを合わせて画面をサンプリングし、これだけだとモザイクがきつすぎて画面が見えないのでLerpで元の画面と混ぜ合わせます
![キャプチャ0002.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/e040204b-7ac5-89ab-fe3c-5e6c9e9b514d.png)







####完成
やったぜ
![キャプチャ0018.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/06b599db-660a-9d0c-ad68-43970fc8581b.png)

ちなみにポスト適用前はこんな感じ
![キャプチャ0025.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/0b9ab762-7f14-a0d7-ebab-6530b3122f85.png)





※モザイクシェーダーの作り方や応用は下記の記事でmokoさんが紹介してくださっており、大変参考にさせていただきました！気になる方は是非！
http://effect.hatenablog.com/entry/checkmosaic





##色分解

こんな感じのやつ作りました
![キャプチャ0027.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/7263ff58-82b2-7fa6-0000-8a085615bd0e.png)


####・作ったマテリアル
作成したマテリアルが以下になります
![キャプチャ0013.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/fc69e85a-b848-7410-da8d-3909e49b40fc.png)


長い・・・・頑張ろう・・・・

####・やっている事


ノイズで乱数を取得し、小数点部分をFrac関数で取得してそれに係数をかけてノイズテクスチャをサンプリングした二つのRGBAを足して割ってます
![キャプチャ0019.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/324fe7e8-670b-a5db-d3ca-4d92120f3687.png)



使用しているノイズテクスチャ
![tex.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/3e0f919d-5c95-5e2d-2c71-0071fe8e8084.png)


上の結果をStep関数で0.6を基準に0か1にして後の計算で-1か1の値にした物に係数をかけて色ズレのオフセット値を出します
![キャプチャ0014.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/0a5ac795-8bf0-27b9-5807-3d4a29a9d457.png)












Uの要素に↑で算出した値を使用してRGBそれぞれに画像をサンプリングします
![キャプチャ0015.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/14053437-aba9-d248-c1bd-bad3f498cefb.png)


ノイズマスクが掛かったところは赤くしたいのでLerpを使用してマスクの所はRの要素を1.2倍するようにしてMakeFloat4でFloat4を作成します。
その値とUをずらしてサンプリングした一番上のスクリーンテクスチャの値をノイズマスクを使用してLerpします
![キャプチャ0016.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/9e02ddc6-3a5c-2de1-6aca-de8e9b6d4f27.png)





####色分解完成
やったぜ
![キャプチャ0020.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/dbadfdd4-e1d2-2ac2-ab98-34a9e2892c24.png)





##モノクロとかなんか色々やってるシェーダー
画面がモノクロになり、画面外側になるにつれて色が出てきて色収差しています。
やりたい事はこれです
![キャプチャ0028.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/0e9f8968-593b-b1c6-ceb5-9fb05b1b2e6b.png)


####・作ったマテリアル
作成したマテリアルが以下になります。
![キャプチャ003.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/ff33e21e-5984-93ec-a4be-f9fc9fedb274.png)


####・やっている事

ブラーは下記フォーラムを参考にコードを少し弄って使用しました
https://forums.unrealengine.com/community/community-content-tools-and-tutorials/28458-radial-blur-postprocess-material?57646-Radial-Blur-PostProcess-Material=&highlight=blur

#####色収差

UVを左右にずらしたものをセットで作成しそれらの色を合成
![キャプチャ0004.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/f5f77ac5-fdad-42e9-2952-0edf15d37d0f.png)
こんなのが出来ます
![キャプチャ0005.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/33c293e8-d141-4b41-3700-9f23d893a5dc.png)
そこから元のスクリーン画面の色を引いてグレイスケールしたものを2倍してRにしたFloat3を作成します
![キャプチャ0006.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/0e6edb30-fb46-43c3-e7c5-a24b9a474e07.png)


こんなのが出来ます
![キャプチャ0008.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/4e980df7-5145-148d-f97e-b582c055d394.png)
これで色収差が出来ました



#####ブラー＆モノクロ
ブラーは基本的に参考にしたフォーラムに記載されているコードを丸コピしてますが、カスタムノードの中身を一部変更しました

```cpp:CosutomNode
const float2 ScreenMult = View.ViewSizeAndInvSize.xy * View.BufferSizeAndInvSize.zw;
const int TexIndex = 14;
const float Samples[3] = {-0.01,-0.02,0.01};

float2 dir = float2(0.5,0.5) - ScreenUV;float4 sum = float4(0.0, 0.0, 0.0, 0.0);
for(int i = 0; i<3; i++)
{
    float2 pos = ScreenUV + dir * Samples[i] * BlurDist;
    pos = clamp(pos, float2(0.0,0.0), float2(1.0, 1.0));
    sum += SceneTextureLookup(pos * ScreenMult, TexIndex, false);
}
const float4 scrColor = SceneTextureLookup(ScreenUV, TexIndex, false);
sum /= 3.0;
return sum;
```
主な変更点としてはScreenMultの計算方法とブラーの処理を行う回数を変更してます


#####これをモノクロにする

CustomNodeの出力を{0.4f,0.4f,0.4f}でDotしてます
※ここはグレイスケール目的でDot計算をしていましたが{0.4f,0.4f,0.4f}の方が何故か最終的な見栄えが自分の求めてた方に近かったのでこのようにしており、しっかりした根拠があるわけでは無いです。この部分を{0.29891f,0.58661f,0.11448f}にして別のやり方もあるかもしれませんが、本記事はこちらの方で進めます
![キャプチャ0009.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/0d73a0c6-67f9-09e4-ae0d-313053aa92f5.png)

#####ブラー＆モノクロ完成
![キャプチャ0022.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/d41a55bd-975b-b03a-ada1-e6f73e760e0d.png)

ちなみにモノクロ前はこんな感じでした
![キャプチャ0021.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/c29070c9-0748-55a5-36ee-9bc0c60906b2.png)

※モノクロに関してはUE4の標準関数にDesaturationという物があるらしいです。
12日に @dgtanaka さんのアドベントカレンダーで紹介してくださってるので気になる方はご覧ください(某epicのあの人も絶賛する神記事です！)
https://qiita.com/dgtanaka/items/f7fa2cb38e58bbe5f4a6#desaturation


#####マスク
これでマスクを作成してます
![キャプチャ0010.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/c139a3ac-f74d-b0be-a167-318c1536f956.png)
プレビューはこんな感じ
![キャプチャ0011.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/908078d7-fc1a-172d-ac0b-6ec72f1ba2cd.png)
これをAlphaとして使用して色収差とブラーをLerpにつなぎます
![キャプチャ0012.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/9f46e1f1-4eae-2fe0-aa34-0db8b542e90f.png)

####完成
やったぜ ※色収差がわかりにくかったので背景を一部変更しました
![キャプチャ0023.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/9f37d7df-8690-ab5e-fcaf-1bbb6598e425.png)
適用前はこんな感じ
![キャプチャ.0026PNG.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386876/fccf4c27-e289-fe9d-eec3-576ef569ae4a.png)





###おわり
これらのマテリアルをLerpとMaterialParameterCollectionとDlayを駆使していい感じに作ったのが最初の動画になります。
元ネタを知ってる人はお察しだとは思いますが全く似なかったですはい(期待して見に来てくださった方はすみません！！！！)
ただ今回の記事を書くにあたって、初めてながら色々試行錯誤したり、いろんなシェーダーの技法を知ったりとマテリアルめちゃ面白いなーと思いました。


次はもっとクオリティを上げて挑戦しますので鶏の次回作にご期待ください！！









明日は[Naotsun](https://qiita.com/Naotsun)さんです！よろしくお願いします！！