How to create a grab pass in RenderGraph in URP

So I tried creating a kind of grab pass after opaques by copying the color target and setting the texture with the copied content as a global variable using RenderGraph, but it does not seem to work. The global texture seems to never be set. What am I missing?

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.RenderGraphModule.Util;
using UnityEngine.Rendering.Universal;

public class GrabPassFeature : ScriptableRendererFeature
{
    class GrabPassRenderPass : ScriptableRenderPass
    {
        const string PassName = "GrabPass";

        private int globalTextureID = Shader.PropertyToID("_GrabPassTexture");

        public class PassData { }
        
        public GrabPassRenderPass()
        {
            requiresIntermediateTexture = true;
        }
        
        public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
        {
            // UniversalResourceData contains all the texture handles used by the renderer, including the active color and depth textures
            // The active color and depth textures are the main color and depth buffers that the camera renders into
            UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();

            // The destination texture is created here, 
            // the texture is created with the same dimensions as the active color texture
            var source = resourceData.activeColorTexture;

            var destinationDesc = renderGraph.GetTextureDesc(source);
            destinationDesc.name = $"CameraColor-{PassName}";
            destinationDesc.clearBuffer = false;

            TextureHandle destination = renderGraph.CreateTexture(destinationDesc);  
           
            if (RenderGraphUtils.CanAddCopyPassMSAA())
            {
                var copyName = PassName + "_Copy";
                
                // This simple pass copies the active color texture to a new texture. 
                renderGraph.AddCopyPass(resourceData.activeColorTexture, destination, passName: copyName);
                
                var setGlobalName = PassName + "_SetGlobal";
                using (var builder = renderGraph.AddRasterRenderPass<PassData>(setGlobalName, out var passData)){

                    // Set a texture to the global texture
                    builder.SetGlobalTextureAfterPass(destination, globalTextureID);
                    
                    builder.SetRenderFunc((PassData data, RasterGraphContext context) => { });
                }
            }
            else
            {
                Debug.Log("Can't add the copy pass due to MSAA");
            }
        }
    }
    
    GrabPassRenderPass grabPassRenderPass;

    public override void Create()
    {
        grabPassRenderPass = new GrabPassRenderPass();
        grabPassRenderPass.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderer.EnqueuePass(grabPassRenderPass);
    }
}

Have you checked to see if your passe that set the global texture might be getting culled?
Do you see any difference if you throw a builder.AllowPassCulling(false); in there?

It seems to be the solution, thanks!

unity has the same texture “_CameraOpaqueTexture” after “RenderPassEvent.AfterRenderingOpaques”

Oh alright, I don’t get how I missed this, but thanks a lot!

Hello.
Because i was a searching a script to allow to have “scene color” after a postprocessing and i couldn’t make this script work (error “execute is not implemented” , i found this after and it works on unity 6 for those who search also that : GitHub - Smajlovycc/GrabPassU6: URP Custom Grab Pass / Grab Screen Feature for Unity 6