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}