2D Beleuchtung und Schatten

Einführung

In dieser Anleitung wird erklärt, wie die 2D-Beleuchtung im Beispiel-Projekt Lichter und Schatten funktioniert. Es beginnt mit einer kurzen Beschreibung der in dem finalen Beispiel verwendeten Ressourcen und beschreibt dann Schritt für Schritt, wie eine Szene wie in diesem Beispiel erstellt wird.

../../_images/light_shadow_main.png

All the resources for this tutorial can be found in the official demo repository on GitHub. I suggest you download it before starting. Alternatively, it can be downloaded from the Project Manager. Launch Godot and in the top bar select "Templates" and search for "2D Lights and Shadows Demo".

Aufbau

Für dieses Beispiel verwenden wir vier Texturen: zwei für die Lichter, eine für die Schattenwerfer und eine für den Hintergrund. Ich habe hier Links zu allen hinzugefügt, wenn Sie sie separat von der Demo herunterladen möchten.

The first is the background image (background.png) used in the demo. You do not necessarily need a background, but we use one for the demo.

The second is a plain black image (caster.png) to use as our shadow caster object. For a top down game this could be a wall or any other object that casts a shadow.

Next is the light itself (light.png). If you click the link you will notice how large it is. The image you use for a light should cover the area you want your light to cover. This image is 1024x1024 pixels, so you should use it to cover 1024x1024 pixels in your game.

Lastly, we have the spotlight image (spot.png). The demo uses a blob to show where the light is and the larger light image to show the effect of the light upon the rest of the scene.

Nodes ("Knoten")

Das Beispiel verwendet vier verschiedene Nodes:

CanvasModulate wird verwendet, um die Szene abzudunkeln.

Sprites werden verwendet, um die Texturen für die Lichtflecken, den Hintergrund und für die Schattenwerfer anzuzeigen.

Light2Ds werden verwendet, um die Szene zu beleuchten. Die Art und Weise, wie ein Licht normalerweise funktioniert, besteht darin eine ausgewählte Textur über dem Rest der Szene hinzuzufügen, um die Beleuchtung zu simulieren. Es kann aber auch auf andere Weise verwendet werden, z.B. um Teile der Szene auszublenden.

LightOccluder2Ds are used to tell the shader which parts of the scene cast shadows. The shadows appear only on areas covered by the Light2D and their direction is based on the center of the Light.

Lichter

Lights cover the entire extent of their respective Texture. They use additive blending to add the color of their texture to the scene.

../../_images/light_shadow_light.png

Lights have four Modes: Add, Sub, Mix, and Mask.

Add Fügt der Szene die Farbe der hellen Textur hinzu. Es hellt den Bereich unter dem Licht auf.

Sub subtrahiert die Farbe des Lichts von der Szene. Es verdunkelt den Bereich unter dem Licht.

Mix mixes the color of the light with the underlying scene. The resulting brightness is halfway between the color of the light and the color underneath.

Mask is used to mask out areas that are covered by the light. Masked out areas are hidden or revealed based on the color of the light.

For the demo the lights have two components, the Light itself (which is the effect of the light), and a Sprite blob which is an image showing the location of the light source. A child Sprite is not necessary to make a Light work.

../../_images/light_shadow_light_blob.png

Schatten

Schatten werden erzeugt, indem ein Licht mit einem LightOccluder2D kombiniert wird.

Standardmäßig sind Schatten deaktiviert. Um sie einzuschalten, klicken Sie auf Light und aktivieren Sie im Abschnitt Shadows Enabled.

In the demo we are using a Sprite with a Texture on it to make the "Shadow Casters", but in reality all you need is a couple of LightOccluder2Ds. By itself the LightOccluder2D looks like a dark spot and in this demo the Sprite is just a black square.

Schritt für Schritt

Now that we have covered the basics of the nodes being used, we can now walk step by step through the process of making a scene like the one found in the demo.

First add a Sprite and set its texture to the background image. For your game this can be any background you choose. For this style of shadow it is most likely to be a floor texture.

../../_images/light_shadow_background.png

Next create three Light2D's and set their textures to the light image. You can alter their color in the top section. By default shadows are turned off and the mode is set to add. This means that each light adds its own color to whatever is underneath.

../../_images/light_shadow_all_lights_no_blob.png

Next add a child Sprite to each of the Light nodes, and set the Sprite's texture to the blob image. Each of these should stay centered on the Light node. The blob is the image of the light itself while the Light shows the effect that the light has on the scene. The LightOccluder2D's will treat the position of the light as the center of the Light node, which is why we want the blob to be centered on its parent Light.

../../_images/light_shadow_all_lights.png

Bemerkung

At the time of writing, 3.0 is the stable release version. The 3.1 development branch contains many changes to the animation system, so the animations in the demo will not be covered here. See Einführung in die 2D-Animation for more information.

Right now the scene should look too bright. This is because all three lights are adding color to the scene. This is why the demo uses a CanvasModulate in the scene. The CanvasModulate multiples the entire viewport by a specific color.

Add a CanvasModulate to the scene and set its color to rgb(70, 70, 70). This will make the scene sufficiently dark to see the effects of the lights distinctly.

../../_images/light_shadow_ambient.png

Jetzt fügen wir die Schattenwerfer hinzu.

The demo uses a Node named "casters" to organize the shadow casters. Add a Node2D to the scene. It will be used to group all the shadow casters together. This way we can show and hide them all at the same time.

Each shadow caster is made of a Sprite, with a LightOccluder2D child. For the demo the Sprite has a texture set to the caster image and nothing else. The child LightOccluder2D is where all the magic happens. In a game the Sprite could be more than a black box; it could be an image of whatever object is casting the shadow: a wall, a magical chest, or anything else.

../../_images/light_shadow_sprites.png

LightOccluder2Ds tell the game what shape the occluder has. They hold an OccluderPolygon2D, which is a container for a polygon and some other information. For this demo, since our wall is a square, we set Polygon to a square. The other default settings are fine.

The first setting, Closed can be either on or off. A closed polygon occludes light coming from all directions. An open polygon only occludes light from one direction

Cull Mode lets you select which direction gets culled. The default is Disabled, meaning the occluder will cast a shadow no matter which side the light is on. The other two settings Clockwise and Counter-Clockwise refer to the winding order of the vertices of the polygon. The winding order is used to determine which side of the line is inside the polygon. Only outward facing lines cast shadows.

To illustrate the difference, here is an image of a LightOccluder2D with Closed set to off in the corresponding OccluderPolygon2D, so that the lines of the polygon can be seen:

../../_images/light_shadow_cull_disabled.png

Bemerkung

Cull Mode is set to Disabled. All three lines cast shadows.

../../_images/light_shadow_cull_clockwise.png

Bemerkung

Cull Mode ist auf Clockwise gesetzt. Nur die obere und rechte Linie werfen Schatten.

../../_images/light_shadow_cull_counter_clockwise.png

Bemerkung

Cull Mode is set to Counter-Clockwise. Only the bottom line casts a shadow. If Closed was set to on there would be an additional vertical line on the left which would cast a shadow as well.

When you have added the LightOccluder2Ds the shadows still won't appear. You need to go back into the Light2Ds and under the Shadow section set Enable to on. This turns on shadows with hard edges like in the image below.

../../_images/light_shadow_filter0_pcf0.png

To give the shadows that nice, soft edge look we set the variables filter, filter smooth, and gradient length. Godot supports Percentage Closer Filtering (PCF), which takes multiple samples of the shadow map around a pixel and blurs them to create a smooth shadow effect. The higher the number of samples the smoother the shadow will look, but the slower it will run. That is why Godot provides 3-13 samples by default and allows you to choose. The demo uses PCF7.

../../_images/light_shadow_normal.png

Bemerkung

This is a shadow rendered with the demo's settings. gradient length is set to 1.3, filter smooth is set to 11.1, and filter is set to PCF7.

../../_images/light_shadow_pcf13.png

Bemerkung

filter is set to PCF13. Notice how the shadow becomes wider, this is because the distance between samples is based on the variable filter smooth.

In order to make use of filtering you need to set the filter smooth variable. This dictates how far apart the samples are. If you want the soft area to extend quite far, you can increase the size of filter smooth. However, with few samples and a large filter smooth, you can see lines forming between the samples.

../../_images/light_shadow_filter30.png

Bemerkung

filter smooth ist auf 30 gesetzt.

The different Light nodes in the demo use different values for filter smooth. Play around with it and see what you like.

../../_images/light_shadow_filter0.png

Bemerkung

filter smooth ist auf 0 gesetzt.

Lastly, there is the variable gradient length. For some smooth shadows it is preferable not to have the shadow start immediately on the object, as this produces a hard edge. The gradient length variable creates a smooth gradient to begin the shadow to reduce the effect of the hard edge.

../../_images/light_shadow_grad0.png

Bemerkung

gradient length ist auf 0 gesetzt.

../../_images/light_shadow_grad10.png

Bemerkung

gradient length ist auf 10 gesetzt.

You will need to play around with the options a bit to find settings that suit your project. There is no right solution for everyone, which is why Godot provides so much flexibility. Just keep in mind that the higher filter set the more expensive the shadows will be.