Deferred Rendering in XNA4.0 Source Code
Posted by Roy Triesscheijn on December 28th, 2010
Lately I’ve been very interested in ‘the 3D stuff’. And because of this I’ve been reading into Deferred Rendering.
Catalin Zima explaind deferred rendering very nicely, by comparing it to traditional rendering methods:
In the Single-Pass lighting method, each object is rendered, and all lights affecting that object are computer in one shader. [snip]. Since everything is done in a single shader, which has a limited instruction count, this technique is only suitable for a small number of lights [snip]. In some games, which only need a small number of lights, such as an outdoor daytime environment, this may prove to be a good choice. The disadvantages of this technique are the small number of lights, and the fact that shading operations may be wasted on surfaces which will be hidden in the final image.
Another method is the Multi-Pass lighting. Here, for each light, objects which are affected by the light are drawn with the current light’s shader. This causes a very high batch count (number of individual Draw calls), which in the worst case is equal to the number of lights multiplied by the number of objects. The problem of shading hidden surfaces still remains. And some operations are repeated many times each frame, such as vertex transformations.
Deferred Shading approaches the problem in a different manner. First, all objects are rendered without lighting computations. Instead, the objects output a set of attributes for each drawn pixel, such as position, normal, specular intensity, etc. After this, each light is applied on the final image as a 2D post process, using the data written in the previous pass. Because all objects use the same shader (the one which outputs the attributes), the engine management is greatly simplified. We no longed need to sort the scene objects based on the material they use. The number of draw calls is reduced to the number of objects + number of lights. Moreover, lighting calculations will only be done for visible pixels (the ones that make it into the final image).
Catalin has an excellent tutorial on deferred rendering, unfortunately some of the code no longer works, because it was written for XNA2.0.
Fortunately (for you) I’ve converted the entire code base to XNA4.0 as a learning exercise.
The code is a bit shorter now, (especially setting effects is so much easier in XNA4). And thus should be slightly easier to understand. The code includes everything that Catalin’s original source code examples included. The camera can be moved using the keyboard (arrows, or w-a-s-d to move, z and x to zoom) or using the Xbox controller.
The source code can be downloaded here: http://www.roy-t.nl/files/DeferredLightingXNA4.rar
As a little benchmarking tool, I’ve already turned of VSync and FixedTimeStep for you. On my modest machine (AMD Athlon GP9400 Quad Core, 4GB ram, and an AMD HD4850) I could easily render 600 lights at 60fps+. (However this looks ugly). The default settings (103 lights) runs at 380~400 fps.
Here’s a screen-shot how it should look (again by Catalin Zima)

Anyway, have fun with it.

December 28th, 2010 at 6:01 PM
[...] You can read all about it on Roy’s blog, here. [...]
January 1st, 2011 at 6:40 PM
thanks for this, been waiting for someone to release a deferred rendering sample for XNA 4
January 2nd, 2011 at 3:05 AM
[...] Deferred Rendering – Roy Triesscheijn updated Catalin Zima Tutorial to XNA 4.0 [...]
January 2nd, 2011 at 4:21 AM
Nice work Roy,
I was going to convert this tutorial too. LOL
I’ve added to this page to the XDSK2, deferred rendering is extremely useful.
BTW, I’m sure you’re already pretty familiar with XNA 4.0 but if you need a cheat sheet converting XNA 3.1 to XNA 4.0,
I created one on my website. XNA 3.1 to XNA 4.0 Cheat Sheet
January 2nd, 2011 at 10:00 AM
@Proof
Thanks for your comment
.
@Nelxon
Ah seems like I beat you too it. Thanks for adding this to the XDSK2 aswell! I got quite a few tutorials/code samples on there now
. I wish I found out earlier about your cheat sheet btw! Quite a few handy things on there!
January 10th, 2011 at 7:04 PM
Oh damn, I just finished porting the code about a week before this was posted. Well, it was a good learning exercise.
January 12th, 2011 at 8:32 AM
Ah yes, and that’s what really matters, I’m sure you understand the code much better now than if you would’ve just c/p’d this code instead.
January 21st, 2011 at 1:05 AM
[...] new code has been developed by Roy Triesscheijn , a computer science student, which has released it in the open source [...]
February 15th, 2011 at 11:32 AM
Great, saves me the trouble
I’ll be digging through this to (hopelly) finally finish a proper deferred decal renderer…
The original tutorial was a great resource, I only did snippets of it, but I’ll be doing the whole thing again soon to soak up as much as possible
Too bad the tutorial itself is still 3.1
February 15th, 2011 at 5:48 PM
Don’t worry about the tutorial being old, it’s mostly syntax that changed all the techniques still apply and the shader code is 100% the same.
April 4th, 2011 at 7:05 AM
You’re the good man, thank you.
June 17th, 2011 at 6:41 PM
Thanks for the updated tutorial. I am trying to follow the orginal tutorial through to understand what is going however I can’t seem to draw the render targets out to see what the gbuffer contains.
spriteBatch.Draw(colorRT, new Rectangle(0, 0, halfWidth, halfHeight), Color.White);
spriteBatch.Draw(normalRT, new Rectangle(0, halfHeight, halfWidth, halfHeight), Color.White);
spriteBatch.Draw(depthRT, new Rectangle(halfWidth, 0, halfWidth, halfHeight), Color.White);
I get the error “XNA Framework HiDef profile requires TextureFilter to be Point when using texture format Single.”
June 19th, 2011 at 4:01 PM
Hey Jack,
In order to directly view the rendertargets on screen you need to begin the spritebatch using the overload to set the correct device state. Try this SpriteBatch.Begin overload: http://msdn.microsoft.com/en-us/library/ff433699.aspx and use SamplerState.Point for the sampler state and it should work.
July 3rd, 2011 at 4:39 PM
Hi Roy,
thanks for the code. Just completed the conversion myself, hehe.
About the number of Lights I can draw.. I can draw, with your code, amazing 2003 lights at around 25-30 fps. Counting in shadows and SSAO, it would probably be a lot less, but still more than with the old way. Thanks again,
Nameless One
August 31st, 2011 at 3:37 PM
Hello,
When I run this code on my computer, I get artifacts at the edges of objects that are lit by point lights. The artifacts are interleaving dark and brighter stripes. Do you know why this happens and if so can it be fixed?
best
Magnus
September 3rd, 2011 at 8:03 PM
Hey Magnus, without further info I wouldn’t know why. What kind of graphics card do you have? Might it be an Intel? They don’t support the more advanced features of DirectX very well.
September 8th, 2011 at 3:15 PM
Hi Roy
I’m having the same problem on my pc, i.e. artifacts that are dark and brighter stripes all over.
My graphics card is an Nvidia 9600GT, so not brand new, but not too shabby.
Here’s a link to a screenshot of a test scene rendered with the deferred renderer.
Do you have any ideas of what could be the problem?
Thanks
Christel
September 8th, 2011 at 3:17 PM
sorry about that here are the links properly:
Test Scene Screenshot 1
Test Scene Screenshot 2
September 11th, 2011 at 8:31 PM
Hey Christel,
Could you also send me artifacts of how the light-map looks? Instead of displaying the final step on screen try using a spritebatch to display all buffers on screen (light, geometry, etc..) so that I can compare where the problem is. It does look light related, but I haven’t encountered this myself.
September 16th, 2011 at 9:27 PM
Maybe it has to do something with the normals? the black lines are aligned to vertices, not to screenspace dimensions
September 22nd, 2011 at 6:19 PM
@Christiel It does look like a problem with the normals. Also it reminds me of per-vertex lighting interpolation which is odd given that all this happens in the pixel shader. Are your meshes made up of many rows of triangles?
October 4th, 2011 at 8:39 AM
Sorry for taking so long to reply… I found my problem… seems I made a mistake and set the Surface Format of the Depth Buffer to Color instead of Single, changed that and it works perfectly now
October 4th, 2011 at 6:02 PM
In case anyone else has the problem:
When I ran this on the Xbox (simply made a xbox 360 copy of the deferred lighting project), I got some annoying flashing blue lines at the top of the screen. Looking closer, I realized that the lines were in fact cornflower blue – and after removing the GraphicsDevice.Clear(Color.CornflowerBlue) in Game1.cs, the problem disappeared. Guess you shouldn’t clear the screen twice, and that the Xbox is more picky about that.
October 11th, 2011 at 12:19 AM
This is good. Really good. Got it running using my own house model and it looks very spooky and atmospheric, just what I wanted. I was using basiceffect which lit every face of the model. How do I add ambient light to the example so I can see in the dark corners of my rooms? I guess it’s sumfink to do wiv shaders
October 11th, 2011 at 2:36 PM
I changed DeferredRenderer.cs to display only a single point light, to see
what was going on. I added some code for ambient light in CombineFinal.fx, however, it is now making the black areas less black. Presumably I need to apply the ambient to the texture not the black pixel. Any ideas?
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
float3 diffuseColor = tex2D(colorSampler,input.TexCoord).rgb;
float4 light = tex2D(lightSampler,input.TexCoord);
float3 diffuseLight = light.rgb;
float specularLight = light.a;
return float4((AmbientColor * AmbientIntensity)+(diffuseColor * diffuseLight + specularLight),1);
}
January 16th, 2012 at 3:12 PM
[...] [...]
January 25th, 2012 at 12:47 PM
[...] and “null_specular.tga”. You’ll need to extract these from Roy’s and add them to your “ProjectVanquishContent” [...]
February 9th, 2012 at 4:17 PM
Please send me the steps in creating an anaglyph and also the source code of your software
February 13th, 2012 at 6:18 PM
Hey Natarajan,
The anaglyph tutorial (with some source code) is here http://roy-t.nl/index.php/2011/05/08/xna-stereoscopic-3d-using-anyglyphs-and-redcyan-3d-glasses/