blade_helpers/
hud.rs

1pub trait ExposeHud {
2    fn populate_hud(&mut self, ui: &mut egui::Ui);
3}
4
5impl ExposeHud for blade_render::RayConfig {
6    fn populate_hud(&mut self, ui: &mut egui::Ui) {
7        ui.add(
8            egui::Slider::new(&mut self.num_environment_samples, 1..=100u32)
9                .text("Num env samples")
10                .logarithmic(true),
11        );
12        ui.checkbox(
13            &mut self.environment_importance_sampling,
14            "Env importance sampling",
15        );
16        ui.add(egui::widgets::Slider::new(&mut self.tap_count, 0..=10).text("Tap count"));
17        ui.add(egui::widgets::Slider::new(&mut self.tap_radius, 1..=50).text("Tap radius (px)"));
18        ui.add(
19            egui::widgets::Slider::new(&mut self.tap_confidence_near, 1..=50)
20                .text("Max confidence"),
21        );
22        ui.add(
23            egui::widgets::Slider::new(&mut self.tap_confidence_far, 1..=50).text("Min confidence"),
24        );
25        ui.add(
26            egui::widgets::Slider::new(&mut self.t_start, 0.001..=0.5)
27                .text("T min")
28                .logarithmic(true),
29        );
30        ui.checkbox(&mut self.pairwise_mis, "Pairwise MIS");
31        ui.add(
32            egui::widgets::Slider::new(&mut self.defensive_mis, 0.0..=1.0).text("Defensive MIS"),
33        );
34    }
35}
36
37impl ExposeHud for blade_render::DenoiserConfig {
38    fn populate_hud(&mut self, ui: &mut egui::Ui) {
39        ui.add(egui::Slider::new(&mut self.temporal_weight, 0.0..=1.0f32).text("Temporal weight"));
40        ui.add(egui::Slider::new(&mut self.num_passes, 0..=5u32).text("A-trous passes"));
41    }
42}
43
44impl ExposeHud for blade_render::PostProcConfig {
45    fn populate_hud(&mut self, ui: &mut egui::Ui) {
46        ui.add(
47            egui::Slider::new(&mut self.average_luminocity, 0.1f32..=1_000f32)
48                .text("Average luminocity")
49                .logarithmic(true),
50        );
51        ui.add(
52            egui::Slider::new(&mut self.exposure_key_value, 0.01f32..=10f32)
53                .text("Key value")
54                .logarithmic(true),
55        );
56        ui.add(egui::Slider::new(&mut self.white_level, 0.1f32..=2f32).text("White level"));
57    }
58}
59
60impl ExposeHud for blade_render::DebugConfig {
61    fn populate_hud(&mut self, ui: &mut egui::Ui) {
62        use strum::IntoEnumIterator as _;
63
64        egui::ComboBox::from_label("View mode")
65            .selected_text(format!("{:?}", self.view_mode))
66            .show_ui(ui, |ui| {
67                for value in blade_render::DebugMode::iter() {
68                    ui.selectable_value(&mut self.view_mode, value, format!("{value:?}"));
69                }
70            });
71
72        ui.label("Draw debug:");
73        for (name, bit) in blade_render::DebugDrawFlags::all().iter_names() {
74            let mut enabled = self.draw_flags.contains(bit);
75            ui.checkbox(&mut enabled, name);
76            self.draw_flags.set(bit, enabled);
77        }
78        ui.label("Ignore textures:");
79        for (name, bit) in blade_render::DebugTextureFlags::all().iter_names() {
80            let mut enabled = self.texture_flags.contains(bit);
81            ui.checkbox(&mut enabled, name);
82            self.texture_flags.set(bit, enabled);
83        }
84    }
85}
86
87pub fn populate_debug_selection(
88    mouse_pos: &mut Option<[i32; 2]>,
89    selection: &blade_render::SelectionInfo,
90    asset_hub: &blade_render::AssetHub,
91    ui: &mut egui::Ui,
92) {
93    let screen_pos = match *mouse_pos {
94        Some(pos) => pos,
95        None => return,
96    };
97
98    let style = ui.style();
99    egui::Frame::group(style).show(ui, |ui| {
100        ui.horizontal(|ui| {
101            ui.label("Pixel:");
102            ui.colored_label(
103                egui::Color32::WHITE,
104                format!("{}x{}", screen_pos[0], screen_pos[1]),
105            );
106            if ui.button("Unselect").clicked() {
107                *mouse_pos = None;
108            }
109        });
110        ui.horizontal(|ui| {
111            let sd = &selection.std_deviation;
112            ui.label("Std Deviation:");
113            ui.colored_label(
114                egui::Color32::WHITE,
115                format!("{:.2} {:.2} {:.2}", sd.x, sd.y, sd.z),
116            );
117        });
118        ui.horizontal(|ui| {
119            ui.label("Samples:");
120            let power = selection
121                .std_deviation_history
122                .next_power_of_two()
123                .trailing_zeros();
124            ui.colored_label(egui::Color32::WHITE, format!("2^{}", power));
125        });
126        ui.horizontal(|ui| {
127            ui.label("Depth:");
128            ui.colored_label(egui::Color32::WHITE, format!("{:.2}", selection.depth));
129        });
130        ui.horizontal(|ui| {
131            let tc = &selection.tex_coords;
132            ui.label("Texture coords:");
133            ui.colored_label(egui::Color32::WHITE, format!("{:.2} {:.2}", tc.x, tc.y));
134        });
135        ui.horizontal(|ui| {
136            let wp = &selection.position;
137            ui.label("World pos:");
138            ui.colored_label(
139                egui::Color32::WHITE,
140                format!("{:.2} {:.2} {:.2}", wp.x, wp.y, wp.z),
141            );
142        });
143        ui.horizontal(|ui| {
144            ui.label("Base color:");
145            if let Some(handle) = selection.base_color_texture {
146                let name = asset_hub
147                    .textures
148                    .get_main_source_path(handle)
149                    .map(|path| path.display().to_string())
150                    .unwrap_or_default();
151                ui.colored_label(egui::Color32::WHITE, name);
152            }
153        });
154        ui.horizontal(|ui| {
155            ui.label("Normal:");
156            if let Some(handle) = selection.normal_texture {
157                let name = asset_hub
158                    .textures
159                    .get_main_source_path(handle)
160                    .map(|path| path.display().to_string())
161                    .unwrap_or_default();
162                ui.colored_label(egui::Color32::WHITE, name);
163            }
164        });
165    });
166}