This is the documentation for Enlighten.

Runtime radiosity updates


The Enlighten runtime solves radiosity to update indirect lighting in real time. The most expensive part of the computation is done by the precompute, so that the runtime can use the Enlighten runtime data to quickly update lightmaps, probes and cubemaps.

We recommend to use the high level runtime to drive the Enlighten runtime. This is a layer on top of the low level runtime which implements the most common use-cases of Enlighten.

Radiosity inputs

To solve radiosity you need to provide the following inputs:

  • Enlighten runtime data
  • Direct illumination from at least one light source, or..
  • Sky lighting values stored in an environment cubemap (optional)
  • Albedo colour values for surfaces with different colours (optional)
  • Emissive colour and intensity values for surfaces that emit light (optional)

To quickly test your runtime implementation, set up a simple scene lit with only a white environment cubemap.

Direct light sources

For indirect lighting that matches the direct lighting displayed by your engine, provide Enlighten with information about the same light sources that you render.

Most engines use the same common light source types: point, spot and directional. Enlighten includes flexible implementations of these standard light types. To use Enlighten with a very different light beam shape or falloff profile, customize your direct light.

When a light source casts shadows, Enlighten needs light visibility data to avoid unwanted bounce light in shadowed areas. Directional lights get this from the the PrecomputedVisibilityData by default. With precomputed directional visibility data, only surfaces that are included in the radiosity computation cast shadows.

If you compute shadows for other light types, or you want shadows for surfaces excluded from the radiosity computation, provide light visibility data to Enlighten.

Sky lighting

The environment light source provides the effect of light from the sky. To control the colour and brightness provide light intensity values in the form of a low resolution cubemap. The intensity defines the amount of light arriving at a surface illuminated by the sky.

To get started use a uniform colour/intensity for the entire cubemap. For the most accurate lighting, render your sky to a higher resolution cubemap and downsample to the low resolution cubemap.

Define the resolution of the cubemap with the environment resolution parameter in your Enlighten scene. We recommend 8 by 8 texels per face for a good balance between accuracy and cost.

In rare cases when using lower resolutions for the cubemap, especially with axis aligned geometry, noise can be visible in the sky lighting. Use a resolution of at least 8 by 8 texels per face to eliminate this noise.

Material colours

Provide initial material colour data computed in advance for each radiosity system.

Optionally, you can change material colours while the game is running.

Radiosity outputs

After solving radiosity to compute the light arriving at each surface or probe, Enlighten encodes the lighting result in a compact format that can easily be stored in a texture.

Enlighten updates each texture on the CPU concurrently while your renderer samples the texture in a GPU shader.

Probe interpolation

The radiosity output contains the indirect lighting at each probe. To provide lighting for a surface, we must find the nearby probes which influence the surface and interpolate lighting values.

Enlighten provides two ways to do this:

  • Per mesh: interpolate once per mesh on the CPU and use the same lighting for all pixels in the mesh.
  • Per pixel: copy probes to a 3D texture and interpolate once per pixel on the GPU.

Efficient updates

The radiosity solve is CPU intensive, and some optimization is required to achieve efficient updates in a large world. Aim for less than 100msec latency for radiosity updates to avoid visible lag. To achieve this:

  • run the computation asynchronously and amortize the cost of a single radiosity update over several rendered frames. 
  • minimize the number of lightmap pixels, probes and cubemaps to be processed in each radiosity update.
  • address problems that cause instances to be grouped into excessively large or small radiosity systems.

To make it easy to schedule efficiently, the computation for the world is broken down into many small tasks that can run asynchronously. There are separate tasks for each system, probe set and cubemap. You can also choose to reduce the rate at which you update lighting in parts of the world that are less critical.