In a nutshell, lightmapping is a technique used to store lighting information into textures, for example shadows, lights and light bounces. We have 2 natural sources of lighting, the Sun and the sky. The Sun – because it’s a nearby star which is also shiny, and sky – because our planet has atmosphere that scatters sunlight, and can vary in color, too. When we combine these two, we get visible lighting and prominent shadows from the sun (directional lighting and shadowing), and more subtle ambient shadows, lighting and coloring that comes from the sky (ambient light). When we add light bouncing of many different surfaces into the mix, we get global illumination (GI). There are also artificial sources of light, but I’ll keep the story focused on natural light sources. Today, there are many techniques to achieve lighting in video games, and now it’s usually done in real-time (in the majority of PC and console games). Of course, that process is very GPU expensive and we need to scale it for mobile devices. That’s where lightmapping, aka “baking light into textures” comes in.
Here is an example of a lightmapped vs non-lightmapped object:
And here is an example of a lightmap (light information is “baked” over typical texture map of the object):
So, instead of lighting our scene in real time, we precalculate all light information and render it into textures, and for this process we use middleware called Beast integrated in Unity 4.x which is now replaced with Enlighten in Unity 5. That way we only employ memory, conserving GPU for other tasks. This technique comes handy when we have static objects in the scene, and it has drawbacks if we have moving objects or moving light sources. In TE 2015 all objects are static, and the best solution is to bake all lighting into textures.
Unity 5 light baking system isn’t compatible with previous versions, so lightmaps baked with Beast won’t work with Enlighten. A glimpse at both middlewares’ web pages can tell us that Enlighten is more advanced and pushed more towards real-time lighting, and it really excells in that area (Frostbyte 2 engine uses Enlighten, check the latest SW Battlefront title), but what about baked lighting?
Top Eleven ground has 54 objects in total (hospitals, stadiums, training, etc), and 3 major city environments (stage 1-3) with their own sets of buildings as backdrop. In order to conserve CPU power, we have to reduce draw calls, and we achieved that by using less materials and textures, so that all objects with the same material can be batched as one draw call. There are 35 materials in total and 33 texture maps (256×256 are the largest, and one 1k splat map used for texturing the terrain). This way, in an ideal scenario, we get 35 draw calls, which is extremely well optimized. Then comes the lightmapping.
Typical light baking scenario is to bake lightmap for every object, which gives us 54 lightmaps, and using these we have 3 major drawbacks – it usually quadruples the drawcalls and has impact on the memory too, because there are 54 new .exr textures that need to be loaded, and finally application size gets bigger. To avoid these issues, we bake all objects into one single 4k lightmap atlas, which is in reality scaled to 2k in Unity. So, we had to put all objects into the scene, and render one complete lightmap for all of them.
Light baking is in a way, iterative work, you have a set of options, and you’re tweaking each of them in order to get a better result. There are per-object settings and scene lighting settings. You tweak some parameters, click on the render button and you wait for the result. Beast was pretty fast, we could iterate the whole process on TE ground in one day, while final render took ~2 hours. It was also very scalable, so anyone could set lowest possible quality settings in order to iterate faster, and it usually took around 15 minutes per render. Some per-object settings are critical for the whole process – scale in lightmap setting as most important one – you use that parameter to scale the area that object will occupy on the lightmap. In this scenario, the lower – the better, BUT it will affect shadow resolution and detail, so you have to find the right balance, in order to pack all lightmaps into one single atlas.
Beast scene lighting settings are pretty much straightforward, you have the Sun as a direct light source, ambient light (skydome or color) and GI parameters as most computationally taxing. It also has “Lightmapping extended” script found on the asset store which gives us plenty of useful parameters to scale settings to our needs. Final result can take some additional actions without the need to rebake everything – for example, mesh replacement as most drastic (not in every situation though).
And then comes Enlighten…
Overall it took ~20 hours for baking, no iterations whatsoever because of the huge amount of time needed for baking, even in the lowest quality. And with some minefields introduced (I’ll clarify those later), whole process took 4 days. Of course, this job needed to be done ASAP, without much time for experimenting or tweaking.
In Enlighten, settings are a bit more simplified, we now have Environment lighting, Baked GI and General GI settings. If you have a simpler scene, (for example that stadium from the .gif image above), you can get results fast (it will take a bit more time than Beast, but still manageable). Enlighten also has a different process for baking, the first build takes some time, but each build after takes considerably less.
Critical settings are:
- Precomputed Real-time GI – OFF (because we don’t use any real-time lighting)
- Baked GI: Baked resolution, Indirect resolution, for the first testing pass use values 1, and 0.001 respectively. 2 and 0.1 are giving good results/speed for outdoor scenery. Ambient occlusion is a bit less taxing, but it’s advisable to set it to 0 for the faster iteration process.
- General GI: Directional mode, use Non-Directional and Default parameters set to Very low resolution
- Turn off “Auto” setting next to the “Build” button, that way you’ll avoid background iterative rendering. By default, lightmap baking starts as soon as you set the parameters and it continues to render in the background.
First lightmap bake takes around 15 minutes, every next tweak considerably less (up to 5 minutes), which is very good. So where’s the problem?
With every additional object on the scene, baking gets slower. Up to the point that whole TE ground took ~20 hours to bake, while it took ~2 hours in Beast. Enlighten just gets exponentially slower the bigger the scene is. It seems to be very good for creating single lightmaps for smaller objects than creating one large lightmap atlas for the whole scene.
Unless you’re absolutely sure, DO NOT change anything geometry-wise in the scene, because that will trigger Enlighten to bake everything from the start, and you’ll lose that faster rendering time in later iterations.
Changing Indirect Resolution parameter also impacts the iterations, and it also triggers longer initial rendering time.
Artifacts – you can usually get some totally black surfaces on your lightmaps. In case your geometry is correct (doesn’t have inverted normals or backfacing issues), it’s easily fixable. To fix that, go into Lighting/ Object/ Advanced Parameters and create custom parameter for that object (name it as you like). Lower the “backface tolerance” parameter. You can find useful parameters for tweaking per-object quality there too.
To achieve better packing of the UV’s for the lightmap, the best way is to do that manually in 3D software, and avoid automatic unwrapping done in Unity during lightmapping. If you decide to leave that job to Unity/Enlighten, cut your geometry in smaller pieces and avoid circular enclosed shapes seen in the example below:
In my opinion, consider baking lightmaps for large scenes with many objects in your 3D software using VRay, for example. Bake every object with single lightmap and then make the atlas. The Enlighten process, the way it is currently, just doesn’t give good results considering how slow it is, and it can be potentially unusable if you’re using a large Unity terrain. You should also onsider employing render farms. If your scene is fairly simple, go with Enlighten.