Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_pbr/src/volumetric_fog/mod.rs
9472 views
1
//! Volumetric fog and volumetric lighting, also known as light shafts or god
2
//! rays.
3
//!
4
//! This module implements a more physically-accurate, but slower, form of fog
5
//! than the [`crate::fog`] module does. Notably, this *volumetric fog* allows
6
//! for light beams from directional lights to shine through, creating what is
7
//! known as *light shafts* or *god rays*.
8
//!
9
//! To add volumetric fog to a scene, add [`bevy_light::VolumetricFog`] to the
10
//! camera, and add [`bevy_light::VolumetricLight`] to directional lights that you wish to
11
//! be volumetric. [`bevy_light::VolumetricFog`] feature numerous settings that
12
//! allow you to define the accuracy of the simulation, as well as the look of
13
//! the fog. Currently, only interaction with directional lights that have
14
//! shadow maps is supported. Note that the overhead of the effect scales
15
//! directly with the number of directional lights in use, so apply
16
//! [`bevy_light::VolumetricLight`] sparingly for the best results.
17
//!
18
//! The overall algorithm, which is implemented as a postprocessing effect, is a
19
//! combination of the techniques described in [Scratchapixel] and [this blog
20
//! post]. It uses raymarching in screen space, transformed into shadow map
21
//! space for sampling and combined with physically-based modeling of absorption
22
//! and scattering. Bevy employs the widely-used [Henyey-Greenstein phase
23
//! function] to model asymmetry; this essentially allows light shafts to fade
24
//! into and out of existence as the user views them.
25
//!
26
//! [Scratchapixel]: https://www.scratchapixel.com/lessons/3d-basic-rendering/volume-rendering-for-developers/intro-volume-rendering.html
27
//!
28
//! [this blog post]: https://www.alexandre-pestana.com/volumetric-lights/
29
//!
30
//! [Henyey-Greenstein phase function]: https://www.pbr-book.org/4ed/Volume_Scattering/Phase_Functions#TheHenyeyndashGreensteinPhaseFunction
31
32
use bevy_app::{App, Plugin};
33
use bevy_asset::{embedded_asset, Assets, Handle};
34
use bevy_core_pipeline::{
35
core_3d::prepare_core_3d_depth_textures,
36
schedule::{Core3d, Core3dSystems},
37
};
38
use bevy_ecs::{resource::Resource, schedule::IntoScheduleConfigs as _};
39
use bevy_light::FogVolume;
40
use bevy_math::{
41
primitives::{Cuboid, Plane3d},
42
Vec2, Vec3,
43
};
44
use bevy_mesh::{Mesh, Meshable};
45
use bevy_render::{
46
render_resource::SpecializedRenderPipelines,
47
sync_component::{SyncComponent, SyncComponentPlugin},
48
ExtractSchedule, Render, RenderApp, RenderStartup, RenderSystems,
49
};
50
use render::{volumetric_fog, VolumetricFogPipeline, VolumetricFogUniformBuffer};
51
52
use crate::volumetric_fog::render::init_volumetric_fog_pipeline;
53
54
pub mod render;
55
56
/// A plugin that implements volumetric fog.
57
pub struct VolumetricFogPlugin;
58
59
#[derive(Resource)]
60
pub struct FogAssets {
61
plane_mesh: Handle<Mesh>,
62
cube_mesh: Handle<Mesh>,
63
}
64
65
impl Plugin for VolumetricFogPlugin {
66
fn build(&self, app: &mut App) {
67
embedded_asset!(app, "volumetric_fog.wgsl");
68
69
let mut meshes = app.world_mut().resource_mut::<Assets<Mesh>>();
70
let plane_mesh = meshes.add(Plane3d::new(Vec3::Z, Vec2::ONE).mesh());
71
let cube_mesh = meshes.add(Cuboid::new(1.0, 1.0, 1.0).mesh());
72
73
app.add_plugins(SyncComponentPlugin::<FogVolume, Self>::default());
74
75
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
76
return;
77
};
78
79
render_app
80
.insert_resource(FogAssets {
81
plane_mesh,
82
cube_mesh,
83
})
84
.init_resource::<SpecializedRenderPipelines<VolumetricFogPipeline>>()
85
.init_resource::<VolumetricFogUniformBuffer>()
86
.add_systems(RenderStartup, init_volumetric_fog_pipeline)
87
.add_systems(ExtractSchedule, render::extract_volumetric_fog)
88
.add_systems(
89
Render,
90
(
91
render::prepare_volumetric_fog_pipelines.in_set(RenderSystems::Prepare),
92
render::prepare_volumetric_fog_uniforms.in_set(RenderSystems::Prepare),
93
render::prepare_view_depth_textures_for_volumetric_fog
94
.in_set(RenderSystems::Prepare)
95
.before(prepare_core_3d_depth_textures),
96
),
97
)
98
.add_systems(
99
Core3d,
100
volumetric_fog
101
.after(Core3dSystems::MainPass)
102
.before(Core3dSystems::PostProcess),
103
);
104
}
105
}
106
107
impl SyncComponent<VolumetricFogPlugin> for FogVolume {
108
type Out = Self;
109
}
110
111