【Unity】【URP】 Chromatic Aberration (色収差)
Chromatic Aberration (色収差) エフェクト
光の屈折率は色によって異なるため、レンズを通過した際に焦点距離に差が発生し、ずれて見えます。
実装
実装方法としてはRチャンネルとBチャンネルを_Intensityに応じて拡大しています。
Shader "Hidden/ChromaticAberration" { Properties { _MainTex ("Texture", 2D) = "white" {} _Intensity ("Intensity", Range(0.0, 1.0)) = 0.1 } SubShader { // No culling or depth Cull Off ZWrite Off ZTest Always Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } sampler2D _MainTex; half _Intensity; fixed4 frag (v2f i) : SV_Target { half4 col = tex2D(_MainTex, i.uv); // uvを-0.5〜0.5にする half2 uvBase = i.uv - 0.5h; // R値を拡大する half2 uvR = uvBase * (1.0h - _Intensity * 2.0h) + 0.5h; col.r = tex2D(_MainTex, uvR).r; // G値を拡大する half2 uvG = uvBase * (1.0h - _Intensity) + 0.5h; col.g = tex2D(_MainTex, uvG).g; return col; } ENDCG } } }
色収差なし
色収差あり
SwapBuffer
今回URPのプロジェクトでポストエフェクトを実装するにあたってURP12の新機能であるSwapBufferを使って実装したので、解説します。
従来のやり方だとカメラのカラーバッファをテンポラリーなRenderTextureに描画しておき、ポストエフェクトをかけながらRenderTextureをカメラのカラーバファーに適応させます。
SwapBufferではURPが裏でテンポラリーなRenderTextureを用意してくれて、ユーザーがマテリアルを渡すだけでBlit処理を行ってくれます。
using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; public sealed class ChromaticAberrationRenderPass : ScriptableRenderPass { private const string RenderPassName = nameof(ChromaticAberrationRenderPass); private readonly Material _material; public ChromaticAberrationRenderPass(Shader shader) { if (shader == null) return; _material = new Material(shader); // このレンダーパスをポストプロセスのタイミングで実行 renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing; } public override void Execute(ScriptableRenderContext context, ref RenderingData data) { if (_material == null) return; var cmd = CommandBufferPool.Get(RenderPassName); // 一回Blitするだけで良くなりました。 Blit(cmd, ref data, _material); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } }
using System; using UnityEngine; using UnityEngine.Rendering.Universal; [Serializable] public sealed class ChromaticAberrationRendererFeature : ScriptableRendererFeature { [SerializeField] private Shader _shader; private ChromaticAberrationRenderPass _postProcessPass; public override void Create() { _postProcessPass = new ChromaticAberrationRenderPass(_shader); } public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { renderer.EnqueuePass(_postProcessPass); } }