はじめに
Unity 2020.2 の Universal RP 向けのグレースケールポストエフェクトを作ってみました。
環境
Unity 2020.2
Universal RP 10.2.2
ポストエフェクトに必要なもの
Universal RP でポストエフェクトを実装する際、以下のようなデータを扱うことになります。
・Universal Render Pipeline Asset
・Forward Renderer Data
・ポストエフェクト用シェーダー (.shader)
・RendererFeature (C#スクリプト)
ポストエフェクト実装の流れ
1. ポストエフェクト用シェーダー (.shader)を作る
2. ポストエフェクトを実行するRendererFeatureを作る
3. ForwardRendererDataを作成し、RendererFeatureをそこへ登録する
4. Universal Render Pipeline アセットにForwardRendererDataを登録
5. シーンのCameraコンポーネントから、使用したいForwardRendererDataを選択
6. 画面にグレースケールがかかるようになる
イメージとしては以下のようになります。
グレースケールエフェクトを作ってみる
1 : ポストエフェクト用シェーダー
画面色のR, G, B からグレースケールを計算するシェーダーを作成します。
今回は CIE XYZ を利用してグレースケールを計算しました。
以下のシェーダーを Grayscale.shader としてUnityプロジェクト内に保存します。
Shader "PostEffect/Grayscale" { Properties { [HideInInspector] _MainTex ("Texture", 2D) = "white" {} } SubShader { 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; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); return dot(col.rgb, fixed3(0.2126, 0.7152, 0.0722)); } ENDCG } } }
2 : RendererFeature
次に、カメラのレンダリング結果にグレースケールを適用するRendererFeatureを実装します。
以下のスクリプトを Grayscale.cs としてUnityプロジェクト内に保存します。
using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; public class Grayscale : ScriptableRendererFeature { [System.Serializable] public class GrayscaleSetting { // レンダリングの実行タイミング public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingTransparents; } /// <summary> /// Grayscale実行Pass /// </summary> class GrayScalePass : ScriptableRenderPass { private readonly string profilerTag = "GrayScale Pass"; public Material grayscaleMaterial; // グレースケール計算用マテリアル public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { var cameraColorTarget = renderingData.cameraData.renderer.cameraColorTarget; // コマンドバッファ var cmd = CommandBufferPool.Get(profilerTag); // マテリアル実行 cmd.Blit(cameraColorTarget, cameraColorTarget, grayscaleMaterial); context.ExecuteCommandBuffer(cmd); } } [SerializeField] private GrayscaleSetting settings = new GrayscaleSetting(); private GrayScalePass scriptablePass; public override void Create() { var shader = Shader.Find("PostEffect/Grayscale"); if (shader) { scriptablePass = new GrayScalePass(); scriptablePass.grayscaleMaterial = new Material(shader); scriptablePass.renderPassEvent = settings.renderPassEvent; } } public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if (scriptablePass != null && scriptablePass.grayscaleMaterial != null) { renderer.EnqueuePass(scriptablePass); } } }
3 : Forward Renderer Data の作成
Forward Renderer Data を作成します。
Forward Renderer Data は以下のような名前にしてみました。
4 : Forward Renderer Data を PIpeline Asset へ登録
Univesal Render Pipeline Asset へ STEP1で作成したForward Renderer Data を登録します。
5 : Forward Renderer Data に Grayscale を登録
Forward Renderer Data に Grayscale を登録します。
Add Renderer Feature ボタンをクリックします。
ドロップダウンメニューからGrayscale を選択します。
6 : カメラの設定
CameraコンポーネントのRenderer にて、 STEP2で PIpeline Asset に登録したForward Renderer Data を 選択します。
結果
画面にグレースケールエフェクトが適用されます。