unlit3d_examples/scenes/
mesh_and_ui.rs1use super::{SceneControl, SceneDef, SceneOptions, TEST_SIZE, camera_view, cube, default_options};
9use unlit_ecs::{Bundle, DynamicBundle, bundle};
10use unlit3d::prelude::*;
11
12const CLEAR_COLOR: wgpu::Color = wgpu::Color {
14 r: 0.02,
15 g: 0.02,
16 b: 0.02,
17 a: 1.0,
18};
19
20struct TiltedCube {
25 mesh: GpuMesh,
26 pipeline: GpuRenderPipeline,
27}
28
29impl Bundle for TiltedCube {
30 fn into_bundle(self) -> DynamicBundle {
31 bundle![
32 Transform {
33 translation: glam::Vec3::new(0.0, 0.2, 0.0),
34 rotation: glam::Quat::from_rotation_y(0.6),
35 scale: glam::Vec3::splat(0.7),
36 },
37 self.mesh,
38 self.pipeline,
39 ]
40 }
41}
42
43pub static SCENE: SceneDef = SceneDef {
45 id: "mesh_and_ui",
46 title: "Mesh and UI",
47 description: "a cube with the rich egui panel over it, one pass",
48 size: TEST_SIZE,
49 baseline: Some(TEST_SIZE),
50 clear: Some(CLEAR_COLOR),
51 frames: 2,
52 step_seconds: None,
53 samples: 1,
54 depth: true,
55 ui: true,
56 reproducible_ui: false,
57 build,
58};
59
60fn build(
62 world: &mut World,
63 context: RenderContext,
64 pass: Entity,
65 ui: Option<Entity>,
66 size: (u32, u32),
67 options: SceneOptions,
68) -> SceneControl {
69 let mut source = MeshSource::new(&world.root_scope(), context);
70 source.register_lit_family(&world.root_scope());
71 let key = LitPipelineKey::new(default_options());
72 let source_entity = world
73 .scope_mut(pass)
74 .expect("the pass is alive")
75 .spawn(bundle![Source::new(source)]);
76
77 let mesh = super::with_mesh_source(world, source_entity, |source, world| {
78 let (positions, uvs, colors, indices) = cube();
79 source.allocate_lit_mesh(
80 world,
81 &key.options,
82 LitMeshDesc {
83 positions: &positions,
84 uvs: Some(&uvs),
85 colors: Some(&colors),
86 indices: Some(&indices),
87 ..Default::default()
88 },
89 )
90 });
91
92 let camera_entity = super::spawn_in(world, source_entity, bundle![camera_view(size)]);
93 super::spawn_in(
94 world,
95 source_entity,
96 TiltedCube {
97 mesh,
98 pipeline: GpuRenderPipeline::new(key),
99 },
100 );
101
102 if options.ui {
103 super::spawn_in(
104 world,
105 ui.expect("the UI source was mounted"),
106 bundle![super::ui_only::rich_panel()],
107 );
108 }
109
110 SceneControl {
111 advance: Box::new(move |world, _frame, _delta, frame_size| {
114 super::aim_camera(
115 world,
116 source_entity,
117 camera_entity,
118 super::DEFAULT_EYE,
119 super::DEFAULT_TARGET,
120 frame_size,
121 );
122 }),
123 snapshot: Box::new(|frame| (frame == 1).then(|| "mesh_and_ui.webp".to_owned())),
124 }
125}
126
127