180 likes | 199 Views
This lecture covers the concepts of forward rendering and deferred rendering in game development, including the use of G-buffers, light volumes, and light quads. It discusses the pros and cons of each approach and explores advanced techniques. The lecture also addresses the challenges of working with many dynamic lights.
E N D
Emerging Technologies for GamesDeferred Rendering CO3303 Week 20
Today’s Lecture • Forward Rendering – Issues • Deferred Rendering – Concept • The G-Buffer • Light Volumes • Light Quads • Ambient & Directional Lights • Pros / Cons • Advanced Approaches
Forward Rendering • Forward Rendering is the name for the method of rendering we have used in all material so far: • Render geometry and light effects on the geometry in a single pass • From mesh to back buffer in one step • To do this we need to know all the lights that affect each particular polygon • Not convenient because lights and geometry are independent • Geometry moves around, the lights might move around differently • The lights affecting geometry are constantly changing • We’ve generally used a brute force solution • Store a global list of lights • Use a shader that renders all lights on all objects • Cost of this naïve approach = Num Objects x Num Lights
Forward Rendering • Try to render this: • Brute force not effective • 100’s of lights • Lots of geometry • Pixel shader far too slow • How to resolve this? • Well, notice the light radiuses are small • Any light only affects local geometry, not whole scene
Forward Rendering • Small light radius and fixed light positions • Majority of lights in a typical scene • Use a spatial partition: • Each partition stores lights that affect it • Geometry only uses lights affecting its own partition • Much smaller number of lights to render in shader • Basis of most forward renderers
Forward Rendering • Here’s a problem: • Small radiuses maybe… • But a huge number in the same place • Dynamic models, makes the partition solution harder • Huge number of lights to render in one place • And yet the background is barely affected • Big variation in shaders needed
Forward Rendering • So another key problem is the pixel shader • Do we write one shader that can handle any number of lights? • Conditional branching will be inefficient • Or one shader for every combination • A shader for 1 point light, another shader for 2, and 3. Then a shader for 1 point and 1 spot light, etc. • Shader explosion, batching problems • In summary Forward Rendering can be effective but: • Need a slow uber-shader, or lots of shaders and batch problems • Doesn’t work well with lots of lights in one place • Or a huge object affected by different lights in different parts • Probably need partitioning scheme for efficiency - more work • Difficult to work with many dynamic lights
Deferred Rendering • Deferred Rendering decouples geometry from lighting • Splits the rendering process into two stages: • First render geometric information without lighting, store this data • Then render the effect of each light in turn, accumulating the result • Idea is to reduce the cost to: Num Objects + Num Lights
G-Buffer • First step is to render the geometry to the g-buffer • G-buffer is several textures holding geometry & surface data Example g-buffer: • Texture 1: Diffuse colour • The basic colour at that pixel • Texture 2: World position • Where the pixel is in the world • Texture 3: World normal • What direction the surface is pointing at that pixel
G-Buffer • A pixel shader can render to several render targets at the same time • So we can build these three textures all in one pass with a special pixel shader • So we start by rendering the scene with fairly standard vertex shaders • With a special MRT pixel shader to fill the g-buffer • Although unusual this pixel shader is quite simple • MRT = Multiple Render Target
G-Buffer • Data in the g-buffer is anything we need to calculate a lit version of the scene • Exact contents are up to us. The typical g-buffer is much more complex than the example given on the previous slide. • In particular, rarely store position as it can be derived from depth • A large g-buffer is a major performance drain • Memory access is slow, cache misses make it worse • So data compression in the g-buffer is common • E.g. Store X & Y of normal, together with a single bit for direction. Calculate Z from this. Faster compared to texture look-up.
Lighting Volumes • The g-buffer is not displayed, it’s data for the next step • Render the actual scene by going through each light and rendering it’s effect on the geometry • Consider a point light, it will light up a sphere around itself • At a certain distance attenuation will reduce the light to almost zero • So to render the effect of a point light, we render a sphere • For each pixel in the sphere, find if it is actually lit up • Use the data in the g-buffer to calculate the amount of light • Use the usual lighting equations • Do this for every light and accumulate = rendered scene
Lighting Volumes / Quads • Same concept works for spotlights • Except they would be bounded by a cone • Don’t need high-poly spheres or cones • These volumes are used only to limit the number of pixels we attempt to light • In fact can just use a bounding quad for each light • A rectangle that covering the area potentially affected by the light • A quad is less polygons to render than a sphere • But a less tight fit, will consider pixels that couldn’t be lit • Calculating the bounding quad has some details • A sphere seen in perspective becomes an ellipse • There’s a method shown in the lab
Bounding Quads Example • A visualisation of the lighting stage • Red: the bounding quads rendered around each light • Bright green: pixels within the quad that actually received any light • Not in a red quad – no lighting needed (*almost none – see later)
Depth • When rendering a light volume or quad, some pixels within the area may too far away or too near - not affected by light • Can use depth to reject pixels that are within the 2D area of the light volume / quad, but are actually far away • With light volumes, use stencil buffer methods to identify the pixels inside • With quads it is easy to reject pixels that are in front, less easy for distant pixels • In practice the work involved can outweigh the advantages Can use stencil buffer to detect pixels inside volumes
Ambient / Directional / Transparency • Ambient light & directional light both affect all pixels • So render these with a full screen quad and g-buffer data • Ambient is very simple, directional not much harder • Can do these two together • Since in most scenes there is only one directional light • Convenient as the first lighting pass • Lay down an initial lighting level for every pixel before accumulating all the point and spot lights on top • On a separate point, note that transparent geometry does not work with standard deferred techniques. • Because the g-buffer only stores the nearest pixel, see through pixels are not accounted for
Pros/Cons of Deferred • Pros: • Lights become very cheap to render • No need for complex partitioning to manage lights • Shaders become simpler, less of them • Better batching performance • G-buffer data can be reused for post-processing • Cons: • Huge g-buffer can be a slow down • G-buffer compression to counter this reduces material flexibility • Transparent objects don’t work, must be rendered separately • MSAA becomes very difficult due to g-buffer • Not actually particularly useful in some scenes (daylight) • More advanced techniques are getting very complex
Advanced Approaches • This has been a very brief overview of the topic • There are many complexities to consider, and variations on the approach • Most notable variants: • Light Pre-pass: Only store normals, use to calculate lighting only. Render a second geometry pass to combine lighting with materials. Reduces g-buffer size • Light Indexed: Lighting pass stores a light ID only per-pixel, second geometry pass can look up exactly what lights affect a pixel. A mix of forward and deferred. • Tiled (popular now): Split screen into tiles, for each tile find the intersecting light volumes. Calculate the lighting for all these lights on one tile simultaneously.