This is the documentation for Enlighten.

Rendering indirect lighting


For each mesh you draw, sample indirect lighting either from lightmaps, probes, or not at all. For approximate local reflections, sample indirect lighting from cubemaps.

Indirect lighting data

Enlighten provides indirect lighting in the form of irradiance: the amount of light arriving from all directions.

In your pixel shader, obtain this lighting data from textures or buffers, and use it to evaluate the final irradiance for the pixel normal.

In a deferred renderer, it's usually simpler to apply indirect lighting in the g-buffer pass rather than in a separate lighting pass.

We recommend to use the Enlighten lighting models to address some limitations of the traditional half-lambert and SH evaluation methods. Our recommended lightmap lighting model requires an additional radiosity normal texture for each radiosity system, which is part of the enlighten runtime data.

Lightmaps

To draw a mesh which receives indirect lighting from Enlighten lightmaps, use the Enlighten lightmap UV coordinates to sample the Enlighten lightmap textures.

Conceptually there is a single lightmap for each radiosity system. The Enlighten lightmap UV coordinates for an instance map to locations within the lightmap of the radiosity system that contains the instance.

To get started quickly, create a separate lightmap texture resource per system and bind that texture before rendering the mesh. 

A separate lightmap texture resource for each system may not be efficient in a large world with many thousands of systems. In this case we recommend to combine the lightmaps of all systems into a single texture atlas, compute a UV transform for each system and apply it when drawing instances contained by that system.

Different lighting models may require more than one layer in the lightmap texture. All lighting models require the irradiance layer. We recommend to use the directional irradiance lighting model which also requires the directional and radiosity normal layers.

To make the Enlighten lightmap UV available in the shader, include an Enlighten lightmap UV vertex stream. We recommend:

  • use 16-bit integer UNORM format for Enlighten lightmap UVs,
  • store Enlighten lightmap UVs in a separate vertex buffer from the other vertex attributes of the mesh,
  • store this vertex buffer along with the persistent runtime data.

Two instances of the same mesh can both share the same Enlighten lightmap UV vertex buffer.

To debug your Enlighten lightmap UV data, we recommend to implement a visualization similar to the Chart renderer in GeoRadiosity. You can use the IMeshSimpOutput interface to colour code each Lightmap pixel by chart, disable texture filtering and draw a checkerboard in your shader.

Probes

To draw a mesh which receives indirect lighting from Enlighten probes, obtain the Enlighten SH coefficients and evaluate the SH function in your pixel shader.

We recommend to use L1 SH to minimize cost, along with Enlighten's improved L1 reconstruction to prevent lighting artifacts with strong HDR light sources.

If you use per pixel probe lighting you don't need any additional data for each mesh; simply sample the 3D virtual texture in your pixel shader.

If you use per mesh probe lighting, store the interpolated result for each mesh in a GPU buffer object that your pixel shader reads from.

Cubemaps

To apply local reflections to a surface, sample from nearby Enlighten cubemaps in your pixel shader. Each cubemap texel represents the light arriving at the cubemap centre from all directions. By default, the high level runtime generates a full mipchain for each cubemap with a box filter.

For the best results, we recommend the commonly used image based lighting techniques. If your engine already implements this for static cubemaps, you can easily substitute Enlighten cubemaps.

If your art style is not photo-realistic, you might choose not to use cubemaps at all. Indirect specular from directional irradiance provides a cheap alternative for low specular powers.