bevy_light/
volumetric.rs

1use bevy_asset::Handle;
2use bevy_camera::visibility::Visibility;
3use bevy_color::Color;
4use bevy_ecs::prelude::*;
5use bevy_image::Image;
6use bevy_math::Vec3;
7use bevy_reflect::prelude::*;
8use bevy_transform::components::Transform;
9
10/// Add this component to a [`DirectionalLight`](crate::DirectionalLight) with a shadow map
11/// (`shadows_enabled: true`) to make volumetric fog interact with it.
12///
13/// This allows the light to generate light shafts/god rays.
14#[derive(Clone, Copy, Component, Default, Debug, Reflect)]
15#[reflect(Component, Default, Debug, Clone)]
16pub struct VolumetricLight;
17
18/// When placed on a [`bevy_camera::Camera3d`], enables
19/// volumetric fog and volumetric lighting, also known as light shafts or god
20/// rays.
21///
22/// Requires using WebGPU on Wasm builds.
23#[derive(Clone, Copy, Component, Debug, Reflect)]
24#[reflect(Component, Default, Debug, Clone)]
25pub struct VolumetricFog {
26    /// Color of the ambient light.
27    ///
28    /// This is separate from Bevy's [`AmbientLight`](crate::AmbientLight) because an
29    /// [`EnvironmentMapLight`](crate::EnvironmentMapLight) is
30    /// still considered an ambient light for the purposes of volumetric fog. If you're using a
31    /// [`EnvironmentMapLight`](crate::EnvironmentMapLight), for best results,
32    /// this should be a good approximation of the average color of the environment map.
33    ///
34    /// Defaults to white.
35    pub ambient_color: Color,
36
37    /// The brightness of the ambient light.
38    ///
39    /// If there's no [`EnvironmentMapLight`](crate::EnvironmentMapLight),
40    /// set this to 0.
41    ///
42    /// Defaults to 0.1.
43    pub ambient_intensity: f32,
44
45    /// The maximum distance to offset the ray origin randomly by, in meters.
46    ///
47    /// This is intended for use with temporal antialiasing. It helps fog look
48    /// less blocky by varying the start position of the ray, using interleaved
49    /// gradient noise.
50    pub jitter: f32,
51
52    /// The number of raymarching steps to perform.
53    ///
54    /// Higher values produce higher-quality results with less banding, but
55    /// reduce performance.
56    ///
57    /// The default value is 64.
58    pub step_count: u32,
59}
60
61impl Default for VolumetricFog {
62    fn default() -> Self {
63        Self {
64            step_count: 64,
65            // Matches `AmbientLight` defaults.
66            ambient_color: Color::WHITE,
67            ambient_intensity: 0.1,
68            jitter: 0.0,
69        }
70    }
71}
72
73#[derive(Clone, Component, Debug, Reflect)]
74#[reflect(Component, Default, Debug, Clone)]
75#[require(Transform, Visibility)]
76pub struct FogVolume {
77    /// The color of the fog.
78    ///
79    /// Note that the fog must be lit by a [`VolumetricLight`] or ambient light
80    /// in order for this color to appear.
81    ///
82    /// Defaults to white.
83    pub fog_color: Color,
84
85    /// The density of fog, which measures how dark the fog is.
86    ///
87    /// The default value is 0.1.
88    pub density_factor: f32,
89
90    /// Optional 3D voxel density texture for the fog.
91    pub density_texture: Option<Handle<Image>>,
92
93    /// Configurable offset of the density texture in UVW coordinates.
94    ///
95    /// This can be used to scroll a repeating density texture in a direction over time
96    /// to create effects like fog moving in the wind. Make sure to configure the texture
97    /// to use `ImageAddressMode::Repeat` if this is your intention.
98    ///
99    /// Has no effect when no density texture is present.
100    ///
101    /// The default value is (0, 0, 0).
102    pub density_texture_offset: Vec3,
103
104    /// The absorption coefficient, which measures what fraction of light is
105    /// absorbed by the fog at each step.
106    ///
107    /// Increasing this value makes the fog darker.
108    ///
109    /// The default value is 0.3.
110    pub absorption: f32,
111
112    /// The scattering coefficient, which measures the fraction of light that's
113    /// scattered toward, and away from, the viewer.
114    ///
115    /// The default value is 0.3.
116    pub scattering: f32,
117
118    /// Measures the fraction of light that's scattered *toward* the camera, as
119    /// opposed to *away* from the camera.
120    ///
121    /// Increasing this value makes light shafts become more prominent when the
122    /// camera is facing toward their source and less prominent when the camera
123    /// is facing away. Essentially, a high value here means the light shafts
124    /// will fade into view as the camera focuses on them and fade away when the
125    /// camera is pointing away.
126    ///
127    /// The default value is 0.8.
128    pub scattering_asymmetry: f32,
129
130    /// Applies a nonphysical color to the light.
131    ///
132    /// This can be useful for artistic purposes but is nonphysical.
133    ///
134    /// The default value is white.
135    pub light_tint: Color,
136
137    /// Scales the light by a fixed fraction.
138    ///
139    /// This can be useful for artistic purposes but is nonphysical.
140    ///
141    /// The default value is 1.0, which results in no adjustment.
142    pub light_intensity: f32,
143}
144
145impl Default for FogVolume {
146    fn default() -> Self {
147        Self {
148            absorption: 0.3,
149            scattering: 0.3,
150            density_factor: 0.1,
151            density_texture: None,
152            density_texture_offset: Vec3::ZERO,
153            scattering_asymmetry: 0.5,
154            fog_color: Color::WHITE,
155            light_tint: Color::WHITE,
156            light_intensity: 1.0,
157        }
158    }
159}