Skip to content

ColorThemeEditor Guide

Bradley Brown edited this page Aug 13, 2026 · 1 revision

Color Theme Editor — Complete Guide

The Color Theme Editor is Fracturing Fog's modeless live-preview palette authoring tool. This guide covers every control, the persistence model, and 20 worked examples.

Companion pages: User Index · ColorGen DSL Guide

Color Theme Editor — new theme, Gradient kind selected.


A friendly tour

The picture on screen is made of two layers stacked on top of each other:

  1. The fractal — a black silhouette of points inside the set, surrounded by points outside it.
  2. The palette — a paint-by-numbers rule that says "this number of escape steps ⇒ this colour".

The Theme Editor lets you edit that paint-by-numbers rule live, with the fractal repainting itself as you drag sliders. Nothing you do here changes the math; it only changes how the math is visualised.

The three things worth understanding first

Thing Plain meaning
Colour Stops A list of (position, colour) pairs. The picture fades between them in order.
Kind Which colouring trick is applied: Gradient, Cycling, Phong3D (faux 3-D), Pbr3D (physically based).
Live Preview When the checkbox is ticked, edits appear in the main window within ~150 ms.

Worked example — "Make my own sunset palette in two minutes"

  1. Open Floating Menu → Edit Theme… (or press T).
  2. Pick Kind = Gradient.
  3. Empty the existing stop list and create four new stops:
    • position 0.00#1A0040 (very dark purple)
    • position 0.40#C42E1C (deep orange-red)
    • position 0.75#FFB347 (warm orange)
    • position 1.00#FFF4B5 (pale yellow)
  4. Tick Live Preview. The fractal repaints with the sunset.
  5. Tweak each stop's position by dragging it left/right. Watch the colour zones grow / shrink.
  6. Type a name (Sunset over Mandelbrot) and click Save to Library.
  7. The new theme appears in the main Theme dropdown — you can pick it any time.

Seahorse Valley at zoom 10³ painted with the "MS Standard Sunrise" gradient — warm amber filaments on cool blue voids.

Worked example — "Sample colours from a photo"

  1. Click From Image… at the bottom of the editor.
  2. Pick any JPG / PNG (an album cover, a landscape photo, a fabric swatch).
  3. The Image Palette helper opens, samples the photo with k-means in CIELAB colour space, and gives you back five evenly-spaced stops.
  4. Click Use as Stops. The Color Stops list is replaced.
  5. Tick Live Preview — the fractal now wears the photo's palette.

Tip

The Image Palette helper sorts stops by hue, then by lightness. If you want a cooler palette from a warm photo, swap stops 1↔5 and 2↔4 by dragging their position handles.

Worked example — "Make the fractal look like polished metal"

  1. Open the editor.
  2. Switch Kind = Pbr3D (physically-based 3-D lighting).
  3. Steepness = 1.5. Ambient = 0.10. Glow exp = 2.0, Glow scale = 0.4.
  4. Material bands: a single entry with metallic = 0.95, roughness = 0.15.
  5. Drag the Key Light direction so it falls roughly top-left. Set its Diffuse RGB to a warm white #FFEBD0.
  6. Tick Live Preview. The fractal grows a metallic sheen with crisp specular highlights.

Table of Contents

  1. Opening the Editor
  2. Layout
  3. Identity Section
  4. Kind Selector
  5. Color Stops
  6. Randomize — Random Theme Generator
  7. Cycle Speed
  8. 3D Lighting (Phong + PBR)
  9. Phong3D Extras
  10. Pbr3D Extras
  11. In-Set Color
  12. Post-FX Defaults
  13. Live Preview + Actions
  14. Image Palette Helper
  15. JSON Schema
  16. Worked Examples
  17. Tips + Troubleshooting

1. Opening the Editor

Three entry points:

  • Toolbar Edit Theme button.
  • Floating Menu → Color Themes → Edit Theme… button.
  • Hotkey T.

The editor seeds from the currently-selected theme. Cancel-without-Save restores the previously active theme on close — your live preview edits don't pollute the library.


2. Layout

┌──────────────────────────────────────────────────────────────────┐
│ Target  : Region ▾   Base theme ▾                                │
│ Identity: Name __________  Kind ▾  Category ▾                    │
│           Description ___________  Max zoom _____                │
├──────────────────┬───────────────────────────────────────────────┤
│ Color Stops      │ 3D Lighting                                   │
│  Add 🎲Random    │  Steepness ___   Ambient ___                  │
│   From/Import/Exp │  Key   Dir XYZ  Diffuse RGB  Spec RGB  Shine  │
│  ☐Experim ☑In-set│  Fill  Dir XYZ  Diffuse RGB  Spec RGB  Shine  │
│   ☐Post-FX       │  ☐ Rim light                                  │
│   Seed ___ ☐Use  │                                               │
│      ☑Interp     │                                               │
│  ☐Inspect  ◎     │                                               │
│  [pos] [swatch]  │                                               │
│  [pos] [swatch]  │                                               │
│ Cycle            │ Phong3D extras                                │
│  Speed ___       │  Key/Fill/Rim  spec + diff scales             │
│                  │                                               │
│ In-Set           │ Pbr3D extras                                  │
│  ☐ Override RGBA │  Lighting mode ▾  Glow exp / scl              │
│                  │  Material bands [start end metal rough] …     │
│ Post-FX defaults │                                               │
│  Brightness ___  │                                               │
│  Contrast   ___  │                                               │
│  Adaptive   ___  │                                               │
│                  │                                               │
│ Actions          │                                               │
│  ☑ Live preview  │                                               │
│  [Apply] [Blank] │                                               │
│  [Revert]        │                                               │
│  [Save] [Export] │                                               │
│  [Save C#]       │                                               │
│  [From Image…]   │                                               │
└──────────────────┴───────────────────────────────────────────────┘

Sections collapse when irrelevant — Phong3D / PBR3D extras hide for Gradient + Cycling kinds.


3. Identity Section

Field Purpose
Name Library key. Must be unique within colorthemes.json.
Kind Gradient / Cycling / Phong3D / Pbr3D
Category Free-form grouping label (used by the right-click sort menu)
Description Optional free-text annotation
Max zoom Optional metadata — UI does not enforce; future-proofing for adaptive theme switching

Save behavior: if the typed Name already exists in the library, the editor prompts to confirm overwrite. Cancel returns to the editor with the existing entry untouched.


4. Kind Selector

Kind When to use
Gradient Single-pass linear ramp across the iter range. Best for escape-time + distance-estimation maps where the iteration count is roughly monotonic.
Cycling Repeats the gradient N times along the iter axis. Best for revealing fine band structure in shallow + medium zooms.
Phong3D Cycling gradient + Blinn-Phong directional lighting computed from a synthesized surface normal (the Z component is built from the iter derivative). Gives a relief-mapped look.
Pbr3D Cycling gradient + Cook-Torrance physically-based shading + per-band metallic/roughness. Gives a real-material look (chrome, brushed steel, ceramic, glass).

Changing Kind shows / hides the relevant lighting sections.


5. Color Stops

Control Behavior
Position [0, 1] Normalised stop along the gradient. 0 = low iter, 1 = high iter.
Swatch Click for the color picker. RGB / hex entry below the swatch also works.
Add Insert a new stop above the selected one.
Delete Remove the selected stop. Editor enforces ≥ 2 stops.
Reorder Drag the position handle to reposition.

Stops interpolate linearly between adjacent positions. Outside [0, 1] the outer stops clamp.

Tip: for smooth gradients, space stops by perceptual distance, not numeric distance. Two close stops in dark regions look smoother than the same stops evenly placed across the full range.


6. Randomize — Random Theme Generator

The 🎲 Random button (top of the Color Stops section) generates a complete theme in one click — not just the palette. It always builds a fresh set of colour stops via a golden-ratio hue walk (maximally-spaced hues so no two stops crowd the wheel), then layers on extra randomized settings chosen by the current Kind and by the toggle row directly beneath the button.

What gets randomized

Area When
Colour stops Always.
Interpolation (Space / Curve / Transfer / Strength / Gamma) When Interpolation is ticked (default on).
Cycle settings (offset / density / speed / wrap mode) Every Kind except Gradient.
3D light rig + shared Steepness / Ambient Phong3D and Pbr3D.
Phong extras (key/fill/rim spec + diff scales) Phong3D only.
PBR lighting mode, glow, and material bands Pbr3D only.
In-set (interior) colour When In-set is ticked (default on).
Post-FX defaults (Brightness / Contrast / Adaptive-HE) When Post-FX is ticked (default off).

The toggle row

Control Default Effect
Random Experimental off Off = artful mode: every value stays inside a logical range, and 3D light colours + the in-set colour are pulled from the palette just generated so the result reads as one family. On = experimental mode: caps are removed and the generator "goes wild" — full-range colours, wider counts, unconstrained placement.
In-set on Include a random interior colour. Artful mode picks a dark member of the palette family (opaque) so the in-set reads as a recessed pocket; experimental mode allows any colour and any alpha.
Post-FX off Include random Post-FX defaults. Ticking this also ticks the Brightness / Contrast / Adaptive Use checkboxes to match (and unticking clears them) so you never have to flip them by hand. Artful mode keeps Brightness/Contrast within ±20 and Adaptive-HE under 50; experimental mode uses the full slider ranges.
Interpolation on Include random Space / Curve / Transfer / Transfer-strength / Palette-gamma. Artful keeps strength and gamma near neutral; experimental spans their full ranges.

Seed and reproducibility

  • Every click records the seed used in the Description field and writes it into the Seed field.
  • Use Seed (default off): while off, the Seed field is greyed out and each click draws a fresh seed — so repeated clicks keep producing new themes. Tick Use Seed to enable the field; the next click uses the value you enter.
  • The same seed with the same toggles, Kind, and Experimental state reproduces an identical theme. A single seeded RNG drives every step in fixed order, so changing any of those inputs changes the result.

Tip

Found a random theme you like? Its seed is already in the Seed field and the Description. Tick Use Seed, then flip Random Experimental on and off (or switch Kind) to explore controlled variations around the same starting point.

Note

Randomize replaces the current stops and the settings it covers. Untick a scope toggle (In-set, Post-FX, Interpolation) to protect those sections from being overwritten.


7. Cycle Speed

Active for Cycling / Phong3D / Pbr3D kinds.

Speed = 0.02 ≈ one full gradient cycle every 50 smoothed-iter units. Higher speed = more bands, tighter rings. Typical range 0.005 – 0.2.

For Phong3D + Pbr3D, the cycle controls the base albedo banding only — the lighting overlays on top, so a moderate cycle (0.02–0.05) usually reads better than a frantic high cycle.


8. 3D Lighting (Phong + PBR)

Shared parameters between Phong3D and Pbr3D kinds:

Parameter Purpose Typical range
Steepness Z-scale on the synthesized normal. Higher = more relief depth. 0.5 – 4.0
Ambient Base illumination before lighting. 0 = pitch-black shadows. 0.0 – 0.3

Lights

Each light carries:

Field Description
Direction (X, Y, Z) Normalised direction vector. (0, 0, 1) = straight at camera.
Diffuse RGB Color of the diffuse contribution. Bright key, dim fill is typical.
Specular RGB Color of the highlight. White / warm for key, cool for fill.
Shininess Specular exponent. 1 = matte, 256 = chrome.

Key Light is the strong, often warm primary. Fill Light is the dim, often cool sim of sky / bounce. Rim Light (optional) is a back-light that highlights silhouette edges.

A balanced 3-point setup: Key 1.0 / Fill 0.4 / Rim 0.3.


9. Phong3D Extras

Phong3D exposes five per-light scale factors on top of the shared 3D-lighting block, letting you dial each light's diffuse / specular contribution independently for atmospheric accent (e.g., a cyan fill halo opposite the warm key spec).

Field Purpose Typical range
Key spec Specular strength of the Key light. 0.4 – 1.2
Fill spec Specular strength of the Fill light. 0.1 – 0.5
Fill diff Diffuse strength of the Fill light. 0.2 – 0.6
Rim spec Specular strength of the Rim light (only when Rim is enabled). 0.5 – 1.5
Rim diff Diffuse strength of the Rim light (only when Rim is enabled). 0.1 – 0.4

Leave them near their defaults for a balanced rig; push a single value when you want one light to dominate.


10. Pbr3D Extras

Pbr3D uses a Cook-Torrance BRDF with a GGX normal-distribution function and Smith geometric occlusion. Material parameters drive the BRDF:

Field Purpose Range
Lighting mode PBRRealistic (filmic curve) / PBRBright (pre-multiplied radiance for a punchier sci-fi look) enum
Glow exp / scale Additive emission near escape (t → 1). 0–10 / 0–5
Material bands List of (start t, end t, metallic, roughness) tuples. Lets you make the cardioid matte ceramic while the filaments turn chrome. per-band

Material bands are evaluated in declared order — the first band whose (start, end) contains the current t wins. Out-of-range t falls back to a default (metallic 0, roughness 0.5).


11. In-Set Color

When the Override checkbox is ticked, the picker sets the RGBA color for points that never escape (the cardioid + bulbs).

Default behavior (override off) draws the in-set with opaque black. Useful overrides:

  • Dark navy (8, 12, 32) to keep contrast without harshness.
  • Very-dark hue-matched color taken from the gradient's tail — keeps the in-set from popping visually.
  • A partial alpha — the interior alpha is honored (per-theme, #96): below 255 the in-set composites over the 2D interior background, and the global InteriorAlpha knob multiplies this value. The swatch previews the authored alpha so a translucent interior reads as faded.

12. Post-FX Defaults

Per-theme defaults for the three Post-FX sliders.

When you select this theme from a combo, the renderer snaps each slider to the corresponding default — unless that slider's Lock checkbox is ticked. Locking lets you preserve a global brightness preference across theme browsing.

Field Range Default
Brightness −100 … +100 0
Contrast −100 … +100 0
Adaptive 0 … 100 0

13. Live Preview + Actions

Action Behavior
Live preview Edits push to the main render via 150 ms debounce. Drag freely; the calculator re-runs once per debounced commit.
Apply Force a push regardless of live-preview state.
New Blank Discard edits; start from a fresh Gradient (2 stops, black → white).
Revert Reload from the last source theme name.
Save to Library Validate Name + ≥ 2 stops, upsert into colorthemes.json. Prompts to confirm overwrite if the name already exists.
Export JSON… Write a single-theme JSON array to disk.
Save C#… Write a compilable ColorThemeData C# class via ColorThemeCsExporter. Drop the file into Models/ColorSchemes/Generated/ and rebuild to ship as built-in.
From Image… Open the Image Palette helper.

14. Image Palette Helper

Sample any PNG / JPG / BMP, get a 5-stop palette via k-means clustering in CIELAB color space, loaded straight into the Color Stops list.

Control Purpose
Source image Click to browse. Loads + downsamples for analysis.
Cluster count 2 – 16 centroids. Default 5.
Sort By hue / by lightness / by frequency.
Sample bias Center / Edges / Uniform — bias which pixels feed the kmeans.
Use as palette Load the centroids as Color Stops.

Tip: pick a source image whose mood matches your fractal target. A sunset photo for a warm Mandelbrot, a CT scan for a sci-fi Mandelbulb.


15. JSON Schema

Each entry in colorthemes.json is a single ColorThemeData object. Field omission follows WhenWritingNull — null fields disappear entirely.

{
  "name": "My Theme",
  "kind": "Phong3D",
  "category": "Custom",
  "description": "Warm dusk shading",
  "maxZoom": 1e20,
  "stops": [
    { "position": 0.0, "r": 8,   "g": 4,   "b": 16  },
    { "position": 0.4, "r": 255, "g": 80,  "b": 16  },
    { "position": 1.0, "r": 255, "g": 230, "b": 180 }
  ],
  "cycleSpeed": 0.03,
  "lighting": {
    "steepness": 1.6,
    "ambient": 0.12,
    "keyLight": {
      "dir": { "x": 0.4, "y": 0.6, "z": 0.7 },
      "diffuse": { "r": 1.0, "g": 0.9, "b": 0.8 },
      "specular": { "r": 1.0, "g": 1.0, "b": 1.0 },
      "shininess": 64
    },
    "fillLight": { ... },
    "rim": null
  },
  "inSet": null,
  "postFxDefaults": {
    "brightness": 0,
    "contrast": 10,
    "adaptive": 0
  }
}

Pbr3D entries add a pbrExtras block with lightingMode, glowExp, glowScale, and a materialBands array.

Colour options (optional, all kinds). Omit for the historical look:

Field Values Default Effect
interpolationSpace Srgb / OkLab / Hsv Srgb Colour space the gradient blends stops in. OkLab = perceptually smooth mid-tones; Hsv = shorter-arc hue sweep. Zero render cost (baked into the LUT).
interpolationCurve Linear / Cosine / Cubic / Step Linear Segment blend shape. Cosine eases at both stops; Cubic = Catmull-Rom spline through stops (sRGB); Step = hard bands.
transferFunction Linear / Sqrt / Cubic / Log / Sine Linear Remaps the mapping scalar before lookup (Ultra-Fractal "transfer"). Log/Sqrt spread deep detail; Cubic compresses shadows. Gradient + Cycling only.
transferStrength float [0,1] 1 Blends identity↔transferFunction.
paletteGamma float [0.2,3] 1 Per-theme gamma baked into the LUT (out = in^(1/gamma)). >1 lifts shadows/brightens, <1 darkens. Zero render cost; compounds with the live image-gamma slider.
colorOffset float 0 Phase rotation of the palette along the iteration axis (Cycling / Phong3D / Pbr3D).
colorDensity float 1 Frequency multiplier — how many cycles fit, independent of cycleSpeed.
wrapMode Repeat / PingPong / Clamp Repeat Boundary behaviour. PingPong mirrors so there is no 1→0 seam.

Each entry in stops also accepts an optional midpoint (float in (0,1), default 0.5): the blend midpoint of the segment starting at that stop. Values below 0.5 push the halfway colour toward this stop, above 0.5 toward the next. Omit (or 0.5) for a straight blend.


16. Worked Examples

Example 1 — Warm Sunset Gradient

  • Kind: Gradient
  • Stops: (0.0, #0A0613) → (0.3, #4B1B30) → (0.6, #C8521C) → (0.85, #FFA13C) → (1.0, #FFE9A8)
  • In-set: override #050308.

Example 2 — Cool Glacier Cycling

  • Kind: Cycling
  • Cycle Speed: 0.025
  • Stops: (0.0, #050E2B) → (0.4, #1E5780) → (0.7, #C0E6FF) → (1.0, #FFFFFF)

Example 3 — Twilight Spiral (3-stop)

  • Kind: Cycling
  • Cycle Speed: 0.04
  • Stops: (0.0, #1A0033) → (0.5, #FF5599) → (1.0, #FFFF99)

Example 4 — Solar Flare Phong3D

  • Kind: Phong3D
  • Cycle Speed: 0.03
  • Stops: (0.0, #100000) → (0.45, #C04000) → (0.85, #FFC050) → (1.0, #FFFFE0)
  • Steepness 2.2, Ambient 0.08
  • Key Light dir (0.5, 0.6, 0.6), diffuse (1.0, 0.85, 0.55), spec (1.0, 1.0, 1.0), shine 96
  • Fill Light dir (-0.4, -0.3, 0.5), diffuse (0.2, 0.3, 0.6), spec (0.4, 0.5, 0.8), shine 32

Example 5 — Brushed Copper Pbr3D

  • Kind: Pbr3D
  • Cycle Speed: 0.02
  • Stops: (0.0, #110804) → (0.5, #C57033) → (1.0, #FFD79A)
  • Lighting mode: PBRRealistic
  • Material bands: [(0.0, 0.5, metallic 1.0, roughness 0.4), (0.5, 1.0, metallic 1.0, roughness 0.18)]
  • Glow exp 6.0, scale 0.4

Example 6 — Chrome Filament

  • Kind: Pbr3D
  • Stops: (0.0, #050505) → (1.0, #FFFFFF)
  • Material bands: [(0.0, 1.0, metallic 1.0, roughness 0.05)]

Example 7 — Domain Coloring Argument

  • Kind: Gradient with HSV-cycling color stops (12 stops around the hue wheel)
  • In-set: override #000000.

Example 8 — Phosphor CRT

  • Stops: (0.0, #000000) → (0.5, #003B00) → (1.0, #6CFFB1)
  • Post-FX defaults: contrast +20, brightness -10.

Example 9 — Bauhaus Primary

  • Kind: Cycling
  • Cycle Speed: 0.05
  • Stops: (0.0, #E63946) → (0.5, #F1FA8C) → (1.0, #1D3557)

Example 10 — Inferno-style

  • Stops: (0.0, #000004) → (0.25, #420A68) → (0.5, #932667) → (0.75, #DD513A) → (1.0, #FCFFA4)

Example 11 — Pastel Cotton Candy

  • Stops: (0.0, #FFC4D6) → (0.5, #C4B5FF) → (1.0, #B8F0FF)
  • Cycle Speed: 0.03

Example 12 — Topo Map

  • Kind: Cycling
  • Cycle Speed: 0.08
  • Stops: (0.0, #2E512E) → (0.4, #5A8C39) → (0.7, #C9B780) → (1.0, #FFFFFF)
  • Repeats every ~12 iter units; reads like elevation rings.

Example 13 — Iridescent Oil Slick

  • Kind: Cycling
  • Cycle Speed: 0.06
  • Stops: 6 stops cycling through magenta → blue → green → yellow → red → magenta.

Example 14 — Tron Grid

  • Kind: Pbr3D
  • Stops: (0.0, #00111A) → (0.5, #00B0E0) → (1.0, #80FFFF)
  • Material bands: [(0.0, 1.0, metallic 0.6, roughness 0.25)]
  • Glow exp 4.0, scale 1.2

Example 15 — Vintage Sepia

  • Stops: (0.0, #2A1505) → (0.6, #A07550) → (1.0, #F0E0C0)
  • Post-FX defaults: contrast +5.

Example 16 — Ice Cave

  • Kind: Phong3D
  • Cycle Speed: 0.025
  • Stops: (0.0, #051F3B) → (0.5, #7EB5E0) → (1.0, #FFFFFF)
  • Steepness 1.8, Ambient 0.15

Example 17 — Volcanic Glass

  • Kind: Pbr3D
  • Stops: (0.0, #050505) → (0.7, #4B0010) → (1.0, #FF7050)
  • Material bands: [(0.0, 0.7, metallic 0.0, roughness 0.6), (0.7, 1.0, metallic 0.0, roughness 0.05)]
  • Glow exp 3.0, scale 0.8

Example 18 — Watercolor

  • Stops: (0.0, #F4E9DC) → (0.5, #B8D8E5) → (1.0, #D4A5A5)
  • Post-FX defaults: brightness +10.

Example 19 — Ultra-Violet

  • Kind: Cycling
  • Cycle Speed: 0.07
  • Stops: 4 stops (#000033 → #6633CC → #CC33FF → #FFFFFF) repeated.
  • Pair with Adaptive = 80 for psychedelic deep-zooms.

Example 20 — Mono Ink

  • Stops: (0.0, #FFFFFF) → (0.5, #777777) → (1.0, #000000)
  • Cycle Speed: 0.04
  • Useful for distance-estimation maps where shape, not color, is the goal.

17. Tips + Troubleshooting

Live preview lagging. Lower Cycle Speed temporarily, or untick Live preview and use Apply between edits.

Banding visible at deep zoom. Increase iteration count (Floating Menu → Iter), or raise Quality. The palette only colors what the calculator computes; bands appear when iter is too low for the depth.

Phong3D looks plastic. Drop Specular RGB and raise Roughness — actually, switch to Pbr3D and use the material band system. Phong's specular model lacks the energy conservation that makes PBR materials look ""real.""

Pbr3D too dark. Raise Ambient to 0.15–0.2, switch Lighting mode to PBRBright, or push the glow scale.

In-set color washes out the rest. Untick the override; the default opaque-black tends to read better. If you must override, pick a desaturated low-luma color.

Save button silently overwrites. As of v0.6.2, the overwrite confirmation prompt prevents accidental clobbering. If you're not seeing the prompt, the typed name doesn't match any existing user theme — Save proceeds as an insert.

My theme disappears after reload. Built-in themes don't write to colorthemes.json; only user-saved themes do. Use Save to Library, not Export JSON, for persistence.

Image Palette returns washed-out colors. Bias toward Edges or pick a more saturated source image. K-means clusters in CIELAB; pure-grey source images give a grey palette.


Color Theme Editor Guide · Fracturing Fog · © 2026

Clone this wiki locally