feat: add shadow coloring
This commit is contained in:
+42
-17
@@ -29,6 +29,8 @@ const INTERACT_DOWNSCALE: u32 = 2;
|
||||
const INTERACT_SETTLE: f64 = 0.12;
|
||||
/// Palette names; index maps to `palette_id` in the shader.
|
||||
const PALETTE_NAMES: &[&str] = &["Amber", "Rainbow", "Ember", "Lime", "Grayscale"];
|
||||
/// Shadow palette names; index maps to `palette_id` in the shader.
|
||||
const SHADOW_PALETTE_NAMES: &[&str] = &["Grayscale", "Red & Blue"];
|
||||
/// Buddhabrot tonemap style names; index maps to `BuddhabrotUniforms::palette`.
|
||||
const BUDDHA_PALETTE_NAMES: &[&str] = &["Nebula", "Yellow", "Grayscale"];
|
||||
|
||||
@@ -121,7 +123,7 @@ const SET_PRESETS: [&[SetPreset]; FractalKind::Lambda as usize + 1] = [
|
||||
"-0.7436438870371587",
|
||||
"0.1318259042053",
|
||||
8.0e-8,
|
||||
10000,
|
||||
2000,
|
||||
None,
|
||||
),
|
||||
],
|
||||
@@ -262,11 +264,14 @@ pub struct FractalApp {
|
||||
color_scale: f32,
|
||||
color_offset: f32,
|
||||
palette: u32,
|
||||
shadow_palette: u32,
|
||||
/// Supersample each pixel 2×2 for smoother edges (costs ~4× fragment work).
|
||||
antialias: bool,
|
||||
/// Distance-estimation shading: darkens toward the set boundary using the
|
||||
/// orbit derivative, giving crisp filaments at deep zoom instead of speckle.
|
||||
de_coloring: bool,
|
||||
// Use shadow coloring
|
||||
shadow: bool,
|
||||
|
||||
/// Render as a Buddhabrot (Monte-Carlo orbit-density histogram) instead of
|
||||
/// the ordinary escape-time set. Plain f32 view — no deep zoom, no
|
||||
@@ -401,8 +406,10 @@ impl FractalApp {
|
||||
color_scale: 0.15,
|
||||
color_offset: 0.0,
|
||||
palette: 0,
|
||||
shadow_palette: 0,
|
||||
antialias: false,
|
||||
de_coloring: false,
|
||||
shadow: false,
|
||||
buddhabrot: false,
|
||||
buddha_r_cap: 50,
|
||||
buddha_g_cap: 500,
|
||||
@@ -576,6 +583,7 @@ impl FractalApp {
|
||||
color_scale: self.color_scale,
|
||||
color_offset: self.color_offset,
|
||||
palette: self.palette,
|
||||
shadow_palette: self.shadow_palette,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,6 +602,8 @@ impl FractalApp {
|
||||
self.color_scale = s.color_scale;
|
||||
self.color_offset = s.color_offset;
|
||||
self.palette = (s.palette as usize).min(PALETTE_NAMES.len() - 1) as u32;
|
||||
self.shadow_palette =
|
||||
(s.shadow_palette as usize).min(SHADOW_PALETTE_NAMES.len() - 1) as u32;
|
||||
// The link carries an explicit iteration count; honor it rather than
|
||||
// letting the auto-scaler immediately overwrite it.
|
||||
self.auto_iterations = false;
|
||||
@@ -802,14 +812,16 @@ impl FractalApp {
|
||||
bailout_sq: BAILOUT_SQ,
|
||||
is_julia: matches!(self.mode, FractalMode::Julia) as u32,
|
||||
palette_id: self.palette,
|
||||
shadow_palette_id: self.shadow_palette,
|
||||
aa_level: if self.antialias { 2 } else { 1 },
|
||||
kind: self.kind as u32,
|
||||
power: self.power,
|
||||
dc_offset: self.dc_offset(),
|
||||
phoenix_p: [self.phoenix_p.0 as f32, self.phoenix_p.1 as f32],
|
||||
lambda_l: [self.lambda_l.0 as f32, self.lambda_l.1 as f32],
|
||||
de_coloring: self.de_coloring as u32,
|
||||
_pad: [0],
|
||||
de_coloring: (self.de_coloring | self.shadow) as u32,
|
||||
shadow: self.shadow as u32,
|
||||
_pad: [0; _],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -833,11 +845,11 @@ impl FractalApp {
|
||||
r_cap: self.buddha_r_cap,
|
||||
g_cap: self.buddha_g_cap,
|
||||
b_cap: self.buddha_b_cap,
|
||||
seed: 0, // set by the callback's own dispatch counter
|
||||
seed: 0, // set by the callback's own dispatch counter
|
||||
samples_this_dispatch: 0, // set by the callback
|
||||
exposure: self.buddha_exposure,
|
||||
width: 0, // set by the callback from size_px
|
||||
height: 0, // set by the callback from size_px
|
||||
width: 0, // set by the callback from size_px
|
||||
height: 0, // set by the callback from size_px
|
||||
total_samples: 0.0, // tracked by the renderer across frames
|
||||
palette: self.buddha_palette,
|
||||
_pad: [0; 3],
|
||||
@@ -1354,22 +1366,35 @@ impl FractalApp {
|
||||
.logarithmic(true),
|
||||
);
|
||||
ui.add(egui::Slider::new(&mut self.color_offset, 0.0..=1.0).text("color offset"));
|
||||
egui::ComboBox::from_label("palette")
|
||||
.selected_text(PALETTE_NAMES[self.palette as usize])
|
||||
.show_ui(ui, |ui| {
|
||||
for (i, name) in PALETTE_NAMES.iter().enumerate() {
|
||||
ui.selectable_value(&mut self.palette, i as u32, *name);
|
||||
}
|
||||
});
|
||||
ui.checkbox(&mut self.shadow, "Shadow");
|
||||
if !self.shadow {
|
||||
egui::ComboBox::from_label("palette")
|
||||
.selected_text(PALETTE_NAMES[self.palette as usize])
|
||||
.show_ui(ui, |ui| {
|
||||
for (i, name) in PALETTE_NAMES.iter().enumerate() {
|
||||
ui.selectable_value(&mut self.palette, i as u32, *name);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
egui::ComboBox::from_label("palette")
|
||||
.selected_text(SHADOW_PALETTE_NAMES[self.shadow_palette as usize])
|
||||
.show_ui(ui, |ui| {
|
||||
for (i, name) in SHADOW_PALETTE_NAMES.iter().enumerate() {
|
||||
ui.selectable_value(&mut self.shadow_palette, i as u32, *name);
|
||||
}
|
||||
});
|
||||
}
|
||||
ui.checkbox(&mut self.antialias, "Antialiasing (2×2)")
|
||||
.on_hover_text("Supersample each pixel for smoother edges (~4× slower).");
|
||||
ui.checkbox(&mut self.de_coloring, "Distance shading")
|
||||
.on_hover_text(
|
||||
"Shade by distance to the set boundary (from the orbit derivative) \
|
||||
if !self.shadow {
|
||||
ui.checkbox(&mut self.de_coloring, "Distance shading")
|
||||
.on_hover_text(
|
||||
"Shade by distance to the set boundary (from the orbit derivative) \
|
||||
for crisp filaments at deep zoom. Exact for the holomorphic kinds \
|
||||
(Mandelbrot/Multibrot/Phoenix), approximate for the abs-based kinds \
|
||||
(Burning Ship/Tricorn/Celtic/Perpendicular/Buffalo).",
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
ui.collapsing("Animation", |ui| {
|
||||
ui.checkbox(&mut self.anim.color, "Cycle colours")
|
||||
|
||||
Reference in New Issue
Block a user