どーも、ぐるたか@guru_takaです。
前々から特定のオブジェクトに特殊エフェクトをかけたい!と思い、実際にやってみました。成果物はこちらです!
© UTJ/UCL
ユニティちゃんにモザイクをかけてみました。結構、面白いです!笑
モザイクだけでなく、グレースケールにしたり歪ませるなど、エフェクト次第で色んな表現ができます。またAR・VRとも相性が良さそうです!
さっそく、特定のオブジェクトにエフェクトを実装するやり方を紹介していきます。GitHubにコードを掲載してますので、こちらも参考にしてみてください!
⇒MosaicSpecificObject | GitHub
目次
主な流れ
超ざっくりまとめると、ポストエフェクトでモザイクをかけます。特定のオブジェクト限定にするため、専用のカメラを用意。最後に良い感じに合成されて、完成!って感じです。
STEP1.モザイクかけるLayerを作成&設定
まずはモザイクをかけるLayerを作成し、設定しましょう!
ここではユニティちゃんに、Layer=PostEffect
としています。
STEP2.複数のカメラを用意&設定
次に3つのカメラを用意します。描画順とざっくりしたイメージはこんな感じ!
カメラの設定は画像の通りです。
Depthは描画順です。Clear FlagsをDon't Clear
にすることで、深度情報を保持したまま、ポストエフェクトを限定してかけられます。
Clear FlagsをDepth Only
にすると、下画像のように、深度情報が関係なくなって上書き描画されるので注意が必要です!
STEP3.ポストエフェクト用のScriptを作成
続いて、ポストエフェクト用のScriptを作成します。
using UnityEngine; public class PostEffect : MonoBehaviour { public Material mosaic; void OnRenderImage(RenderTexture src, RenderTexture dest) { Graphics.Blit(src, dest, mosaic); } }
STEP4.モザイクShaderを作成&アタッチ
次に、モザイクシェーダーを作成します。シェーダーの解説はメインでないので割愛します!興味ある方は参考リンクをご覧ください。
Shader "Custom/mosaic" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _PixelNumber ("PixelNum", float) = 100 } SubShader { Pass { Tags { "RenderType"="Opaque" } CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _MainTex; float _PixelNumber; struct v2f { half4 pos : POSITION; half2 uv : TEXCOORD0; }; float4 _MainTex_ST; v2f vert(appdata_base v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); return o; } half4 frag(v2f i) : COLOR { half2 uv = floor(i.uv * _PixelNumber) / _PixelNumber; fixed4 col = tex2D(_MainTex, uv); return col; } ENDCG } } FallBack "Diffuse" }参考 Unityを利用して2D画像にモザイク効果をかけるSTYLY シェーダーが完成できたら、ポストエフェクト用カメラにアタッチしましょう!
STEP5.影のレンダリングを調整するScriptを作成
この状態でレンダリングすると、こんな風になります。
これはモザイクとキレイなオブジェクトが重なっている状態を意味しています。カメラの位置をずらすと一目瞭然!
シンプルにメインカメラでCulling MaskでLayer”PostEffect”を外せば良いじゃん!と思うかもしれませんが、罠が待ち受けています。
影が出なくなるんですね…。ここでめちゃくちゃ悩み、詰まりました。最終的に、以下のような処理で解決!
- メインカメラのレンダリング前に影のみ描画するよう指示
- メインカメラのレンダリング後にオブジェクトも描画するよう指示
ソースはこちらです。
using UnityEngine; public class PostShadow : MonoBehaviour { public GameObject renderTarget; protected Renderer[] _rendererComponents; void Start() { _rendererComponents = renderTarget.GetComponentsInChildren(); } void OnPreRender() { foreach (var renderer in _rendererComponents) { renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; } } void OnPostRender() { foreach (var renderer in _rendererComponents) { renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; } } }
メインカメラにアタッチして完成です!
最後に
以上です。
Unityでの表現の参考に少しでもなれば幸いです!
コメントを残す