For context, I’m working on a project which has a style which uses lines drawn in a fullscreen pass. In addition to using depths and normals for outlines I also used an ‘id’ render texture to create “in-lines” on the model. Because it was so central to the look, I decided to modify the existing gbuffer to add a buffer specifically for the id.
So far I’ve had success in adding the buffer, modifying the gbuffer shader code, and adding a new render pass to draw the effect to the screen.
However, I’ve run into the problem where the line effect “smears” across the screen when I move the camera. Using the frame debugger I can see that the buffer has not been cleared. I’ve tried to find where urp submits a command to clear the gbuffers but I haven’t found any. I can see some Clear calls in the frame debugger but besides one who’s RenderTarget is given as _GBuffer2 none of them appear to target the others.
I can see that many scriptable render passes have calls to ConfigureClear but GBufferPass.cs specifically sets the clearflag to none.
So, my question is where can I find this clear operation? In the case that I’m mistaken and there is none, how does the renderer determine which pixels have old data from a previous frame?
I’ve attached two images, the first is what it looks like when I drag a quad while in game mode. The second is what the ID buffer looks like in the frame debugger. Pretty notably, the problem only occurs where the skybox is drawn
Screen in game mode
Buffer in frame debugger
Welp, in the end I just ended up adding another Scriptable Render Pass to clear the gbuffer.
Besides the logic to pass the render target identifier the pass was very simple to set up, just needed a ConfigureTarget and ConfigureClear. Didn’t even need to place anything in Execute(). Still, if I could modify GbufferPass to clear it for me that would be ideal, I figure that it would cut down one SetRenderTarget command.
What I initially missed in the frame debugger was that passes can specify a LoadAction and StoreAction and that the Gbuffer passes use Clear for their LoadAction for Attachment 0 which I believe is gbuffer for albedo + material flags. All that to say that just because there is no “Clear” in the frame debugger doesn’t mean the target in question is never cleared.
I’m having the same problem, thanks for sharing your solution! Can you please share how you are referencing the GBuffer in the clearing Render Pass? I’m not sure what to pass to ConfigureTarget.
It’s been a while since I’ve worked on this project so I can’t say if this will work for the latest version of URP. I was using version 12.0.0. What I did was pass the DeferredLights class to the clear pass through its constructor, then I got the RenderTargetIdentifier from the GbufferAttachmentIdentifiers[ ] and indexed into it using a custom index that I added to DeferredLights. Search for GBufferAlbedoIndex to find where the indices are.
On my end it was only cleared when the pixel had depth. If the pixel was just the skybox since nothing else was drawn over it in the depth buffer, it would not be cleared. All I had to do was check the depth to see if the pixel is sky or not:
float depth = tex2D(_CameraDepthTexture, i.uv);
float isNotSky = -step(depth, 0) + 1;
float4 gbuff2 = tex2D(_GBuffer2, i.uv) * isNotSky;