太郎Work

Unityとかで困ったこと等を残しておきます

Unityステンシルでポストエフェクト

前回の記事ではステンシル情報を用いてアウトラインを表現しましたが、
せっかくステンシル情報を書き込んだのでポストエフェクトにも応用してみました

f:id:tarowork:20140803012110p:plain
キャラクターだけモザイク処理

f:id:tarowork:20140803012144p:plain
ステージのみモノクロ

Terrainの草にシェーダを指定する方法が分からなかったのでその部分にステンシルをかけられませんでした。

WebPlayer版
右側にあるボタンでモザイク、モノクロ、通常と前回の記事のアウトラインが切り替えられます。
Stencil Test




モザイクに関しては間に何個か処理を挟んでいるので紹介ます。
OnRenderImageで以下のスクリプトを実装しました
ステンシル領域から白黒のマスク画像を作成し、縮小してから拡大しています。

// 一時テクスチャ作成
var tmp = RenderTexture.GetTemporary (source.width, source.height, source.depth);
var mosaicTex = RenderTexture.GetTemporary (source.width / mosaic, source.height / mosaic);
mosaicTex.filterMode = FilterMode.Point;
RenderTexture.active = tmp;
GL.Clear (false, true, Color.clear);
RenderTexture.active = null;
Graphics.Blit (source, tmp, material, 2);

Graphics.Blit (tmp, mosaicTex, material, 3);
RenderTexture.ReleaseTemporary (tmp);
tmp = RenderTexture.GetTemporary (mosaicTex.width, mosaicTex.height);
tmp.filterMode = FilterMode.Point;
material.SetFloat ("_Size", size);
material.SetTexture ("_SubTex", source);
Graphics.Blit (mosaicTex, tmp, material, 5);
material.SetTexture ("_SubTex", tmp);
Graphics.Blit (source, destination, material, 1);
RenderTexture.ReleaseTemporary (tmp);
RenderTexture.ReleaseTemporary (mosaicTex);

2パス目のシェーダではキャラクターの領域からマスク画像を作成します。
5パス目ではモザイク領域を一回り大きくする処理が入っています。

Pass {
  ZTest Always Cull Off ZWrite Off
  Fog { Mode off }
  Stencil {
    Ref 3
    Comp equal
  }
  CGPROGRAM
  #pragma vertex vert_img
  #pragma fragment frag_main
  #pragma fragmentoption ARB_precision_hint_fastest 
  ENDCG
}

詳細はここでは書きませんが、Stencilで指定した部分のみにピクセル操作が行われるので様々な表現ができるかと思います。
Stencilにうまく書き込んでおけば好きな領域のみにエフェクトが掛けられるというサンプルでした。