Point Light Rendering

ℹ️
Please note that this article will not go too much into the computer graphics theory behind the light rendering part, such as the GGX model or how to render the area lighting. The main focus of this article is to provide a go-through map of the processing. Readers who are interested in more details can refer to the presentation or papers linked in the article, and can also check the code mentioned here.

Vertex Shader

The engine renders a sphere geometry with the same radius as the point light source.

image
image

Then, trigger the pixel rendering for the pixels covered by this sphere.

Overview of the pixel shader

ℹ️
/Engine/Private/DeferredLightPixelShaders.usf

The main process of the pixel shader can be treated as follows:

  • Obtain the light data and depth of the current pixel.
  • Obtain the shadow attenuation. In our case, the cube is not covered by any shadow. However, if it were, the data would be loaded from here.
  • Call the GetDynamicLighting function.

The final output buffer looks like this:

image

The core calculation is performed inside the GetDynamicLighting function. Let's take a look.

Light Radiance Calculation

ℹ️
/Engine/Private/DeferredLightingCommon.ush: GetDynamicLighting

This part is already discussed in an old unreal engine 4 siggraph presentation : https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf

I highly recommend reading the PDF to understand the theory behind the calculation. In this chapter, I will only explain how it works, rather than talking too much about why.

image

This flow chart shows how the 4 important terms: diffuse, specular, shadow and distance attenuation effect the final radiance of this light source.

Local Light Attenuation

The local light attenuation step follows the inverse squared rule.

The inverse squared light attenuation is a physical phenomenon that describes how the intensity of light decreases as the distance from its source increases. This phenomenon follows the inverse square law, which states that the intensity of light is inversely proportional to the square of the distance from the light source.

In other words, if you double the distance from a light source, the intensity of the light will decrease by a factor of four. This is because the light is spreading out over a larger surface area as it moves away from the source, which means that the same amount of light is being distributed over a larger area.

You can check the function GetLocalLightAttenuation to see how the inverse square falloff is calculated.

Lambert Diffuse Lighting

ℹ️
/Engine/Private/BRDF.ush: Diffuse_Lambert

The diffuse term is actually really simple:

DiffuseColor=BaseColorBaseColorMetalicDiffuseColor = BaseColor - BaseColor * Metalic

Then:

Lighting.Diffuse=DiffuseColorπLighting.Diffuse = \frac{DiffuseColor}{\pi}

This matches the paper perfectly:

(Shading Model \ Diffuse BRDF)
image

We evaluated Burley’s diffuse model but saw only minor differences compared to Lambertian diffuse (Equation 1), so we couldn’t justify the extra cost. In addition, any more sophisticated diffuse model would be difficult to use efficiently with image-based or spherical harmonic lighting. As a result, we didn’t invest much effort in evaluating other choices.

GGX Specular Lighting

ℹ️
/Engine/Private/ShadingModels.ush: SpecularGGX

This part is also perfectly matching the paper, so I don’t have too much to discuss here:

image

If you want to see the code yourself:

Code