2d_lights_and_shadows.rst 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. .. _doc_2d_lights_and_shadows:
  2. 2D lights and shadows
  3. =====================
  4. Introduction
  5. ------------
  6. This tutorial explains how the 2D lighting works in the
  7. `lights and shadows <https://github.com/godotengine/godot-demo-projects/tree/master/2d/lights_and_shadows>`_ demo project.
  8. It begins with a brief description of the resources used in the final demo and then describes how
  9. to make a scene like the demo step by step.
  10. .. image:: img/light_shadow_main.png
  11. All the resources for this tutorial can be found in the `official demo repository <https://github.com/godotengine/godot-demo-projects>`_
  12. on github. I suggest you download it before starting. Alternatively,
  13. it can be downloaded from the Project Manager. Launch Godot and in the top
  14. bar select "Templates" and search for "2D Lights and Shadows Demo".
  15. Setup
  16. -----
  17. For this demo we use four textures: two for the lights, one for the shadow casters,
  18. and one for the background. I've included links to them all here if you want to download them
  19. separately from the demo.
  20. The first is the background image (`bg.png <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/bg.png>`_)
  21. used in the demo. You do not necessarily need a background, but we use one for the demo.
  22. The second is a plain black image (`caster.png <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/caster.png>`_)
  23. to use as our shadow caster object. For a top down game this could be a wall or any
  24. other object that casts a shadow.
  25. Next is the light itself (`light.png <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/light.png>`_).
  26. If you click the link you will notice how large it is. The image you use
  27. for a light should cover the area you want your light to cover. This image is
  28. 1024x1024 pixels, so you should use it to cover 1024x1024 pixels in your game.
  29. Lastly, we have the spotlight image (`spot.png <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/spot.png>`_).
  30. The demo uses a blob to show where the light is and the larger light
  31. image to show the effect of the light upon the rest of the scene.
  32. Nodes
  33. -----
  34. The demo uses four different nodes:
  35. * :ref:`CanvasModulate <class_CanvasModulate>`
  36. * :ref:`Sprite <class_Sprite>`
  37. * :ref:`Light2D <class_Light2D>`
  38. * :ref:`LightOccluder2D <class_LightOccluder2D>`
  39. :ref:`CanvasModulate<class_CanvasModulate>` is used to darken the scene.
  40. :ref:`Sprites <class_Sprite>` are used to display the textures for the light blobs, the
  41. background, and for the shadow casters.
  42. :ref:`Light2Ds <class_Light2D>` are used to light the scene. The way a light typically works
  43. is by adding a selected texture over the rest of the scene to simulate lighting. But it can be
  44. used in other ways, for example masking out parts of the scene.
  45. :ref:`LightOccluder2Ds <class_LightOccluder2D>` are used to tell the shader which parts of
  46. the scene cast shadows. The shadows appear only on areas covered by the :ref:`Light2D <class_Light2D>` and
  47. their direction is based on the center of the :ref:`Light <class_Light2D>`.
  48. Lights
  49. ------
  50. :ref:`Lights <class_Light2D>` cover the entire extent of their respective Texture. They use additive
  51. blending to add the color of their texture to the scene.
  52. .. image:: img/light_shadow_light.png
  53. :ref:`Lights <class_Light2D>` have four ``Modes``: ``Add``, ``Sub``, ``Mix``, and ``Mask``.
  54. ``Add`` adds the color of the light texture to the scene. It brightens the area under the light.
  55. ``Sub`` subtracts the color of the light from the scene. It darkens the area under the light.
  56. ``Mix`` mixes the color of the light with the underlying scene. The resulting brightness is
  57. halfway between the color of the light and the color underneath.
  58. ``Mask`` is used to mask out areas that are covered by the light. Masked out areas are hidden or revealed based on
  59. the color of the light.
  60. For the demo the lights have two components, the :ref:`Light <class_Light2D>` itself (which
  61. is the effect of the light), and a :ref:`Sprite <class_Sprite>` blob which is an image showing the
  62. location of the light source. A child :ref:`Sprite <class_Sprite>` is not necessary to make a
  63. :ref:`Light <class_Light2D>` work.
  64. .. image:: img/light_shadow_light_blob.png
  65. Shadows
  66. -------
  67. Shadows are made by intersecting a :ref:`Light <class_Light2D>` with a :ref:`LightOccluder2D <class_LightOccluder2D>`.
  68. By default shadows are turned off. To turn them on click on the :ref:`Light <class_Light2D>`
  69. and under the Shadows section check ``Enabled``.
  70. In the demo we are using a :ref:`Sprite <class_Sprite>` with a Texture on it to make the "Shadow Casters",
  71. but in reality all you need is a couple of :ref:`LightOccluder2Ds <class_LightOccluder2D>`. By itself
  72. the :ref:`LightOccluder2D <class_LightOccluder2D>` looks like a dark spot and in this demo the :ref:`Sprite <class_Sprite>` is
  73. just a black square.
  74. Step by step
  75. ------------
  76. Now that we have covered the basics of the nodes being used, we can now walk step by step through
  77. the process of making a scene like the one found in the demo.
  78. First add a :ref:`Sprite <class_Sprite>` and set its texture to the `background image <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/bg.png>`_. For your game this can be any
  79. background you choose. For this style of shadow it is most likely to be a floor texture.
  80. .. image:: img/light_shadow_background.png
  81. Next create three :ref:`Light2D's <class_Light2D>` and set their textures to the `light image <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/light.png>`_. You can alter their
  82. color in the top section. By default shadows are turned off and the ``mode`` is set to ``add``. This
  83. means that each light adds its own color to whatever is underneath.
  84. .. image:: img/light_shadow_all_lights_no_blob.png
  85. Next add a child :ref:`Sprite <class_Sprite>` to each of the :ref:`Light <class_Light2D>` nodes, and set
  86. the :ref:`Sprite's <class_Sprite>` texture to the `blob image <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/spot.png>`_. Each of these
  87. should stay centered on the :ref:`Light <class_Light2D>` node. The blob is the image of the light
  88. itself while the :ref:`Light <class_Light2D>` shows the effect that the light has on the scene. The
  89. :ref:`LightOccluder2D's <class_LightOccluder2D>` will treat the position of the light as the center of the :ref:`Light <class_Light2D>`
  90. node, which is why we want the blob to be centered on its parent :ref:`Light <class_Light2D>`.
  91. .. image:: img/light_shadow_all_lights.png
  92. .. note:: At the time of writing, 3.0 is the stable release version. The 3.1 development branch contains
  93. many changes to the animation system, so the animations in the demo will not be covered here.
  94. See :ref:`doc_introduction_2d_animation` for more information.
  95. Right now the scene should look too bright. This is because all three lights are adding color to the scene.
  96. This is why the demo uses a :ref:`CanvasModulate <class_CanvasModulate>` in the scene. The
  97. :ref:`CanvasModulate <class_CanvasModulate>` multiples the entire viewport by a specific color.
  98. Add a :ref:`CanvasModulate <class_CanvasModulate>` to the scene and set its color to ``rgb(70, 70, 70)``.
  99. This will make the scene sufficiently dark to see the effects of the lights distinctly.
  100. .. image:: img/light_shadow_ambient.png
  101. Now we add the shadow casters.
  102. The demo uses a :ref:`Node <class_Node2D>` named "casters" to organize the shadow casters. Add a
  103. :ref:`Node2D <class_Node2D>` to the scene. It will be used to group all the shadow casters together.
  104. This way we can show and hide them all at the same time.
  105. Each shadow caster is made of a :ref:`Sprite <class_Sprite>`, with a :ref:`LightOccluder2D <class_LightOccluder2D>`
  106. child. For the demo the :ref:`Sprite <class_Sprite>` has a texture
  107. set to the `caster image <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/caster.png>`_ and nothing else. The child :ref:`LightOccluder2D <class_LightOccluder2D>` is where all the magic happens. In a
  108. game the :ref:`Sprite <class_Sprite>` could be more than a black box; it could be an image of whatever object is casting
  109. the shadow: a wall, a magical chest, or anything else.
  110. .. image:: img/light_shadow_sprites.png
  111. :ref:`LightOccluder2Ds <class_LightOccluder2D>` tell the game what shape the occluder has. They hold
  112. an :ref:`OccluderPolygon2D <class_OccluderPolygon2D>`, which is a container
  113. for a polygon and some other information. For this demo, since our wall is a square, we
  114. set ``Polygon`` to a square. The other default settings are fine.
  115. The first setting, ``Closed`` can be either ``on`` or ``off``. A closed polygon occludes light
  116. coming from all directions. An open polygon only occludes light from one direction
  117. ``Cull Mode`` lets you select which direction gets culled. The default is ``Disabled``, meaning the occluder
  118. will cast a shadow no matter which side the light is on. The other two settings ``Clockwise`` and
  119. ``Counter-Clockwise`` refer to the winding order of the vertices of the polygon. The winding order
  120. is used to determine which side of the line is inside the polygon. Only outward facing lines cast shadows.
  121. To illustrate the difference, here is an image of a :ref:`LightOccluder2D <class_LightOccluder2D>` with ``Closed``
  122. set to ``off`` in the corresponding :ref:`OccluderPolygon2D <class_OccluderPolygon2D>`, so that the
  123. lines of the polygon can be seen:
  124. .. image:: img/light_shadow_cull_disabled.png
  125. .. note:: ``Cull Mode`` is set to ``Disabled``. All three lines cast shadows.
  126. .. image:: img/light_shadow_cull_clockwise.png
  127. .. note:: ``Cull Mode`` is set to ``Clockwise``. Only the top and right lines cast shadows.
  128. .. image:: img/light_shadow_cull_counter_clockwise.png
  129. .. note:: ``Cull Mode`` is set to ``Counter-Clockwise``. Only the bottom line casts a shadow.
  130. If ``Closed`` was set to ``on`` there would be an additional vertical line on the
  131. left which would cast a shadow as well.
  132. When you have added the :ref:`LightOccluder2Ds <class_LightOccluder2D>` the shadows still won't
  133. appear. You need to go back into the :ref:`Light2Ds <class_Light2D>` and under the Shadow
  134. section set ``Enable`` to ``on``. This turns on shadows with hard edges like in the image below.
  135. .. image:: img/light_shadow_filter0_pcf0.png
  136. To give the shadows that nice, soft edge look we set the variables ``filter``, ``filter smooth``, and
  137. ``gradient length``. Godot supports `Percentage Closer Filtering <https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch11.html>`_
  138. (PCF), which takes multiple samples of the shadow map around a pixel and blurs them to create
  139. a smooth shadow effect. The higher the number of samples the smoother the shadow will
  140. look, but the slower it will run. That is why Godot provides 3-13 samples by default and allows you to choose.
  141. The demo uses PCF7.
  142. .. image:: img/light_shadow_normal.png
  143. .. note:: This is a shadow rendered with the demo's settings. ``gradient length`` is set
  144. to ``1.3``, ``filter smooth`` is set to ``11.1``, and ``filter`` is set to ``PCF7``.
  145. .. image:: img/light_shadow_pcf13.png
  146. .. note:: ``filter`` is set to ``PCF13``. Notice how the shadow becomes wider, this is because the
  147. distance between samples is based on the variable ``filter smooth``.
  148. In order to make use of filtering you need to set the ``filter smooth`` variable.
  149. This dictates how far apart the samples are. If you want the soft area to extend quite far, you can increase
  150. the size of ``filter smooth``. However, with few samples and a large filter smooth, you can see lines
  151. forming between the samples.
  152. .. image:: img/light_shadow_filter30.png
  153. .. note:: ``filter smooth`` is set to ``30``.
  154. The different :ref:`Light <class_Light2D>` nodes in the demo use different values for filter smooth.
  155. Play around with it and see what you like.
  156. .. image:: img/light_shadow_filter0.png
  157. .. note:: ``filter smooth`` is set to ``0``.
  158. Lastly, there is the variable ``gradient length``. For some smooth shadows it is preferable not to have the
  159. shadow start immediately on the object, as this produces a hard edge. The gradient length variable creates
  160. a smooth gradient to begin the shadow to reduce the effect of the hard edge.
  161. .. image:: img/light_shadow_grad0.png
  162. .. note:: ``gradient length`` is set to ``0``.
  163. .. image:: img/light_shadow_grad10.png
  164. .. note:: ``gradient length`` is set to ``10``.
  165. You will need to play around with the options a bit to find settings that suit your project. There is no right solution
  166. for everyone, which is why Godot provides so much flexibility. Just keep in mind that the higher ``filter``
  167. set the more expensive the shadows will be.