
マイケル
みなさんこんにちは!
マイケルです!
マイケルです!

エレキベア
こんにちクマ〜〜〜

マイケル
今日もシェーダーを触っていきます!
今回はポストエフェクトの実装だ!
今回はポストエフェクトの実装だ!

エレキベア
ポストエフェクトってUnityだとパッケージでかけれなかったクマ??

マイケル
そう、UnityだとPost-Processing Version 2パッケージを使ってポストエフェクトをかけることが多いと思うけど、自分でシェーダーを実装してかけることもできるんだ!

エレキベア
自分で実装できたら思うようにできそうクマね

マイケル
早速触っていこう!!
ポストエフェクトの実装方法

マイケル
ポストエフェクト用(2D用)のシェーダーの雛形は「Shader > Image Effect Shader」から作成することができます。

マイケル
作成直後は下記のような状態になっていて、
デフォルトでネガポジ反転(RGB値を反転させたもの)が実装されています。
デフォルトでネガポジ反転(RGB値を反転させたもの)が実装されています。
↑作成直後の状態(ネガポジ反転)

マイケル
あとは下記スクリプトをカメラオブジェクトにアタッチして、このシェーダーを適用したマテリアルをアタッチすれば完了です!
↑ポストエフェクトをかけるスクリプト

エレキベア
これだけなのクマね

マイケル
OnRenderImage関数ではそれぞれ
src: 最終的に描画される画像(入力)
dest: 最終的に描画される画像(出力)
として渡されてくるため、Graphics.Blit関数でsrcからdestへコピーする際にマテリアルを適用することで最終的な画像にエフェクトをかける、といった流れになっています。
src: 最終的に描画される画像(入力)
dest: 最終的に描画される画像(出力)
として渡されてくるため、Graphics.Blit関数でsrcからdestへコピーする際にマテリアルを適用することで最終的な画像にエフェクトをかける、といった流れになっています。
OnRenderImage | Unityスクリプトリファレンス
Graphics-Blit | Unityスクリプトリファレンス

エレキベア
なるほどクマ
最終的な描画の処理になるクマね
最終的な描画の処理になるクマね

マイケル
ポストエフェクトをかける前後では下記のように変化することが確認できます!

エレキベア
おお〜〜〜
ちゃんとエフェクトがかかっているクマ〜〜〜
ちゃんとエフェクトがかかっているクマ〜〜〜
いくつかポストエフェクトを作ってみる

マイケル
ポストエフェクトのかけ方が分かったところで、いくつか実装してみましょう!
グレースケール

マイケル
まずはグレースケール!
こちらはNTSC加重平均法というものを用いて、RGBの輝度として(0.298, 0.586, 0.114)を重みとして乗算してモノクロ化します。
こちらはNTSC加重平均法というものを用いて、RGBの輝度として(0.298, 0.586, 0.114)を重みとして乗算してモノクロ化します。
参考:
より自然なグレースケール変換 | ゆるゆるプログラミング

エレキベア
なんという絶妙な数値クマ・・・

マイケル
今回は数値はざっくりとしたものを指定して下記のように実装してみます。
Frag関数の処理を少し修正しただけですね
Frag関数の処理を少し修正しただけですね
↑グレースケールの実装

マイケル
こちらを適応した結果は下記のようになります。

エレキベア
ちゃんとグレースケールになってるクマ〜〜〜
放射状ブラー

マイケル
次は少し難易度を上げて放射状ブラーを実装してみます。
こちらはLIGHT11さんの下記記事を参考にさせていただきました!
こちらはLIGHT11さんの下記記事を参考にさせていただきました!
参考:
【Unity】【シェーダ】Radial Blur(放射状ブラー)のポストエフェクトを実装する | LIGHT11

マイケル
こちらの実装は下記のようになります。

マイケル
frag関数内の処理を見れば分かる通り、指定回数ループするごとに内側のピクセルをサンプリングして加算、最終的に平均値を求めることでブラーを表現しています。
パラメータはとりあえず下記のようにサンプル数:12、強さ:0.7を指定してみると、下記のように描画されることが確認できます。
パラメータはとりあえず下記のようにサンプル数:12、強さ:0.7を指定してみると、下記のように描画されることが確認できます。

エレキベア
ちゃんと外側に引き伸ばされたようなブラーになったクマ〜〜

マイケル
こんな感じで繰り返しながらサンプリングしていく手法はいろいろと応用が効きそうだね!
複数エフェクトの適用

マイケル
次にこれらのエフェクトを複数かけたい場合にどうするか?についてですが、
これはエフェクトをかける用のRenderTextureを自前で用意して最終的にdestにかける方法で適用することができます。
実装は下記のようになります。
これはエフェクトをかける用のRenderTextureを自前で用意して最終的にdestにかける方法で適用することができます。
実装は下記のようになります。

エレキベア
なるほどクマ
エフェクトをかけている間は自作のRenderTextureで退避しておくクマね
エフェクトをかけている間は自作のRenderTextureで退避しておくクマね

マイケル
ちょっと面倒くさいけど、下記のように複数かけれることが確認できました!

エレキベア
段々使いこなしてきたクマね
描画パスの切替とワイプ処理

マイケル
最後に、シェーダーコード内に複数パスを記述して切り替える方法についても紹介します!
描画するパスに関しては下記のようにGraphics.Blitの第4引数に渡すことで指定することができます。
描画するパスに関しては下記のようにGraphics.Blitの第4引数に渡すことで指定することができます。
↑描画パスの指定

エレキベア
なるほどクマ
あとは渡すパスを切り替えればいいクマね
あとは渡すパスを切り替えればいいクマね

マイケル
今回は3種類のワイプエフェクトを切り替える処理として、下記のように実装してみました!
合わせて_WipeSizeパラメータにワイプ量を渡すようにも実装しています。
合わせて_WipeSizeパラメータにワイプ量を渡すようにも実装しています。
↑3種類のワイプエフェクト適用処理

マイケル
シェーダー側のワイプエフェクトのコードは下記のように実装してみました!
3種類のエフェクトをPassとして分けて実装しています。
3種類のエフェクトをPassとして分けて実装しています。
↑3種類のワイプエフェクト

エレキベア
共通部分は外に出してるクマね

マイケル
なお、ワイプエフェクトに関しては下記の書籍を参考にさせていただきました!
内容はC++ですが、Unityにも応用することができるので一読して損無しです!
内容はC++ですが、Unityにも応用することができるので一読して損無しです!
HLSL シェーダーの魔導書 シェーディングの基礎からレイトレーシングまで

エレキベア
シェーダーの日本語書籍はありがたいクマね〜〜〜

マイケル
それぞれのワイプエフェクトの実装と適用結果は下記のようになっています。
X方向のワイプ

マイケル
まず単純にX方向にワイプする処理についてですが、これは単純にワイプ量をuvのx座標から引いてマイナスなら黒を返却、という形で実装しています。

エレキベア
おお〜〜ちゃんといい感じにワイプしてるクマね
方向指定のワイプ

マイケル
そして次に応用範囲を広げてワイプの方向を指定できるようにしたものが下記になります。
指定した方向とUV座標の内積結果を見てクリップするかどうかを判定していますが、指定した向きによって座標位置を反転させないといけない点には注意しましょう。
指定した方向とUV座標の内積結果を見てクリップするかどうかを判定していますが、指定した向きによって座標位置を反転させないといけない点には注意しましょう。

エレキベア
だいぶ実用的になったクマね
チェッカーボードのワイプ

マイケル
そして最後はチェッカーボード模様のワイプ処理です!
これは行番号を求めて奇数行の場合にはX座標をシフトさせて縦じまワイプをかけることで実装しています。
少しややこしいですが一つ一つ見ていくと理解できてくるはずです!
これは行番号を求めて奇数行の場合にはX座標をシフトさせて縦じまワイプをかけることで実装しています。
少しややこしいですが一つ一つ見ていくと理解できてくるはずです!

エレキベア
しゃれおつクマ〜〜〜〜
行ごとにオフセットさせるやり方は応用が効きそうクマね
行ごとにオフセットさせるやり方は応用が効きそうクマね
おわりに

マイケル
というわけで今回はポストエフェクトの実装でした!
どうだったかな??
どうだったかな??

エレキベア
かけるの自体は意外と簡単だったクマが、いろいろクセもあるから注意クマね

マイケル
一回覚えてしまえばシェーダーで自由にいじれるから覚えておいて損はないね!
これからガンガン活用していこう!!
これからガンガン活用していこう!!

マイケル
それでは今日はこの辺で!
アデューー!!
アデューー!!

エレキベア
クマ〜〜〜〜〜
【Unity】ポストエフェクトをシェーダーで実装する(基礎、複数エフェクト適用、描画パス切替)【シェーダー】〜完〜