What is Fabric
Fabric renders raymarched SDF shapes, glTF meshes, GPU particles and SDF text — sharing one frame and one depth buffer, driven by JSX components and signals.
It exists because the alternative did not fit. A general 3D library’s smallest sensible build is larger than fabric’s largest.
- Engine overview — how it actually works.
File map
Section titled “File map”src/lib/fabric/├── index.ts Public API barrel — named exports only, no side effects├── sdf.wgsl SDF shader: proxy-cube vs + fs / fs_fast / fs_fast_effect / fs_fast_effect_depth / fs_refract├── primitives/ 25 distance functions, one file each — #included by sdf.wgsl├── materials/ phong, cell, fresnel, matcap, anisotropic — #included into both fs and fs_fast├── noise.wgsl Hash + value-noise for roughness / grain — #included by sdf.wgsl├── text.wgsl Direct-Bezier glyph shader, no atlas — loaded by textEngine├── Camera/│ ├── index.tsx Camera component — props, bridge switches, CameraRig forwarding│ └── CameraRig.tsx Pointer/touch/gyro listeners → camPosRef damping├── Composers.ts Re-exports Effect, Fast├── Effect.tsx Composition-stack frame for outline/glow effects├── Fast.tsx Composition-stack frame for the fast path├── Mesh.tsx GLB mesh component — dynamic-imports loadGLB + meshEngine├── Scene.tsx Global scene params: world transform, axes, raymarch tuning, stats HUD├── Text.tsx Flat 2D text component — dynamic-imports textEngine├── View.tsx Registers a tracked DOM rect + camera as a view (per-view scissor/viewport)├── Visible.tsx DOM-driven culling scope — off-screen descendants skip the record write├── _materialDeps.ts The one list of material fields a shape subscribes to├── components/│ ├── Grid.tsx Particle / point-cloud component — the primary particle pass│ ├── Wave.tsx A numeric signal drawn as a waveform in its own particle layer│ ├── Rig.tsx Drag-handle wrapper — dynamic-imports rigGizmo│ └── StatsHUD.tsx Debug overlay — dynamic-imported by Scene├── core/│ ├── types.ts All shared TS types│ ├── fabricState.ts Module signals + refs + useFabric() + initState│ ├── scope.ts Dynamic scope stacks (Effect/Fast/Modifier/Visible/Rig)│ ├── helpers.ts toVec3, toRad, subscribeToSignals│ ├── init.ts startFabricEngine (engine + interaction bootstrap)│ ├── engine.ts WebGPU lifecycle + RAF│ ├── interact.ts Canvas pointer events → ray pick│ └── gpuState.ts GPUState type + mat4 helpers├── hooks/│ └── useGraviton.ts Bootstrap orchestrator: cursor seed + engine start + publish RAF├── modifiers/ Bend, Displace, Twist, Onion, Symmetry, Elongate, Extrude, Revolve (+ barrel)├── render/│ ├── renderer.ts submitFrame — the passes, per-view scissor, glass pre-passes, blit│ ├── pipelines.ts Particle sim + render pipelines (static imports of src/wgsl)│ ├── uniforms.ts Uniform layout, hex colour parsing│ ├── particles.ts Grid particle buffers — dynamic-imports loadGeometry for a geometryUrl│ ├── particleLayer.ts Extra particle layers (Wave), drawn after the Grid pass│ ├── loadGeometry.ts PLY point-cloud loader│ ├── sdfEngine.ts SDF shapes: the record write, pipelines, spatial grid — dynamic-imported by each shape│ ├── meshEngine.ts Mesh buffers, bind groups, pipelines — dynamic-imported by Mesh│ ├── loadGLB.ts glTF 2.0 reader + CPU skinning — dynamic-imported by Mesh│ ├── textEngine.ts Glyph instancing over text.wgsl — dynamic-imported by Text│ ├── textLayout.ts Glyph layout in em-space│ ├── axes.ts <Scene showAxes> origin gizmo — dynamic-imported by renderer│ ├── rigGizmo.ts Per-shape translate handles — dynamic-imported by Rig│ ├── bgmip.ts Background mip chain for glass roughness — dynamic-imported by renderer│ └── blit.ts Offscreen → swapchain copy for adaptive resize — dynamic-imported by engine├── shapes/ 22 SDF primitives (+ barrel)└── shapes2d/ Circle2D, Rect2D, RoundedRect2D (+ barrel)
src/wgsl/ Outside the lib, imported by it├── grid.wgsl Spatial-grid compute (clear + assign) — dynamic-imported by sdfEngine├── particles.wgsl Particle render shader — pipelines.ts└── simulate.wgsl Particle sim compute — pipelines.tsThe fabric-shake plugin first strips the regions the app’s source never uses —
primitives, material and modifier branches, glass features — then
vite-plugin-glsl inlines the surviving #include lines and minifies. Both run
in dev as well as in a build — see
Lazy subsystems.