Dynamic box - #4
Merged
Merged
Conversation
…d perf sampling reports
…rationale - Add check-shaders.js: wraps each shaders/*.metal with the same prelude as DynamicBoxRenderer.wrapShaderSource() and compiles it with xcrun metal to catch type/compile errors for files excluded from the Xcode target. - Wire it into the Xcode build as a Run Script build phase (Check DynamicBox Shaders) that runs before Sources compile and fails the build on error. Disabled ENABLE_USER_SCRIPT_SANDBOXING at the target level to avoid an EPERM (uv_cwd) sandbox restriction on spawning node. - Add a structured '设计方案' (design rationale) comment block to the top of every shader file: approach, key parameters, perf characteristics, and known limitations/optimization directions. - Update README with build-time type-check docs.
…rs-* as surface-borne fiber lines - apollonian.metal: replace unstable unconditional sphere-inversion DE (q diverges/collapses with no domain repeat) with the classic domain-repeat + clamped-scale Apollonian formula, which reliably fills the box instead of rendering almost empty. - fractree.metal: fix treeSDF only ever folding the i==0 branch distance into the running minimum (later 6 levels were computed and discarded). Now every level contributes via d = min(d, seg / scale). - fibers-wave/vortex/coral.metal: reworked from 'thin tube SDFs' to the requested model — multiple semi-transparent surfaces (wavy sheets / twisted cylindrical shells / lobed spherical shells) with a warped periodic flow field on each surface producing thin, naturally curved fiber lines covering ~25% of the surface area. Rendered via fixed-step volumetric front-to-back alpha compositing so surfaces stay translucent while fibers read as denser threads on top.
…harper fiber lines
Perf log review (shader-performance.log / server.log) showed:
- knots: up to 410ms/frame (worst by far)
- fibers-wave/coral/vortex: up to 231/159/98 ms
- nebula: consistently 90-140ms
- kaleidoscope/liquids: repeated 40-140ms samples
Changes:
- knots.metal: coarse-search samples 20->10, refine halvings 5->3, march
steps 80->56.
- nebula.metal: fbm octaves 3->2, reuse one noise sample for both color
mixes instead of two separate fbm calls, march steps 100->72.
- kaleidoscope.metal: KIFS iterations 14->10, march steps 100->80.
- liquids.metal: fbm octaves 4->3, march steps 80->60.
- fibers-wave/vortex/coral.metal: switched from fixed-step brute-force
volumetric marching to distance-based adaptive stepping (leap through
empty space, only sample finely near a shell), cutting iteration counts
well below the old 210-230 step caps.
Also reworked the fiber line mask per user feedback ('lines are too thick
and flat'): halfWidth reduced (~0.125 -> 0.045-0.05) for genuinely thin
lines, added a narrower 'core' highlight band mixed toward a bright color
to fake a rounded thread cross-section instead of a flat painted stripe,
and raised fiberAlpha so the now-thinner lines stay clearly visible.
Adds PatternMenuModel.nextDynamicBoxShader(), which cycles dynamicBoxSelectedShader to the next entry in dynamicBoxAvailableShaders (wrapping around) and relies on its existing didSet to trigger the hot-reload. Wired to a small '下一个' button in ContentView's DynamicBox panel, disabled when fewer than 2 shaders are available.
…ign, new higher-dimensional fractals, and petal bloom Highlights: - **fractree**: replaced broken folded-fragment distance field with an explicit multi-level branching tree (trunk → 4 primary branches → sub-branches → twigs). - **maze3d**: completely redesigned from a deterministic serpentine corridor to a randomized 3D growing-tree spanning-tre maze with vertical shafts connecting 3 floors and 1.5 m passage widths. - **quaternion-julia**: new 4D escape-time fractal using quaternion iteration (z → z² + c) instead of spherical coordinates; refined to 11 DE iterations with tighter hit/normal thresholds based on performance log data. - **hyper-menger**: new 4D Menger sponge — extends the 3D cross-fold algorithm to four components with 4D rotation and perspective projection. - **sierpinski5cell**: new 4D IFS chaos-game fractal (5-cell simplex) whose W slice is independently time-drifted for genuinely different 4D cross-sections. - **kaleido-ribbons / kaleido-bloom / kaleido-crystal**: three kaleidoscope variants — flowing ribbons, breathing petal blooms, and faceted drifting crystal lattice — complementing the existing kaleidoscope without replacing it. - **petal-particles**: outward-radiating particle bloom with 6-fold symmetry, each petal drawn by 7 independently-cycled particles whose age-fraction easing creates slow unfolding petal arcs; a slow envelope makes the whole flower gently open and close over ~63 s. - **ContentView**: compacted the DynamicBox shader picker next-item control to a small icon-only button. - **project.pbxproj**: kept all runtime shaders in membership exceptions so they are excluded from static Metal compilation but still checked at build time.
There was a problem hiding this comment.
Pull request overview
This PR expands and hardens the DynamicBox “hot-reloadable fragment shader” workflow by adding many new runtime-loadable shaders, improving shader server functionality (listing order + perf reporting), adding an Xcode build-phase type-check for runtime shaders, and updating the UI/selection model to better control shader activation and switching.
Changes:
- Add a large set of new DynamicBox
.metalshaders and update several existing ones (often with design/perf notes and tighter iteration budgets). - Improve the local Node shader server: deterministic shader ordering (Git-aware) and a new
/report-perfendpoint + docs/logging updates. - Add local build-time shader type-checking (
check-shaders.js) via a Run Script Build Phase; update UI to allow “next shader” cycling and revised refresh behavior.
Reviewed changes
Copilot reviewed 47 out of 48 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| vr-dive/Renderer/Renderer.swift | Adjusts reset behavior and wires UI-driven DynamicBox shader loads. |
| vr-dive/Renderer/PatternSelection.swift | Refactors DynamicBox shader panel activation, selection behavior, and shader list refresh logic. |
| vr-dive/ContentView.swift | Updates DynamicBox controls UI (next-shader button, refresh button, activation task behavior). |
| vr-dive/Demos/DynamicBox/DynamicBoxRenderer.swift | Improves error reporting and networking behavior for shader fetch/compile; updates (but currently misdocuments) server paths. |
| vr-dive/Demos/DynamicBox/DynamicBoxShaders.metal | Changes the embedded default fragment to a new “glowing points” approach and adds edge fading. |
| vr-dive/Demos/DynamicBox/shader-server.js | Adds Git-aware shader ordering and perf report ingestion endpoint. |
| vr-dive/Demos/DynamicBox/README.md | Updates docs for new logs, perf sampling, and build-time shader type-checking. |
| vr-dive/Demos/DynamicBox/check-shaders.js | New: wraps runtime shaders with a prelude and compiles them via xcrun metal for type-checking. |
| vr-dive.xcodeproj/project.pbxproj | Adds “Check DynamicBox Shaders” build phase; excludes many runtime shaders from target compilation; disables user script sandboxing. |
| .gitignore | Updates ignored items; clarifies DynamicBox log ignores. |
| vr-dive/Demos/DynamicBox/shaders/waves.metal | Adds extended design/perf commentary to an existing shader. |
| vr-dive/Demos/DynamicBox/shaders/sdf-shapes.metal | Adds extended design/perf commentary to an existing shader. |
| vr-dive/Demos/DynamicBox/shaders/nebula.metal | Reduces fbm octaves and march steps; reuses noise sample to reduce cost; adds design notes. |
| vr-dive/Demos/DynamicBox/shaders/metaballs.metal | Adds extended design/perf commentary to an existing shader. |
| vr-dive/Demos/DynamicBox/shaders/menger.metal | Adds extended design/perf commentary to an existing shader. |
| vr-dive/Demos/DynamicBox/shaders/maze3d.metal | Major redesign to a finite 3D spanning-tree maze + visual shaft highlighting + extensive design notes. |
| vr-dive/Demos/DynamicBox/shaders/mandelbulb.metal | Adds extended design/perf commentary to an existing shader. |
| vr-dive/Demos/DynamicBox/shaders/liquids.metal | Reduces fbm octaves and march steps; adds design/perf notes. |
| vr-dive/Demos/DynamicBox/shaders/knots.metal | Tightens sampling/refinement and march step budgets; adds design/perf notes. |
| vr-dive/Demos/DynamicBox/shaders/kaleidoscope.metal | Reduces iteration/march budgets; adds design/perf notes. |
| vr-dive/Demos/DynamicBox/shaders/infinity.metal | Adds extended design/perf commentary to an existing shader. |
| vr-dive/Demos/DynamicBox/shaders/hyper4d.metal | Adds extended design/perf commentary to an existing shader. |
| vr-dive/Demos/DynamicBox/shaders/gyroid.metal | Adds extended design/perf commentary to an existing shader. |
| vr-dive/Demos/DynamicBox/shaders/fractree.metal | Replaces prior fold-based approach with explicit connected branch capsules; adds design notes. |
| vr-dive/Demos/DynamicBox/shaders/apollonian.metal | Switches to a stable domain-repeat + clamped inversion variant; adds design/perf notes. |
| vr-dive/Demos/DynamicBox/shaders/topographic-velvet.metal | New runtime-loadable shader. |
| vr-dive/Demos/DynamicBox/shaders/sierpinski5cell.metal | New runtime-loadable shader (4D IFS slice concept). |
| vr-dive/Demos/DynamicBox/shaders/sediment-ribbons.metal | New runtime-loadable shader. |
| vr-dive/Demos/DynamicBox/shaders/radial-gills.metal | New runtime-loadable shader. |
| vr-dive/Demos/DynamicBox/shaders/quaternion-julia.metal | New runtime-loadable shader (parameter-drifting quaternion Julia). |
| vr-dive/Demos/DynamicBox/shaders/quaternion-julia-slice.metal | New runtime-loadable shader (moving 4D slice through stable quaternion Julia). |
| vr-dive/Demos/DynamicBox/shaders/pleated-marble.metal | New runtime-loadable shader. |
| vr-dive/Demos/DynamicBox/shaders/petal-particles.metal | New runtime-loadable shader. |
| vr-dive/Demos/DynamicBox/shaders/newton-basins-3d.metal | New runtime-loadable shader (Newton-basin-inspired shell). |
| vr-dive/Demos/DynamicBox/shaders/mandelbox-fold.metal | New runtime-loadable shader. |
| vr-dive/Demos/DynamicBox/shaders/mandelbox-fast.metal | New runtime-loadable shader (performance-focused variant). |
| vr-dive/Demos/DynamicBox/shaders/mandelbox-cavern.metal | New runtime-loadable shader (cavity/CSG variant). |
| vr-dive/Demos/DynamicBox/shaders/liquid-contours.metal | New runtime-loadable shader. |
| vr-dive/Demos/DynamicBox/shaders/hyper-menger.metal | New runtime-loadable shader (4D-inspired variant). |
| vr-dive/Demos/DynamicBox/shaders/hopf-weave.metal | New runtime-loadable shader. |
| vr-dive/Demos/DynamicBox/shaders/fiber-pleats.metal | New runtime-loadable shader. |
| vr-dive/Demos/DynamicBox/shaders/fibers-wave.metal | New runtime-loadable shader (semi-transparent volumetric-ish sheets + fiber lines). |
| vr-dive/Demos/DynamicBox/shaders/fibers-vortex.metal | New runtime-loadable shader (semi-transparent cylindrical shells + fiber lines). |
| vr-dive/Demos/DynamicBox/shaders/fibers-coral.metal | New runtime-loadable shader (lobed shells + fiber lines). |
| vr-dive/Demos/DynamicBox/shaders/coral-folds.metal | New runtime-loadable shader. |
| vr-dive/Demos/DynamicBox/shaders/kaleido-ribbons.metal | New runtime-loadable shader. |
| vr-dive/Demos/DynamicBox/shaders/kaleido-crystal.metal | New runtime-loadable shader. |
| vr-dive/Demos/DynamicBox/shaders/kaleido-bloom.metal | New runtime-loadable shader. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
323
to
326
| if patternCoordinator.shouldReset() { | ||
| pattern?.resetToInitialState() | ||
| gameManager.resetPatternNavigation() | ||
| patternCoordinator.clearResetFlag() | ||
| } |
Comment on lines
90
to
99
| func reloadShader(named name: String) async -> String? { | ||
| // "default" uses the embedded shader compiled into the app – no server fetch. | ||
| if name == "default" { | ||
| guard let vertFn = library.makeFunction(name: "dynamicBoxVertex"), | ||
| let fragFn = library.makeFunction(name: "dynamicBoxFragment") | ||
| else { | ||
| let msg = "Embedded default shader functions not found." | ||
| await reportToServer(msg) | ||
| return msg | ||
| } | ||
| do { | ||
| pipelineState = try DynamicBoxRenderer.makePipeline( | ||
| device: device, vertexFn: vertFn, fragmentFn: fragFn, | ||
| maxViewCount: maxViewCount) | ||
| currentShaderName = "default" | ||
| return nil | ||
| } catch { | ||
| let msg = "Pipeline creation error: \(error.localizedDescription)" | ||
| await reportToServer(msg) | ||
| return msg | ||
| } | ||
| } | ||
|
|
||
| let rawSource: String | ||
| do { | ||
| rawSource = try await fetchShaderSource(named: name) | ||
| } catch { | ||
| let msg = "Failed to fetch shader \"\(name)\": \(error.localizedDescription)" | ||
| await reportToServer(msg) | ||
| let msg = "Shader fetch failed [\(name)] URL=\(serverBaseURL)/shaders/\(name).metal — \(Self.describeNetworkError(error))" | ||
| print("[DynamicBox] \(msg)") | ||
| await reportErrorToServer(msg) | ||
| return msg | ||
| } |
Comment on lines
10
to
+16
| // - Embedded default shader ("3D grid of light points") ships in DynamicBoxShaders.metal | ||
| // - A companion Node.js server (vr-dive/Demos/DynamicBox/shader-server.js) serves .metal | ||
| // files from its shaders/ subdirectory on port 8888 | ||
| // - A companion Node.js server (scripts/shader-server.js) serves .metal files from | ||
| // scripts/shaders/ on port 8888 | ||
| // - The "Load Shader" button fetches a named shader, compiles it with Metal, and | ||
| // swaps the fragment function in the render pipeline | ||
| // - Compilation errors are POSTed back to the server and written to | ||
| // shader-compiling-error.log in the DynamicBox directory | ||
| // scripts/shader-compiling-error.log |
| float glowFalloff = 120.0f; // sharpness of glow | ||
| float maxMarch = tExit + 0.5f; // march a bit past exit for edge glow | ||
|
|
||
| float3 pos = eye; |
Comment on lines
+99
to
+118
| // Prefer the order files first appeared in Git, then filesystem creation time, | ||
| // then the most recent Git modification. This survives copies between machines | ||
| // while still giving new, uncommitted shaders a sensible place in the picker. | ||
| function listShaderFiles() { | ||
| return fs.readdirSync(SHADERS_DIR) | ||
| .filter(file => file.endsWith(".metal")) | ||
| .map(file => { | ||
| const filePath = path.join(SHADERS_DIR, file); | ||
| const gitPath = GIT_ROOT ? path.relative(GIT_ROOT, filePath) : filePath; | ||
| const createdAt = fs.statSync(filePath).birthtimeMs; | ||
| return { | ||
| file, | ||
| createdAt, | ||
| gitAddedAt: gitTimestamp(["log", "--diff-filter=A", "--format=%ct", "--reverse", "--", gitPath]), | ||
| gitModifiedAt: gitTimestamp(["log", "-1", "--format=%ct", "--", gitPath]), | ||
| }; | ||
| }) | ||
| .sort(compareShaderFiles) | ||
| .map(entry => entry.file); | ||
| } |
Comment on lines
224
to
229
| CODE_SIGN_STYLE = Automatic; | ||
| CURRENT_PROJECT_VERSION = 1; | ||
| DEVELOPMENT_TEAM = 29T757U3Y2; | ||
| ENABLE_PREVIEWS = YES; | ||
| ENABLE_USER_SCRIPT_SANDBOXING = NO; | ||
| GENERATE_INFOPLIST_FILE = YES; |
Comment on lines
254
to
259
| CODE_SIGN_STYLE = Automatic; | ||
| CURRENT_PROJECT_VERSION = 1; | ||
| DEVELOPMENT_TEAM = 29T757U3Y2; | ||
| ENABLE_PREVIEWS = YES; | ||
| ENABLE_USER_SCRIPT_SANDBOXING = NO; | ||
| GENERATE_INFOPLIST_FILE = YES; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.