おもちゃラボ

Unityで遊びを作ってます

【Unityシェーダ入門】画面をセピア色にするポストエフェクトを作る

今回はスクリーンをセピア調にするポストエフェクトシェーダを作ります。ちなみに・・・Wikipediaによるとセピアとはイカスミのことらしいです。

セピア(sepia)とは、イカ墨のこと。また、イカ墨由来の黒褐色をも意味する。かつてモノクロ写真などにこの色のインクが用いられたために、古い写真は褪色し淡い褐色になった。

ゲーム画面をセピア色に変換(ポストエフェクト)した結果は次のようになります。

f:id:nn_hokuson:20170508224217j:plain

ポストエフェクトを使って画面をグレースケール変換する方法は、こちらの記事で紹介しているので参考にしてみて下さい。

nn-hokuson.hatenablog.com

描画する画像をフックする

カメラに映った画像を取得してポストエフェクトをかけるために、画面をレンダリングする途中で画像をフックして画像処理します。

f:id:nn_hokuson:20170508233734p:plain

プロジェクトビューで「PostEffect.cs」というファイルを作成し、次のプログラムを入力してください。

using UnityEngine;
using System.Collections;

public class PostEffect : MonoBehaviour {

	public Material sepia;

	void OnRenderImage(RenderTexture src, RenderTexture dest)
	{
		Graphics.Blit (src, dest, sepia);
	}
}

上記の「ポストエフェクトで画面をグレースケール化する」のページでも説明していますが、OnRenderImageメソッドはレンダリングが完了した後に呼び出されるメソッドで、この中でBlitメソッドを使ってポストエフェクトをかけています。Blitメソッドはsrc画像に第三引数で指定したポストエフェクトをかけてdest画像に書き込みます。

スクリプトが保存できたら、PostEffect.csをカメラオブジェクトにアタッチしてください。

f:id:nn_hokuson:20170508230018j:plain:w550

Unityでセピアシェーダとマテリアルを作る

画面をセピア色にするためのシェーダを作ります。プロジェクトビューで「右クリック」→「Create」→「Shader」→「Standard Surface Shader」を選択し、作成したファイル名をSepiaに変更します。続いてこのシェーダファイルをアタッチするマテリアルも作成しましょう。monoToneのシェーダをを選択した状態で「右クリック」→「Create」→「Material」を選択して「Custom_Sepia」を作成します。

f:id:nn_hokuson:20170508225601p:plain:w180
Sepia.shaderを開いて次のスクリプトを入力してください。

Shader "Custom/sepia" {
    Properties {
    	_Darkness("Dark", Range(0, 0.1)) = 0.04
    	_Strength("Strength", Range(0.05, 0.15)) = 0.05
        _MainTex("MainTex", 2D) = ""{}
    }

    SubShader {
        Pass {
            CGPROGRAM

            #include "UnityCG.cginc"

            #pragma vertex vert_img
            #pragma fragment frag

            sampler2D _MainTex;
            half _Darkness;
            half _Strength;

            fixed4 frag(v2f_img i) : COLOR {
                fixed4 c = tex2D(_MainTex, i.uv);
                half gray = c.r * 0.3 + c.g * 0.6 + c.b * 0.1 - _Darkness;
                gray = ( gray < 0 ) ? 0 : gray;

                half R = gray + _Strength;
                half B = gray - _Strength;

                R = ( R > 1.0 ) ? 1.0 : R;
                B = ( B < 0 ) ? 0 : B;
                c.rgb = fixed3(R, gray, B);
                return c;
            }

            ENDCG
        }
    }
}

上記のプログラムでははセピア変換処理はフラグメントシェーダ(fragメソッドの中)で行っています。このフラグメントシェーダでは、次の3ステップで画像をセピア色に変換しています。

  1. 画像のグレースケール変換
  2. 明度を修正
  3. グレースケール値から赤成分を足し、青成分を減らす

ステップ2で使用する画像を暗くする量(Darkness)と、Step3で使用するセピア色の強さ(Strength)はUnityのインスペクタからも変更できるように、プロパティの部分で宣言しています。

グレースケール化に関しては下記のページを参考にして下さい。

nn-hokuson.hatenablog.com

画像をセピア色に変換するアルゴリズムは、各ピクセルの赤成分を足して、青成分を引くだけです。数式としては非常に簡単ですが、案外それっぽい見た目になりますよ〜!

カメラにセピア用マテリアルをセットする

作成したマテリアルを、カメラにアタッチしたPostEffectスクリプトのSepia欄にドラッグ&ドロップします。これで、画面をセピア色にするポストエフェクトをかける準備ができました。

f:id:nn_hokuson:20170508231327j:plain:w550

実行結果は次のようになります。ポストエフェクトの効果で画面がセピア色になっていますね。

f:id:nn_hokuson:20170508233259j:plain

先ほど、シェーダファイルで「画面の明度」と「セピア色の強さ」はプロパティに設定したので、インスペクタから調整可能です。

f:id:nn_hokuson:20170508233020p:plain:w300

パラメータを調節することで同じセピア色でも色々な表情を作れるので、自分のゲームに合った色合いを見つけてみてくださいね〜!

f:id:nn_hokuson:20170508232951j:plain