ポストエフェクトとは、カメラに映ったゲームシーンを一枚の画像として加工する処理のことです。UnityにはStandard Assetとして次のようなエフェクトが用意されています。
今回は画面を白黒にするモノクロのエフェクトを作りながらポストエフェクトの作り方を説明します。
今回の記事の内容は次の通りです。
カメラのメソッドをフックする
まずはシーンビューに3Dオブジェクトを表示しておきます。これは、なんというか、雰囲気を出すためだけのものなので、あってもなくても良いです(笑)
ここでは、とりあえずUnityちゃんを配置してみました。
カメラに映った画像を取得してポストエフェクトをかけるために、レンダリングする途中で画像をフックします。
プロジェクトビューで「PostEffect.cs」というファイルを作成し、次のプログラムを入力してください。
using UnityEngine; using System.Collections; public class PostEffect : MonoBehaviour { public Material monoTone; void OnRenderImage(RenderTexture src, RenderTexture dest) { Graphics.Blit (src, dest, monoTone); } }
OnRenderImageメソッドはすべてのオブジェクトのレンダリングが完了した後に呼び出されるメソッドです。
このOnRenderImageメソッドの中でBlitメソッドを使ってポストエフェクトをかけています。 Blitメソッドはsrc画像に第三引数で指定したポストエフェクトをかけてdest画像に書き込みます。
スクリプトが保存できたら、PostEffect.csをMainCameraにドラッグ&ドロップしてアタッチしておきます。
Unityでモノクロシェーダとマテリアルを作る
つづいて、画面をモノクロにするためのシェーダを作ります。プロジェクトビューで「右クリック」→「Create」→「Shader」→「Standard Surface Shader」を選択し、作成したファイル名をmonoToneに変更します。続いてこのシェーダファイルをアタッチするマテリアルも作成しましょう。monoToneのシェーダをを選択した状態で「右クリック」→「Create」→「Material」を選択すると、monoToneというマテリアルが作成されます。
monoTone.shaderを開いて次のスクリプトを入力してください。
Shader "Custom/monoTone" { Properties { _MainTex("MainTex", 2D) = ""{} } SubShader { Pass { CGPROGRAM #include "UnityCG.cginc" #pragma vertex vert_img #pragma fragment frag sampler2D _MainTex; fixed4 frag(v2f_img i) : COLOR { fixed4 c = tex2D(_MainTex, i.uv); float gray = c.r * 0.3 + c.g * 0.6 + c.b * 0.1; c.rgb = fixed3(gray, gray, gray); return c; } ENDCG } } }
今回はサーフェスシェーダではなく、バーテックスシェーダとフラグメントシェーダを使っています。具体的なモノクロ処理はフラグメントシェーダで行っています。
フラグメントシェーダでは、画面に描画する予定の色を取得し、それをグレースケール化してから出力しています。グレースケールの変換式については、次の記事で紹介しています。
カメラにマテリアルをセットして実行する
作成したマテリアルを、先ほどカメラにアタッチしたPostEffectスクリプトのmonoTone欄にドラッグ&ドロップします。これで、画面をモノクロにするポストエフェクトをかける準備ができました。
実行結果は次のようになります。ポストエフェクトの効果で画面がモノクロになっています。
ポストエフェクトはただの画像処理なので、モノクロやセピア調に変換したり、2値化やエッジ検出、ぼかし、などの効果を簡単に作ることができます。
参考書籍
画像処理に関しては、今給黎さんのシェーダ本がおすすめです!
今給黎さんの「シェーダプログラミングブック」では基本的にDirectXを使って説明されていますが、シェーダやポストエフェクトに関しては、一般的なお話や理論が多いので非常に役に立ちます(めっちゃ読み込みました!)