In this tutorial we will give you an overview of how lighting works with Unity's real-time Global Illumination engine. We will walk you through the different lighting techniques available, explain how to setup your project for lighting and then explore the various tools at your disposal when considering how to light a scene.
Modern game lighting makes extensive use of ‘global illumination’.
Global illumination, or ‘GI’, is a term used to describe a range of techniques and mathematical models which attempt to simulate the complex behaviour of light as it bounces and interacts with the world. Simulating global illumination accurately is challenging and can be computationally expensive. Because of this, games use a range of approaches to handle these calculations beforehand, rather than during gameplay.
The same scene: With no lighting (Left), with ‘direct light’ only (Center) & with indirect 'global illumination' (Right). Note how colors are transferred as light ‘bounces’ between surfaces, giving a much more realistic result.
In this document we will give you an overview of how GI works in Unity. We will walk you through the different lighting techniques available, explain how to setup your project for lighting and then explore the various tools at your disposal when considering how to light a scene.
Choosing a Lighting Technique
Broadly speaking, lighting in Unity can be considered as either ‘realtime’ or ‘precomputed’ in some way and both techniques can be used in combination to create immersive scene lighting.
In this section we will give a brief overview of what opportunities the different techniques offer, their relative advantages and individual performance characteristics.
By default, lights in Unity - directional, spot and point, are realtime. This means that they contribute direct light to the scene and update every frame. As lights and GameObjects are moved within the scene, lighting will be updated immediately. This can be observed in both the scene and game views.
The effect of realtime light alone. Note that shadows are completely black as there is no bounced light. Only surfaces falling within the cone of the Spotlight are affected.
Realtime lighting is the most basic way of lighting objects within the scene and is useful for illuminating characters or other movable geometry.
Unfortunately, the light rays from Unity’s realtime lights do not bounce when they are used by themselves. In order to create more realistic scenes using techniques such as global illumination we need to enable Unity’s precomputed lighting solutions.
Baked GI Lighting
When 'baking’ a ‘lightmap', the effects of light on static objects in the scene are calculated and the results are written to textures which are overlaid on top of scene geometry to create the effect of lighting.
Left: A simple lightmapped scene. Right: The lightmap texture generated by Unity. Note how both shadow and light information is captured.
These ‘lightmaps’ can include both the direct light which strikes a surface and also the ‘indirect’ light that bounces from other objects or surfaces within the scene. This lighting texture can be used together with surface information like color (albedo) and relief (normals) by the ‘Shader’ associated with an object’s material.
With baked lighting, these light textures (lightmaps) cannot change during gameplay and so are referred to as ‘static’. Realtime lights can be overlaid and used additively on top of a lightmapped scene but cannot interactively change the lightmaps themselves.
With this approach, we trade the ability to move our lights at gameplay for a potential increase in performance, suiting less powerful hardware such as mobile platforms.
Precomputed Realtime GI Lighting
Whilst traditional, static lightmaps are unable to react to changes in lighting conditions within the scene, Precomputed Realtime GI does offer us a technique for updating complex scene lighting interactively.
With this approach it is possible to create lit environments featuring rich global illumination with bounced light which responds, in realtime, to lighting changes. A good example of this would be a time of day system - where the position and color of the light source changes over time. With traditional baked lighting, this is not possible.
A simple example of time of day using Precomputed Realtime GI.
In order to deliver these effects at playable framerates, we need to shift some of the lengthy number-crunching from being a realtime process, to one which is ‘precomputed’.
Precomputing shifts the burden of calculating complex light behaviour from something that happens during gameplay, to something which can be calculated when time is no longer so critical. We refer to this as an ‘offline’ process.
So how does this work?
Most frequently it is indirect (bounced) light that we want to store in our lightmaps when trying to create realism in our scene lighting. Fortunately, this tends to be soft with few sharp, or 'high frequency’ changes in color. Unity’s Precomputed Realtime GI solution exploits these ‘diffuse’ characteristics of indirect light to our advantage.
Finer lighting details, such as crisp shadowing, are usually better generated with realtime lights rather than baking them into lightmaps. By assuming we don’t need to capture these intricate details we can greatly reduce the resolution of our global illumination solution.
By making this simplification during the precompute, we effectively reduce the number of calculations we need to make in order to update our GI lighting during gameplay. This is important if we were to change properties of our lights - such as color, rotation or intensity, or even make change to surfaces in the scene.
To speed up the precompute further Unity doesn’t directly work on lightmaps texels, but instead creates a low resolution approximation of the static geometry in the world, called ‘clusters’.
Left: With scene view set to ‘Albedo’ the texels generated by Unity’s Precomputed Realtime GI can clearly be seen. By default a texel in this view is roughly the size of a cluster. Right: The scene as it appears in-game once the lighting has been calculated and the results converted to lightmap textures and applied. Traditionally when calculating global illumination, we would ‘ray trace’ light rays as they bounce around the static scene. This is very processing intensive and therefore too demanding to be updated in realtime. Instead, Unity uses ray tracing to calculate the relationships between these surface clusters beforehand - during the 'Light Transport' stage of the precompute.
By simplifying the world into a network of relationships, we remove the need for expensive ray tracing during the performance-critical gameplay processes.
We have effectively created a simplified mathematical model of the world which can be fed different input during gameplay. This means we can make modifications to lights, or surface colors within the scene and quickly see the effects of GI in scene lighting update at interactive framerates. The resulting output from our lighting model can then be turned into lightmap textures for rendering on the GPU, blended with other lighting and surface maps, processed for effects and finally output to the screen.
Benefits and Costs
Although it is possible to simultaneously use Baked GI lighting and Precomputed Realtime GI, be wary that the performance cost of rendering both systems simultaneously is exactly the sum of them both. Not only do we have to store both sets of lightmaps in video memory, but we also pay the processing cost of decoding both in shaders.
The cases in which you may wish to choose one lighting method over another depend on the nature of your project and the performance capabilities of your intended hardware. For example, on mobile where video memory and processing power is more limited, it is likely that a Baked GI lighting approach would be more performant. On ‘standalone computers’ with dedicated graphics hardware, or recent games consoles, it is quite possible to use Precomputed Realtime GI or even to use both systems simultaneously.
The decision on which approach to take will have to be evaluated based on the nature of your particular project and desired target platform. Remember that when targeting a range of different hardware, that often it is the least performant which will determine which approach is needed.
Enabling Baked GI or Precomputed Realtime GI
By default, both Precomputed Realtime GI and Baked GI are enabled in Unity’s Lighting panel (Lighting>Scene). With both enabled, which technique is used can then be controlled by each light individually (Inspector>Light>Baking).
Using both Baked GI and Precomputed Realtime GI together in your scene can be detrimental to performance. A good practise is to ensure that only one system is used at a time, by disabling the other globally. This can be done by unchecking the box next to either Precomputed Realtime GI or Baked GI from Unity’s lighting panel (Lighting>Scene). Now only the checked option will be present in your scene, and any settings configured per-light will be overridden.
The default baking mode for each light is ‘Realtime’. This means that the selected light(s) will still contribute direct light to your scene, with indirect light handled by Unity’s Precomputed Realtime GI system.
However, if the baking mode is set to ‘Baked’ then that light will contribute lighting solely to Unity’s Baked GI system. Both direct and indirect light from those lights selected will be ‘baked’ into lightmaps and cannot be changed during gameplay.
Point light with the per-light Baking mode set to ‘Realtime’.
Selecting the ‘Mixed’ baking mode, GameObjects marked as static will still include this light in their Baked GI lightmaps. However, unlike lights marked as ‘Baked’, Mixed lights will still contribute realtime, direct light to non-static GameObjects within your scene. This can be useful in cases where you are using lightmaps in your static environment, but you still want a character to use these same lights to cast realtime shadows onto lightmapped geometry.
The Precompute Process
In Unity, precomputed lighting is calculated in the background - either as an automatic process, or it is initiated manually. In either case, it is possible to continue working in the editor while these processes run behind-the-scenes.
When the precompute process is running, a blue progress bar will appear in the bottom right of the Editor. There are different stages which need to be completed depending on whether Baked GI or Precomputed Realtime GI is enabled. Information on the current process is shown on-top of the progress bar.
Progress bar showing the current state of Unity’s precompute.
In the example above, we can see that we are at task 5 of 11 which is, ‘Clustering’ and there are 108 jobs remaining before that task is complete and the precompute moves on to task 6. The various stages are listed below:
Starting a Precompute
Only static geometry is considered by Unity’s precomputed lighting solutions. To begin the lighting precompute process we need at least one GameObject marked as ‘static’ in our scene. This can either be done individually, or by shift-selecting multiple GameObjects from the hierarchy panel.
From the Inspector panel, the Static checkbox can be selected (Inspector>Static). This will set all of the GameObject’s ‘static options’, or ‘flags’, including navigation and batching, to be static, which may not be desirable. For Precomputed Realtime GI, only 'Lightmap Static' needs to be checked.
For more fine-grained control, individual static options can be set from the drop-down list accessible to the right of the Static checkbox in the Inspector panel. Additionally, objects can also be set to Static in the Object area of the lighting window.
If your scene is set to Auto (Lighting>Scene>Auto), Unity’s lighting precompute will now begin automatically. Otherwise it will need to be started manually as described below.
If ‘Auto’ is checked from the bottom of Unity’s Lighting panel (Lighting>Scene>Auto), then this precompute will begin automatically as a background process whenever changes are made to static geometry within your scene.
However, if Auto is not selected, you will need to manually start a precompute by clicking the ‘Build’ button next to it. This will begin the precompute in much the same way, while giving you control over when this process starts.
Manually initiating a precompute will cause all aspects of your scene lighting to be evaluated and (re)computed. If you wish to selectively recalculate Reflection probes by themselves, this can be done via the drop-down menu next to the Build button (Lighting>Scene>Build).
In either Baked GI or Precomputed Realtime GI, Unity ‘caches’ (stores) data about your scene lighting in the ‘GI Cache’, and will try to reuse this data whenever possible to save time during precompute. The number and nature of the changes you have made to your scene will determine how much of this data can be reused, if at all.
This cache is stored outside of your Unity project and can be cleared using (Preference>GI Cache>Clear Cache). Clearing this means that all stages of the precompute will need to be recalculated from the beginning and this can therefore be time consuming. However in some cases, where perhaps you need to reduce disk usage, this may be helpful.
Choosing a Rendering Path
Unity supports a number of rendering techniques, or ‘paths’. An important early decision which needs to be made when starting a project is which path to use. Unity’s default is 'Forward Rendering”.
In Forward Rendering, each object is rendered in a ‘pass’ for each light that affects it. Therefore each object might be rendered multiple times depending upon how many lights are within range.
The advantages of this approach is that it can be very fast - meaning hardware requirements are lower than alternatives. Additionally, Forward Rendering offers us a wide range of custom ‘shading models’ and can handle transparency quickly. It also allows for the use of hardware techniques like ‘multi-sample anti-aliasing’ (MSAA) which are not available in other alternatives, such as Deferred Rendering which can have a great impact on image quality.
However, a significant disadvantage of the forward path is that we have to pay a render cost on a per-light basis. That is to say, the more lights affecting each object, the slower rendering performance will become. For some game types, with lots of lights, this may therefore be prohibitive. However if it is possible to manage light counts in your game, Forward Rendering can actually be a very fast solution.
In 'Deferred' rendering, on the other hand, we defer the shading and blending of light information until after a first pass over the screen where positions, normals, and materials for each surface are rendered to a ‘geometry buffer’ (G-buffer) as a series of screen-space textures. We then composite these results together with the lighting pass. This approach has the principle advantage that the render cost of lighting is proportional to the number of pixels that the light illuminates, instead of the number of lights themselves. As a result you are no longer bound by the number of lights you wish to render on screen, and for some games this is a critical advantage.
Deferred Rendering gives highly predictable performance characteristics, but generally requires more powerful hardware. It is also not supported by certain mobile hardware.
For more information on the Deferred, Forward and the other available rendering paths, please see the documentation here.
Choosing a Color Space
In addition to selecting a rendering path, it’s important to choose a ‘Color Space’ before lighting your project. Color Space determines the maths used by Unity when mixing colors in lighting calculations or reading values from textures. This can have a drastic effect on the realism of your game, but in many cases the decision over which Color Space to use will likely be forced by the hardware limitations of your target platform.
Linear Color Space
The preferred Color Space for realistic rendering is Linear. This can be selected using the ‘Color Space’ property from (Edit>Project Settings>Player).
A significant advantage of using Linear space is that the colors supplied to shaders within your scene will brighten linearly as light intensities increase. With the alternative, ‘Gamma’ Color Space, brightness will quickly begin to turn to white as values go up, which is detrimental to image quality.
Image comparing objects lit using Linear and Gamma Color Space. Notice how colors quickly turn to white as light intensities increase using the Gamma Color Space.
Another main benefit of Linear is that shaders can also sample textures without Gamma (midtone) compensation. This helps to ensure that color values remain consistent throughout their journey through the render pipeline. The result is increased accuracy in color calculations with improved overall realism in the eventual screen output.
Gamma Color Space
Unfortunately Linear Color Space is not supported by some mobile hardware and even certain games consoles. In these instances, Gamma must be used instead. Linear is currently supported on PC, newer mobile hardware and current generation consoles.
It’s important to confirm that your target platform supports your selected Color Space before proceeding.
For more information on Color Space please see the documentation here.
High Dynamic Range (HDR)
As well as Color Space, the ‘dynamic range’ of your camera needs to be configured. Essentially, this defines how extremely bright or dark colors are captured by scene cameras. HDR can be enabled from the camera component in the Inspector by using the HDR checkbox. Note that HDR is unsupported by some mobile hardware. It is also not supported in Forward Rendering when using techniques such as multi-sample anti-aliasing (MSAA).
HDR is best used in combination with Linear Color Space in order to preserve accuracy when handling very bright colors.
By default, cameras in Unity use a Low Dynamic Range (LDR). Colors are stored using 8-bits per channel - red, green and blue. 8-bits refers to the ‘precision’ and means that color data is stored with 8 values of either 1 or 0, giving 256 possible unique combinations for each color channel. 256 x 256 x 256 colors per channel means that by storing values using 8-bits we are able to uniquely reference over 16 million color variations ranging in intensity from black to white.
In reality, colors in the real world extend far outside this 16 million color range. There are infinite permutations of color possibilities, and brightness goes beyond what our eyes can even see. Similarly Unity is capable of handling extremely bright lights which produce colors beyond that which can be displayed on an LDR device such as your computer screen. However, despite this potential limitation in the output device, these extreme light values still remain useful to us in a number of applications.
By enabling HDR on your scene camera, colors will be stored with much greater precision (using the floating point representation). Many more unique colors over a much brighter range of luminance can be handled.
HDR enables us to preserve the great differences in brightness between, say, outdoor lighting in our scenes and shaded areas. We can also create effects like ‘blooms’ or glows by applying effects to these bright colors in your scene. Special effects like these can add realism to particles or other visible light sources. However, these extreme color values also need to be handled somehow to prevent them being ‘clamped’ to white.
Using the analogy of photography, if we were to photograph our scene using different exposure settings, then we could start to see these extreme color details which otherwise might have been lost. Light tones in the brightest areas of the image which have been lost to white can be recovered, or dark tones lost to black. This is analogous to ‘tonemapping’ in computer graphics, where we take colors outside of the range reproducible by our target device (computer screen, for example) and shift them mathematically into a range which can be reproduced. The resulting output still makes sense perceptually, because colors remain relative to one another. They are correct in context.
When using HDR cameras, the Tonemapping Image Effect from Standard Assets (Assets>Import Package>Effects) must be added to the camera. This script provides you control over how very bright color intensities recorded by your camera are converted into colors which can be displayed.
More information on Tonemapping can be found here.
By default, objects in a scene are rendered using Unity’s ‘Standard Shader’. The Standard Shader is a 'physically based shader' (PBS). This attempts to accurately represent the behavior of light on materials by mimicking physical properties such as reflectivity and the principles of ‘energy conservation’ which exist in the real world.
When using the Standard Shader, every material has a degree of reflectivity based on its ‘specularity’, or ‘metalness’. Without hardware powerful enough to ray trace reflections in realtime we have to rely on pre-rendering reflections. We do this with a cubemap - a 6-sided image of the world derived either from the sky, or from a ‘Reflection Probe’ which renders the environment from a specific point in space, writing the results to a texture. This is then blended with other lighting and surface data by a material’s shader in order to approximate the effects of reflectivity, like we see in the real world.
By default, highly Specular/Metal materials in your scene will reflect the Skybox, defined by the Reflection Source property of the Environment Lighting Panel. This behaviour can be changed by choosing a different source, or by adding a Reflection Probe to your scene.
By default, objects in a Unity scene will reflect the Skybox. However, this behaviour can be changed globally in the Lighting window using the ‘Reflection Source’ property. The Skybox, or alternatively, a custom cubemap may be used. This ‘Reflection Source’ can be thought of as a scene-wide cubemap used by all objects in the scene, unless overridden - by adding a Reflection Probe.
Often it is undesirable for objects to simply reflect the Skybox in a Unity scene. In many instances, objects may be blocked or ‘occluded’ from the sky. They may be indoors or underneath an architectural feature like a bridge or tunnel . To create more accurate reflections we need to sample what objects ‘see’ using a ‘Reflection Probe’. These probes render the world from their position in 3D space and write the results to a cubemap. This can then be used by nearby objects to give the impression that they are reflecting the world around them.
A reflection probe can be added via (GameObject>Light>Reflection Probe).
The position of a Reflection Probe will determine what the generated cubemap looks like, and therefore what is ‘seen’ in the reflections. Generally, for performance reasons it is better to use as few probes as possible. Remember, reflection probes are not meant to give physically accurate results, but instead give the impression of reflections in the game world. A few well placed probes throughout your scene will be sufficient in most cases.
Left: Our scene with default reflections. Right: With a Reflection Probe added.
In the Inspector panel for a Reflection Probe we can set the ‘Type’ property of the probe to choose between ‘Baked’, ‘Custom’ or ‘Realtime’. It should be noted that Realtime Reflection Probes are extremely detrimental to performance as we are effectively rendering the scene an additional 6 times for each probe. There are specific cases where a realtime reflection probe is required and this expense is justified, but as a general rule, Baked Reflection Probes are preferable as they are considerably more performant.
Note that GameObjects are only visible to Baked Reflection Probes if marked as ‘Reflection Probe Static’ from the ‘Static’ drop-down at the top of the Inspector panel. Conversely, ‘Realtime’ probes render all visible GameObjects in the world unless a culling mask is applied.
An important contributor to the overall look and brightness of a scene is ‘ambient lighting’. This can be thought of as a global light source affecting objects in the scene from every direction.
Ambient light can be useful in a number of cases, depending upon your chosen art style. An example would be bright, cartoon-style rendering where dark shadows may be undesirable or where lighting is perhaps hand-painted into textures. Ambient light can also be useful if you need to increase the overall brightness of a scene without adjusting individual lights.
Without using one of Unity’s precomputed lighting solutions, ambient light will not be occluded and therefore will not be physically accurate. However if either Baked GI or Precomputed Realtime GI are enabled in your scene then this ‘skylight’ will be blocked by objects in your scene - giving a more realistic result.
The same scene with no light whatsoever (Left) and with only Ambient Light (Right). Notice how the visible Skybox does not change when changes are made to the Ambient Intensity.
Now using Precomputed Realtime GI by marking the objects as static. Notice how light is now occluded in areas of contact between surfaces.
A significant advantage of using ambient light is that it is cheap to render and so particularly useful for mobile applications where perhaps it is desirable to minimize the number of lights in your scene.
Ambient Lighting can be controlled in the Lighting window from the ‘Environment Lighting’ section (Lighting>Scene>Ambient Source).
The default value is for the ‘Ambient Source’ property to be set to ‘Skybox’. The Skybox in this case is the default procedural Skybox that - with default settings - contributes a blue tint to the Ambient Lighting of the scene. The other options for the ‘Ambient Source’ include a solid color, or a ‘Gradient’ which is a simple color ramp applied over the hemisphere.
Note that changing the color of the ambient source does not affect the visible Skybox, instead it only affects the color of lighting within the scene.
We have now covered some of the project settings which need to be considered before beginning work on lighting your scenes in Unity. Hopefully at this point you should have your project configured appropriately for your target platform (generally Baked GI and Gamma Color Space for mobile, Precomputed Realtime GI and Linear Color Space for Standalone PC or recent games consoles).
Let’s move on to looking at the tools available for achieving the lighting you want in your game.
‘Directional Lights’ are very useful for creating effects such as sunlight in your scenes. Behaving in many ways like the sun, Directional Lights can be thought of as distant light sources which exist infinitely far away.
Light rays emitted from Directional Lights are parallel to one another and do not diverge like those from other light types. As a result, shadows cast by Directional Lights look the same, regardless of their position relative to the source. This is useful to us, especially when lighting outdoor scenes.
As Directional Lights do not have a source position, they can be placed anywhere in your scene without changing the effect of the light. Rotating the light however does greatly affect the visual result.
With other light types where there is an obvious source position, such as Spotlights, character shadows will change as the character moves closer to the light source. This can be a problem when trying to generate character shadows in interior levels. Directional lights are advantageous in these situations as shadows remain consistent regardless of proximity to the light source.
Directional Lights do not diminish over distance. As they affect all surfaces in your scene (unless culled), they pose a performance cost when using the Deferred Rendering path. Remember that when using this rendering technique, the performance cost of a light is relative to the number of pixels it illuminates. However, despite the cost, performance will at least be consistent and as such, easier to balance.
By default, every new Unity scene contains a Directional Light. In Unity 5, this is linked to the procedural sky system defined in the Environment Lighting section of the Lighting Panel (Lighting>Scene>Skybox). You can change this behaviour by deleting the default Directional Light and creating a new light or simply by specifying a different GameObject from the ‘Sun’ parameter (Lighting>Scene>Sun).
Rotating the default Directional Light (or ‘Sun’) causes the ‘Skybox’ to update. With the light angled to the side, parallel to the ground, sunset effects can be achieved. Additionally, pointing the light upwards causes the sky to turn black, as if it’s nighttime. With the light angled from above, the sky will resemble daylight.
If the Skybox is selected as the ambient source, Ambient Lighting will change in relation to these colors.
A Point Light can be thought of as a point in 3D space from which light is emitted in all directions. These are useful for creating effects like light bulbs, weapon glow or explosions where you expect light to radiate out from an object.
The intensity of of Point Lights in Unity diminishes quadratically from full intensity at the centre of the light, to zero at the limit of the light’s reach defined by the ‘Range’ property of the component in the Inspector. Light intensity is inversely proportional to the square of the distance from the source. This is known as ‘inverse square law’ and is similar to how light behaves in the real world.
Point Lights emit light in all directions from their position in the world. The spherical gizmo represents the ‘Range’ of the Light. Direct Light will ‘Falloff’ to zero when it reaches this limit, however bounced - or indirect light can continue much further.
Enabling shadows for Point Lights can be expensive and so must be used sparingly. Point Lights require that shadows have to be rendered six times for the six world directions and on slower hardware this can be an unacceptable performance cost.
When adding Point Lights to a scene it’s worth noting that currently they do not support indirect bounce light shadowing.This means that the light created by Point Lights will continue through objects and bounce on the other side unless attenuated by range. This can lead to light ‘leaks’ through walls and floors and therefore lights must be carefully placed to avoid such problems. This however is not a problem when using Baked GI.
Spotlights project a cone of light in their forward (+Z) direction. The width of this cone is defined by the light’s ‘Spot Angle’ parameter. Light will ‘falloff’ from the source position towards the extent of the light’s range, where it will eventually diminish to zero. Light also diminishes at the edges of the Spotlight’s cone. Widening the Spot Angle increases the width of the cone and with it, increases the size of this fade, known as the ‘penumbra’.
Spotlights have many useful applications for scene lighting. They can be used to great effect as street lights, wall downlights or used dynamically, for creating effects like a flashlight. As their area of influence can be precisely controlled, Spotlights are extremely useful for creating focus on a character or for creating dramatic stage lighting effects
Light will diminish as distance increases from the source. Notice how light also fades towards the edges of the cone. We call this the Light’s penumbra and this increases as the angle of the cone increases.
Like Point Lights, Spotlights do not presently support indirect shadowing when using Precomputed Realtime GI. This means that light produced by Spotlights will travel through geometry and will bounce on the other side. Placement therefore needs to be carefully considered.
Area Lights can be thought of as similar to a photographer’s softbox. In Unity they are defined as rectangles from which light is emitted in all directions, from one side only - the object’s +Z direction. Presently only available in Baked GI, these Area Lights illuminate uniformly across their surface area. There is no manual control for the range of an Area Light, however intensity will diminish at inverse square of the distance as it travels away from the source.
Light is emitted across the surface of an Area Light producing a diffuse light with soft shadowing.
Area Lights are useful in situations where you wish to create soft lighting effects. As light is emitted in all directions across the surface of the light, the rays produced travel in many directions - creating a diffuse lighting effect across a subject. A common use for this might be a ceiling striplight or a backlit panel.
In order to achieve this, we must fire a number of rays from each lightmap texel in the world, back towards the light in order to determine whether the light can be seen. This means that Area Lights can be quite computationally expensive and can increase bake times. However, used well, they can add a great depth of realism to your scene lighting and this extra precomputation may be justified. Note that as they are baked only, gameplay performance is not affected.
Whilst Area Lights are not supported by Precomputed Realtime GI, similar soft lighting effects are still possible using ‘Emissive Materials.’ Like Area Lights, emissive materials emit light across their surface area. They contribute to bounced light in your scene and associated properties such as color and intensity can be changed during gameplay.
‘Emission’ is a property of the Standard Shader which allows static objects in our scene to emit light. By default the value of ‘Emission’ is set to zero. This means no light will be emitted by objects assigned materials using the Standard Shader. The HDR color picker can be used to select colors with intensities beyond the 0-1 range in order to create bright light effects similar to those of Area Lights.
There is no range value for emissive materials but light emitted will again falloff at a quadratic rate. Emission will only be received by objects marked as ‘Static’ or “Lightmap Static’ from the Inspector. Similarly, emissive materials applied to non-static, or dynamic geometry such as characters will not contribute to scene lighting.
However, materials with an emission above zero will still appear to glow brightly on-screen even if they are not contributing to scene lighting. This effect can also be produced by selecting ‘None’ from the Standard Shader’s ‘Global Illumination’ Inspector property. Self-illuminating materials like these are a useful way to create effects such as neons or other visible light sources.
Simple neon sign created using the ‘Emission’ property of Unity’s Standard Shader. Notice how the emission from the sign is still shadowed by static geometry - in this case, the sphere.
Emissive materials only directly affect static geometry in your scene. If you need dynamic, or non-static geometry - such as characters, to pick up light from emissive materials, Light Probes must be used. Changing emission values at gameplay will update Light Probes interactively and the results will be visible on any objects presently receiving light from those probes.
Only static objects are considered by Unity’s Baked or Precomputed Realtime GI systems. In order for dynamic objects such as interactive scene elements or characters to pick up some of the rich bounced light that our static geometry receives, we need to record this lighting information into a format which can be quickly read and used in our lighting equations during gameplay.
We do this by placing sample points in the world and then capturing light from all directions. The color information these points record is then encoded into a set of values (or ‘coefficients’) which can be quickly evaluated during gameplay. In Unity, we call these sample points, ‘Light Probes’.
Scene using Light Probes. Notice how they have been placed in greater density around areas of lighting change - such as shadows or color transition.
Light Probes allow moving objects to respond to the same complex bounced lighting which is affecting our lightmaps regardless of whether Baked GI or Precomputed Realtime GI is used. An object’s mesh renderer will look for the Light Probes around its position and blend between their values. This is done by looking for tetrahedrons made up by the position of Light Probes, and then deciding which tetrahedron the object’s pivot falls into. This allows us to place moving characters in scenes and have them appear properly integrated. Without Light Probes, dynamic objects would not receive any global illumination and would appear darker than surrounding, lightmapped geometry.
By default there are no Light Probes in a scene so these will need to be placed using a Light Probe Group (GameObjects>Light>Light Probe Group).
If the ‘Auto’ box is checked at the bottom of your scene precompute settings (Lighting>Scene>Auto), Light Probes will update whenever changes are made to the scene lighting or static geometry. Otherwise they will be updated when the Build button is clicked.
In this document we have given an overview of the considerations which need to be made prior to setting up a scene for lighting. We have also briefly looked at the tools available for creating various lighting effects. However, there is still a lot which we haven’t yet covered.
For a more in-depth look at optimizing your Scenes for Unity's Precomputed Realtime GI, please see our tutorial here.