background_occlusion_example/
background-occlusion-example.rs1use mittens_engine::{engine, utils};
2
3#[path = "example_util/mod.rs"]
4mod example_util;
5
6fn hash_u32(mut x: u32) -> u32 {
7 x ^= x >> 16;
8 x = x.wrapping_mul(0x7feb_352d);
9 x ^= x >> 15;
10 x = x.wrapping_mul(0x846c_a68b);
11 x ^= x >> 16;
12 x
13}
14
15fn rand01(seed: u32) -> f32 {
16 (hash_u32(seed) as f32) / (u32::MAX as f32)
17}
18
19fn main() {
20 mittens_engine::example_support::ensure_model_assets();
21 utils::logger::init();
22
23 let world = engine::ecs::World::default();
24 let mut universe = engine::Universe::new(world);
25
26 let clear = universe
28 .world
29 .add_component(engine::ecs::component::BackgroundColorComponent::new());
30 let clear_c = universe
31 .world
32 .add_component(engine::ecs::component::ColorComponent::rgba(
33 0.62, 0.38, 0.56, 1.0,
34 ));
35 let _ = universe.world.add_child(clear, clear_c);
36 universe.add(clear);
37
38 let ambient = universe
40 .world
41 .add_component(engine::ecs::component::AmbientLightComponent::rgb(
42 0.20, 0.15, 0.3,
43 ));
44 universe.add(ambient);
45
46 let input = universe
48 .world
49 .add_component(engine::ecs::component::InputComponent::new().with_speed(2.0));
50 let input_mode = universe.world.add_component(
51 engine::ecs::component::InputTransformModeComponent::forward_z().with_roll_axis_y(),
52 );
53 let _ = universe.attach(input, input_mode);
54
55 let rig_transform = universe.world.add_component(
56 engine::ecs::component::TransformComponent::new().with_position(0.0, 0.0, 6.0),
57 );
58 let _ = universe.attach(input, rig_transform);
59
60 let camera3d = universe.world.add_component(
61 engine::ecs::component::Camera3DComponent::new()
62 .with_far(200.0)
63 .with_fov(70.0),
64 );
65 let _ = universe.attach(rig_transform, camera3d);
66
67 example_util::spawn_desktop_camera_controls_hint(&mut universe, rig_transform);
69
70 let sun = universe.world.add_component(
75 engine::ecs::component::DirectionalLightComponent::new()
76 .with_intensity(1.6)
77 .with_color(1.0, 0.98, 0.92),
78 );
79 let sun_dir = universe.world.add_component(
81 engine::ecs::component::TransformComponent::new().with_position(0.15, 0.65, 0.75),
82 );
83 let _ = universe.attach(sun_dir, sun);
84
85 let light_a = universe.world.add_component(
87 engine::ecs::component::PointLightComponent::new()
88 .with_distance(80.0)
89 .with_intensity(3.0)
90 .with_color(0.9, 0.95, 1.0),
91 );
92 let light_a_tx = universe.world.add_component(
93 engine::ecs::component::TransformComponent::new().with_position(8.0, 8.0, 5.0),
94 );
95 let _ = universe.attach(light_a_tx, light_a);
96
97 let light_b = universe.world.add_component(
98 engine::ecs::component::PointLightComponent::new()
99 .with_distance(80.0)
100 .with_intensity(2.2)
101 .with_color(1.0, 0.9, 0.85),
102 );
103 let light_b_tx = universe.world.add_component(
104 engine::ecs::component::TransformComponent::new().with_position(-10.0, 4.0, -6.0),
105 );
106 let _ = universe.attach(light_b_tx, light_b);
107
108 universe.add(input);
109 universe.add(sun_dir);
110 universe.add(light_a_tx);
111 universe.add(light_b_tx);
112
113 let cube_mesh = universe
114 .render_assets
115 .get_mesh(engine::graphics::BuiltinMeshType::Cube);
116
117 let bg_root = universe.world.add_component(
121 engine::ecs::component::BackgroundComponent::new().with_occlusion_and_lighting(),
122 );
123 universe.add(bg_root);
124
125 let cluster_count: u32 = 9;
129 for (group_i, group_x) in [-16.0_f32, 16.0_f32].into_iter().enumerate() {
130 let group_tx = universe.world.add_component(
131 engine::ecs::component::TransformComponent::new().with_position(group_x, 0.0, 0.0),
132 );
133 let _ = universe.attach(bg_root, group_tx);
134
135 for cluster_i in 0..cluster_count {
136 let seed = (0xC10u32 ^ (group_i as u32).wrapping_mul(0x9E37_79B9))
137 ^ (cluster_i.wrapping_mul(7919));
138
139 let cx = (rand01(seed ^ 0xA341_316C) - 0.5) * 18.0;
140 let cy = (rand01(seed ^ 0xC801_3EA4) - 0.5) * 10.0 + 2.0;
141 let cz = -18.0 - rand01(seed ^ 0xB529_7A4D) * 26.0;
142
143 let center_tx = universe.world.add_component(
144 engine::ecs::component::TransformComponent::new().with_position(cx, cy, cz),
145 );
146 let _ = universe.attach(group_tx, center_tx);
147
148 let puffs = 18u32;
149 for puff_i in 0..puffs {
150 let puff_seed = seed ^ puff_i.wrapping_mul(1_103_515_245);
151
152 let ox = (rand01(puff_seed ^ 0x68bc_21eb) - 0.5) * 7.0;
154 let oy = (rand01(puff_seed ^ 0x02e5_be93) - 0.5) * 3.0;
155 let oz = (rand01(puff_seed ^ 0xa1d3_4f2b) - 0.5) * 7.0;
156
157 let base = 0.7 + rand01(puff_seed ^ 0x9e37_79b9) * 2.6;
158 let sx = base * (0.7 + rand01(puff_seed ^ 0x243f_6a88) * 0.8);
159 let sy = base * (0.6 + rand01(puff_seed ^ 0x85a3_08d3) * 0.9);
160 let sz = base * (0.7 + rand01(puff_seed ^ 0x1319_8a2e) * 0.8);
161
162 let tx = universe.world.add_component(
163 engine::ecs::component::TransformComponent::new()
164 .with_position(ox, oy, oz)
165 .with_scale(sx, sy, sz),
166 );
167 let renderable =
168 universe
169 .world
170 .add_component(engine::ecs::component::RenderableComponent::new(
171 engine::graphics::primitives::Renderable::new(
172 cube_mesh,
173 engine::graphics::primitives::MaterialHandle::TOON_MESH,
174 ),
175 ));
176
177 let t = rand01(puff_seed ^ 0x7f4a_7c15);
179 let r = 0.55 + 0.10 * t;
180 let g = 0.58 + 0.10 * t;
181 let b = 0.66 + 0.12 * t;
182 let color = universe
183 .world
184 .add_component(engine::ecs::component::ColorComponent::rgba(r, g, b, 1.0));
185
186 let _ = universe.attach(center_tx, tx);
187 let _ = universe.attach(tx, renderable);
188 let _ = universe.attach(renderable, color);
189 }
190 }
191 }
192
193 let fg_tx = universe.world.add_component(
195 engine::ecs::component::TransformComponent::new()
196 .with_position(0.0, -0.5, -4.0)
197 .with_scale(1.2, 0.8, 1.2),
198 );
199 let fg_renderable =
200 universe
201 .world
202 .add_component(engine::ecs::component::RenderableComponent::new(
203 engine::graphics::primitives::Renderable::new(
204 cube_mesh,
205 engine::graphics::primitives::MaterialHandle::TOON_MESH,
206 ),
207 ));
208 let fg_color = universe
209 .world
210 .add_component(engine::ecs::component::ColorComponent::rgba(
211 0.9, 0.2, 0.2, 1.0,
212 ));
213
214 universe.add(fg_tx);
215 let _ = universe.attach(fg_tx, fg_renderable);
216 let _ = universe.attach(fg_renderable, fg_color);
217
218 let floor_root = universe.world.add_component(
220 engine::ecs::component::TransformComponent::new().with_position(0.0, -10.5, -10.0),
221 );
222 universe.add(floor_root);
223
224 let spacing = 10_f32;
225 let half = 5_f32;
226 for x in 0..16u32 {
227 for z in 0..64u32 {
228 let px = (x as f32 - half) * spacing;
229 let pz = (z as f32 * -1.0 + half) * spacing;
230 let tx = universe.world.add_component(
231 engine::ecs::component::TransformComponent::new()
232 .with_position(px, -5.0, pz)
233 .with_scale(5.0, 0.5, 5.0),
234 );
235 let renderable =
236 universe
237 .world
238 .add_component(engine::ecs::component::RenderableComponent::new(
239 engine::graphics::primitives::Renderable::new(
240 cube_mesh,
241 engine::graphics::primitives::MaterialHandle::TOON_MESH,
242 ),
243 ));
244 let color = universe
245 .world
246 .add_component(engine::ecs::component::ColorComponent::rgba(
247 1.0, 1.0, 1.0, 1.0,
248 ));
249
250 let _ = universe.attach(floor_root, tx);
251 let _ = universe.attach(tx, renderable);
252 let _ = universe.attach(renderable, color);
253 }
254 }
255
256 universe.systems.process_commands(
257 &mut universe.world,
258 &mut universe.visuals,
259 &mut universe.render_assets,
260 &mut universe.command_queue,
261 );
262
263 universe.enable_repl();
264 engine::Windowing::run_app(universe).expect("Windowing failed");
265}