UniversalRPで出来るだけシンプルなRendererFeatureを作って画面に色をかぶせる

<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61266/b52e3c6f-7bb3-0a4e-2007-9f729c4295e9.png">
画面の色を変える画面効果を、出来るだけシンプルなカスタムRendererFeatureで実装してみました。

```cs:ColorOverlayRendererFeature.cs
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

namespace ScreenPocket
{
    /// <summary>
    /// 色をかぶせるRendererFeature
    /// </summary>
    public sealed class ColorOverlayRendererFeature : ScriptableRendererFeature
    {
        /// <summary>
        /// 描画パス
        /// </summary>
        private sealed class Pass : ScriptableRenderPass
        {
            private const string ProfilerTag = "ColorOverlay Pass";
            private static readonly ProfilingSampler ProfilingSampler = new(ProfilerTag);

            private Material _material;
            private Color _color;
            private int _propertyIdColor;

            public Pass(RenderPassEvent evt)
            {
                profilingSampler = new ProfilingSampler(nameof(Pass));
                renderPassEvent = evt;
                _propertyIdColor = Shader.PropertyToID("_Color");
            }

            public void Setup(Material material, Color color)
            {
                _material = material;
                _color = color;
            }

            public override void Execute(
                ScriptableRenderContext context,
                ref RenderingData renderingData)
            {
                var cmd = CommandBufferPool.Get();
                using (new ProfilingScope(cmd, ProfilingSampler))
                {
                    _material.SetColor(_propertyIdColor, _color);
                    cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity);
                    cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, _material);
                    cmd.SetViewProjectionMatrices(renderingData.cameraData.camera.worldToCameraMatrix, renderingData.cameraData.camera.projectionMatrix);
                }

                context.ExecuteCommandBuffer(cmd);
                CommandBufferPool.Release(cmd);
            }
        }

        /// <summary>
        /// かぶせる色
        /// </summary>
        [SerializeField]
        private Color _color;
        
        /// <summary>
        /// 塗りつぶし用Material
        /// </summary>
        private Material _material;
        
        /// <summary>
        /// 描画パス本体
        /// </summary>
        private Pass _pass;

        public override void Create()
        {
            _material = CoreUtils.CreateEngineMaterial(Shader.Find("Sprites/Default"));
            _pass = new Pass(RenderPassEvent.AfterRenderingPostProcessing);
        }

        public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
        {
            _pass.Setup(_material, _color);
            renderer.EnqueuePass(_pass);
        }

        protected override void Dispose(bool disposing)
        {
            CoreUtils.Destroy(_material);
            base.Dispose(disposing);
        }
    }
}
```

ポイントは

* 前半は描画パス本体、後半はRendererFeature本体
* 描画パス本体は渡されたMaterial,Colorを使って、CommandBufferでRenderingUtils.fullscreenMeshを用いて画面を塗りつぶしています。
* RendererFeatureはSprites/Defaultシェーダを持ったマテリアルを作り、パスに渡し、Disposeで解放処理を行っています
* シェーダは何を使うかを迷いましたが、簡単にColorをブレンドできそうなのでSprites/Defaultを使いました。
    * もしかするともっと相応しいシェーダがあるかもしれません
    * いっそ自分で書いた方が良いかもしれません
        * 私は結局ブレンド処理を選択できるシェーダを自作しました
* RenderPassEvent.AfterRenderingPostProcessingタイミングを指定しているので、カメラ毎に色を重ねることが出来ます
    * なので冒頭のスクショではCameraStackに積んでいるUI側では色の重ね合わせがされていない事が確認できます
    * UIにもかぶせたい場合はRenderPassEvent.AfterRenderingに変更すればいける…はず（未確認）
    * ただ、複数カメラに指定すると色は共有されてしまうかも（未確認）

でしょうか

---
ちょっと画面を色付けしたり、動的に値を変えられるようにすればフェード処理などで使えそうです。
何かオリジナル効果を作る際の叩き台としてご利用ください。