1use bevy::camera::ScalingMode;
4use bevy::prelude::*;
5
6fn main() {
7 App::new()
8 .add_plugins(DefaultPlugins)
9 .add_systems(Startup, setup)
10 .add_systems(Update, environment_map_load_finish)
11 .run();
12}
13
14fn setup(
16 mut commands: Commands,
17 mut meshes: ResMut<Assets<Mesh>>,
18 mut materials: ResMut<Assets<StandardMaterial>>,
19 asset_server: Res<AssetServer>,
20) {
21 let sphere_mesh = meshes.add(Sphere::new(0.45));
22 for y in -2..=2 {
24 for x in -5..=5 {
25 let x01 = (x + 5) as f32 / 10.0;
26 let y01 = (y + 2) as f32 / 4.0;
27 commands.spawn((
29 Mesh3d(sphere_mesh.clone()),
30 MeshMaterial3d(materials.add(StandardMaterial {
31 base_color: Srgba::hex("#ffd891").unwrap().into(),
32 metallic: y01,
34 perceptual_roughness: x01,
35 ..default()
36 })),
37 Transform::from_xyz(x as f32, y as f32 + 0.5, 0.0),
38 ));
39 }
40 }
41 commands.spawn((
43 Mesh3d(sphere_mesh),
44 MeshMaterial3d(materials.add(StandardMaterial {
45 base_color: Srgba::hex("#ffd891").unwrap().into(),
46 unlit: true,
48 ..default()
49 })),
50 Transform::from_xyz(-5.0, -2.5, 0.0),
51 ));
52
53 commands.spawn((
54 DirectionalLight {
55 illuminance: 1_500.,
56 ..default()
57 },
58 Transform::from_xyz(50.0, 50.0, 50.0).looking_at(Vec3::ZERO, Vec3::Y),
59 ));
60
61 commands.spawn((
63 Text::new("Perceptual Roughness"),
64 TextFont {
65 font_size: 30.0,
66 ..default()
67 },
68 Node {
69 position_type: PositionType::Absolute,
70 top: px(20),
71 left: px(100),
72 ..default()
73 },
74 ));
75
76 commands.spawn((
77 Text::new("Metallic"),
78 TextFont {
79 font_size: 30.0,
80 ..default()
81 },
82 Node {
83 position_type: PositionType::Absolute,
84 top: px(130),
85 right: Val::ZERO,
86 ..default()
87 },
88 UiTransform {
89 rotation: Rot2::degrees(90.),
90 ..default()
91 },
92 ));
93
94 commands.spawn((
95 Text::new("Loading Environment Map..."),
96 TextFont {
97 font_size: 30.0,
98 ..default()
99 },
100 Node {
101 position_type: PositionType::Absolute,
102 bottom: px(20),
103 right: px(20),
104 ..default()
105 },
106 EnvironmentMapLabel,
107 ));
108
109 commands.spawn((
111 Camera3d::default(),
112 Transform::from_xyz(0.0, 0.0, 8.0).looking_at(Vec3::default(), Vec3::Y),
113 Projection::from(OrthographicProjection {
114 scale: 0.01,
115 scaling_mode: ScalingMode::WindowSize,
116 ..OrthographicProjection::default_3d()
117 }),
118 EnvironmentMapLight {
119 diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
120 specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
121 intensity: 900.0,
122 ..default()
123 },
124 ));
125}
126
127fn environment_map_load_finish(
128 mut commands: Commands,
129 asset_server: Res<AssetServer>,
130 environment_map: Single<&EnvironmentMapLight>,
131 label_entity: Option<Single<Entity, With<EnvironmentMapLabel>>>,
132) {
133 if asset_server
134 .load_state(&environment_map.diffuse_map)
135 .is_loaded()
136 && asset_server
137 .load_state(&environment_map.specular_map)
138 .is_loaded()
139 {
140 if let Some(label_entity) = label_entity {
142 commands.entity(*label_entity).despawn();
143 }
144 }
145}
146
147#[derive(Component)]
148struct EnvironmentMapLabel;