bevy_core_pipeline/auto_exposure/settings.rs
1use core::ops::RangeInclusive;
2
3use super::compensation_curve::AutoExposureCompensationCurve;
4use bevy_asset::Handle;
5use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
6use bevy_image::Image;
7use bevy_reflect::{std_traits::ReflectDefault, Reflect};
8use bevy_render::extract_component::ExtractComponent;
9use bevy_utils::default;
10
11/// Component that enables auto exposure for an HDR-enabled 2d or 3d camera.
12///
13/// Auto exposure adjusts the exposure of the camera automatically to
14/// simulate the human eye's ability to adapt to different lighting conditions.
15///
16/// Bevy's implementation builds a 64 bin histogram of the scene's luminance,
17/// and then adjusts the exposure so that the average brightness of the final
18/// render will be middle gray. Because it's using a histogram, some details can
19/// be selectively ignored or emphasized. Outliers like shadows and specular
20/// highlights can be ignored, and certain areas can be given more (or less)
21/// weight based on a mask.
22///
23/// # Usage Notes
24///
25/// **Auto Exposure requires compute shaders and is not compatible with WebGL2.**
26#[derive(Component, Clone, Reflect, ExtractComponent)]
27#[reflect(Component, Default)]
28pub struct AutoExposure {
29 /// The range of exposure values for the histogram.
30 ///
31 /// Pixel values below this range will be ignored, and pixel values above this range will be
32 /// clamped in the sense that they will count towards the highest bin in the histogram.
33 /// The default value is `-8.0..=8.0`.
34 pub range: RangeInclusive<f32>,
35
36 /// The portion of the histogram to consider when metering.
37 ///
38 /// By default, the darkest 10% and the brightest 10% of samples are ignored,
39 /// so the default value is `0.10..=0.90`.
40 pub filter: RangeInclusive<f32>,
41
42 /// The speed at which the exposure adapts from dark to bright scenes, in F-stops per second.
43 pub speed_brighten: f32,
44
45 /// The speed at which the exposure adapts from bright to dark scenes, in F-stops per second.
46 pub speed_darken: f32,
47
48 /// The distance in F-stops from the target exposure from where to transition from animating
49 /// in linear fashion to animating exponentially. This helps against jittering when the
50 /// target exposure keeps on changing slightly from frame to frame, while still maintaining
51 /// a relatively slow animation for big changes in scene brightness.
52 ///
53 /// ```text
54 /// ev
55 /// ➔●┐
56 /// | ⬈ ├ exponential section
57 /// │ ⬈ ┘
58 /// │ ⬈ ┐
59 /// │ ⬈ ├ linear section
60 /// │⬈ ┘
61 /// ●───────────────────────── time
62 /// ```
63 ///
64 /// The default value is 1.5.
65 pub exponential_transition_distance: f32,
66
67 /// The mask to apply when metering. The mask will cover the entire screen, where:
68 /// * `(0.0, 0.0)` is the top-left corner,
69 /// * `(1.0, 1.0)` is the bottom-right corner.
70 ///
71 /// Only the red channel of the texture is used.
72 /// The sample at the current screen position will be used to weight the contribution
73 /// of each pixel to the histogram:
74 /// * 0.0 means the pixel will not contribute to the histogram,
75 /// * 1.0 means the pixel will contribute fully to the histogram.
76 ///
77 /// The default value is a white image, so all pixels contribute equally.
78 ///
79 /// # Usage Notes
80 ///
81 /// The mask is quantized to 16 discrete levels because of limitations in the compute shader
82 /// implementation.
83 pub metering_mask: Handle<Image>,
84
85 /// Exposure compensation curve to apply after metering.
86 /// The default value is a flat line at 0.0.
87 /// For more information, see [`AutoExposureCompensationCurve`].
88 pub compensation_curve: Handle<AutoExposureCompensationCurve>,
89}
90
91#[deprecated(since = "0.15.0", note = "Renamed to `AutoExposure`")]
92pub type AutoExposureSettings = AutoExposure;
93
94impl Default for AutoExposure {
95 fn default() -> Self {
96 Self {
97 range: -8.0..=8.0,
98 filter: 0.10..=0.90,
99 speed_brighten: 3.0,
100 speed_darken: 1.0,
101 exponential_transition_distance: 1.5,
102 metering_mask: default(),
103 compensation_curve: default(),
104 }
105 }
106}