Deferred Rendering in XNA4.0 Source Code

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)
Deferred Rendering

Anyway, have fun with it.

Edit 22-05-2012: here’s a quick guide on how to add your own content to this sample.

61 Responses to “Deferred Rendering in XNA4.0 Source Code”

  1. xykudyax says:

    Hi there roy, I took a look at the source code and then I realized this is intended to be used for 3D, how could one apply a similar technique for 2D only? Could you please write a post on it? or send me an email with a sample source or explanation?
    Thank you very much,

    Francisco Dias

  2. Hey Francisco,

    I’ve been toying with deferred rendering for 2D, but it doesn’t really make sense since lighting in 2D is a bit of an off thing. Of course it is possible but deferred lighting is overkill :).

  3. Adrin Nic says:

    Why this source is not working on the computer without graphic card ?

  4. Breakfast says:

    Hi!

    First, thanks for this Tutorial !

    We are french student in Video game school and We try to implement this feature in our Student project.

    We have a problems with the skybox. Our skybox dont use the deffered Renderer and it’s drawing before the Scene. It’s only a Box made by our own vertex , and draw with this code :

    EntityManager.GraphicDevice.DepthStencilState = DepthStencilState.Default;
    EntityManager.GraphicDevice.BlendState = BlendState.AlphaBlend;

    SkyWorldMatrix = Matrix.CreateTranslation(_position);
    _device.SetVertexBuffer(vertices);
    _device.Indices = indices;

    skyEffect.Parameters["WVP"].SetValue(SkyWorldMatrix * _view * _projection);
    skyEffect.CurrentTechnique.Passes[0].Apply();

    _device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, number_of_vertices, 0, number_of_indices / 3);

    i think it’s incompatible with the deferred.

    must we managed the Skybox as a 3d model ?

    And how made a shadow map with deferred ?

    Thanks for help !

    Breakfast

    ps : Sorry for my bad english

  5. Hey,

    What exactly is going wrong. Without more info and pictures I can’t be much help. Btw for a quick reply its best to ask these kind of questions at http://gamedev.stackexchange.com and then sent me a link so I can take a look as well :).

  6. Ray says:

    Thank you so much for this revised code for 4.0!

  7. Nifty Systems says:

    Hi Roy and thanks for this !

    Like Breakfast I try to combine deferred with forward renderring, this time for a skysphere. I’m a beginner in deffered technique and I beg your help ;)

    Deffered & forward works fine separatly but only deffered is drawn when i combine both.
    If I’m not wrong the good order is deffered then forward so hardware depth have to be set. But the DEPTH sementic is not used in your renderGBuffer effet, is it the source of my problem ?

    Thanks again, for your tuto and for your help ;)

  8. Hey Nifty,

    You can best render the result of the forward step to an extra buffer and then combine them in your shader. Since Deferred rendering doesn’t directly write to a normal depth-buffer I don’t think you can use the results.

  9. Jan says:

    I disagree on deferred for 2D is overkill, right now it is only viable way in project I am working on. You did great job with rewriting your code for XNA 4.0 and I be most grateful if you could answer few question regarding application in 2D.

  10. Hey Jan,

    You’re right and I am using something that looks a lot like deferred rendering in a 2D project right now. What did you want to know? (For a faster reply you can also try twitter: @roytries)

Leave a Reply