bevy_pbr/light/
point_light.rs

1use bevy_render::view::{self, Visibility};
2
3use super::*;
4
5/// A light that emits light in all directions from a central point.
6///
7/// Real-world values for `intensity` (luminous power in lumens) based on the electrical power
8/// consumption of the type of real-world light are:
9///
10/// | Luminous Power (lumen) (i.e. the intensity member) | Incandescent non-halogen (Watts) | Incandescent halogen (Watts) | Compact fluorescent (Watts) | LED (Watts) |
11/// |------|-----|----|--------|-------|
12/// | 200  | 25  |    | 3-5    | 3     |
13/// | 450  | 40  | 29 | 9-11   | 5-8   |
14/// | 800  | 60  |    | 13-15  | 8-12  |
15/// | 1100 | 75  | 53 | 18-20  | 10-16 |
16/// | 1600 | 100 | 72 | 24-28  | 14-17 |
17/// | 2400 | 150 |    | 30-52  | 24-30 |
18/// | 3100 | 200 |    | 49-75  | 32    |
19/// | 4000 | 300 |    | 75-100 | 40.5  |
20///
21/// Source: [Wikipedia](https://en.wikipedia.org/wiki/Lumen_(unit)#Lighting)
22///
23/// ## Shadows
24///
25/// To enable shadows, set the `shadows_enabled` property to `true`.
26///
27/// To control the resolution of the shadow maps, use the [`PointLightShadowMap`] resource.
28#[derive(Component, Debug, Clone, Copy, Reflect)]
29#[reflect(Component, Default, Debug, Clone)]
30#[require(
31    CubemapFrusta,
32    CubemapVisibleEntities,
33    Transform,
34    Visibility,
35    VisibilityClass
36)]
37#[component(on_add = view::add_visibility_class::<LightVisibilityClass>)]
38pub struct PointLight {
39    /// The color of this light source.
40    pub color: Color,
41
42    /// Luminous power in lumens, representing the amount of light emitted by this source in all directions.
43    pub intensity: f32,
44
45    /// Cut-off for the light's area-of-effect. Fragments outside this range will not be affected by
46    /// this light at all, so it's important to tune this together with `intensity` to prevent hard
47    /// lighting cut-offs.
48    pub range: f32,
49
50    /// Simulates a light source coming from a spherical volume with the given
51    /// radius.
52    ///
53    /// This affects the size of specular highlights created by this light, as
54    /// well as the soft shadow penumbra size. Because of this, large values may
55    /// not produce the intended result -- for example, light radius does not
56    /// affect shadow softness or diffuse lighting.
57    pub radius: f32,
58
59    /// Whether this light casts shadows.
60    pub shadows_enabled: bool,
61
62    /// Whether soft shadows are enabled.
63    ///
64    /// Soft shadows, also known as *percentage-closer soft shadows* or PCSS,
65    /// cause shadows to become blurrier (i.e. their penumbra increases in
66    /// radius) as they extend away from objects. The blurriness of the shadow
67    /// depends on the [`PointLight::radius`] of the light; larger lights result
68    /// in larger penumbras and therefore blurrier shadows.
69    ///
70    /// Currently, soft shadows are rather noisy if not using the temporal mode.
71    /// If you enable soft shadows, consider choosing
72    /// [`ShadowFilteringMethod::Temporal`] and enabling temporal antialiasing
73    /// (TAA) to smooth the noise out over time.
74    ///
75    /// Note that soft shadows are significantly more expensive to render than
76    /// hard shadows.
77    #[cfg(feature = "experimental_pbr_pcss")]
78    pub soft_shadows_enabled: bool,
79
80    /// Whether this point light contributes diffuse lighting to meshes with
81    /// lightmaps.
82    ///
83    /// Set this to false if your lightmap baking tool bakes the direct diffuse
84    /// light from this point light into the lightmaps in order to avoid
85    /// counting the radiance from this light twice. Note that the specular
86    /// portion of the light is always considered, because Bevy currently has no
87    /// means to bake specular light.
88    ///
89    /// By default, this is set to true.
90    pub affects_lightmapped_mesh_diffuse: bool,
91
92    /// A bias used when sampling shadow maps to avoid "shadow-acne", or false shadow occlusions
93    /// that happen as a result of shadow-map fragments not mapping 1:1 to screen-space fragments.
94    /// Too high of a depth bias can lead to shadows detaching from their casters, or
95    /// "peter-panning". This bias can be tuned together with `shadow_normal_bias` to correct shadow
96    /// artifacts for a given scene.
97    pub shadow_depth_bias: f32,
98
99    /// A bias applied along the direction of the fragment's surface normal. It is scaled to the
100    /// shadow map's texel size so that it can be small close to the camera and gets larger further
101    /// away.
102    pub shadow_normal_bias: f32,
103
104    /// The distance from the light to near Z plane in the shadow map.
105    ///
106    /// Objects closer than this distance to the light won't cast shadows.
107    /// Setting this higher increases the shadow map's precision.
108    ///
109    /// This only has an effect if shadows are enabled.
110    pub shadow_map_near_z: f32,
111}
112
113impl Default for PointLight {
114    fn default() -> Self {
115        PointLight {
116            color: Color::WHITE,
117            // 1,000,000 lumens is a very large "cinema light" capable of registering brightly at Bevy's
118            // default "very overcast day" exposure level. For "indoor lighting" with a lower exposure,
119            // this would be way too bright.
120            intensity: 1_000_000.0,
121            range: 20.0,
122            radius: 0.0,
123            shadows_enabled: false,
124            affects_lightmapped_mesh_diffuse: true,
125            shadow_depth_bias: Self::DEFAULT_SHADOW_DEPTH_BIAS,
126            shadow_normal_bias: Self::DEFAULT_SHADOW_NORMAL_BIAS,
127            shadow_map_near_z: Self::DEFAULT_SHADOW_MAP_NEAR_Z,
128            #[cfg(feature = "experimental_pbr_pcss")]
129            soft_shadows_enabled: false,
130        }
131    }
132}
133
134impl PointLight {
135    pub const DEFAULT_SHADOW_DEPTH_BIAS: f32 = 0.08;
136    pub const DEFAULT_SHADOW_NORMAL_BIAS: f32 = 0.6;
137    pub const DEFAULT_SHADOW_MAP_NEAR_Z: f32 = 0.1;
138}