bevy_light/
probe.rs

1use bevy_asset::Handle;
2use bevy_camera::visibility::Visibility;
3use bevy_ecs::prelude::*;
4use bevy_image::Image;
5use bevy_math::{Quat, UVec2};
6use bevy_reflect::prelude::*;
7use bevy_transform::components::Transform;
8
9/// A marker component for a light probe, which is a cuboid region that provides
10/// global illumination to all fragments inside it.
11///
12/// Note that a light probe will have no effect unless the entity contains some
13/// kind of illumination, which can either be an [`EnvironmentMapLight`] or an
14/// [`IrradianceVolume`].
15///
16/// The light probe range is conceptually a unit cube (1×1×1) centered on the
17/// origin. The [`Transform`] applied to this entity can scale, rotate, or translate
18/// that cube so that it contains all fragments that should take this light probe into account.
19///
20/// When multiple sources of indirect illumination can be applied to a fragment,
21/// the highest-quality one is chosen. Diffuse and specular illumination are
22/// considered separately, so, for example, Bevy may decide to sample the
23/// diffuse illumination from an irradiance volume and the specular illumination
24/// from a reflection probe. From highest priority to lowest priority, the
25/// ranking is as follows:
26///
27/// | Rank | Diffuse              | Specular             |
28/// | ---- | -------------------- | -------------------- |
29/// | 1    | Lightmap             | Lightmap             |
30/// | 2    | Irradiance volume    | Reflection probe     |
31/// | 3    | Reflection probe     | View environment map |
32/// | 4    | View environment map |                      |
33///
34/// Note that ambient light is always added to the diffuse component and does
35/// not participate in the ranking. That is, ambient light is applied in
36/// addition to, not instead of, the light sources above.
37///
38/// A terminology note: Unfortunately, there is little agreement across game and
39/// graphics engines as to what to call the various techniques that Bevy groups
40/// under the term *light probe*. In Bevy, a *light probe* is the generic term
41/// that encompasses both *reflection probes* and *irradiance volumes*. In
42/// object-oriented terms, *light probe* is the superclass, and *reflection
43/// probe* and *irradiance volume* are subclasses. In other engines, you may see
44/// the term *light probe* refer to an irradiance volume with a single voxel, or
45/// perhaps some other technique, while in Bevy *light probe* refers not to a
46/// specific technique but rather to a class of techniques. Developers familiar
47/// with other engines should be aware of this terminology difference.
48#[derive(Component, Debug, Clone, Copy, Default, Reflect)]
49#[reflect(Component, Default, Debug, Clone)]
50#[require(Transform, Visibility)]
51pub struct LightProbe;
52
53impl LightProbe {
54    /// Creates a new light probe component.
55    #[inline]
56    pub fn new() -> Self {
57        Self
58    }
59}
60
61/// A pair of cubemap textures that represent the surroundings of a specific
62/// area in space.
63///
64/// See `bevy_pbr::environment_map` for detailed information.
65#[derive(Clone, Component, Reflect)]
66#[reflect(Component, Default, Clone)]
67pub struct EnvironmentMapLight {
68    /// The blurry image that represents diffuse radiance surrounding a region.
69    pub diffuse_map: Handle<Image>,
70
71    /// The typically-sharper, mipmapped image that represents specular radiance
72    /// surrounding a region.
73    pub specular_map: Handle<Image>,
74
75    /// Scale factor applied to the diffuse and specular light generated by this component.
76    ///
77    /// After applying this multiplier, the resulting values should
78    /// be in units of [cd/m^2](https://en.wikipedia.org/wiki/Candela_per_square_metre).
79    ///
80    /// See also <https://google.github.io/filament/Filament.html#lighting/imagebasedlights/iblunit>.
81    pub intensity: f32,
82
83    /// World space rotation applied to the environment light cubemaps.
84    /// This is useful for users who require a different axis, such as the Z-axis, to serve
85    /// as the vertical axis.
86    pub rotation: Quat,
87
88    /// Whether the light from this environment map contributes diffuse lighting
89    /// to meshes with lightmaps.
90    ///
91    /// Set this to false if your lightmap baking tool bakes the diffuse light
92    /// from this environment light into the lightmaps in order to avoid
93    /// counting the radiance from this environment map twice.
94    ///
95    /// By default, this is set to true.
96    pub affects_lightmapped_mesh_diffuse: bool,
97}
98
99impl Default for EnvironmentMapLight {
100    fn default() -> Self {
101        EnvironmentMapLight {
102            diffuse_map: Handle::default(),
103            specular_map: Handle::default(),
104            intensity: 0.0,
105            rotation: Quat::IDENTITY,
106            affects_lightmapped_mesh_diffuse: true,
107        }
108    }
109}
110
111/// A generated environment map that is filtered at runtime.
112///
113/// See `bevy_pbr::light_probe::generate` for detailed information.
114#[derive(Clone, Component, Reflect)]
115#[reflect(Component, Default, Clone)]
116pub struct GeneratedEnvironmentMapLight {
117    /// Source cubemap to be filtered on the GPU, size must be a power of two.
118    pub environment_map: Handle<Image>,
119
120    /// Scale factor applied to the diffuse and specular light generated by this
121    /// component. Expressed in cd/m² (candela per square meter).
122    pub intensity: f32,
123
124    /// World-space rotation applied to the cubemap.
125    pub rotation: Quat,
126
127    /// Whether this light contributes diffuse lighting to meshes that already
128    /// have baked lightmaps.
129    pub affects_lightmapped_mesh_diffuse: bool,
130}
131
132impl Default for GeneratedEnvironmentMapLight {
133    fn default() -> Self {
134        GeneratedEnvironmentMapLight {
135            environment_map: Handle::default(),
136            intensity: 0.0,
137            rotation: Quat::IDENTITY,
138            affects_lightmapped_mesh_diffuse: true,
139        }
140    }
141}
142
143/// Lets the atmosphere contribute environment lighting (reflections and ambient diffuse) to your scene.
144///
145/// Attach this to a [`Camera3d`](bevy_camera::Camera3d) to light the entire view, or to a
146/// [`LightProbe`] to light only a specific region.
147/// Behind the scenes, this generates an environment map from the atmosphere for image-based lighting
148/// and inserts a corresponding [`GeneratedEnvironmentMapLight`].
149///
150/// For HDRI-based lighting, use a preauthored [`EnvironmentMapLight`] or filter one at runtime with
151/// [`GeneratedEnvironmentMapLight`].
152#[derive(Component, Clone)]
153pub struct AtmosphereEnvironmentMapLight {
154    /// Controls how bright the atmosphere's environment lighting is.
155    /// Increase this value to brighten reflections and ambient diffuse lighting.
156    ///
157    /// The default is `1.0` so that the generated environment lighting matches
158    /// the light intensity of the atmosphere in the scene.
159    pub intensity: f32,
160    /// Whether the diffuse contribution should affect meshes that already have lightmaps.
161    pub affects_lightmapped_mesh_diffuse: bool,
162    /// Cubemap resolution in pixels (must be a power-of-two).
163    pub size: UVec2,
164}
165
166impl Default for AtmosphereEnvironmentMapLight {
167    fn default() -> Self {
168        Self {
169            intensity: 1.0,
170            affects_lightmapped_mesh_diffuse: true,
171            size: UVec2::new(512, 512),
172        }
173    }
174}
175
176/// The component that defines an irradiance volume.
177///
178/// See `bevy_pbr::irradiance_volume` for detailed information.
179///
180/// This component requires the [`LightProbe`] component, and is typically used with
181/// [`bevy_transform::components::Transform`] to place the volume appropriately.
182#[derive(Clone, Reflect, Component, Debug)]
183#[reflect(Component, Default, Debug, Clone)]
184#[require(LightProbe)]
185pub struct IrradianceVolume {
186    /// The 3D texture that represents the ambient cubes, encoded in the format
187    /// described in `bevy_pbr::irradiance_volume`.
188    pub voxels: Handle<Image>,
189
190    /// Scale factor applied to the diffuse and specular light generated by this component.
191    ///
192    /// After applying this multiplier, the resulting values should
193    /// be in units of [cd/m^2](https://en.wikipedia.org/wiki/Candela_per_square_metre).
194    ///
195    /// See also <https://google.github.io/filament/Filament.html#lighting/imagebasedlights/iblunit>.
196    pub intensity: f32,
197
198    /// Whether the light from this irradiance volume has an effect on meshes
199    /// with lightmaps.
200    ///
201    /// Set this to false if your lightmap baking tool bakes the light from this
202    /// irradiance volume into the lightmaps in order to avoid counting the
203    /// irradiance twice. Frequently, applications use irradiance volumes as a
204    /// lower-quality alternative to lightmaps for capturing indirect
205    /// illumination on dynamic objects, and such applications will want to set
206    /// this value to false.
207    ///
208    /// By default, this is set to true.
209    pub affects_lightmapped_meshes: bool,
210}
211
212impl Default for IrradianceVolume {
213    #[inline]
214    fn default() -> Self {
215        IrradianceVolume {
216            voxels: Handle::default(),
217            intensity: 0.0,
218            affects_lightmapped_meshes: true,
219        }
220    }
221}