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}