Rendering Pipeline Details
Forward Rendering Path Details

Deferred Shading Rendering Path

This page details the Deferred Shading rendering path. See the wikipedia page for an introductory technical overview.

Visión General

When using Deferred Shading, there is no limit on the number of lights that can affect an object. All lights are evaluated per-pixel, which means that they all interact correctly with normal maps, etc. Additionally, all lights can have cookies and shadows.

Deferred shading has the advantage that the processing overhead of lighting is proportional to the number of pixels the light shines on. This is determined by the size of the light volume in the scene regardless of how many objects it illuminates. Therefore, performance can be improved by keeping lights small. Deferred shading also has highly consistent and predictable behaviour. The effect of each light is computed per-pixel, so there are no lighting computations that break down on large triangles.

On the downside, deferred shading has no real support for anti-aliasing and can’t handle semi-transparent objects (these will be rendered using forward rendering). There is also no support for the Mesh Renderer’s Receive Shadows flag and culling masks are only supported in a limited way. You can only use up to four culling masks. That is, your culling layer mask must at least contain all layers minus four arbitrary layers, so 28 of the 32 layers must be set. Otherwise you will get graphical artefacts.

Requirements

It requires a graphics card with Multiple Render Targets (MRT), Shader Model 3.0 (or later), support for Depth render textures and two-sided stencil buffers. Most PC graphics cards made after 2006 support deferred shading, including GeForce 8xxx and later, Radeon X2400 and later, Intel G45+ and later. On mobile, support is much more limited due to MRT formats used (some GPUs which do support multiple render targets, still only support very limited bit counts).

Note: Deferred rendering is not supported when using Orthographic projection. If the camera’s projection mode is set to Orthographic, these values are overridden, and the camera will always use Forward rendering.

Performance Considerations

The rendering overhead of realtime lights in deferred shading is proportional to the number of pixels illuminated by the light and not dependent on scene complexity. So small point or spot lights are very cheap to render and if they are fully or partially occluded by scene objects then they are even cheaper.

Of course, lights with shadows are much more expensive than lights without shadows. In deferred shading, shadow-casting objects still need to be rendered once or more for each shadow-casting light. Furthermore, the lighting shader that applies shadows has a higher rendering overhead than the one used when shadows are disabled.

Implementation Details

When Deferred Shading is used, the rendering process in Unity happens in two passes:

  1. G-buffer Pass: objects are rendered to produce screen-space buffers with diffuse color, specular color, smoothness, world space normal, emission and depth.
  2. Lighting pass: the previously generated buffers are used to add lighting into emission buffer.

Objects with shaders that can’t handle deferred shading are rendered after this process is complete, using the forward rendering path.

The default g-buffer layout is as follows:

  • RT0, ARGB32 format: Diffuse color (RGB), occlusion (A).
  • RT1, ARGB32 format: Specular color (RGB), roughness (A).
  • RT2, ARGB2101010 format: World space normal (RGB), unused (A).
  • RT3, ARGB2101010 (non-HDR) or ARGBHalf (HDR) format: Emission + lighting + lightmaps + reflection probes buffer.
  • Depth+Stencil buffer.

So the default g-buffer layout is 160 bits/pixel (non-HDR) or 192 bits/pixel (HDR).

Emission+lighting buffer (RT3) is logarithmically encoded to provide greater dynamic range than is usually possible with an ARGB32 texture, when camera is not using HDR.

Note that when the camera is using HDR rendering, then there’s no separate render target being created for Emission+lighting buffer (RT3); instead the render target that the camera will render into (i.e. the one that will be passed to the image effects) is used as RT3.

G-Buffer Pass

The g-buffer pass renders each object once. Diffuse and specular colors, surface smoothness, world space normal, and emission+ambient+reflections+lightmaps are rendered into g-buffer textures. The g-buffer textures are setup as global shader properties for later access by shaders (CameraGBufferTexture0 .. CameraGBufferTexture3 names).

Lighting Pass

The lighting pass computes lighting based on g-buffer and depth. Lighting is computed in screen space, so the time it takes to process is independent of scene complexity. Lighting is added to the emission buffer.

Point and spot lights that do not cross the camera’s near plane are rendered as 3D shapes, with the Z buffer’s test against the scene enabled. This makes partially or fully occluded point and spot lights very cheap to render. Directional lights and point/spot lights that cross the near plane are rendered as fullscreen quads.

If a light has shadows enabled then they are also rendered and applied in this pass. Note that shadows do not come for “free”; shadow casters need to be rendered and a more complex light shader must be applied.

The only lighting model available is Standard. If a different model is wanted you can modify the lighting pass shader, by placing the modified version of the Internal-DeferredShading.shader file from the Built-in shaders into a folder named “Resources” in your “Assets” folder. Then go to the Edit->Project Settings->Graphics window. Changed the “Deferred” dropdown to “Custom Shader”. Then change the Shader option which appears to the shader you are using.

Rendering Pipeline Details
Forward Rendering Path Details