Course contentsShow
← Unreal Engine Game Development
Lesson 478 of 8807. Visual Fidelity and RenderingFree lesson

Implementing Lighting Calculations in Deferred Shading

You will analyze how deferred shading decouples geometry from lighting, allowing for the efficient rendering of hundreds of dynamic light sources simultaneously.

In this lesson, you will learn how deferred shading decouples geometry from lighting to enable the rendering of hundreds of dynamic light sources without a linear performance hit.

The Decoupling Principle

In traditional Forward Rendering, every time an object is drawn, the engine calculates lighting for every light source affecting that object. If you have 100 objects and 50 lights, you are potentially performing 5,000 lighting calculations.

Deferred shading flips this by splitting the process into two distinct stages. Instead of calculating lighting immediately, the first pass renders the scene’s geometric information—such as world-space normals, base color, and depth—into a set of textures called the G-Buffer (Geometry Buffer). Once the geometry is "baked" into these buffers, the lighting pass treats the scene as a collection of 2D image data rather than complex 3D meshes.

Lighting as a Screen-Space Pass

Because the lighting pass uses the G-Buffer, it doesn't care about the original vertex count of your meshes. When you place a light in your scene, the engine simply renders a light volume (like a sphere for a point light) and calculates the contribution for every pixel covered by that light based only on the data stored in the G-Buffer.

For example, a basic lighting calculation in this pipeline conceptually looks like this:

// Simplified representation of a point light calculation in a deferred shader
float3 CalculateLighting(float3 WorldNormal, float3 WorldPos, float3 LightPos, float LightRadius) {
    float3 LightDir = normalize(LightPos - WorldPos);
    float Attenuation = CalculateAttenuation(WorldPos, LightPos, LightRadius);
    float Diffuse = max(dot(WorldNormal, LightDir), 0.0);
    return Diffuse * Attenuation;
}

By querying the WorldNormal and WorldPos directly from the G-Buffer, the GPU only executes the lighting math for the pixels that are actually visible on screen. If a light is occluded or falls off, the GPU skips the work entirely. This allows for massive numbers of light sources, as the complexity is now tied to the resolution of your screen rather than the complexity of your scene's geometry.

Key Takeaway: Deferred shading decouples geometry complexity from lighting by storing object properties in the G-Buffer, allowing the GPU to calculate lighting as a screen-space post-process pass.