Skip to main content

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/// (`shadow_maps_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/// A unit cube of fog at the origin. Can be positioned and scaled with a [`Transform`].
74/// Only visible by cameras with a [`VolumetricFog`] component when lit by a directional light with [`VolumetricLight`].
75#[derive(Clone, Component, Debug, Reflect)]
76#[reflect(Component, Default, Debug, Clone)]
77#[require(Transform, Visibility)]
78pub struct FogVolume {
79    /// The color of the fog.
80    ///
81    /// Note that the fog must be lit by a [`VolumetricLight`] or ambient light
82    /// in order for this color to appear.
83    ///
84    /// Defaults to white.
85    pub fog_color: Color,
86
87    /// The density of fog, which measures how dark the fog is.
88    ///
89    /// The default value is 0.1.
90    pub density_factor: f32,
91
92    /// Optional 3D voxel density texture for the fog.
93    pub density_texture: Option<Handle<Image>>,
94
95    /// Configurable offset of the density texture in UVW coordinates.
96    ///
97    /// This can be used to scroll a repeating density texture in a direction over time
98    /// to create effects like fog moving in the wind. Make sure to configure the texture
99    /// to use `ImageAddressMode::Repeat` if this is your intention.
100    ///
101    /// Has no effect when no density texture is present.
102    ///
103    /// The default value is (0, 0, 0).
104    pub density_texture_offset: Vec3,
105
106    /// The absorption coefficient, which measures what fraction of light is
107    /// absorbed by the fog at each step.
108    ///
109    /// Increasing this value makes the fog darker.
110    ///
111    /// The default value is 0.3.
112    pub absorption: f32,
113
114    /// The scattering coefficient, which measures the fraction of light that's
115    /// scattered toward, and away from, the viewer.
116    ///
117    /// The default value is 0.3.
118    pub scattering: f32,
119
120    /// Measures the fraction of light that's scattered *toward* the camera, as
121    /// opposed to *away* from the camera.
122    ///
123    /// Increasing this value makes light shafts become more prominent when the
124    /// camera is facing toward their source and less prominent when the camera
125    /// is facing away. Essentially, a high value here means the light shafts
126    /// will fade into view as the camera focuses on them and fade away when the
127    /// camera is pointing away.
128    ///
129    /// The default value is 0.8.
130    pub scattering_asymmetry: f32,
131
132    /// Applies a nonphysical color to the light.
133    ///
134    /// This can be useful for artistic purposes but is nonphysical.
135    ///
136    /// The default value is white.
137    pub light_tint: Color,
138
139    /// Scales the light by a fixed fraction.
140    ///
141    /// This can be useful for artistic purposes but is nonphysical.
142    ///
143    /// The default value is 1.0, which results in no adjustment.
144    pub light_intensity: f32,
145}
146
147impl Default for FogVolume {
148    fn default() -> Self {
149        Self {
150            absorption: 0.3,
151            scattering: 0.3,
152            density_factor: 0.1,
153            density_texture: None,
154            density_texture_offset: Vec3::ZERO,
155            scattering_asymmetry: 0.5,
156            fog_color: Color::WHITE,
157            light_tint: Color::WHITE,
158            light_intensity: 1.0,
159        }
160    }
161}