diff --git a/tutorials/3d/global_illumination/img/lightmap_gi_shadowmask.webp b/tutorials/3d/global_illumination/img/lightmap_gi_shadowmask.webp new file mode 100644 index 00000000000..82f5cac947f Binary files /dev/null and b/tutorials/3d/global_illumination/img/lightmap_gi_shadowmask.webp differ diff --git a/tutorials/3d/global_illumination/using_lightmap_gi.rst b/tutorials/3d/global_illumination/using_lightmap_gi.rst index fab949bb3f5..9a24f166b56 100644 --- a/tutorials/3d/global_illumination/using_lightmap_gi.rst +++ b/tutorials/3d/global_illumination/using_lightmap_gi.rst @@ -291,6 +291,11 @@ This mode allows performing *subtle* changes to a light's color, energy and position while still looking fairly correct. For example, you can use this to create flickering static torches that have their indirect light baked. +Depending on the value of **Shadowmask Mode**, it is possible to still get +distant baked shadows for DirectionalLight3D. This allows shadows up close to be +real-time and show dynamic objects, while allowing static objects in the +distance to still cast shadows. + Static ~~~~~~ @@ -364,6 +369,12 @@ Tweaks especially with fully baked lights (since they also have direct light baked). The downside is that directional lightmaps are slightly more expensive to render. They also require more time to bake and result in larger file sizes. +- **Shadowmask Mode:** If set to a mode other than **None**, the first DirectionalLight3D + in the scene with the **Dynamic** global illumination mode will have its static shadows + baked to a separate texture called a *shadowmask*. This can be used to allow distant + static objects to cast shadows onto other static objects regardless of the distance + from the camera. See the :ref:`section on shadowmasking ` + for further details. - **Interior:** If enabled, environment lighting will not be sourced. Use this for purely indoor scenes to avoid light leaks. - **Use Texture for Bounces:** If enabled, a texture with the lighting @@ -397,6 +408,74 @@ Tweaks - **Gen Probes > Subdiv:** See :ref:`doc_using_lightmap_gi_dynamic_objects`. - **Data > Light Data:** See :ref:`doc_using_lightmap_gi_data`. +.. _doc_using_lightmap_gi_shadowmask: + +Using shadowmasking for distant directional shadows +--------------------------------------------------- + +When using a DirectionalLight3D, the maximum distance at which it can draw +real-time shadows is limited by its **Shadow Max Distance** property. This can +be an issue in large scenes, as distant objects won't appear to have any shadows +from the DirectionalLight3D. While this can be resolved by using the **Static** +global illumination mode on the DirectionalLight3D, this has several downsides: + +- Since both direct and indirect light are baked, there is no way for dynamic + objects to cast shadows onto static surfaces in a realistic manner. Godot skips + shadow sampling entirely in this case to avoid "double lighting" artifacts. +- Static shadows up close lack in detail, as they only rely on the lightmap texture + and not on real-time shadow cascades. + +We can avoid these downsides while still benefiting from distant shadows by +using *shadowmasking*. While dynamic objects won't receive shadows from the +shadowmask, it still greatly improves visuals since most scenes are primarily +comprised of static objects. + +Since the lightmap texture alone doesn't contain shadow information, we can bake +this shadow information to a separate texture called a *shadowmask*. + +Shadowmasking only affects the first DirectionalLight3D in the scene (determined +by tree order) that has the **Dynamic** global illumination mode. It is not +possible to use shadowmasking with the **Static** global illumination mode, as +this mode skips shadow sampling on static objects entirely. This is because the +Static global illumination mode bakes both direct and indirect light. + +Three shadowmasking modes are available: + +- **None (default):** Don't bake a shadowmask texture. Directional shadows will + not be visible outside the range specified by the DirectionalLight3D's + **Shadow Max Distance** property. +- **Replace:** Bakes a shadowmask texture, and uses it to draw directional + shadows when outside the range specified by the DirectionalLight3D's **Shadow + Max Distance** property. Shadows within this range remain fully real-time. + This option generally makes the most sense for most scenes, as it can deal + well with static objects that exhibit subtle motion (e.g. foliage shadows). +- **Overlay:** Bakes a shadowmask texture, and uses it to draw directional + shadows regardless of the distance from the camera. Shadows within the range + of the DirectionalLight3D's **Shadow Max Distance** property will be overlaid + with real-time shadows. This can make the transition between real-time and + baked shadows less jarring, at the cost of a "smearing" effect present on + static object shadows depending on lightmap texel density. Also, this mode + can't deal as well with static objects that exhibit subtle motion (such as + foliage), as the baked shadows can't be animated over time. Still, for scenes + where the camera moves quickly, this may be a better choice than **Replace**. + +Here's a visual comparison of the shadowmask modes with a scene where the +**Shadow Max Distance** was set very low for comparison purposes. The blue boxes +are dynamic objects, while the rest of the scene is a static object. There is +only a single DirectionalLight3D in the scene with the Dynamic global +illumination mode: + +.. figure:: img/lightmap_gi_shadowmask.webp + :align: center + :alt: Comparison between shadowmask modes + + Comparison between shadowmask modes + +.. note:: + + It is possible to switch between the **Replace** and **Overlay** shadowmask + modes without having to bake lightmaps again. + Balancing bake times with quality ---------------------------------