[Custom Render Pipeline] How do I render to a RT instead of the camera RT?

I’m working on a custom render pipeline, I’ve made a separate override material with a shader that outputs depth only, and when I call ScriptableRenderContext.DrawRenderers() it displays correctly in game. What I want to do is to store the value in a RenderTexture or something, do post-process, and composite the final image onto the camera. How can I do this?

Call CommandBuffer.SetRenderTarget before drawing your meshes to set the active render texture.

I’m currently drawing using ScriptableRenderContext.DrawRenderers(). So does Setting RenderTarget on any CommandBuffer make DrawRenderers() use that RT?

Something like this:

        RenderTexture colorTarget = new RenderTexture(1024, 1024, 0, RenderTextureFormat.ARGBHalf);
        RenderTexture depthTarget = new RenderTexture(1024, 1024, 24, RenderTextureFormat.Depth);
        CommandBuffer commandBuffer = new CommandBuffer();

        void Render(ScriptableRenderContext srpContext)
        {
            commandBuffer.SetRenderTarget(colorTarget, depthTarget);
            srpContext.ExecuteCommandBuffer(commandBuffer);
            commandBuffer.Clear();

            srpContext.DrawRenderers();
        }

I recommend you go through CatLikeCoding tutorials for scriptable render pipeline, it helped me a ton when I started:
https://catlikecoding.com/unity/tutorials/scriptable-render-pipeline/

3 Likes

Thanks for the response. I’m following the catlikecoding tuts, because AFAIK there isn’t any other resource. I’d just like to clarify a few things which I might be thinking of incorrectly:

What I think: Each CommandBuffer object points to one RenderTarget which is not related to the default screen RenderTarget. All the methods executed on this CommandBuffer just affects that pointed-to RenderTarget (color/depth) when executed. But Context.DrawRenderers() automatically executes on the default screen RenderTarget, which may or may not be the CommandBuffer target.

If this is not correct, please do let me know, I’d appreciate it.

Command buffers dont point to anything, its just a list of command that will be added to the stack of command that will later be executed by the unity renderer.

In my first example, there is two commands being generated in this order:

SetRenderTarget()
DrawRenderers()

By default unity set the render target to the camera target (which is what is shown on your screen).

If you want to target the screen again later, you need to call this:

CommandBuffer.SetRenderTarget(BuiltinRenderTextureType.CameraTarget);

After that, every draw call you will make will draw to the screen again.

Further example:

        RenderTexture colorTarget = new RenderTexture(1024, 1024, 0, RenderTextureFormat.ARGBHalf);
        RenderTexture depthTarget = new RenderTexture(1024, 1024, 24, RenderTextureFormat.Depth);
        CommandBuffer commandBuffer = new CommandBuffer();

        void Render(ScriptableRenderContext srpContext)
        {
            // Set the target to a render texture
            commandBuffer.SetRenderTarget(colorTarget, depthTarget);
            srpContext.ExecuteCommandBuffer(commandBuffer);
            commandBuffer.Clear();

            // Draw renderers to a texture
            srpContext.DrawRenderers(...);

            // Set the target to the screen
            commandBuffer.SetRenderTarget(BuiltinRenderTextureType.CameraTarget);

            // Set the input texture for post processing
            commandBuffer.SetGlobalTexture("_RenderedScenesTexture", colorTarget);

            // Configure the full screen quad for the post process...

            // Draw the full screen quad for the post process
            commandBuffer.DrawMesh(...);
            srpContext.ExecuteCommandBuffer(commandBuffer);
            commandBuffer.Clear();

            // This will submit all the commands to the unity renderer
            srpContext.Submit();
        }
4 Likes

hi, what I’m trying to do is just like the example, but I cannot make the later drawcalls render to the screen. I used a DrawRenderers after setting the render target back to CameraTarget. What could possibly be wrong? Thanks.