Skip to content

Commit 8a0fa5e

Browse files
authored
Merge pull request #11364 from JellyBoonz/fix-2d-lights-shadows-nearest-filtering-doc
Describe how 2D lighting and shadows are computed
1 parent faf45ef commit 8a0fa5e

File tree

1 file changed

+40
-0
lines changed

1 file changed

+40
-0
lines changed

tutorials/2d/2d_lights_and_shadows.rst

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,46 @@ The following properties can be adjusted on 2D lights that have shadows enabled:
236236
- **Item Cull Mask:** Controls which LightOccluder2D nodes cast shadows,
237237
depending on their respective **Occluder Light Mask** properties.
238238

239+
.. note::
240+
241+
**Lighting and shadow resolution in pixel-art games**
242+
243+
The engine computes 2D lighting and shadows at the **Viewport's pixel resolution**,
244+
not at the source texture's texel resolution. The appearance of lights and shadows
245+
depends on your window or Viewport resolution, not on the resolution of individual
246+
sprite textures.
247+
248+
If you create a pixel-art game and want pixelated or blocky lighting and shadows
249+
that match your art style, **Nearest** texture filtering will **not** achieve
250+
this effect. Nearest filtering affects only how the engine samples textures — it
251+
does not change how the engine renders lighting and shadows.
252+
253+
To achieve pixelated lighting and shadows, use a custom shader to modify
254+
``LIGHT_VERTEX`` and ``SHADOW_VERTEX`` to snap light sampling to a pixel grid.
255+
The following shader snaps lighting to a grid using the ``floor()`` function:
256+
257+
.. code-block:: glsl
258+
259+
shader_type canvas_item;
260+
261+
uniform float pixel_size = 4.0;
262+
263+
void fragment() {
264+
// Snap lighting and shadows to pixel grid.
265+
LIGHT_VERTEX.xy = floor(LIGHT_VERTEX.xy / pixel_size) * pixel_size;
266+
SHADOW_VERTEX = floor(SHADOW_VERTEX / pixel_size) * pixel_size;
267+
268+
// Normal rendering.
269+
COLOR = texture(TEXTURE, UV);
270+
}
271+
272+
This works by dividing the position by ``pixel_size`` to convert to grid space,
273+
using ``floor()`` to round down to the nearest grid point, then multiplying back
274+
to convert to screen space. The result forces the engine to sample lighting from
275+
discrete grid positions, which creates the pixelated effect.
276+
277+
For more information on canvas item shaders, see :ref:`CanvasItem shaders <doc_canvas_item_shader>`.
278+
239279
.. figure:: img/2d_lights_and_shadows_hard_shadow.webp
240280
:align: center
241281
:alt: Hard shadows

0 commit comments

Comments
 (0)