Working with lighting in Unity – theory and practice.

Beautiful real-time illumination in video games greatly impacts the productivity, which can be critical for mobile devices. Therefore developers have to look for the ways to solve this problem. Lightmapping is a technology, that stores the lighting information in a texture, which saves a lot of computing resources. In this article I’ll explain how does the lighting in games work, I’ll also describe the process of creating a lightmap in Unity 5. Besides I’ll share a few tips on lighting.

Over the last few years I’ve been dealing with lightmapping a lot on both my job and my own indie-project. When your team is pretty small and you don’t have a lot of time to create unique graphics for your game locations, the lighting becomes one of the things, that help spice the game up. 

Theory of lighting.

Indirect Illumination
Lighting in computer graphics divides into two categories: 

  •   Direct Illumination. Light rays strike the surface directly.
  •   Indirect Illumination. The rays bounce off the surface and scatter around, creating soft ambient light.

There’s lots of ways to simulate realistic indirect light, 2 most well-known of them are Global Illumination (GI) and Final Gather (FG). You can use them separately, but you’ll get the best of them when used together. However, with great power comes great responsibility: rendering (i.e. the process of calculating and visualizing complex lighting) takes up huge amount of time.

Global Illumination (GI) is “the fairest” way to simulate the complex behavior of the light as it bounces and interacts with the world. Light source emits photons, i.e. particles carrying information about the color and brightness of the light. When striking a surface photons light it up, at the same time losing part of their energy, which alters the data (about color and brightness) they carry. Then the photons bounce off the surface and strike another surface, losing part of the energy again. It happens a few times depending on the rendering settings.
Final Gather (FG) This method scatters points (final gather points) around the scene, then the points cast around light rays (instead of photons). Rays sample the surrounding area and bring the brightness and color values back to the point. Picture that: late evening, the sun has almost set over the horizon; it’s getting dark, but small part of the room is still lit by orange sunset light. A final gather point on the floor casts around a few rays, some of which reach the lit part of the room and bring the information back to the point, at the same time slightly illuminating the floor with the indirect orange light. It’s not that “fair” compared to GI, but it gives good results, and is widely used to set up beautiful soft light for the scene. 

For the following image I cranked up the indirect light parameters so you could see, how light particles bounce off the objects. 

Ambient Occlusion

Besides the indirect light you need to know about Ambient Occlusion (AO). This is the effect of shading in the corners and cracks. Imagine a light ray striking a room corner: it will repeatedly reflect from both walls, gradually fading away. The farther away a corner is, the less light reaches there. 

Usually Ambient Occlusion is used to artistically highlight the shading effect. In the reality light rays don’t lose their energy that fast for the room corners to be as dark, as we can see in games. If you are rendering physically correct lighting, your engine calculates the rate of energy loss for you, so you don’t need to render an Ambient Occlusion map for that. But you still can do it, if you need it to implement an artistic concept.

By the way, some 2D-artists like imitating this effect when drawing. Their work process is generally similar to creating 3D-graphics. 

Texture atlases

Another term you have to know is texture atlas. In a nutshell it’s a big texture, that holds smaller textures. Texture atlases are most often used to save computing resources. For example, there’s a tavern in your game. It has 20 wooden objects inside (tables, chairs, spoons etc.). Each of them has its own texture. As a result your CPU will request the GPU to render each object separately (20 times). If we assign one sole material to all 20 wooden objects, querying one texture atlas, that holds all 20 textures, the GPU will be able to render objects using only1 draw call (I’ll share interesting links on that topic in the end of the article).

In case of lightmapping there’s a small texture, created for every object in the scene. The lighting information is baked into each texture. After that thousands of small textures for different objects are put into bigger texture atlases. As well as with the wooden objects, the productivity increases.  
Working with Unity

General information

Let’s get back to the lightmapping in Unity. First of all arm yourself with patience and get a powerful computer, if you can. Rendering process usually takes up all processor and memory resources, that’s why I run it before I go to work or turn in. This way when I get back to the computer, the rendering process is already done. 
Let me warn you that Unity is caching all the intermediate results of calculating. If you notice that your system disk decreased in size for10 Gb – that’s exactly it! To customize caching go to Edit — Preferences — GI Cache. You can set the path for saving and define maximum cache size. You might want to turn the compression off, it will take up more disk space, but the process will speed up. You can also clean cache, but be aware that if you have a scene with already calculated lightmaps, the lightmaps will be erased too. Be careful!
Unity provides us with 5 light source types:

  •   Directional Light. The simplest one, it imitates the sun light. Basically it’s the infinite count of rays, that are parallel to one another. 
  •   Point Light. It can be thought of as a point in 3D space from which light is emitted in all directions. A good example of point light would be a light bulb. 
  •   Area Light. Imagine a rectangle from which light is emitted in all directions. This kind of light sources is commonly used in offices, malls and other untenantable buildings, where a lot of space needs to be lit up. 
  •   Ambient Light. This can be thought of as a global light source affecting objects in the scene from every direction. Use cases: lighting up too dark shadows, spicing up a dungeon by adding idle light of bioluminescent plants. 
  •   Light Probes. Special type of light source, that only affects dynamic objects. Technically it’s not a light source, but let’s call it that way to keep things simple.

All objects in Unity are either dynamic or static. Static objects are the ones that don’t move during the game. We can use baking for this type of objects. On the other hand dynamic objects are the ones, that move during the game. This includes heroes, monsters, a waving flag, a rolling stone etc. You can’t use lightmapping for this kind of objects, instead they are illuminated by either real-time light sources or using light probes (more details on this subject in the end).

Light source properties

Here I’ll highlight a few key properties of light sources (some light sources may have or not have particular properties). 

  •   Baking. This allows you to choose the light source processing method. For lightmapping choose “Baked”.
  •   Color. The light source color. 
  •   Range.  How far light is emitted from the center of the object (Point and Spot lights only).
  •   Intensity. Brightness of the light.
  •   Bounce Intensity. Defines brightness  of indirect rays, cast from the current light source.
  •   Shadow Type. Determines whether Hard Shadows Soft Shadows or no shadows at all will be cast by this light. I recommend using Soft Shadows, as it gives beautiful shadows by taking up more time for rendering.
  •   Baked Shadow Angle. Only available for Soft Shadows. Imagine a long shadow. The farther away from the object it gets, the more blurry it becomes. If you set the parameter to 0, the shadow practically won’t blur. If it’s set to more than 0, you’ll get the blur effect.

Scene lighting properties        

The Lighting Window (Window — Lighting) consists of 3 tabs: Object, Scene, Lightmaps. To run the rendering process click the “Build” button at the bottom of the window. There’s an “Auto” check too. This one helps you run rendering automatically every time you make changes to the scene; only check it if you have a powerful computer. 
A bit lower the information about count and size of lightmaps is shown, it appears once the lightmapping process is finished.

Object tab

The Object tab contains settings for a particular object. If you select an environmental object on the scene, you’ll see a list of properties and parameters. If the object is static, the “Lightmap Static” check is checked. The field you will use most often is “Scale in Lightmap”. As I already mentioned, every object gets its lighting baked into a separate little texture, which is later placed into a big lightmap-atlas. By changing this value, you can alter the amount of space the texture will take. Sure thing, the less space it takes, the worse baked lighting quality it’s going to have. The default value is 1.0, but if you know that the object is hardly and/or rarely seen, or it’s located far away, you can readily decrease this value down to 0.1 or even less. 

Scene tab

The Scene tab contains all the key lighting settings. I am explaining ABCs of working with lighting, plus I’m sharing my experience on lightmapping particularly for mobile platforms. That’s why I intentionally leave out the things like Real-time GI and HDR-textures usage. 

In Ambient Source you customize Ambient Light (the light that is present all around the scene and doesn’t come from any specific source object). You can choose either one of Skybox (sky is a texture), Color (uses a flat color for all ambient light in the scene), or Gradient (gradient based skies). 
I prefer using the Gradient option. It lets you set 3 colors – sky, horizon and ground, which will create a pretty complex and interesting ambient light effect for your scene. Ambient Intensity sets the brightness of ambient light. Depending on your artistic idea, you can even have a really bright scene, only illuminated by Ambient Light itself. 

In the Baked GI section you can find basic lighting quality settings for both direct and indirect light, including GI and FG. 
Before we continue let me give you a little tip. You should always keep in mind, that when setting up light sources in the scene, customizing shadows and Ambient Light, eventually (after the lightmaps rendering is done) you will get something completely different from what you’ve expected, slightly reminding the image you’ve seen in the scene. Therefore I recommend you working iteratively: 
1) set lighting quality to minimum, so the rendering process runs quickly; 2) check out the result; 3) make changes and restart the rendering process. When you’re close to being satisfied with the result, you can increase the rendering quality and turn on the Final Gather. It’s gonna take a while, so I recommend running it before you are going to leave the computer for a relatively long period of time.  

All Baked GI settings operate with a unit called “texel”. In a nutshell texel is a pixel, but not on the screen, rather in the texture space of a 3D model. Anyway, don't worry about the theory behind it, I can’t tell how Unity operates texels and how do they depend on the objects’ scale, so just go ahead and experiment! E.g. when doing final rendering for my mobile RPG I set Baked Resolution to 25.

Texel in Wiki

Before I explain you more about the parameters you need to know something. If you run rendering in Unity, in the bottom right corner you can see what the engine is currently doing. At the very end of rendering process it’ll read “Compositing”.

The thing is a lightmap is generated by layers. A few separate textures are generated during the rendering. I don’t know what exact maps does Unity create, but the list probably contains either all or some of these: Diffuse (direct light), Global Illumination, Final Gather, Ambient Occlusion. After that the engine merges the maps together (laying them on top of one another). For example, Diffuse can be a base map, then on top of it an FG layer is laid using Lighten blend mode (just like in Photoshop), on top of that an AO layer is laid using Multiply mode… As a result the layers merge into an image and eventually you get a final lightmap.

Baked GI tab Section

  •   Baked Resolution. This can be thought of as general lightmap quality (a.k.a. Diffuse). The higher the value is, the better image quality you get. But don’t get too involved, there’s a certain threshold, when reached, you won’t see any difference. It’s important to find a balance between baking quality and rendering time. 
  •   Baked Padding. This one is a distance between contiguous textures in the big atlas. If the compression is on and the atlas becomes more blurry, some of the textures may overlap. I usually set it between 1 and 3. 
  •   Compressed. This one is usually checked, hence Unity is compressing lightmap-altases. If not compressed, they can reach humongous sizes. 
  •   Indirect Resolution. This parameter can be thought of as a quality or detailing of the GI, FG and AO layers. There’s no need in setting a big value to this parameter. You won’t see huge difference. E.g. if you set Baked Resolution to 40, you can easily set Indirect Resolution between 3 and 8.
  •   Ambient Occlusion. As I mentioned before, AO is the effect of shading in the corners, cracks etc. This parameter defines how fast the energy is dispersed. Again, AO is an artistic trick, it has anything to do with a real, physically correct lighting. 
  •   Max Distance. This one is simply a distance of darkening for Ambient Occlusion. If Max Distance is high enough, the shading effect will start far from a corner, if Max Distance is set to a small value, only space deeply in the corner will be shaded.
  •   Final Gather. Turns on the FG method described before. By default only GI is rendered, by enabling this you add FG to it. You can not control number of points, that FG is scattering around the scene. I suppose it somehow depends on the Indirect Resolution parameter. 
  •   Ray Count. Number of the rays emitted by every FG point. 32 or 64 rays would most probably be enough for you.

General GI section

Let’s take a look at some of the settings from the General GI section:

  •   Directional Mode. That’s a pretty specific parameter, that bakes a second atlas for each lightmap. Straight lightmap is a plain texture, which is later set on top of your objects, imitating their illumination. The second atlas, which is referred to as Directional, holds information about the light rays direction. This mode can only be used if you are using normal maps and developing not a mobile game. Otherwise – pick Non Directional.
  •   Indirect Intensity. This parameter is the brightness of indirect lighting layers, including FG. As I mentioned, a lightmap is basically built from the layers placed on top of one another.
  •   Bounce Boost. Lets you adjust brightness of the reflected photons. Information about them is stored in the GI layer.
  •   Atlas Size. The size of the full lightmap (atlas) with baked lighting. If you are developing a mobile game for mobile devices straight from the 19th century, you can set it to 1024, because 2048 textures aren’t supported by the really old devices. Otherwise I recommend setting it to 2048, it’ll be supported by most of the devices, made over the last years. The smaller size of an atlas is, the more atlases will be made. If you know what a draw call is, you probably understand that increase of atlases count will impact game productivity. Therefore, if you don’t have specific requirements, your best bet is to use 2048. 

Fog section

Finally, the Fog! This has nothing to do with the lighting rendering, it can be turned on and off at any time. It’s pretty simple, go ahead and experiment! Just let me notice that the fog works as a pretty powerful artistic trick. You can drastically change the scene by using fog, making a sunny scene sunnier and a dark scene darker. 

Besides the fog can be used as a tool to increase productivity. E.g. you may switch off textures for the far objects and hide them with the fog. In the old versions of World of Warcraft you couldn’t help but notice what heavy fog they used. 

Lightmaps seciton

The third section is called Lightmaps. That’s where the rendered lightmaps will be shown. If you have a lot of atlases, you won’t be able to see all of them in the top part of the section, because you can’t use scrolling in that window. That’s why drag the mouse to the bottom part of the window and then scroll. 

The important thing is to see to what extent is the last lightmap-atlas filled with textures. If it’s almost empty, increase the lightmap quality to fill the entire atlas, or decrease the quality to get rid of the last (almost empty) atlas. The following image has 2 “good” atlases and one atlas, that’s half empty. 

Lightmaps are stored in EXR files, that have 32-bit color depth. 

Light Probes

As I promised I’m telling you about the Light Probes. They can be thought of as little spheres, that absorb the information about lighting. If their quantity is big enough, they make up kind of a map of your level or location illumination. Then they are used to light up dynamic objects, that can’t reap benefits of baking. 

For better understanding I’ll give you an example. You have one Point Light in your scene, that is used for baking (Baking parameter is set to Baked). You don’t set it to Real-time, because it’s expensive in terms of productivity, leaving out the fact that many mobile devices don’t even support this kind of light source at all. After that you lightmap the scene and see that your Point Light is lighting up the space around it. But if you take a monster and put it next to the light source, it will still remain dark, because the monster is a dynamic object, and your Point Light only affects static objects. 

What you do next is set up a network of Light Maps around the light source, then bake again. Wow! Now the monster can walk around the Point Light and get illuminated by it! This is very efficient and “cheap” way of imitating lighting. In order to add light probes to the scene choose Game Object — Light — Light Probe Group. A cube of 4 spheres now appears. To choose a sphere use Ctrl + click. Inspector will change, so you’d be able to add or delete spheres. You can also use Ctrl + D for sphere duplicating. 

Set up the Light Probes neatly and thoughtfully. To avoid graphic artefacts and flickering light make sure that Light Probes make up a smooth, good-looking network. 

Below you can see a screenshot of a correctly set up network. If you look closer, you can notice that Light Probes are not just randomly scattered. They surround light sources trying to “catch” the transition between light and shadow and vica versa.


In the end I’ll give you a tip about creating environmental models for lightmapping. When creating game content I knew beforehand where would the camera shoot from, so to optimize the game I had deleted back parts of some objects. At the time I had a rendering experience in Maya, but not in Unity. As it turned out in Unity during the lighting rendering, next to the objects with the “holes” (i.e. deleted polygons) really bad artefacts are created. Take this into consideration. 
Useful links.
Explanation of physically based rendering  system, written for 3D-artists.
  For more information on draw calls and graphics optimization, check out this great article for non-programmers -   render hell 2.0.   There’s also a good ⦁    description of Unity lighting system on Unity official web-site.


All data posted on the site represents accessible information that can be browsed and downloaded for free from the web.


User replies

No replies yet