LoginSignup
5
1

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-12-07

image.png
画面の色を変える画面効果を、出来るだけシンプルなカスタムRendererFeatureで実装してみました。

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に変更すればいける…はず(未確認)
    • ただ、複数カメラに指定すると色は共有されてしまうかも(未確認)

でしょうか


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

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1