Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/3d/atmosphere.rs
6592 views
1
//! This example showcases pbr atmospheric scattering
2
3
use std::f32::consts::PI;
4
5
use bevy::{
6
camera::Exposure,
7
core_pipeline::tonemapping::Tonemapping,
8
light::{light_consts::lux, AtmosphereEnvironmentMapLight, CascadeShadowConfigBuilder},
9
pbr::{Atmosphere, AtmosphereSettings},
10
post_process::bloom::Bloom,
11
prelude::*,
12
};
13
14
fn main() {
15
App::new()
16
.add_plugins(DefaultPlugins)
17
.add_systems(Startup, (setup_camera_fog, setup_terrain_scene))
18
.add_systems(Update, dynamic_scene)
19
.run();
20
}
21
22
fn setup_camera_fog(mut commands: Commands) {
23
commands.spawn((
24
Camera3d::default(),
25
Transform::from_xyz(-1.2, 0.15, 0.0).looking_at(Vec3::Y * 0.1, Vec3::Y),
26
// This is the component that enables atmospheric scattering for a camera
27
Atmosphere::EARTH,
28
// The scene is in units of 10km, so we need to scale up the
29
// aerial view lut distance and set the scene scale accordingly.
30
// Most usages of this feature will not need to adjust this.
31
AtmosphereSettings {
32
aerial_view_lut_max_distance: 3.2e5,
33
scene_units_to_m: 1e+4,
34
..Default::default()
35
},
36
// The directional light illuminance used in this scene
37
// (the one recommended for use with this feature) is
38
// quite bright, so raising the exposure compensation helps
39
// bring the scene to a nicer brightness range.
40
Exposure::SUNLIGHT,
41
// Tonemapper chosen just because it looked good with the scene, any
42
// tonemapper would be fine :)
43
Tonemapping::AcesFitted,
44
// Bloom gives the sun a much more natural look.
45
Bloom::NATURAL,
46
// Enables the atmosphere to drive reflections and ambient lighting (IBL) for this view
47
AtmosphereEnvironmentMapLight::default(),
48
));
49
}
50
51
#[derive(Component)]
52
struct Terrain;
53
54
fn setup_terrain_scene(
55
mut commands: Commands,
56
mut meshes: ResMut<Assets<Mesh>>,
57
mut materials: ResMut<Assets<StandardMaterial>>,
58
asset_server: Res<AssetServer>,
59
) {
60
// Configure a properly scaled cascade shadow map for this scene (defaults are too large, mesh units are in km)
61
let cascade_shadow_config = CascadeShadowConfigBuilder {
62
first_cascade_far_bound: 0.3,
63
maximum_distance: 3.0,
64
..default()
65
}
66
.build();
67
68
// Sun
69
commands.spawn((
70
DirectionalLight {
71
shadows_enabled: true,
72
// lux::RAW_SUNLIGHT is recommended for use with this feature, since
73
// other values approximate sunlight *post-scattering* in various
74
// conditions. RAW_SUNLIGHT in comparison is the illuminance of the
75
// sun unfiltered by the atmosphere, so it is the proper input for
76
// sunlight to be filtered by the atmosphere.
77
illuminance: lux::RAW_SUNLIGHT,
78
..default()
79
},
80
Transform::from_xyz(1.0, -0.4, 0.0).looking_at(Vec3::ZERO, Vec3::Y),
81
cascade_shadow_config,
82
));
83
84
let sphere_mesh = meshes.add(Mesh::from(Sphere { radius: 1.0 }));
85
86
// light probe spheres
87
commands.spawn((
88
Mesh3d(sphere_mesh.clone()),
89
MeshMaterial3d(materials.add(StandardMaterial {
90
base_color: Color::WHITE,
91
metallic: 1.0,
92
perceptual_roughness: 0.0,
93
..default()
94
})),
95
Transform::from_xyz(-0.3, 0.1, -0.1).with_scale(Vec3::splat(0.05)),
96
));
97
98
commands.spawn((
99
Mesh3d(sphere_mesh.clone()),
100
MeshMaterial3d(materials.add(StandardMaterial {
101
base_color: Color::WHITE,
102
metallic: 0.0,
103
perceptual_roughness: 1.0,
104
..default()
105
})),
106
Transform::from_xyz(-0.3, 0.1, 0.1).with_scale(Vec3::splat(0.05)),
107
));
108
109
// Terrain
110
commands.spawn((
111
Terrain,
112
SceneRoot(
113
asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/terrain/terrain.glb")),
114
),
115
Transform::from_xyz(-1.0, 0.0, -0.5)
116
.with_scale(Vec3::splat(0.5))
117
.with_rotation(Quat::from_rotation_y(PI / 2.0)),
118
));
119
}
120
121
fn dynamic_scene(mut suns: Query<&mut Transform, With<DirectionalLight>>, time: Res<Time>) {
122
suns.iter_mut()
123
.for_each(|mut tf| tf.rotate_x(-time.delta_secs() * PI / 10.0));
124
}
125
126