Hour 16. Lights and Shadows
What You’ll Learn in This Hour:
How to add and position lights inGodot
Different types of light
How to configure shadows
Types of shadow filters
During this hour, you’ll see how to set up lights inGodot, and how to add them to the scene and position them using the editor. You’ll see how
to set up the properties of lighting. You’ll learn how to enable shadow and configure its properties, and how filtering works for shadows. You’ll
also learn about techniques such as ambient occlusion and shadow mapping.
Light Sources
An important part of a 3D scene is the lighting. It can make the mood of the scene and improve the focus of the action. You can have an
outside setting where the sun is the main light source and everything is visible. You can have a claustrophobic room in a horror game with only
the beam of a flashlight as a light source. These details can enrich the atmosphere of your scenes.
There are many ways to light a scene inGodot. You can use the lighting nodes, use ambient lighting from the environment, or make use of
emissive materials. The combination of these techniques makes a scene shine in your game.
Directional Light
This type of light is very common in games. It represents a big source of light that is very far away, like the sun. You can have it in your scene by
adding a
DirectionalLight node. The position of the light does not matter, so you can move it around to place the editor gizmo where it
doesn’t disturb you. The only important setting is the direction, which is defined by the node’s rotation (Figure 16.1).
FIGURE 16.1
Directional lighting applied to a simple scene.
Since this is a very simple light, it does not have any specific properties. It’s also very light on performance, because the light rays all travel in
the same direction (though it doesn’t have the easiest shadow mapping, as we’ll see later). Still, there are a few properties inherent to every
light node (see Table 16.1).
TABLE 16.1 Light Properties
PropertyDescription
Color
The color of the light. Setting it for something other than white will tint the environment. Setting it to black will be the same as having
no light.
Energy
Sets the amount of light emitted by the node. Zero means that no light will be emitted, and values over 1 will overexpose the scene.
Negative If enabled, the light source will emit a “shadow” (i.e., remove light from other sources).
Specular Specifies how much of a specular highlight the materials will receive from the light source. If the value is 0, the specular property of
the materials won’t have any effect.
Cull
Mask
Sets up the masking for reflection, and is used with a
ReflectionProbe node. The probe will only reflect if the masks match.
Editor
Only
If enabled, the light will only be visible in the editor, not in the game. This is useful when adding extra illumination to your scene while
designing a dark level.
TRY IT YOURSELF
Directional Lighting
Follow this simple exercise to see the effect of light in a scene:
1. Create a new scene and add a
Spatial node as the root.
2. Add a
MeshInstance node. Set its Mesh property as a new
CapsuleMesh.
3. Create a
WorldEnvironment node and add an empty
Environment to it.
4. Add a
DirectionalLight to the scene.
5. Change the rotation of the light. See how it changes the illumination of the mesh.
6. Change the position of the light. Notice that this type of light isn’t affected by its position.
111111111
22222222Omni Light
The
OmniLight node disperses a light in all directions from a single point (Figure 16.2). This is the equivalent of a light bulb without a
lampshade, and also means that the light is attenuated for objects farther away from the source (see Table 16.2).
FIGURE 16.2
A simple scene with anOmni Light in the middle.
TABLE 16.2 OmniLight Properties
Property Description
Range
Sets how far the lighting goes. It can also be edited by moving the gizmo in the visual editor.
AttenuationConfigures the attenuation curve of the emission. Higher values will make it attenuate faster (i.e., show a weaker light on distant
objects).
Shadow
Mode
Selects the shadow mapping technique. Dual Paraboloid is a faster method, so it has better performance (at the cost of accuracy).
The Cube mode produces more accurate shadows.
Shadow
Detail
Specifies the focus of the shadow detail. If you’re casting the shadow onto a wall, select Vertical; if it’s being cast onto a floor,
select the Horizontal detail.
In the real world, lights attenuate by an inverse square law, but since that can be tricky to work with in an artistic setting, Godot provides an
option to adjust the attenuation curve. This allows you to use less intense light that reaches farther away than a real lamp would. You can also
do the opposite: create a bright light that doesn’t reach very far.
Spot Light
The last type of 3D light node is the
SpotLight. This is not very different than anOmniLight, except it focuses as a cone instead of
spreading the light in every direction. It is very useful for flashlights, street lamps, or any source that can be pointed.
The properties of the
SpotLight (Figure 16.3) aren’t very different from the
OmniLight’s. The range is not a radius but the distance
from the source. There’s also an Angle property, which lets you configure the aperture of the light to make it narrower or wider. This type of light
also attenuates over distance.
FIGURE 16.3
A SpotLight applied to a simple scene.
TIP
Choosing the Right Type of Light
Each type of light can be used in a specific situation. Note that you can put many light sources in a scene, so you are not limited to a specific
one. You should mix and match different types to achieve the desired effect.
Directional lights are used to emulate the sun, and is great for outside scenes. Sometimes, you can get away with it as your single light source.
Omni lights are used for sources that go in all directions, such as a lamp bulb. The spot lights can be used for flood lights and even for tractor
beams.
Essentially, you should think of how the light will flow from the source. You can try different types to see what looks best for your scene. Also
note that not every illumination needs to come from a light node; you can use ambient light and emissive materials too.
Other Light Sources
Besides the lighting nodes, you can use some other sources for illumination. Most come from the environment, which will be covered in greater
detail in Hour 18. For the sake of completeness, let’s go through the other ways to add light to a scene.
Ambient and Sky Light
The
Environment resource can provide illumination by itself. It can use the light from the sky or from a custom color. Note that such
lighting does not have a specific source: it lights every pixel with the same intensity, so it won’t produce a shadow.
Emissive Materials
The materials of the objects can emit light too. They need a
GIProbe node (a special node to make Global Illumination, which will be
shown in Hour 18) to properly illuminate the environment around them, but this can be easily achieved. While this should not be abused and
works best for static items, it provides an interesting effect, and works great for glowing objects.
Indirect Lighting
The
GIProbe node also provides indirect lighting for the scene by calculating the light that bounces off objects to illuminate others. This
isn’t a light source per se because it depends on other sources, but it can provide an atmospheric effect for objects that aren’t lit by direct light.
111111111
22222222Shadows
The polar opposite of a light is a shadow. To create a realistic effect, you’ll need to keep light from reaching areas where the object blocks it.
Objects that do not cast shadows don’t seem to belong in the game world, so shadows are quite useful for creating a nice ambience.
Shadows are a property of lights, so you can configure each individually via Light nodes. You can even disable the shadows for a specific light
(in fact, they are disabled by default). Table 16.3 shows the properties of shadows available in the Light nodes.
TABLE 16.3 Properties of Shadows
Property
Description
Enabled
Enables the propagation of shadows from the light source.
Color
Sets the color of the shadow. Realistic shadows are usually black, but you can change this for an effect or to debug lighting
issues.
Bias
Adjusts where the shadow should begin. This is a useful setting for self-shadowing meshes.
Contact
If the shadows aren’t touching the bottom of an object, you can adjust this value to increase the contact point.
Reverse Cull
Face
If enabled, this uses the reverse face to cast the shadow (i.e., the internal faces of the mesh).
NOTE
Self-Shadowing Meshes
Sometimes, a mesh can cast a shadow upon itself. This depends on the light type and position as well as the mesh shape. It makes it hard to
predict where the shadows should hit; this is why the Bias property is available.
If you’re having issues with self-shadowing, even on meshes that should not do it, try adjusting the Bias and see how it affects the scene. Often,
the look can be improved by changing the properties of the nodes.
Directional Light Shadows
One thing to consider when placing a
DirectionalLight is that it illuminates large areas. This may become an issue, since the resolution of
the shadow texture is limited. You can improve the look of the shadows by choosing a different mapping mode.
Orthogonal mode uses the same number of pixels for the entire scene, so it will use the same detail even for places far away from the camera.
To mitigate that, you can use the Parallel Split Shadow Mapping (PSSM) mode, which divides the scene in two or four sections and uses less
detail for farther objects, since they’re visually smaller anyway. This option comes with a performance hit, as more splits consume more power.
NOTE
Shadow Mapping
The term “shadow mapping” is a general concept that represents the process of computing the shadows of dynamic objects in computer
graphics. The engine generates a texture that indicates where the shadow will be applied (the “map”) and uses it to draw the scene.
While the algorithm is provided byGodot, it is up to the artist to configure its properties to make the scene look better.
Omni Light Shadows
For Omni Lights, generating the shadow map is also a bit troublesome, because it’s hard to use a single texture that maps 360 degrees of
light rays. Essentially, Godot offers two solutions for this: dual-paraboloid mapping and cube mapping.
Dual-Paraboloid Shadow Mapping (DPSM) is a fast technique that relies on a paraboloid-shaped shadow map (Figure 16.4). It facilitates the
calculation of the map, but it’s not very accurate. It may have poor results on weaker systems, such as mobile phones. It also may have
problems if the objects aren’t well tessellated (i.e., it might require more vertices in the meshes to look good). Still, if the scene looks good with
this, it’s likely the best option.
FIGURE 16.4
Dual Paraboloid Shadow Mapping (left) compared to a cube map (right). The first method is faster, but leads to imperfections.
Cube mapping relies on a cube around the map, so it needs six textures (one for each face), and comes at the cost of GPU memory. It also
needs more passes to render the shadow, making it more expensive. This mode produces more accurate shadows, though, so it might be
necessary for some scenes.
TIP
Shadow Filter
To make the shadows look softer and less blocky, Godot uses a technique called Percentage Closer Filtering (PCF). It consists of taking more
samples to decide which fragments fall under the shadow. The more samples it takes, the softer the shadow looks (at the cost of GPU
resources).
The default is a safe bet, but you can change it in Project Settings (under Rendering > Quality) if you intend to have higher hardware
requirements for your game.
Ambient Occlusion
111111111
22222222Another technique to increase the shadowing of the scene is Ambient Occlusion. This consists of darkening the parts of the object that
wouldn’t be reached by direct ambient light. This type of shadow isn’t generated by the lights: instead, it takes light from the material of the
mesh or the environment properties.
There are essentially two possibilities for adding ambient occlusion inGodot: Screen Space Ambient Occlusion (SSAO) and the occlusion
texture in the material. SSAO has the advantage of being generated by the engine, but it isn’t as good-looking as a properly crafted occlusion
texture.
Lights in 2D
Godot also offers the possibility of lighting in 2D games, though in a much simpler fashion given the limited dimensions for light to flow. Still, it
can add a nice effect to some games.
The
Light2D node is responsible for adding light into a 2D world (Table 16.4). For it to work, you’ll need to add a texture to give it shape
and color. This texture will be cast onto the other objects on the screen to give them light. Notice that it doesn’t affect the viewport background.
TABLE 16.4 Properties of Light2D
PropertyDescription
Enabled Enable or disable the light effect.
Editor
Only
Has the same function as for 3D lights. If enabled, it will only affect the editor and not the running game.
Texture
Sets the texture that makes the color and shape of the light. Gradients with alpha works very well for this property.
Offset
Changes the position of the light in respect to its transform. Can be used to effectively change the pivot point of rotation, and to make
shake effects without affecting the transform. Also affects the point from where the light is propagated, which makes a difference
when using shadows.
Texture
Scale
Modifies the size of the light texture. You can use this to make the light bigger or smaller, independently of the scale of the node.
Color
Tints the light color. This is useful for making different light colors with the same texture. (Note that if you set the alpha to 0, the light
won’t have any effect.)
Energy
Affects how powerful the light is. A value of 0 has the same effect as disabling the light. You can set it to a value greater than 1 to
have it overexposed.
Mode
Changes the alpha blending mode of the light.
NOTE
Light Range and Normal Mapping
The
Light2D node has a Range property section with which you can set up how the light will interact with different layers of objects. You can
set a limit to the Z-range, which will affect only items that have their Z-property in that (inclusive) range. The same applies to the layer, which
applies to objects that are children to a
CanvasLayer node.
You can also set the height of the light, though this only has a meaningful effect for Sprite nodes with a Normal Map applied. This can give the
player a sense of depth without going into a 3D game.
Shadows in 2D
To stop the light from propagating, you’ll need a
LightOccluder2D node. This prevents the light from reaching a certain area and creating
shadows. Note that it only makes a difference if the
Light2D node has its shadows enabled.
Once you add the node, you can create a new polygon for it using the
Create Polygon tool in the editor. You’ll need to close the polygon
for it to work as intended, even if you don’t need it to be closed (you can right-click in the editor to close it). While the polygon is shown with a
darker tint in the editor, it won’t be seen like this in the running game. Instead, it just stops the light from crossing its border (see Figure 16.5).
FIGURE 16.5
Lights and shadows in 2D.
NOTE
Light Cull Mask
Another property of the
Light2D node is the Light Cull Mask. This affects how the occluders are selected. A light will only affect occluders
that have the same light mask, allowing you to be selective about how lights and shadows will be formed.
For instance, you can have the player character emit a light from its center but not be affected by it, while still casting shadows from other light
sources.
The
OccluderPolygon2D resource has a couple of properties. Cull mode can change how the light is blocked, so it’s possible to make
an object that is fully lit but casts a shadow in the opposite direction of the light. You can also set the polygon as open so that the last side won’t
occlude the light.
111111111
22222222TIP
Soft Shadows
It is possible to achieve soft shadows in 2D by changing the Gradient and Filter properties of the Shadow section in the
Light2D node.
Check out the 2D Lighting demo available withGodot to see an example of this.
Summary
This hour covered the basic ideas of lights and shadows inGodot. First, you learned about the three direct light sources for 3D. Then you saw
other options available for indirect lighting, and learned how to enable and configure shadows.
Q&A
Q. My shadows don’t look right. What can I do?
A. Shadows are quite tricky to create. Essentially, you’ll need to tweak the shadow settings to get a better look. Sometimes, you’ll need to
move things or change the geometry of your objects to help the generation of shadows.
Q. Can I have any number of lights?
A. You might hit some hard limits imposed byGodot if you add too much, but you’ll likely hit hardware limits before that happens. Usually,
having well-placed lights looks better than having a large amount of them.
Workshop
Answer the following questions to recapitulate this hour’s content.
Quiz
1. What are the three light nodes for 3D scenes?
2. True or False: Only light nodes can provide illumination to a scene.
3. True or False: It does not matter if you change the position of
DirectionalLight.
4. True or False: You can’t have soft shadows in 2D games.
Answers
1.
DirectionalLight,
OmniLight, and
SpotLight.
2. False. You can also have ambient light and emissive materials.
3. True. Directional lights simulate rays that come from a very far place, so its transform position isn’t relevant.
4. False. Godot 3 provides configurable shadows in 2D that can cast soft shadows.
Exercises
Try this exercise to get a better feel of lights and shadows inGodot.
1. Create a new scene and add a
Spatial node as the root. Save the scene.
2. Add a
WorldEnvironment node. Create a new empty
Environment for it.
3. Create a
MeshInstance node. Add a
PlaneMesh primitive and set its size to (50, 50). This will be the ground.
4. Add another
MeshInstance with a
CapsuleMesh attached to it. Increase its Y-axis position so it’s above the ground.
5. Add a
DirectionalLight to the scene. Enable shadow casting.
6. Change the rotation of the light. Note how it affects the illumination of the floor and the capsule.
7. Disable the visibility of the light so that it has no effect.
8. Add an
OmniLight node. Remember to enable the shadows on it.
9. Change its position and range. See the effects of the properties in the scene.
10. Disable the visibility on this light too.
11. Now add a
SpotLight to the scene and activate its shadows.
12. Again, change its properties to light the object and see how it affects the objects in the scene.
111111111
22222222