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}