Add color engine, Mandelbulb 3D explorer, render resolution, and cursor-lock zoom - #1
Add color engine, Mandelbulb 3D explorer, render resolution, and cursor-lock zoom#1Jasonilization wants to merge 8 commits into
Conversation
…ion tier Series approximation lets every pixel skip the leading iterations that are still identical (within tolerance) across the whole frame instead of looping from n=0, roughly halving to quartering CPU time at extreme zoom in testing (cross-validated against the non-SA reference orbit; smooth mu values match to 5-6 significant figures). The first pass now also tiles the image and streams completed tiles back to the iteration texture as they land, so a slow deep-zoom render visibly fills in instead of freezing on the old frame until the whole buffer is ready. Also folds in previously-uncommitted local work (async shader pipeline compilation with a loading overlay, idle-frame GPU savings, a basic auto-zoom toggle) that was sitting in the working tree, and fixes a pre-existing bug in the headless preset-preview diagnostic tool where it didn't wait for shader compilation before capturing, spuriously failing every GPU-tier preset on a fresh build.
Auto-zoom now steers toward visually rich boundary structure instead of diving straight into whatever's centered: it periodically reads back the just-rendered frame, scores a coarse grid by interior/exterior boundary presence and iteration-count variation (AutoZoomScoring), and eases the zoom pivot toward the best cell. When nothing on screen clears the boredom threshold (a flat interior lake, a featureless exterior) it backs off the zoom and sweeps the target around nearby instead of plunging into it. FractalRecorder drives that same steered path offline at a fixed per-frame timestep (independent of how long each frame actually takes to render) and encodes straight to H.264 .mov via AVAssetWriter, with adjustable resolution/fps/duration and an optional zoom-level overlay. Recording takes over the live viewport for its duration (interaction and the live auto-zoom toggle are locked) so the two never fight over the same camera state; the on-screen view mirrors progress. Cross-validated with a headless recording+thumbnail-extraction test (RECORDING_TEST_PATH) that caught and fixed a real frame-orientation bug in the overlay compositing.
HelpView is a built-in, beginner-friendly-but-accurate tutorial (toolbar Help button): what the Mandelbrot set is (z -> z^2 + c, inside vs. outside, how color encodes escape speed), controls, why deep zoom needs perturbation theory + series approximation, and what each of the three rendering modes does. A GitHub toolbar button and an About tab link the profile (github.com/Jasonilization) alongside "Created by Jason". The sidebar now also surfaces the live precision budget (~digits from the arbitrary-precision term count) and, in perturbation mode, how many iterations series approximation skipped -- and the status bar gets a color-coded GPU/GPU-DD/CPU rendering-mode chip so the active tier is visible without opening the sidebar. Verified with a from-scratch debug and release build plus the full headless preset/ladder/recording diagnostic suite (all match prior runs byte-for-byte on the GPU tiers).
- Render Resolution picker (0.5x-2x internal scale, independent of window size) plus a selectable Save Image export resolution. - "Lock Cursor to Detail" toggle: manual scroll/pinch zoom snaps its pivot onto nearby detailed structure instead of requiring pixel-perfect aim, reusing auto-zoom's boundary/gradient scoring locally. - Color engine: positioned gradient stops (add/remove/reposition, HSB + ColorPicker, live preview) via a new Palette Editor sheet, with custom palettes persisted to disk; new Classic Rainbow/Ice/Neon/Monochrome/ Scientific presets alongside the existing ones. - Three color modes -- escape time (smooth or banded), distance estimation, and orbit trap (circle/line/cross/custom point) -- plus a cheap relief shading pass, all implemented consistently across the float32, double- double, and CPU perturbation tiers. Fixed several correctness bugs found via a new COLOR_MODE_TEST_DIR headless diagnostic along the way: a gradient-cycle-speed regression, distance estimation's absolute-epsilon clamp breaking at deep zoom, and orbit trap's series-approximation-skip derivative/baseline seeding. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New "Mandelbulb Explorer" tab, alongside (not replacing) the 2D Mandelbrot explorer, sharing a native macOS tab bar and toolbar: - Standard power-N Mandelbulb distance estimator (spherical-coordinate triplex formula), ray-marched in a single Metal compute kernel with analytic normals, ambient occlusion, and soft self-shadows. - Orbit camera: click-drag to rotate, scroll/pinch to zoom, smoothly eased. - Quality tiers (Low/Medium/High/Ultra) controlling ray-march steps, AO/ shadows, and resolution scale; renders at reduced quality while the camera moves and refines once it settles, mirroring the 2D explorer's progressive-rendering approach. - Power/iteration/hollow-variant controls, adjustable lighting, reset camera, and screenshot/render export. - Presets: Classic Mandelbulb, Seahorse-like (power 4), Hollow Forms (an abs-transform variant), Spiky Forms (power 12). - A new Mandelbulb topic in the Help sheet, and a MANDELBULB_TEST_DIR headless diagnostic mirroring the existing preset-preview tooling. Verified end-to-end in the actual windowed app (not just headless): both tabs render correctly and switching between them preserves each one's state. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Julia Set Explorer is a new tab sharing the exact same rendering engine as the Mandelbrot explorer (GPU tiers, CPU perturbation with series approximation, progressive tiled rendering, color pipeline, export, recording) -- FractalRenderer is now parameterized by FractalKind (Mandelbrot vs. Julia) rather than duplicated. The reference-orbit and series-approximation math generalizes to support the Julia case (c fixed, z varies) alongside the Mandelbrot case (c varies, z starts at 0), preserving perturbation-tier deep zoom for Julia sets too. Double-clicking a point in the Mandelbrot tab (or the sidebar's "Open Julia Set at Center" button) opens that point's Julia set. The Julia sidebar adds c-parameter controls (live-updating fields/sliders, random, presets, favorites) while reusing the shared rendering/color/export sections via a new FractalCommonSidebarSections. Also fixes a black-frame flash: the perturbation tier's iteration texture used to blank to a flat interior color whenever its render size changed (at the start/end of every interaction), showing briefly before progressive tiles filled back in. It's now seeded with a bilinear resample of the previous frame instead, so the transition reads as an instant, blurry continuation rather than a black flash. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Added in this update:
Verified via headless diagnostics (full Mandelbrot preset/zoom-depth ladder to 1e80 across all three tiers, new Julia-mode GPU/perturbation tests, and a direct arbitrary-precision cross-check of the Julia perturbation math) plus manual GUI testing of tab switching, the Julia sidebar controls, and the Mandelbrot→Julia double-click handoff. |
While panning/zooming, maxIterations is temporarily cut to keep frame rate smooth. A point that hasn't escaped by that cut budget might be genuinely interior, or might just need more iterations than the current frame allows -- those are indistinguishable without iterating further. The renderer previously guessed "interior" and painted the flat interior color, which read as incorrect black holes punched into boundary detail during any interaction at real zoom depth (verified: cutting the budget from 2000 to 250 iterations at a typical deep-zoom boundary view wrongly painted 100% of the genuinely-exterior pixels needing >250 iterations as solid interior). Adds a previewMode flag (GPU kernels + CPU perturbation) that colors an unresolved point the same as an escaping point at the cap instead of guessing "interior," so it blends into the surrounding gradient until a full-iteration pass resolves it for real. Also changes the animated iteration cut from a fixed number to one proportional to the view's real maxIterations (with a floor), so deep zooms keep meaningfully more live detail during interaction instead of collapsing to a near-fixed floor regardless of depth. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Follow-up fix on top of the previous update: found and fixed a real correctness bug in the interactive-zoom quality reduction. The bug: while panning/zooming, The fix: a Added a |
Replaces the zoomed-detail Fire-palette icon with the classic full-set view (not zoomed into anything in particular) rendered with the color dials turned down, composited into a dark glass squircle: a circular panel with a soft drop shadow, a bright rim-light along its top edge, and a specular highlight, approximating macOS Tahoe's Liquid Glass material with plain CoreGraphics gradients since the app ships a flat PNG rather than a layered Icon Composer asset. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Summary
Test plan
swift buildclean, no errorsPRESET_PREVIEW_DIR) -- all 24 renders across all 3 precision tiers succeed, no regressionsCOLOR_MODE_TEST_DIRheadless diagnostic -- every color mode/orbit trap shape/shading combination verified visually correct on both GPU and perturbation tiers (caught and fixed 4 real bugs along the way: gradient-cycle-speed regression, distance-estimation's absolute-epsilon clamp breaking at deep zoom, and orbit trap's series-approximation-skip derivative/baseline seeding)MANDELBULB_TEST_DIRheadless diagnostic -- power/variant/quality combinations render correctly.apprelease bundle successfully🤖 Generated with Claude Code