Skip to content

Dynamic box - #4

Merged
tiye merged 14 commits into
mainfrom
dynamic-box
Aug 1, 2026
Merged

Dynamic box#4
tiye merged 14 commits into
mainfrom
dynamic-box

Conversation

@tiye

@tiye tiye commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

No description provided.

tiye added 14 commits July 31, 2026 01:42
…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.
@tiye
tiye requested review from a team and Copilot July 30, 2026 17:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 .metal shaders 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-perf endpoint + 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;
@tiye
tiye merged commit 3aed1ad into main Aug 1, 2026
1 check passed
@tiye
tiye deleted the dynamic-box branch August 1, 2026 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants