bevy_pbr/light/spot_light.rs
1use bevy_render::view::Visibility;
2
3use super::*;
4
5/// A light that emits light in a given direction from a central point.
6///
7/// Behaves like a point light in a perfectly absorbent housing that
8/// shines light only in a given direction. The direction is taken from
9/// the transform, and can be specified with [`Transform::looking_at`](Transform::looking_at).
10#[derive(Component, Debug, Clone, Copy, Reflect)]
11#[reflect(Component, Default, Debug)]
12#[require(Frustum, VisibleMeshEntities, Transform, Visibility)]
13pub struct SpotLight {
14 /// The color of the light.
15 ///
16 /// By default, this is white.
17 pub color: Color,
18
19 /// Luminous power in lumens, representing the amount of light emitted by this source in all directions.
20 pub intensity: f32,
21
22 /// Range in meters that this light illuminates.
23 ///
24 /// Note that this value affects resolution of the shadow maps; generally, the
25 /// higher you set it, the lower-resolution your shadow maps will be.
26 /// Consequently, you should set this value to be only the size that you need.
27 pub range: f32,
28
29 /// Simulates a light source coming from a spherical volume with the given
30 /// radius.
31 ///
32 /// This affects the size of specular highlights created by this light, as
33 /// well as the soft shadow penumbra size. Because of this, large values may
34 /// not produce the intended result -- for example, light radius does not
35 /// affect shadow softness or diffuse lighting.
36 pub radius: f32,
37
38 /// Whether this light casts shadows.
39 ///
40 /// Note that shadows are rather expensive and become more so with every
41 /// light that casts them. In general, it's best to aggressively limit the
42 /// number of lights with shadows enabled to one or two at most.
43 pub shadows_enabled: bool,
44
45 /// Whether soft shadows are enabled.
46 ///
47 /// Soft shadows, also known as *percentage-closer soft shadows* or PCSS,
48 /// cause shadows to become blurrier (i.e. their penumbra increases in
49 /// radius) as they extend away from objects. The blurriness of the shadow
50 /// depends on the [`SpotLight::radius`] of the light; larger lights result in larger
51 /// penumbras and therefore blurrier shadows.
52 ///
53 /// Currently, soft shadows are rather noisy if not using the temporal mode.
54 /// If you enable soft shadows, consider choosing
55 /// [`ShadowFilteringMethod::Temporal`] and enabling temporal antialiasing
56 /// (TAA) to smooth the noise out over time.
57 ///
58 /// Note that soft shadows are significantly more expensive to render than
59 /// hard shadows.
60 #[cfg(feature = "experimental_pbr_pcss")]
61 pub soft_shadows_enabled: bool,
62
63 /// A value that adjusts the tradeoff between self-shadowing artifacts and
64 /// proximity of shadows to their casters.
65 ///
66 /// This value frequently must be tuned to the specific scene; this is
67 /// normal and a well-known part of the shadow mapping workflow. If set too
68 /// low, unsightly shadow patterns appear on objects not in shadow as
69 /// objects incorrectly cast shadows on themselves, known as *shadow acne*.
70 /// If set too high, shadows detach from the objects casting them and seem
71 /// to "fly" off the objects, known as *Peter Panning*.
72 pub shadow_depth_bias: f32,
73
74 /// A bias applied along the direction of the fragment's surface normal. It is scaled to the
75 /// shadow map's texel size so that it can be small close to the camera and gets larger further
76 /// away.
77 pub shadow_normal_bias: f32,
78
79 /// The distance from the light to the near Z plane in the shadow map.
80 ///
81 /// Objects closer than this distance to the light won't cast shadows.
82 /// Setting this higher increases the shadow map's precision.
83 ///
84 /// This only has an effect if shadows are enabled.
85 pub shadow_map_near_z: f32,
86
87 /// Angle defining the distance from the spot light direction to the outer limit
88 /// of the light's cone of effect.
89 /// `outer_angle` should be < `PI / 2.0`.
90 /// `PI / 2.0` defines a hemispherical spot light, but shadows become very blocky as the angle
91 /// approaches this limit.
92 pub outer_angle: f32,
93
94 /// Angle defining the distance from the spot light direction to the inner limit
95 /// of the light's cone of effect.
96 /// Light is attenuated from `inner_angle` to `outer_angle` to give a smooth falloff.
97 /// `inner_angle` should be <= `outer_angle`
98 pub inner_angle: f32,
99}
100
101impl SpotLight {
102 pub const DEFAULT_SHADOW_DEPTH_BIAS: f32 = 0.02;
103 pub const DEFAULT_SHADOW_NORMAL_BIAS: f32 = 1.8;
104 pub const DEFAULT_SHADOW_MAP_NEAR_Z: f32 = 0.1;
105}
106
107impl Default for SpotLight {
108 fn default() -> Self {
109 // a quarter arc attenuating from the center
110 Self {
111 color: Color::WHITE,
112 // 1,000,000 lumens is a very large "cinema light" capable of registering brightly at Bevy's
113 // default "very overcast day" exposure level. For "indoor lighting" with a lower exposure,
114 // this would be way too bright.
115 intensity: 1_000_000.0,
116 range: 20.0,
117 radius: 0.0,
118 shadows_enabled: false,
119 shadow_depth_bias: Self::DEFAULT_SHADOW_DEPTH_BIAS,
120 shadow_normal_bias: Self::DEFAULT_SHADOW_NORMAL_BIAS,
121 shadow_map_near_z: Self::DEFAULT_SHADOW_MAP_NEAR_Z,
122 inner_angle: 0.0,
123 outer_angle: core::f32::consts::FRAC_PI_4,
124 #[cfg(feature = "experimental_pbr_pcss")]
125 soft_shadows_enabled: false,
126 }
127 }
128}