In 2019.2, we removed the Lightmap Static Flag, replacing it with Contribute to global illumination (GI). At the same time, we have introduced the ability to choose whether global illumination is received from lightmap or Light Probes. This seemingly minor change can have a huge impact on baking performance and the quality of Scene lighting. Let’s explore this further.
Global illumination involves complex calculations to compute the way light bounces from surface to surface once it leaves its source. This is generally difficult to do accurately without adding costly calculations during run-time. A common approach for solving this problem while achieving the best-quality output is to shift the heavy computation to a precomputation step, which would happen in Edit mode.
To do this, we assume that several objects and light sources in a Scene will stay in place relative to one another, will not deform, and will not rotate or change any of their appearance properties. With these assumptions made, light can then be computed using a technique known as lightmapping.
To mark such objects, Unity provided the Lightmap Static flag. While this feature name made sense when it was created, the name also implied that only static objects were using lightmaps. But static lightmaps are just one of many different ways to store global illumination in a Scene, and they come with certain disadvantages, which we will discuss later.
Using a lightmapping approach to global illumination, non-static (or dynamic) objects cannot contribute to global illumination because they violate the assumption that they’re static. Computing global illumination for an object that later moves means that lighting would only be valid for the position in which it was initially lit. This is a major limitation of traditional lightmapping.
Dynamic objects can still receive global illumination from other static objects via Light Probes. Light Probes are positions in space where a sample of the light coming from all directions is stored. This light is encoded into special values called “spherical harmonics.” During run-time, dynamic objects can then receive values from surrounding Light Probes as the object moves through the world. This allows dynamic objects to receive local lighting in order to appear correctly integrated with surrounding lighting conditions.
Technically, nothing would prevent a static object from using Light Probes instead of lightmaps.
Why would you want to do that?
Objects that need to be lightmapped must be unwrapped and have space reserved in a lightmap. Depending on the resolution, each object projected into a lightmap will reserve a certain amount of texels.
As an example, a unit cube (dimension 1x1x1) at a lightmap resolution of one texel per unit of space will reserve one texel for each side. This would mean six texels in total. For each of these texels, the lightmapper would then need to compute the light arriving at that texel’s world position. This is done by casting rays and bouncing them through the Scene until they find a light source. The more texels used, the more work required to compute the result. In Scenes with many small objects, this adds up to a lot of work. In fact, unwrapping, charting, and lightmapping these types of objects is the most common cause of lightmap bakes failing or taking an unacceptably long time.
Small objects, such as pebbles and debris, or thin objects like wires and poles can easily produce “waste texels.” These are texels that don’t contribute significantly to the overall look of an object but still add computation time and consume space in the lightmap.
Thin objects often produce unwraps in which one or two pixels wrap around an object’s length and therefore have very little impact on the look. Similarly, small objects tend to produce several texels in the lightmap that – given the size of the object on screen – do not contribute much, if anything, to the final look. The end result is that a lot of computation time is lost on texels that do not matter to us visually, but still increase the amount of lightmap space needed.
A good way to optimize the time it takes to produce a lightmap is removing these small objects out of lightmap calculations by making them non-static. This reduces the number of occupied lightmap texels which need to be calculated. However, in some cases these objects may have had a significant influence on lighting in the Scene. Imagine a case where there’s a very brightly colored object, or perhaps one with an emissive material. If these objects aren’t lightmap static, they will not be able to contribute to global illumination in the Scene. Their potentially significant influence on the expected lighting result would be missing.
One is now left with two options for how to deal with these types of objects: Lightmap them to include their influence on the rest of the Scene, even though this can make baking times longer and waste space in lightmaps, or drop their influence, at the cost of the overall look and global illumination quality. How do you solve this dilemma?
In 2019.2, we’ve added the ability to make objects receive global illumination from light probes while still contributing lighting to the Scene. This can be enabled using a small dropdown menu added to the Inspector under the Mesh Renderer.
Here, you can choose whether a Mesh Renderer will Receive Global Illumination from Lightmaps (formerly the only option for static objects) or Light Probes (previously the only option for dynamic objects).
By enabling the Contribute Global Illumination flag, an object will be included in the global illumination computation of the lightmapper. While the assumption that objects will always be static remains, now you can explicitly control whether objects use Light Probes or lightmaps, depending on the fidelity of lighting required. Objects that Contribute Global Illumination but then Receive Global Illumination from Light Probes will still influence their surroundings. A tall lamp post will still throw a shadow that will be computed for the lightmaps around it, while an emissive material on this lamp post would still illuminate the surrounding Scene.
With this newly available functionality in Unity, optimizing away problematic small objects and thin objects is straightforward: Simply set the Receive Global Illumination field on Mesh Renderers to Light Probes. With this setting, the objects will no longer take up space in your lightmaps, meaning these texels will no longer make the lightmapper busy unnecessarily.
A key beneficial side effect of using Light Probes is that they don’t need proper UVs, which can be time-consuming to unwrap. If you have a dynamic object that looks great with Light Probes but that never actually moves, rotates, or is otherwise modified, you can now choose to flag it with Contribute Global Illumination. The object can then influence surrounding lightmapped objects without increasing the bake time. This speed means an increase in productivity while reducing memory usage.
With this innovation, dynamic (or non-Static) objects can be lit with Light Probes. This lets you specify whether the objects included in your global illumination calculations receive indirect lighting from Light Probes or lightmaps, giving you the ability to decrease texel usage in Lightmaps. Overall, this change could substantially reduce the computation time for lightmaps, lower memory usage, and offer better run time performance.
If you are interested in more ways to optimize global illumination in your project, you can watch this talk from Unite 2018.
Want to learn more? Meet us at Unite Copenhagen, which takes place September 23–26. It’s a unique opportunity to engage with thousands of talented creators and top developers from around the world!