2d_lights_and_shadows.rst 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. .. _doc_2d_lights_and_shadows:
  2. 2D lights and shadows
  3. =====================
  4. Introduction
  5. ------------
  6. By default, 2D scenes in Godot are unshaded, with no lights and shadows visible.
  7. While this is fast to render, unshaded scenes can look bland. Godot provides the
  8. ability to use real-time 2D lighting and shadows, which can greatly enhance the
  9. sense of depth in your project.
  10. .. figure:: img/2d_lights_and_shadows_disabled.webp
  11. :align: center
  12. :alt: No 2D lights or shadows, scene is unshaded
  13. No 2D lights or shadows, scene is unshaded
  14. .. figure:: img/2d_lights_and_shadows_enabled_no_shadows.webp
  15. :align: center
  16. :alt: 2D lights enabled (without shadows)
  17. 2D lights enabled (without shadows)
  18. .. figure:: img/2d_lights_and_shadows_enabled.webp
  19. :align: center
  20. :alt: 2D lights and shadows enabled
  21. 2D lights and shadows enabled
  22. Nodes
  23. -----
  24. There are several nodes involved in a complete 2D lighting setup:
  25. - :ref:`CanvasModulate <class_CanvasModulate>` (to darken the rest of the scene)
  26. - :ref:`PointLight2D <class_PointLight2D>` (for omnidirectional or spot lights)
  27. - :ref:`DirectionalLight2D <class_PointLight2D>` (for sunlight or moonlight)
  28. - :ref:`LightOccluder2D <class_LightOccluder2D>` (for light shadow casters)
  29. - Other 2D nodes that receive lighting, such as Sprite2D or TileMap.
  30. :ref:`CanvasModulate <class_CanvasModulate>` is used to darken the scene by
  31. specifying a color that will act as the base "ambient" color. This is the final
  32. lighting color in areas that are *not* reached by any 2D light. Without a
  33. CanvasModulate node, the final scene would look too bright as 2D lights would
  34. only brighten the existing unshaded appearance (which appears fully lit).
  35. :ref:`Sprite2Ds <class_Sprite2D>` are used to display the textures for the light
  36. blobs, the background, and for the shadow casters.
  37. :ref:`PointLight2Ds <class_PointLight2D>` are used to light the scene. The way a
  38. light typically works is by adding a selected texture over the rest of the scene
  39. to simulate lighting.
  40. :ref:`LightOccluder2Ds <class_LightOccluder2D>` are used to tell the shader
  41. which parts of the scene cast shadows. These occluders can be placed as
  42. independent nodes or can be part of a TileMap node.
  43. The shadows appear only on areas covered by the :ref:`PointLight2D
  44. <class_PointLight2D>` and their direction is based on the center of the
  45. :ref:`Light <class_PointLight2D>`.
  46. .. note::
  47. The background color does **not** receive any lighting. If you want light to
  48. be cast on the background, you need to add a visual representation for the
  49. background, such as a Sprite2D.
  50. The Sprite2D's **Region** properties can be helpful to quickly create a
  51. repeating background texture, but remember to also set **Texture > Repeat** to
  52. **Enabled** in the Sprite2D's properties.
  53. Point lights
  54. ------------
  55. Point lights (also called positional lights) are the most common element in 2D
  56. lighting. Point lights can be used to represent light from torches, fire,
  57. projectiles, etc.
  58. PointLight2D offers the following properties to tweak in the inspector:
  59. - **Texture:** The texture to use as a light source. The texture's size
  60. determines the size of the light. The texture may have an alpha channel, which
  61. is useful when using Light2D's **Mix** blend mode, but it is not required if
  62. using the **Add** (default) or **Subtract** blend modes.
  63. - **Offset:** The offset for the light texture. Unlike when you move the light
  64. node, changing the offset does *not* cause shadows to move.
  65. - **Texture Scale:** The multiplier for the light's size. Higher values will
  66. make the light extend out further. Larger lights have a higher performance
  67. cost as they affect more pixels on screen, so consider this before increasing
  68. a light's size.
  69. - **Height:** The light's virtual height with regards to normal mapping. By
  70. default, the light is very close to surfaces receiving lights. This will make
  71. lighting hardly visible if normal mapping is used, so consider increasing this
  72. value. Adjusting the light's height only makes a visible difference on
  73. surfaces that use normal mapping.
  74. If you don't have a pre-made texture to use in a light, you can use this "neutral"
  75. point light texture (right-click > **Save Image As…**):
  76. .. figure:: img/2d_lights_and_shadows_neutral_point_light.webp
  77. :align: center
  78. :alt: Neutral point light texture
  79. Neutral point light texture
  80. If you need different falloff you can procedurally create a texture by assigning
  81. a **New GradientTexture2D** on the light's **Texture** property. After creating
  82. the resource, expand its **Fill** section and set the fill mode to **Radial**.
  83. You will then have to adjust the gradient itself to start from opaque white to
  84. transparent white, and move its starting location to be in the center.
  85. Directional light
  86. -----------------
  87. New in Godot 4.0 is the ability to have directional lighting in 2D. Directional
  88. lighting is used to represent sunlight or moonlight. Light rays are casted
  89. parallel to each other, as if the sun or moon was infinitely far away from the
  90. surface that is receiving the light.
  91. DirectionalLight2D offers the following properties:
  92. - **Height:** The light's virtual height with regards to normal mapping (``0.0``
  93. = parallel to surfaces, ``1.0`` = perpendicular to surfaces). By default, the
  94. light is fully parallel with the surfaces receiving lights. This will make
  95. lighting hardly visible if normal mapping is used, so consider increasing this
  96. value. Adjusting the light's height only makes a visual difference on surfaces
  97. that use normal mapping. **Height** does not affect shadows' appearance.
  98. - **Max Distance:** The maximum distance from the camera center objects can be
  99. before their shadows are culled (in pixels). Decreasing this value can prevent
  100. objects located outside the camera from casting shadows (while also improving
  101. performance). Camera2D zoom is not taken into account by **Max Distance**,
  102. which means that at higher zoom values, shadows will appear to fade out sooner
  103. when zooming onto a given point.
  104. .. note::
  105. Directional shadows will always appear to be infinitely long, regardless
  106. of the value of the **Height** property. This is a limitation of the shadow
  107. rendering method used for 2D lights in Godot.
  108. To have directional shadows that are not infinitely long, you should disable
  109. shadows in the DirectionalLight2D and use a custom shader that reads from
  110. the 2D signed distance field instead. This distance field is automatically
  111. generated from LightOccluder2D nodes present in the scene.
  112. Common light properties
  113. -----------------------
  114. Both PointLight2D and DirectionalLight2D offer common properties, which are part
  115. of the Light2D base class:
  116. - **Enabled:** Allows toggling the light's visibility. Unlike hiding the light
  117. node, disabling this property will not hide the light's children.
  118. - **Editor Only:** If enabled, the light is only visible within the editor. It
  119. will be automatically disabled in the running project.
  120. - **Color:** The light's color.
  121. - **Energy:** The light's intensity multiplier. Higher values result in a brighter light.
  122. - **Blend Mode:** The blending formula used for light computations. The default
  123. **Add** is suited for most use cases. **Subtract** can be used for negative
  124. lights, which are not physically accurate but can be used for special effects.
  125. The **Mix** blend mode mixes the value of pixels corresponding to the light's
  126. texture with the values of pixels under it by linear interpolation.
  127. - **Range > Z Min:** The lowest Z index affected by the light.
  128. - **Range > Z Max:** The highest Z index affected by the light.
  129. - **Range > Layer Min:** The lowest visual layer affected by the light.
  130. - **Range > Layer Max:** The highest visual layer affected by the light.
  131. - **Range > Item Cull Mask:** Controls which nodes receive light from this node,
  132. depending on the other nodes' enabled visual layers **Occluder Light Mask**.
  133. This can be used to prevent certain objects from receiving light.
  134. Setting up shadows
  135. ------------------
  136. After enabling the **Shadow > Enabled** property on a PointLight2D or
  137. DirectionalLight2D node, you will not see any visual difference initially. This
  138. is because no nodes in your scene have any *occluders* yet, which are used as a
  139. basis for shadow casting.
  140. For shadows to appear in the scene, LightOccluder2D nodes must be added to the
  141. scene. These nodes must also have occluder polygons that are designed to match
  142. the sprite's outline.
  143. Along with their polygon resource (which must be set to have any visual effect),
  144. LightOccluder2D nodes have 2 properties:
  145. - **SDF Collision:** If enabled, the occluder will be part of a real-time
  146. generated *signed distance field* that can be used in custom shaders. When not
  147. using custom shaders that read from this SDF, enabling this makes no visual
  148. difference and has no performance cost, so this is enabled by default for
  149. convenience.
  150. - **Occluder Light Mask:** This is used in tandem with PointLight2D and
  151. DirectionalLight2D's **Shadow > Item Cull Mask** property to control which
  152. objects cast shadows for each light. This can be used to prevent specific
  153. objects from casting shadows.
  154. There are two ways to create light occluders:
  155. Automatically generating a light occluder
  156. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  157. Occluders can be created automatically from Sprite2D nodes by selecting the
  158. node, clicking the **Sprite2D** menu at the top of the 2D editor then choosing
  159. **Create LightOccluder2D Sibling**.
  160. In the dialog that appears, an outline will surround your sprite's edges. If the
  161. outline matches the sprite's edges closely, you can click **OK**. If the outline
  162. is too far away from the sprite's edges (or is "eating" into the sprite's
  163. edges), adjust **Grow (pixels)** and **Shrink (pixels)**, then click **Update
  164. Preview**. Repeat this operation until you get satisfactory results.
  165. Manually drawing a light occluder
  166. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  167. Create a LightOccluder2D node, then select the node and click the "+" button at
  168. the top top of the 2D editor. When asked to create a polygon resource, answer
  169. **Yes**. You can then start drawing an occluder polygon by clicking to create
  170. new points. You can remove existing points by right-clicking them, and you can
  171. create new points from the existing line by clicking on the line then dragging.
  172. The following properties can be adjusted on 2D lights that have shadows enabled:
  173. - **Color:** The color of shaded areas. By default, shaded areas are fully
  174. black, but this can be changed for artistic purposes. The color's alpha
  175. channel controls how much the shadow is tinted by the specified color.
  176. - **Filter:** The filter mode to use for shadows. The default **None** is the
  177. fastest to render, and is well suited for games with a pixel art aesthetic
  178. (due to its "blocky" visuals). If you want a soft shadow, use **PCF5**
  179. instead. **PCF13** is even softer, but is the most demanding to render. PCF13
  180. should only be used for a few lights at once due to its high rendering cost.
  181. - **Filter Smooth:** Controls how much softening is applied to shadows when
  182. **Filter** is set to **PCF5** or **PCF13**. Higher values result in a softer
  183. shadow, but may cause banding artifacts to be visible (especially with PCF5).
  184. - **Item Cull Mask:** Controls which LightOccluder2D nodes cast shadows,
  185. depending on their respective **Occluder Light Mask** properties.
  186. .. figure:: img/2d_lights_and_shadows_hard_shadow.webp
  187. :align: center
  188. :alt: Hard shadows
  189. Hard shadows
  190. .. figure:: img/2d_lights_and_shadows_soft_shadow.webp
  191. :align: center
  192. :alt: Soft shadows (PCF13, Filter Smooth 1.5)
  193. Soft shadows (PCF13, Filter Smooth 1.5)
  194. .. figure:: img/2d_lights_and_shadows_soft_shadow_streaks.webp
  195. :align: center
  196. :alt: Soft shadows with streaking artifacts due to Filter Smooth being too high (PCF5, Filter Smooth 4)
  197. Soft shadows with streaking artifacts due to Filter Smooth being too high (PCF5, Filter Smooth 4)
  198. Occluder draw order
  199. ^^^^^^^^^^^^^^^^^^^
  200. **LightOccluder2Ds follows the usual 2D drawing order.** This is important for 2D
  201. lighting, as this is how you control whether the occluder should occlude the
  202. sprite itself or not.
  203. If the LightOccluder2D node is a *sibling* of the sprite, the occluder will
  204. occlude the sprite itself if it's placed *below* the sprite in the scene tree.
  205. If the LightOccluder2D node is a *child* of the sprite, the occluder will
  206. occlude the sprite itself if **Show Behind Parent** is disabled on the
  207. LightOccluder2D node (which is the default).
  208. Normal and specular maps
  209. ------------------------
  210. Normal maps and specular maps can greatly enhance the sense of depth of your 2D
  211. lighting. Similar to how these work in 3D rendering, normal maps can help make
  212. lighting look less flat by varying its intensity depending on the direction of
  213. the surface receiving light (on a per-pixel basis). Specular maps further help
  214. improve visuals by making some of the light reflect back to the viewer.
  215. Both PointLight2D and DirectionalLight2D support normal mapping and specular
  216. mapping. Since Godot 4.0, normal and specular maps can be assigned to any 2D
  217. element, including nodes that inherit from Node2D or Control.
  218. A normal map represents the direction in which each pixel is "pointing" towards.
  219. This information is then used by the engine to correctly apply lighting to 2D
  220. surfaces in a physically plausible way. Normal maps are typically created from
  221. hand-painted height maps, but they can also be automatically generated from
  222. other textures.
  223. A specular map defines how much each pixel should reflect light (and in which
  224. color, if the specular map contains color). Brighter values will result in a
  225. brighter reflection at that given spot on the texture. Specular maps are
  226. typically created with manual editing, using the diffuse texture as a base.
  227. .. tip::
  228. If you don't have normal or specular maps for your sprites, you can generate
  229. them using the free and open source `Laigter <https://azagaya.itch.io/laigter>`__
  230. tool.
  231. To set up normal maps and/or specular maps on a 2D node, create a new
  232. CanvasTexture resource for the property that draws the node's texture. For
  233. example, on a Sprite2D:
  234. .. figure:: img/2d_lights_and_shadows_create_canvastexture.webp
  235. :align: center
  236. :alt: Creating a CanvasTexture resource for a Sprite2D node
  237. Creating a CanvasTexture resource for a Sprite2D node
  238. Expand the newly created resource. You can find several properties you will need
  239. to adjust:
  240. - **Diffuse > Texture:** The base color texture. In this property, load the
  241. texture you're using for the sprite itself.
  242. - **Normal Map > Texture:** The normal map texture. In this property, load a
  243. normal map texture you've generated from a height map (see the tip above).
  244. - **Specular > Texture:** The specular map texture, which controls the specular
  245. intensity of each pixel on the diffuse texture. The specular map is usually
  246. grayscale, but it can also contain color to multiply the color of reflections
  247. accordingly. In this property, load a specular map texture you've created (see
  248. the tip above).
  249. - **Specular > Color:** The color multiplier for specular reflections.
  250. - **Specular > Shininess:** The specular exponent to use for reflections. Lower
  251. values will increase the brightness of reflections and make them more diffuse,
  252. while higher values will make reflections more localized. High values are more
  253. suited for wet-looking surfaces.
  254. - **Texture > Filter:** Can be set to override the texture filtering mode,
  255. regardless of what the node's property is set to (or the
  256. **Rendering > Textures > Canvas Textures > Default Texture Filter** project
  257. setting).
  258. - **Texture > Repeat:** Can be set to override the texture filtering mode,
  259. regardless of what the node's property is set to (or the
  260. **Rendering > Textures > Canvas Textures > Default Texture Repeat** project
  261. setting).
  262. After enabling normal mapping, you may notice that your lights appear to be
  263. weaker. To resolve this, increase the **Height** property on your PointLight2D
  264. and DirectionalLight2D nodes. You may also want to increase the lights's
  265. **Energy** property slightly to get closer to how your lighting's intensity
  266. looked prior to enabling normal mapping.