##はじめに
この記事はUnreal Engine 4 (UE4) Advent Calendar 2019の17日目の記事です。
色々あってアドカレを書くことになった鶏です。
本記事ではそんな鶏が某有名タイトルのPエンドで発生しているシステム汚染エフェクトを再現しようと頑張った話になります。
マテリアルについては最近勉強し始めたばかりの初心者なので、
もし何かお気づきの点があればコメントか上谷のTwitterに優しくDM等お願いします。
UE4.23.1 で動作確認してます。
##やること
こんな感じのをやります。※上のTwitterが見れない人は[こちら](https://twitter.com/kamitani_08/status/1206535683638063104?s=20) 本記事では上の動画で使用している3つのマテリアルを以下のフォーマットに沿って紹介していきます。 1、概要 : その章で作りたいマテリアルの概要です。大体こんなのがやりたいんだなーと感じてくれたらと思います。 2、作ったマテリアル : 実際に作ったマテリアルの全容です。 3、やっている事 : 2のマテリアルの説明です。1を見て大体の構想が解る人は見なくても大丈夫ですはい。どーが pic.twitter.com/8H6LEYFHWS
— 上谷🍖 (@kamitani_08) December 16, 2019
では始めまーす
##モザイク
某有名タイトルのエフェクトを見ていると通常のUVを分割してその範囲をサンプリングした色で塗り潰すようなモザイク表現とは少し違い、下記のように横に分割はされていますが縦の分割はされず、画像が引き延ばされているような表現をされてました。
それを真似てこんな感じのやつ作りました
####・作ったマテリアル
作成したマテリアルが以下になります。
####・やっている事
まず横の分割数を取得するのにNoise関数とLerpで一定の範囲の乱数を算出
取得した乱数を使用して分割することでその範囲で画像が横に伸びるようにする
計算結果とVを合わせて画面をサンプリングし、これだけだとモザイクがきつすぎて画面が見えないのでLerpで元の画面と混ぜ合わせます
※モザイクシェーダーの作り方や応用は下記の記事でmokoさんが紹介してくださっており、大変参考にさせていただきました!気になる方は是非!
http://effect.hatenablog.com/entry/checkmosaic
##色分解
####・作ったマテリアル
作成したマテリアルが以下になります
長い・・・・頑張ろう・・・・
####・やっている事
ノイズで乱数を取得し、小数点部分をFrac関数で取得してそれに係数をかけてノイズテクスチャをサンプリングした二つのRGBAを足して割ってます
上の結果をStep関数で0.6を基準に0か1にして後の計算で-1か1の値にした物に係数をかけて色ズレのオフセット値を出します
Uの要素に↑で算出した値を使用してRGBそれぞれに画像をサンプリングします
ノイズマスクが掛かったところは赤くしたいのでLerpを使用してマスクの所はRの要素を1.2倍するようにしてMakeFloat4でFloat4を作成します。
その値とUをずらしてサンプリングした一番上のスクリーンテクスチャの値をノイズマスクを使用してLerpします
##モノクロとかなんか色々やってるシェーダー
画面がモノクロになり、画面外側になるにつれて色が出てきて色収差しています。
やりたい事はこれです
####・作ったマテリアル
作成したマテリアルが以下になります。
####・やっている事
ブラーは下記フォーラムを参考にコードを少し弄って使用しました
https://forums.unrealengine.com/community/community-content-tools-and-tutorials/28458-radial-blur-postprocess-material?57646-Radial-Blur-PostProcess-Material=&highlight=blur
#####色収差
UVを左右にずらしたものをセットで作成しそれらの色を合成
こんなのが出来ます
そこから元のスクリーン画面の色を引いてグレイスケールしたものを2倍してRにしたFloat3を作成します
#####ブラー&モノクロ
ブラーは基本的に参考にしたフォーラムに記載されているコードを丸コピしてますが、カスタムノードの中身を一部変更しました
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}にして別のやり方もあるかもしれませんが、本記事はこちらの方で進めます
※モノクロに関してはUE4の標準関数にDesaturationという物があるらしいです。
12日に @dgtanaka さんのアドベントカレンダーで紹介してくださってるので気になる方はご覧ください(某epicのあの人も絶賛する神記事です!)
https://qiita.com/dgtanaka/items/f7fa2cb38e58bbe5f4a6#desaturation
#####マスク
これでマスクを作成してます
プレビューはこんな感じ
これをAlphaとして使用して色収差とブラーをLerpにつなぎます
####完成
やったぜ ※色収差がわかりにくかったので背景を一部変更しました
適用前はこんな感じ
###おわり
これらのマテリアルをLerpとMaterialParameterCollectionとDlayを駆使していい感じに作ったのが最初の動画になります。
元ネタを知ってる人はお察しだとは思いますが全く似なかったですはい(期待して見に来てくださった方はすみません!!!!)
ただ今回の記事を書くにあたって、初めてながら色々試行錯誤したり、いろんなシェーダーの技法を知ったりとマテリアルめちゃ面白いなーと思いました。
次はもっとクオリティを上げて挑戦しますので鶏の次回作にご期待ください!!
明日はNaotsunさんです!よろしくお願いします!!