I’m trying to render, in order the following:
- OPAQUE mesh (terrain)
- TRANSPARENT blob shadows
- OPAQUE props (trees and such)
- TRANSPARENT fog
Every step is a “Render Objects” step in my forward renderer. Step 2. and 4 need to have access to the depth that was written in step 1 and 3, respectively. What should the render events be for these individual steps?
Constraints:
- I want to render these things in the order above.
- In 2, I need the depth as it just was just after 1.
- In 4, I need the depth as it just was just after 3.
I’ve been trying to get this to work for the last few days, but the results I’m getting do not make any sense. I’m either not getting the right depth buffer, or an outdated one.
I’ve build a test case to explore what’s going on.

The plane is (1), opaque geometry.
The blue quad is (2), transparent and visualizing depth.
The opaque cube is (3) and the red quad is (4).
Let’s go:
Test case A
We’ll make sure our forward renderer doesn’t render anything, except though our own custom ‘render objects’ features. For the event, we’ll choose ‘AfterRenderingOpaques’ for now, which is the default Unity suggest. Click here to see the render pipeline:
Our things will now be rendered in the correct order (1, 2, 3, 4), but we quickly see that something goes wrong. When rendering (2), the transparent blue quad, it takes its depth from _CameraDepthTexture, which somehow has depth info, even from the cube in (3)! This mysterious depths comes, I think, from the last frame.
So what has happened here? At AfterRenderingOpaques, which is when we execute step 2, Unity has not yet populated _CameraDepthTexture for the CURRENT frame (this happens later, at the green arrow). We’ll need our depth from (1) in _CameraDepthTexture before we start rendering step 2.
We now have two options. The first option is to let Unity handle that for us. We’ll just start rendering (2) after unity has written to _CameraDepthTexture, which will be somewhere between the end op the opaque queue and the start of the transparent queue. So we keep step 1 in AfterRenderingOpaques, but bump step 2 to BeforeRenderingTransparents.
However, this solution does not scale. We can do this once, but we’ll need another update of _CameraDepthTexture between steps 3 and 4. Where would these then go?
So that leaves us with the only other option we have: manually copy over the depth to just before we need it.
Test case B
We’ll create a custom render feature like so (C# script on pastebin): CopyDepthRenderFeature - Pastebin.com
At least, that’s how I think it should look like.
This will allow us to use Unity’s inbuilt shader for copying over the depth texture whenever we want. We’ll then add these copy-features between steps 1 and 2.
The renderer now looks like this (click to expand):
And the result looks very promising! As we can see, there’s no leftover depth from the ‘previous’ frame, and we’re using depth as it is after step 1.
BUT!
Now things are becoming really spooky. Don’t continue reading if you’re easily scared.
Even through step 2 has depth from just after (1), it still seems to be lagging a frame behind! We can see this become apparent when we move the camera quickly!
[see image in reply because of 5-image upload limit]
This would suggest that the frames would be doing some sort of interlacing dance:
-
Frame 1 step 1: write depth
-
Frame 1 step 2: ???
-
Frame 1 step 3: write depth
-
Frame 1 step 4: ???
-
Frame 2 step 1: write depth
-
Frame 2 step 2: read depth as it was in FRAME 1, STEP 1
-
Frame 2 step 3: write depth
-
Frame 2 step 4: read depth as it was in FRAME 1, STEP 3
I’m getting this effect consistently, and it doesn’t matter whether I use ‘BeforeRenderingOpaques’, ‘AfterRenderingOpaques’, ‘BeforeRenderingTransparents’ or ‘AfterRenderingTransparents’.
What boggles my mind is that:
- Depth is read ‘from’ the correct stage within the frame, but still lagging at least 1 full frame!
- Adding another depth copy between step 3 and 4 seems to makes the lag WORSE
Note that this lag becomes more than just a nuisance; it fully brakes down visually in depth sensitive situation, such as smoothly zooming, as demonstrated in this thread .
This test case built from a clean Unity project (version 2020.3.3 LTS) and can be downloaded HERE (be sure to open SampleScene.unity).
In short, my question is: what causes this lag, and how can I prevent it?
- Am I getting data from an old buffer instead of the latest?
- Am I not using the right input/output for my copy operation?
- Is there some sort of process interfering?
I’m running out of ideas, so any help is very much appreciated.
Thanks!





