Skip to content

Commit fa1a9bc

Browse files
committed
feat: palette-coherent showcase presets (accent-to-palette-stop, rework Aurora)
Keep every temporal-colored cell on the active palette's own gradient, per the requirement that added front colors must agree with the palette: - Accent-mode default accent now samples the palette's own vivid stop (palette_accent_color, brightness 0.85) instead of the hot end (1.0), which is white/desaturated on many palettes (Slime, Cosmic) and washed the front. - All four showcase presets use Accent mode with palette-derived accents (temporal_accent: None); dropped the foreign hand-picked gold/cyan and the off-palette hue-mode drift (Aurora/Bloom were hue). - Rework Aurora: deep Ocean palette + restrained afterglow (0.15) + higher white-point (max_brightness 26) so the luminous network reads against a dark body instead of washing to a pale fill. Regenerates the 4 showcase goldens and temporal_color_accent (now reflects the palette-derived accent). All existing presets remain byte-identical.
1 parent 5fe6f2e commit fa1a9bc

8 files changed

Lines changed: 64 additions & 28 deletions

File tree

src/render/palette.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2786,10 +2786,13 @@ fn temporal_modulate(
27862786
oklch_to_srgb(oklch.l, oklch.c, h)
27872787
}
27882788
TemporalMode::Accent => {
2789-
// Front accent = the palette's hot end (brightness 1.0). Blend toward it
2790-
// for the growing front (blend > 0). Mix in OKLch for perceptual evenness.
2789+
// Front accent defaults to the palette's own vivid bright stop
2790+
// (brightness 0.85), NOT the hot end (brightness 1.0) — many palettes
2791+
// desaturate to white/gray at 1.0, which gives a washed, off-palette
2792+
// front. Sampling the palette keeps the accent on its own gradient.
2793+
// A hand-picked `accent` (CLI/preset) overrides this.
27912794
let accent =
2792-
accent.unwrap_or_else(|| map_brightness_rgb(1.0, palette, false, false, 0.0, None));
2795+
accent.unwrap_or_else(|| palette_accent_color(&palette, false, false, 0.0, None));
27932796
let t = blend.max(0.0) * strength;
27942797
mix_oklch(base, accent, t)
27952798
}
@@ -2939,16 +2942,21 @@ mod tests {
29392942
Palette::Slime,
29402943
Some(custom),
29412944
);
2942-
let hot_end = temporal_modulate(base, 0.9, TemporalMode::Accent, 1.0, Palette::Slime, None);
2945+
let palette_default =
2946+
temporal_modulate(base, 0.9, TemporalMode::Accent, 1.0, Palette::Slime, None);
29432947
assert_ne!(
2944-
with_custom, hot_end,
2945-
"custom accent must differ from hot-end"
2948+
with_custom, palette_default,
2949+
"custom accent must differ from the palette-derived accent"
29462950
);
2947-
// None path must equal the pre-change behavior (hot-end accent).
2948-
let manual_accent = map_brightness_rgb(1.0, Palette::Slime, false, false, 0.0, None);
2951+
// The None path blends toward the palette's own vivid stop
2952+
// (`palette_accent_color`, brightness 0.85), NOT the hot end (1.0).
2953+
let palette_accent = palette_accent_color(&Palette::Slime, false, false, 0.0, None);
29492954
let t = (TEMPORAL_TANH_K * 0.9_f32).tanh() * 1.0;
2950-
let expect_none = mix_oklch(base, manual_accent, t);
2951-
assert_eq!(hot_end, expect_none, "None must reproduce hot-end accent");
2955+
let expect_none = mix_oklch(base, palette_accent, t);
2956+
assert_eq!(
2957+
palette_default, expect_none,
2958+
"None must blend toward palette_accent_color"
2959+
);
29522960
}
29532961

29542962
#[test]

src/render_art_defaults.rs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,27 @@ impl From<Preset> for RenderArtDefaults {
5959
fn from(preset: Preset) -> Self {
6060
use crate::render::charset::{Charset, GlyphConfig, GlyphSelection};
6161
use crate::render::palette::{
62-
IntensityMapping, Palette, PaletteCycle, PaletteCycleMode, RgbColor, TemporalMode,
62+
IntensityMapping, Palette, PaletteCycle, PaletteCycleMode, TemporalMode,
6363
};
64+
// All showcase presets use Accent mode with `temporal_accent: None`, so
65+
// the growing front blends toward the palette's OWN vivid stop
66+
// (`palette_accent_color`, brightness 0.85) — keeping every rendered
67+
// color on the palette gradient (no foreign hand-picked hues, no
68+
// off-palette hue rotation).
6469
match preset {
6570
Preset::Lumen => Self {
6671
temporal_color: 0.5,
6772
temporal_lag_frames: 8.0,
6873
temporal_mode: TemporalMode::Accent,
69-
temporal_accent: Some(RgbColor::from_hex(0xffb347)), // warm gold
7074
palette: Some(Palette::Slime),
7175
intensity_mapping: IntensityMapping::smoothstep(),
7276
..Self::default()
7377
},
7478
Preset::Aurora => Self {
75-
temporal_color: 0.3,
79+
temporal_color: 0.4,
7680
temporal_lag_frames: 12.0,
77-
temporal_mode: TemporalMode::Hue,
78-
palette: Some(Palette::Cosmic),
81+
temporal_mode: TemporalMode::Accent,
82+
palette: Some(Palette::Ocean),
7983
intensity_mapping: IntensityMapping::smoothstep(),
8084
..Self::default()
8185
},
@@ -86,13 +90,12 @@ impl From<Preset> for RenderArtDefaults {
8690
mode: PaletteCycleMode::Mirror,
8791
},
8892
temporal_color: 0.2,
89-
temporal_mode: TemporalMode::Hue,
93+
temporal_mode: TemporalMode::Accent,
9094
..Self::default()
9195
},
9296
Preset::Etching => Self {
9397
temporal_color: 0.4,
9498
temporal_mode: TemporalMode::Accent,
95-
temporal_accent: Some(RgbColor::from_hex(0x00e5ff)), // cyan
9699
palette: Some(Palette::Neon),
97100
charset: Some(Charset::Braille),
98101
glyph: GlyphConfig {
@@ -155,9 +158,31 @@ mod tests {
155158
lumen.temporal_mode,
156159
crate::render::palette::TemporalMode::Accent
157160
);
158-
assert!(lumen.temporal_accent.is_some());
161+
// Showcase presets blend toward their OWN palette's vivid stop, so the
162+
// accent is intentionally None (palette-derived, not a foreign hue).
163+
assert_eq!(lumen.temporal_accent, None);
159164
assert_eq!(lumen.palette, Some(crate::render::palette::Palette::Slime));
160165

166+
// All showcase presets use palette-coherent Accent mode (no hue-mode
167+
// drift off the gradient).
168+
for p in [
169+
Preset::Lumen,
170+
Preset::Aurora,
171+
Preset::Bloom,
172+
Preset::Etching,
173+
] {
174+
let d = RenderArtDefaults::from(p);
175+
assert_eq!(
176+
d.temporal_mode,
177+
crate::render::palette::TemporalMode::Accent,
178+
"{p:?} must use Accent mode"
179+
);
180+
assert_eq!(
181+
d.temporal_accent, None,
182+
"{p:?} accent must be palette-derived"
183+
);
184+
}
185+
161186
let etching = RenderArtDefaults::from(Preset::Etching);
162187
assert_eq!(
163188
etching.charset,

src/simulation/config.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -865,18 +865,21 @@ impl Preset {
865865
}];
866866
}
867867
Preset::Aurora => {
868-
// Exploratory base, slow decay, soft glow.
868+
// Exploratory base, soft Gaussian glow on a deep Ocean palette.
869+
// Moderate decay + restrained afterglow keep a dark body so the
870+
// luminous network reads against it (avoids the washed-out fill
871+
// that heavy afterglow + a low white-point produced).
869872
config.sensor_angle = 45.0;
870873
config.sensor_distance = 15.0;
871874
config.rotation_angle = 60.0;
872-
config.decay_factor = 0.96;
875+
config.decay_factor = 0.92;
873876
config.deposit_amount = 3.0;
874877
config.diffusion_kernel = DiffusionKernel::Gaussian;
875878
config.diffusion_sigma = 2.5;
876879
config.diffuse_weight = 0.6;
877-
config.afterglow = 0.4;
878-
config.decay_gamma = 0.6;
879-
config.max_brightness = 12.0;
880+
config.afterglow = 0.15;
881+
config.decay_gamma = 0.7;
882+
config.max_brightness = 26.0;
880883
config.species_configs = vec![SpeciesConfig {
881884
name: "default".to_string(),
882885
count: 30_000,

tests/golden/aurora_preset.txt

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

tests/golden/bloom_preset.txt

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

tests/golden/etching_preset.txt

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

tests/golden/lumen_preset.txt

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

tests/golden/temporal_color_accent.txt

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)