XNA Tutorials, Samples and Thoughts
Restoring the Depth Buffer
A long time ago, when I wrote the Deferred Rendering article, in the last chapter I mentioned adding transparent objects to the rendering pipeline. To do that, we would need to restore the depth buffer, as if the objects in the scene were there. This information was lost when we began applying the different passes of deferred rendering.
In this month’s sample, I’ll show you how to restore the depth buffer, using the information stored inside a depth texture.
To make an example out of this, the sample does the following things:
- Render a ship on the scene, once on a render target that holds the color, and once on a render target that holds depth information
- Apply post processing effects on the color texture. In this sample, I simply blur the image a little, and add sepia
- Restore the color information into the back buffer, and restore depth values into the depth buffer
- Draw another ship
If at step 3, we would only restore the color information, the resulting image would have incorrect object intersections. When doing post processing on the initial scene, we lose all depth information, so the ship drawn at step 4 would appear in front of everything else
By restoring the depth buffer also, we can see how parts of the post processed image that should appear in front of the ship drawn at step 4 actually appear in front of it.
To achieve this, we used the DEPTH pixel shader output semantic. This semantic is used in a pixel shader to write a specific value to the depth buffer. By taking this values from the depth texture generated at step 1, you can actually restore the contents of the depth buffer. The shader code that does this can be found in RestoreBuffers.fx.
void RestoreBuffersPixelShader(in float2 texCoord : TEXCOORD0,
out float4 color: COLOR0,
out float depth : DEPTH)
{
//write the color
color = tex2D(ColorSampler, texCoord);
//write the depth
depth = tex2D(DepthSampler, texCoord).r;
}
When running the sample, use the R keyboard key to toggle the restoration of the depth buffer, and the P key to toggle post processing.
The sample is written in 3.0 CTP, but the technique works just as well in 2.0
The sample can be downloaded here: DepthRecovery.zip

about 3 years ago
Hey,
I see you have a full blown sample about the question i asked last week. Nice!
I solved my problem by the way!
Regards,
Ted
about 3 years ago
Nice example! One quick note. When sampling from a texture containing items such as depth, etc., you’ll want to use POINT sampling and not LINEAR.
about 3 years ago
You’re right. But when the texture is the exact same size as the destination, it makes little to no difference, as long as the texels are properly aligned.
But indeed, POINT would probably be better.
about 2 years ago
Hi Catalin,
Let me start off by saying that you saved me! I am currently implementing your Deferred Renderer together with XNA’s XML Particles sample and this tutorial helped me a lot to place the particles correctly in the scene instead of on top of the scene.
I just have a question though. Upon using the RestoreBuffers method in your sample and supplying the combined scene render target instead of “sceneRT”, I am getting some black border artifacts. Do I still need to do some texel offsetting in the RestoreBuffer.fx shader?
about 2 years ago
You shouldn’t need to, since SpriteBatch takes care of aligning pixels to texels.
Do the black borders appear all around, or only on some edges (left and top) ?
about 2 years ago
Only the left and top. I tried to modify the offsets in the Combine Final shader. Instead of subtracting the offset, I added the offset. Adding 3 times the halfpixel offset seemed to remove the border problem but now the render seems to be a bit blurry, probably 1 to 2 pixels of blur.
about 2 years ago
Try and use POINT sampling when reading from the depth/color textures, and see if it solves anything.
about 2 years ago
Ok thanks. Thank you for the quick reply. I’m still at the office, so it’ll be sometime until I can try it out at home. If things don’t go well, I’ll start a thread in the Creator Club forums and place in full details there. Thanks again.
about 11 months ago
Thanks very much for the sample, just what I was looking for.
For anyone interested, I converted the project to XNA4 and uploaded it here: http://www.2shared.com/file/7hQ8ux90/RestoreDepthBufferXNA4.html?
about 7 months ago
@Linchy : Line 69 in Game1.cs should be
depthRT = new RenderTarget2D(GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight, false, SurfaceFormat.Single, DepthFormat.Depth24);
The modification is assigning a depth buffer instead of none, it’s still useful during the depth writing pass.