How to allocate a separate render pass and render texture for each object at runtime in URP? (I am trying to render transparent objects.)

Hello Unity community,

Anybody here familiar with customizing URP with the render graph API?

I am implementing a 3D trail renderer. Imagine Unity’s built-in trail renderer, except instead of drawing a strip of triangles that always face the camera, it’s a strip of cylinders.

Here is a good example image of what I hope to achieve:

I know how to procedurally generate meshes; that’s not what I need help with.
What I need help with is preventing overlapping frontfaces from applying the transparency effect twice to the same pixel.

Below is an image of the problem (Cull Back, ZTest On, ZWrite Off):

I will have more than one of these 3D trail renderers at runtime. If two 3D trail renderers overlap, then I want both transparency effects to be applied. But again, if two frontfaces from the same trail renderer overlap, the transparency effect should only be applied once.

The solution I am trying to implement is as follows:

Do a depth prepass for each 3D trail renderer. Later when we go to actually render 3D trails to the screen, we can use the depth texture to cull frontfaces that are occluded by another frontface.

But I have never customized Unity’s render pipeline before in my life.

I am using URP and Unity 6 which uses the render graph API. With some research, I figured out how to add a custom ScriptableRendererFeature and add custom ScriptableRenderPasses. Using a RendererListDesc, I can collect the trail renderers I need to render. But I don’t know how to allocate a separate pass and depth texture for each 3D trail renderer at runtime. How do I do this?

Any help would be appreciated. Thanks.

Hi @slowheii, I think you are on the right track!

Did you have a look at the URP Render Graph samples? You can find them with the package manager when selecting Universal RP as a package, there is a sample tab. Also you have an updated list of Render Graph resources here.

Regarding the actual trail renderer logic, I’m not sure, it might be a bit costly to have one pass per trail if you have a lot of trails in the same frame. But if not, I think I would try first to have a single ScriptableRenderPass where I would loop on the number of trails to add render graph passes (RenderGraph.AddRasterRenderPass) and depth textures ( RenderGraph.CreateTexture) for each of them.

Thank you for the response and links to resources!

After giving a render graph pass read-access to a depth texture using IRasterRenderGraphBuilder.UseTexture(), how do I access this texture in my shader?

I am aware that I can use IRasterRenderGraphBuilder.SetRenderAttachmentDepth() to use the texture as a depth buffer that works automatically with Shaderlab keywords like ZTest, but I’d like to have full control of what is written to my depth texture.

I am writing HLSL, not using Shadergraph.