Unreal Engine 4 (UE4) Advent Calendar 2014 - Qiita
の二日目です。
記事名の通り、UE4のポストプロセスマテリアルについて雑多に色々書きます
今回は基本編です。この記事の内容をベースに色々してみたことを
来週に書きます。(記事が長くなり過ぎたので分割しました)
参考サイト
- Unreal Engine | ポストプロセス マテリアル
- ポストプロセス - UE4 Document@com04
- もんしょの巣穴blog [UE4] ポストエフェクトを自作してみる
- ノンフォトリアルやセルルック等の独特なレンダリングを! - Unreal Engine Forums
あなた「この記事を見なくても、この参考サイトを巡回すればいいんじゃね?」
わたし「…君のような勘のいいガキは嫌いだよ」
「そもそもポストプロセスマテリアルってなんやねん?」という方には、
@aizen76さんのこの記事がオススメです
UE4 ポストプロセスエフェクトについて - Let's Enjoy Unreal Engine
Hello PostMaterial World
まずは、最もシンプルなポストプロセスマテリアルを作ってみます。
M_SimplePostという名前のマテリアルを作成し、レベルに配置した
PostProcessVolumeのMisc/Blendablesに追加します
そして、M_SimplePostは以下のように設定します。処理内容をざっくり説明すると、
各画素に割り当てられたテクスチャ座標(Texcoord)を用いて、
レンダリング結果を保存したテクスチャ(SceneTexture:SceneColor)を参照し、
その値をそのまま出力に渡しています
なので、描画結果に変化はありません。
おまけ
TexCoordの値は左上(0,0)右上(1,0)左下(0,1)右下(1,1)になっています
その為TexCoordを出力に繋ぐと、結果は↑のようになります
皆大好きアウトライン(輪郭線)フィルタ
ポストマテリアルを触る理由の98割はアウトラインフィルタだと思います(超絶偏見)
ということで、早速作ってみましょう
アウトライン描画をポストプロセスで実現するには、エッジ検出をする必要があります
今回はエッジ検出手法の1つである、Prewittフィルタを実装してみましょう
※ エッジ検出手法には他にも、SobleフィルタやLaplacianフィルタがあります
前者は@monsho1977さんのサイト、後者は@com04さんのサイトで
実装・解説されています
※ 輪郭線描画で、ポストプロセス以外の手法としては押出法があります
こちらは、@com04さんのサイトで実装・解説されています
エッジ検出ってなんなのさ?
先ほどの結果画像からキャラクターの左目付近を拡大した画像です
かなり荒い画像ですが、キャラクターと背景の色が異なるので
判別できていると思います。
さらに細かく書くと、
キャラクターの輪郭線にあたる画素のRGB値と、その右側にある
背景画素のRGB値が大きく異なる為、脳内で境界線を引く事ができています。
(逆に、肌と髪の毛の色は似ているので判断しづらいと思います)
つまり、エッジ処理を実現するためには、各画素毎に以下の処理をします
- 周辺の画素情報を取得
- 周辺画素と処理対象画素との変化量を計算
- 変化量が一定以上なら輪郭線と判断
そして、この処理を効率よく、かつ効果的にする手法として生み出されたのが
上で挙げた各フィルタ処理です。
Laplacianフィルタの場合だと、こんな感じの処理になります。
http://www.technotype.net/tutorial/tutorial.php?fileId=%7BImage+processing%7D§ionId=%7Bwhat-is-spatial-filter%7D
今回実装するPrewittフィルタは、水平方向と垂直方向の2回に分けて処理を行います
解説すると、さらに長くなるので解説サイトを置いておきます
ちなみに、Sobelフィルタも同様に、水平・垂直で2回処理を行います
☆PROJECT ASURA☆ [OpenGL] 『Prewittフィルタ』
edge detection (Sobel filter/Prewitt filter)
フィルタ処理の実装するぞい
誰得な解説が終わったので、早速実装に移ります
上で「RGBの変化が~」と説明しましたが、今回のフィルター処理では
RGB値ではなくデプス値を使用します。その方が綺麗にエッジ検出できるからです
今回は↓のような感じで、フィルターの各係数を渡せるマテリアル関数を作ります
我ながら超ベンリです。
この関数の中身と、中で使用しているマテリアル関数は以下のとおりです
隣り合う画素情報の取得は、参考サイト様からの丸パクリです
@monsho1977さんのサイト
@com04さんのサイト
隣り合う画素のTexcoord取得
MF_GetOffsetPixel
隣り合う画素のデプス値取得
MF_GetOffsetPixelDepth
フィルター処理
MF_FilterFunctionDepth
Prewittフィルタ
↑の状態で適応した結果が↓です。こわいです
デプス値の変化量が多いほど、出力値が大きい=白色になっているのが
分かると思います。あとは、以下の処理を加えれば完成です
- 真っ白な部分のみを抽出
- 黒色の輪郭線にしたいので、白黒反転
- 元々の描画結果に重畳
で、結果はこんな感じ。今度はかわいい
ついでに、各フィルタでの比較(見栄え重視で、調整用パラメータ弄ってます)
Laplacianフィルタはエッジ検出し過ぎるので、輪郭線には向かないかもしれません…
SobelかPrewittはお好みでという所でしょうか?
調整用のパラメータ次第で幾らでも変わるので、色々と試して見て下さい
Tips
終わる前に紹介したいTipsを1つ
マテリアル関数の引数の順番指定について
今回作成したフィルター関数のように、引数(ピン)の順番を
指定したくなる時があります
そんな時は、Inputに指定したノードのSortPriorityの値を設定しましょう
この数値が低い順で、上からピンが配置されます。便利です
予告編
駆け足説明になりましたが、これで輪郭線が書けました!
Happy End!
…が、これは前座です!前座です!(大切なことなので
来週12/9に公開する記事では、さらに色々工夫することで
面白い画を作る方法について説明します!
少し前に流行った漫画風フィルターとか…
かま○たちの夜的な表現だったり!
お楽しみに!
明日12/3の担当は@kurosaurusさんで、
タイトルは「Bitmap2Materialで写真から簡単物理マテリアル」です
こんなマテリアルができました。詳細は12/3のUnreal Engine 4 (UE4) Advent Calendar 2014で。http://t.co/LJsXogWh6G pic.twitter.com/BpywNCbNiZ
— Kurosawa (@kurosaurus) 2014年12月1日
しゅごい…楽しみです!