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