I’m posting this to discuss the merits and potential of deferred rendering systems as I believe there is a lot of confusion over the matter as well as a lot of “Well how can I accomplish this like I did using traditional forward rendering?” questions.
Deferred Rendering
What is it?
Deferred rendering is where we draw or render the geometry of a scene and then save that geometry data in memory so that lighting calculations can be applied after ALL of the geometry has been generated (we ‘defer’ or ‘hold off’ on the lighting calculations). Variations do exist where this may be accomplished in a different number of steps, where geometry data is stored differently or where different methods of using this data to light the scene are used.
How is it different?
Forward Rendering (used in around 95% of all games) is where we generate our geometry, immediately convert that geometry into pixels and then apply lighting calculations to each pixel. Forward Rendering provides no control over the order in which each pixel is lit and so your shader code can never be aware of adjacent pixels or geometry; amongst other limitations, this makes efficiently filtering out if a pixel should be shaded or not very difficult. As Deferred Rendering provides what is essentially an image of the front most geometry (geometry that isn’t hidden by closer objects) we have quickly narrowed down all visible polygons and as we have the geometrical data of these polygons stored in a ‘geometry buffer’, we can simply check their 3d locations against the volume coverage of a light source (which can be hardware accelerated using the stencil buffer). Compared to Single-Pass Forward Rendering, Deferred Rendering allows us to shade only the pixels that require shading and not pixels that will later be discarded using efficient shader code. In the case of Multi-Pass Forward Rendering, Deferred Rendering allows us to shade only pixels that will not later be hidden by other geometry or appear outside the user’s viewport (field of vision), it also prevents us from having to recalculate our geometry for each individual light source.
Why has it not been adopted on a mass scale?
- Deferred Rendering is difficult to implement. Some companies will have determined that it may be more effective to stick with known approaches to programming their games to reduce cost and/or development time.
- Traditional Anti-Aliasing (the removal of jagged edges) was not compatible with this method.
- You could not use the same quick filtering method to calculate shadows, as objects that can cast shadows may have been outside of the geometry buffer.
- Requires more graphical memory to store the extra information as well as high memory bandwidth to access this information.
- Partly due to reason 4 and also due to the hardware configuration of graphics cards, deferred rendering struggled to provide the performance that was expected of it.
Why is NOW the time to consider its use? (how have the hurdles from the above limitations been overcome)
- Deferred rendering is still difficult to implement, however, improved documentation and examples are now available on the internet. New OpenGL extensions and new shader capabilities have made it possible to more directly implement the technology with far less program workarounds being required.
- New methods of performing Anti-Aliasing on deferred rendering framebuffers have been documented. The ability to now store geometry data in textures has allowed for hardware acceleration of many filtering effects that can be used to improve the overall image.
- Shadows can be calculated by redrawing the geometry from the point of view of each light source onto a texture and then mapping (transforming) that texture to the angle seen by the user. You may think that this would defeat the objective of deferred rendering, however, using hardware acceleration called early z-culling (which has improved greatly in the latest generation of graphics cards), you can calculate visible geometry very quickly with the limitation of being unable to shade it, which we don’t require for shadowing.
- Graphics cards now have much more memory with much more bandwidth to that memory available. The use of more advanced compression can also be used in certain situations.
- The hardware of graphics cards is now much more flexible and can be maximised for use with deferred rendering. Shader Model 4.0 has provided us with unified shaders. Previous graphics cards were designed purely for forward rendering; as such they had an allocation of a shader units that could only perform vertex (simple geometry) calculations and units that could only perform pixel (lighting) calculations. This was fine when geometry data was always passed immediately through from the vertex shaders to be rendered by the pixel shaders, however, as deferred rendering has stages where only vertex calculations are being used and stages where only lighting calculations were ran, a large amount of graphical power was wasted. Unified shaders allow the graphics card to use all of its shading units for just vertices and then reassign them just for pixel shading, allowing deferred rendering to make full use of a graphics card’s processing power.
On another note. Shader Model 4.0 graphics cards from nVidia and ATI offer the ability to break away from the shader unit model and perform much more flexible calculations. Provided with the geometry data generated by the deferred rendering system, this can allow for the possibility of several advanced lighting techniques to be considered.
I hope the information I’ve provided here can help shine a light on the merits of deferred rendering. Good look in your implementation.