【Unity】ShaderGraphで使用できる半透明オブジェクト含む背景テクスチャ_CameraTransparentTextureを作成、表示できるパスを追加する(URP14版)

はじめに

bravememo.hatenablog.com

これのURP14版のやり方を紹介します

環境は Unity 2022.2です

コード

下記クラスを作成したら前の記事のようにRendererFeatureに登録すれば_CameraTransparentTextureを使用することができます

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

namespace UnityEngine.Rendering.Universal.Internal
{
    public class TransparentRendererFeature : ScriptableRendererFeature
    {
        private CopyTransparentPass _copyTransparentPass = null;//パス
        public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingTransparents;//レンダリングタイミング
        public Downsampling downsampling;//解像度指定
        private string textureName = "_CameraTransparentTexture";//テクスチャの名前

        /// <summary>
        /// パス生成
        /// </summary>
        public override void Create()
        {
            _copyTransparentPass = new CopyTransparentPass(renderPassEvent, Shader.PropertyToID(textureName),downsampling);
        }
        /// <summary>
        /// レンダーターゲットが初期化後の処理
        /// </summary>
        /// <param name="renderer"></param>
        /// <param name="renderingData"></param>
        public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
        {
            //カメラの描画情報を送る
            _copyTransparentPass.SetRenderTarget(renderingData.cameraData.renderer.cameraColorTargetHandle);
        }
        /// <summary>
        /// パス登録する
        /// </summary>
        /// <param name="renderer"></param>
        /// <param name="renderingData"></param>
        public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
        {
            //パスを実行できるようにする
             renderer.EnqueuePass(_copyTransparentPass);
        }
    }
}

using UnityEngine.Experimental.Rendering;
using  UnityEngine.Rendering.Universal;

namespace UnityEngine.Rendering.Universal.Internal
{
    /// <summary>
    /// 半透明を含むカメラの描画結果をグローバルテクスチャに設定するためのパス
    /// </summary>
    public class CopyTransparentPass : ScriptableRenderPass
    {
        const string m_ProfilerTag = "TestPass";//FrameDebuggerで表示される名前
        private int TextueID = 0;
        private Downsampling downsampling;
        
        private RTHandle  cameraColorTarget;//コピー元(カメラの描画結果)
        private RTHandle  testTarget;//コピー先

        public CopyTransparentPass(RenderPassEvent evt, int id, Downsampling sampling)
        {
            renderPassEvent = evt;
            TextueID = id;
            downsampling = sampling;
        }

        public void SetRenderTarget(RTHandle target)
        {
            cameraColorTarget = target;
        }

        /// <summary>
        /// レンダリング前の処理
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="cameraTextureDescripor"></param>
        public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescripor)
        {
            //解像度を下げる
            var down = downsampling switch
            {
                Downsampling._2xBilinear => 2,
                Downsampling._4xBilinear => 4,
                Downsampling._4xBox => 4,
                _ => 1
            };
            cameraTextureDescripor.width /= down;
            cameraTextureDescripor.height /= down;
            //depthとStencilは使用しないので無効にする これをしないと正常に描画がされない
            cameraTextureDescripor.depthStencilFormat = GraphicsFormat.None;
            //テクスチャ生成 AllocではなくReAllocateIfNeededを使用してRTHandleがテクスチャを確保していた場合にテクスチャを自動で解放します
            RenderingUtils.ReAllocateIfNeeded(ref testTarget, cameraTextureDescripor , name: "Test");

        }

        /// <summary>
        /// 描画処理
        /// </summary>
        /// <param name="context"></param>
        /// <param name="renderingData"></param>
        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            //シーンでの描画は省く
            if (renderingData.cameraData.camera.cameraType != CameraType.Game)
            {
               return;
            }
            //カメラの描画がうまく設定されてないときは省く
            if (cameraColorTarget == null || string.IsNullOrEmpty(cameraColorTarget.name))
            {
                return;
            }
             //バイリニアフィルタリングを使用するか
            bool bilinear = downsampling == Downsampling._2xBilinear || downsampling == Downsampling._4xBilinear;
            CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
            //描画 コピー先レンダーテクスチャにコピーする
            Blitter.BlitCameraTexture(cmd,cameraColorTarget,testTarget,0,bilinear);
            //コピーしたテクスチャをグローバルテクスチャとして設定する
            cmd.SetGlobalTexture(TextueID,testTarget);
            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
        }
    }
}

depthStencilFormat を設定しないとうまく描画されないのですが原因がいまいちわかりません...