@mkbabb/glass-ui 4.0.1 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{CardAction-CW7a0m8M.js → CardAction-8whJrLWt.js} +23 -8
- package/dist/{CommandShortcut-DvZNQ_HF.js → CommandShortcut-D3yxgHNn.js} +23 -12
- package/dist/{ConfiguratorRow-BR4l-ixA.js → ConfiguratorRow-CaP7U3ZA.js} +11 -11
- package/dist/ContextMenuContent-B3ZsheLV.js +90 -0
- package/dist/{ContextMenuSubContent-xol4sD2q.js → ContextMenuSubContent-DDRID3qC.js} +15 -15
- package/dist/{DataTable-CuKwF7wr.js → DataTable-Bc9kUtu_.js} +2 -2
- package/dist/{DialogContent-DcKK8k9i.js → DialogContent-6JtTB5x2.js} +8 -5
- package/dist/DialogFooter-9phqcRIS.js +80 -0
- package/dist/DialogScrollContent-TTuovQst.js +93 -0
- package/dist/HoverCardContent-Bel1gdLZ.js +88 -0
- package/dist/{IconChip-BTD-nay5.js → IconChip-DhbdGdFQ.js} +1 -1
- package/dist/{IconTooltip-Bl8gFZ8d.js → IconTooltip-B0zimd2H.js} +1 -1
- package/dist/Input-Cg9DF62r.js +57 -0
- package/dist/{Notification-VUwexFUf.js → Notification-CphK7AAm.js} +3 -3
- package/dist/NumberFieldContent-D8cXeyO4.js +140 -0
- package/dist/PagerDots-Cjx96la-.js +98 -0
- package/dist/{SelectScrollDownButton-CrA8F0iV.js → SelectScrollDownButton-DAKCBEdW.js} +62 -57
- package/dist/{SelectSeparator-DXswVdRz.js → SelectSeparator-C2UGOkXF.js} +1 -1
- package/dist/Separator-DQcwC2TR.js +44 -0
- package/dist/Switch-B8RscmRu.js +49 -0
- package/dist/{Toaster-Bw4xR8xV.js → Toaster-D9qIHjBI.js} +1 -1
- package/dist/{ToggleGroupItem-pEM9vIhs.js → ToggleGroupItem-BLtr3TJq.js} +2 -2
- package/dist/TooltipProvider-BJ_Y5EGX.js +109 -0
- package/dist/animated-digit.js +1 -1
- package/dist/api/index.d.ts +15 -32
- package/dist/api/types-extra.d.ts +31 -0
- package/dist/api.js +1 -1
- package/dist/aurora.js +579 -251
- package/dist/border-progress.js +49 -57
- package/dist/{button-DYCUa-tH.js → button-5dY1Dvhd.js} +13 -14
- package/dist/button.js +1 -1
- package/dist/canvas.js +2 -3
- package/dist/card.js +1 -1
- package/dist/carousel.js +20 -20
- package/dist/color-Cs0-oxYL.js +116 -0
- package/dist/color.js +2 -2
- package/dist/command.js +1 -1
- package/dist/completion-seal.d.ts +1 -0
- package/dist/completion-seal.js +89 -0
- package/dist/components/custom/aurora/Aurora.vue.d.ts +10 -5
- package/dist/components/custom/aurora/composables/color.d.ts +13 -0
- package/dist/components/custom/aurora/composables/frameLoop.d.ts +9 -0
- package/dist/components/custom/aurora/composables/runtime.d.ts +12 -0
- package/dist/components/custom/aurora/composables/uniformBridgeWGPU.d.ts +11 -2
- package/dist/components/custom/aurora/composables/wgpuSetup.d.ts +8 -0
- package/dist/components/custom/aurora/constants/presets.d.ts +18 -0
- package/dist/components/custom/aurora/constants/renderMode.d.ts +16 -8
- package/dist/components/custom/aurora/constants/shaders/aurora-mediums.wgsl.d.ts +1 -0
- package/dist/components/custom/aurora/constants/shaders/aurora.wgsl.d.ts +1 -1
- package/dist/components/custom/border-progress/composables/spectrum-walk.d.ts +25 -0
- package/dist/components/custom/border-progress/composables/useBorderSpectrum.d.ts +14 -18
- package/dist/components/custom/border-progress/index.d.ts +1 -1
- package/dist/components/custom/completion-seal/CompletionSeal.vue.d.ts +21 -0
- package/dist/components/custom/completion-seal/composables/useCompletionSeal.d.ts +37 -0
- package/dist/components/custom/completion-seal/constants.d.ts +46 -0
- package/dist/components/custom/completion-seal/index.d.ts +4 -0
- package/dist/components/custom/concentric/composables/concentricGLSetup.d.ts +7 -0
- package/dist/components/custom/concentric/composables/concentricWGPUSetup.d.ts +9 -0
- package/dist/components/custom/concentric/composables/ringField.d.ts +57 -16
- package/dist/components/custom/concentric/composables/uniformBridgeWGPU.d.ts +2 -1
- package/dist/components/custom/concentric/composables/useConcentric.d.ts +4 -4
- package/dist/components/custom/concentric/constants.d.ts +30 -6
- package/dist/components/custom/concentric/index.d.ts +2 -2
- package/dist/components/custom/concentric/shaders/concentric.glsl.d.ts +2 -2
- package/dist/components/custom/concentric/shaders/concentric.wgsl.d.ts +1 -1
- package/dist/components/custom/confirm-dialog/ConfirmDialog.vue.d.ts +3 -3
- package/dist/components/custom/constellation/Constellation.vue.d.ts +5 -4
- package/dist/components/custom/constellation/composables/constellationGLSetup.d.ts +10 -0
- package/dist/components/custom/constellation/composables/constellationWGPUSetup.d.ts +19 -0
- package/dist/components/custom/constellation/composables/uniformBridgeWGPU.d.ts +66 -0
- package/dist/components/custom/constellation/composables/useConstellation.d.ts +3 -10
- package/dist/components/custom/constellation/constants.d.ts +33 -0
- package/dist/components/custom/constellation/constellationField.d.ts +31 -1
- package/dist/components/custom/constellation/constellationInteraction.d.ts +23 -14
- package/dist/components/custom/constellation/constellationRender.d.ts +25 -0
- package/dist/components/custom/constellation/constellationTypes.d.ts +38 -0
- package/dist/components/custom/constellation/constellationWell.d.ts +15 -0
- package/dist/components/custom/constellation/index.d.ts +5 -5
- package/dist/components/custom/constellation/shaders/constellation-lines.glsl.d.ts +2 -0
- package/dist/components/custom/constellation/shaders/constellation-lines.wgsl.d.ts +1 -0
- package/dist/components/custom/constellation/shaders/constellation-points.glsl.d.ts +2 -0
- package/dist/components/custom/constellation/shaders/constellation-points.wgsl.d.ts +1 -0
- package/dist/components/custom/deck/DeckPager.vue.d.ts +29 -0
- package/dist/components/custom/deck/composables/useDeck.d.ts +27 -0
- package/dist/components/custom/deck/composables/useDeckKeyboard.d.ts +25 -0
- package/dist/components/custom/deck/composables/useDeckSpring.d.ts +22 -0
- package/dist/components/custom/deck/constants.d.ts +14 -0
- package/dist/components/custom/deck/index.d.ts +8 -0
- package/dist/components/custom/dock/DockIconButton.vue.d.ts +12 -0
- package/dist/components/custom/dock/DockStack.vue.d.ts +65 -0
- package/dist/components/custom/dock/GlassDock.vue.d.ts +4 -2
- package/dist/components/custom/dock/composables/dockMorphMeasure.d.ts +80 -0
- package/dist/components/custom/dock/composables/index.d.ts +2 -0
- package/dist/components/custom/dock/composables/useDockSearch.d.ts +85 -0
- package/dist/components/custom/dock/composables/useDockShellProps.d.ts +11 -0
- package/dist/components/custom/dock/constants.d.ts +18 -14
- package/dist/components/custom/dock/index.d.ts +5 -2
- package/dist/components/custom/dot-flow-field/DotFlowField.vue.d.ts +15 -11
- package/dist/components/custom/dot-flow-field/composables/flowField.d.ts +48 -6
- package/dist/components/custom/dot-flow-field/composables/uniformBridgeWGPU.d.ts +23 -8
- package/dist/components/custom/dot-flow-field/composables/useDotFlowField.d.ts +6 -5
- package/dist/components/custom/dot-flow-field/composables/useFlowParticles.d.ts +18 -5
- package/dist/components/custom/dot-flow-field/constants.d.ts +42 -21
- package/dist/components/custom/dot-flow-field/index.d.ts +2 -2
- package/dist/components/custom/dot-flow-field/shaders/flow-field.compute.wgsl.d.ts +1 -1
- package/dist/components/custom/dot-flow-field/shaders/flow-field.glsl.d.ts +4 -20
- package/dist/components/custom/dot-flow-field/shaders/flow-field.render.wgsl.d.ts +1 -1
- package/dist/components/custom/dot-matrix/DotMatrix.vue.d.ts +43 -0
- package/dist/components/custom/dot-matrix/composables/dotMatrixField.d.ts +89 -0
- package/dist/components/custom/dot-matrix/composables/uniformBridgeWGPU.d.ts +52 -0
- package/dist/components/custom/dot-matrix/composables/useDotMatrix.d.ts +34 -0
- package/dist/components/custom/dot-matrix/composables/useDotSphere.d.ts +27 -0
- package/dist/components/custom/dot-matrix/constants.d.ts +58 -0
- package/dist/components/custom/dot-matrix/index.d.ts +5 -0
- package/dist/components/custom/dot-matrix/shaders/dot-matrix.glsl.d.ts +4 -0
- package/dist/components/custom/dot-matrix/shaders/dot-matrix.wgsl.d.ts +1 -0
- package/dist/components/custom/easing/EasingPicker.vue.d.ts +2 -2
- package/dist/components/custom/easing/composables/useEasingPicker.d.ts +5 -0
- package/dist/components/custom/expandable-container/ExpandableContainer.vue.d.ts +11 -0
- package/dist/components/custom/fourier-field/FourierField.vue.d.ts +40 -47
- package/dist/components/custom/fourier-field/composables/fourierFieldGLSetup.d.ts +15 -0
- package/dist/components/custom/fourier-field/composables/fourierFieldWGPUSetup.d.ts +20 -0
- package/dist/components/custom/fourier-field/composables/uniformBridgeWGPU.d.ts +41 -0
- package/dist/components/custom/fourier-field/composables/useFourierField.d.ts +40 -37
- package/dist/components/custom/fourier-field/constants.d.ts +61 -4
- package/dist/components/custom/fourier-field/index.d.ts +23 -18
- package/dist/components/custom/fourier-field/shaders/fourier-field.compute.wgsl.d.ts +1 -0
- package/dist/components/custom/fourier-field/shaders/fourier-field.glsl.d.ts +4 -0
- package/dist/components/custom/fourier-field/shaders/fourier-field.render.wgsl.d.ts +1 -0
- package/dist/components/custom/goo-blob/GooBlob.vue.d.ts +9 -1
- package/dist/components/custom/goo-blob/constants.d.ts +1 -1
- package/dist/components/custom/goo-blob/index.d.ts +1 -1
- package/dist/components/custom/goo-blob/shaders/metaball-noise.wgsl.d.ts +1 -0
- package/dist/components/custom/goo-blob/shaders/metaball-palette.wgsl.d.ts +1 -0
- package/dist/components/custom/goo-blob/shaders/metaball-uniforms.glsl.d.ts +1 -1
- package/dist/components/custom/goo-blob/shaders/metaball.wgsl.d.ts +1 -1
- package/dist/components/custom/goo-blob/types.d.ts +36 -0
- package/dist/components/custom/goo-dot-matrix/GooDotMatrix.vue.d.ts +49 -0
- package/dist/components/custom/goo-dot-matrix/composables/gooDotLattice.d.ts +24 -0
- package/dist/components/custom/goo-dot-matrix/composables/gooDotSetup.d.ts +50 -0
- package/dist/components/custom/goo-dot-matrix/composables/uniformBridgeWGPU.d.ts +35 -0
- package/dist/components/custom/goo-dot-matrix/composables/useGooDotMatrix.d.ts +31 -0
- package/dist/components/custom/goo-dot-matrix/constants.d.ts +76 -0
- package/dist/components/custom/goo-dot-matrix/index.d.ts +5 -0
- package/dist/components/custom/goo-dot-matrix/shaders/goo-dot.frag.d.ts +11 -0
- package/dist/components/custom/goo-dot-matrix/shaders/goo-dot.wgsl.d.ts +3 -0
- package/dist/components/custom/labeled-field/LabeledField.vue.d.ts +21 -2
- package/dist/components/custom/metric-stack/MetricRow.vue.d.ts +15 -0
- package/dist/components/custom/pager-dots/PagerDots.vue.d.ts +9 -0
- package/dist/components/custom/pager-dots/index.d.ts +2 -0
- package/dist/components/custom/pager-dots/pagerWindow.d.ts +9 -0
- package/dist/components/custom/paper-grid/PaperGrid.vue.d.ts +42 -0
- package/dist/components/custom/paper-grid/composables/paperGrid.d.ts +90 -0
- package/dist/components/custom/paper-grid/composables/paperGridGLSetup.d.ts +16 -0
- package/dist/components/custom/paper-grid/composables/paperGridWGPUSetup.d.ts +19 -0
- package/dist/components/custom/paper-grid/composables/uniformBridgeWGPU.d.ts +16 -0
- package/dist/components/custom/paper-grid/composables/usePaperGrid.d.ts +31 -0
- package/dist/components/custom/paper-grid/constants.d.ts +57 -0
- package/dist/components/custom/paper-grid/index.d.ts +5 -0
- package/dist/components/custom/paper-grid/shaders/paper-grid.glsl.d.ts +4 -0
- package/dist/components/custom/paper-grid/shaders/paper-grid.wgsl.d.ts +1 -0
- package/dist/components/custom/search/FuzzySearch.vue.d.ts +8 -2
- package/dist/components/custom/search/SearchBar.vue.d.ts +8 -0
- package/dist/components/custom/search/index.d.ts +2 -0
- package/dist/components/custom/search/searchVariants.d.ts +19 -0
- package/dist/components/custom/selectable-chip/SelectableChip.vue.d.ts +50 -0
- package/dist/components/custom/selectable-chip/index.d.ts +2 -0
- package/dist/components/custom/selectable-chip/selectableChipVariants.d.ts +23 -0
- package/dist/components/custom/split-chars/SplitChars.vue.d.ts +39 -0
- package/dist/components/custom/split-chars/index.d.ts +1 -0
- package/dist/components/custom/tabs/SegmentedTabs.vue.d.ts +8 -6
- package/dist/components/custom/tabs/constants.d.ts +20 -2
- package/dist/components/custom/watercolor-dot/WatercolorDot.vue.d.ts +29 -16
- package/dist/components/custom/watercolor-dot/useWatercolorBlob.d.ts +10 -5
- package/dist/components/ui/_shared/index.d.ts +2 -0
- package/dist/components/ui/_shared/useControlSize.d.ts +46 -0
- package/dist/components/ui/button/index.d.ts +1 -1
- package/dist/components/ui/card/Card.vue.d.ts +45 -0
- package/dist/components/ui/card/index.d.ts +1 -1
- package/dist/components/ui/carousel/CarouselNext.vue.d.ts +1 -1
- package/dist/components/ui/carousel/CarouselPrevious.vue.d.ts +1 -1
- package/dist/components/ui/command/CommandDialog.vue.d.ts +9 -3
- package/dist/components/ui/command/CommandList.vue.d.ts +3 -0
- package/dist/components/ui/context-menu/ContextMenuContent.vue.d.ts +5 -1
- package/dist/components/ui/dropdown-menu/DropdownMenuContent.vue.d.ts +4 -0
- package/dist/components/ui/hover-card/HoverCardContent.vue.d.ts +3 -0
- package/dist/components/ui/input/Input.vue.d.ts +3 -0
- package/dist/components/ui/number-field/NumberFieldInput.vue.d.ts +6 -1
- package/dist/components/ui/select/SelectContent.vue.d.ts +3 -0
- package/dist/components/ui/switch/Switch.vue.d.ts +2 -0
- package/dist/components/ui/textarea/Textarea.vue.d.ts +3 -0
- package/dist/components/ui/tooltip/TooltipContent.vue.d.ts +3 -0
- package/dist/composables/color/index.d.ts +2 -0
- package/dist/composables/color/useAccentTone.d.ts +34 -0
- package/dist/composables/glass/useVizChoreography.d.ts +123 -0
- package/dist/composables/glass/webgl/createCanvasLifecycle.d.ts +10 -0
- package/dist/composables/glass/webgl/shaders/flow.wgsl.d.ts +1 -0
- package/dist/composables/glass/webgpu/index.d.ts +1 -1
- package/dist/composables/glass/webgpu/useGpuSubstrate.d.ts +28 -7
- package/dist/composables/glass/webgpu/useWebGPUCanvas.d.ts +1 -0
- package/dist/composables/glass/webgpu/webgpuDevice.d.ts +42 -0
- package/dist/composables/motion/core/index.d.ts +3 -0
- package/dist/composables/motion/scrollReader.d.ts +25 -0
- package/dist/composables/motion/springPresets.d.ts +20 -1
- package/dist/composables/motion/useCharStagger.d.ts +44 -0
- package/dist/composables/motion/useDockCtaReceive.d.ts +31 -6
- package/dist/composables/motion/useScrollChrome.d.ts +58 -0
- package/dist/composables/motion/useScrollTrigger.d.ts +67 -0
- package/dist/composables/motion/useSpringPress.d.ts +5 -5
- package/dist/composables/motion/useStaggerReveal.d.ts +24 -0
- package/dist/composables/sidebar/index.d.ts +4 -1
- package/dist/composables/sidebar/types.d.ts +68 -3
- package/dist/composables/sidebar/useClickDelegate.d.ts +4 -0
- package/dist/composables/sidebar/useLazyLoader.d.ts +5 -0
- package/dist/composables/sidebar/useScrollTo.d.ts +5 -0
- package/dist/composables/virtual/index.d.ts +4 -0
- package/dist/composables/virtual/useVirtualSectionWindow.d.ts +72 -0
- package/dist/composables/virtual/useWindowedStore.d.ts +43 -0
- package/dist/composables/virtual/virtualSectionLayout.d.ts +103 -0
- package/dist/concentric.js +495 -221
- package/dist/configurator.js +2 -2
- package/dist/confirm-dialog.js +62 -47
- package/dist/constellation.js +635 -235
- package/dist/context-menu.js +2 -2
- package/dist/controls.js +1 -1
- package/dist/createCanvasLifecycle-Gh45Ce-p.js +93 -0
- package/dist/dark.js +1 -1
- package/dist/data-table.js +1 -1
- package/dist/deck.d.ts +1 -0
- package/dist/deck.js +105 -0
- package/dist/dialog.js +4 -3
- package/dist/dock.js +602 -458
- package/dist/dot-flow-field.js +580 -290
- package/dist/dot-matrix.d.ts +1 -0
- package/dist/dot-matrix.js +630 -0
- package/dist/dotMatrixField-D_x9_1qq.js +48 -0
- package/dist/{dropdown-menu-CofSZuk8.js → dropdown-menu-aJmV5SqE.js} +83 -79
- package/dist/dropdown-menu.js +1 -1
- package/dist/easing.js +188 -176
- package/dist/expandable-container.js +42 -20
- package/dist/fading-scroll.js +1 -1
- package/dist/flow.glsl-B2P7e0MT.js +4 -0
- package/dist/forms.js +62 -60
- package/dist/fourier-field.js +825 -178
- package/dist/fourier-math.js +1 -1
- package/dist/glass-ui.css +1 -1
- package/dist/glass-ui.js +145 -104
- package/dist/goo-blob.js +171 -1228
- package/dist/goo-dot-matrix.d.ts +1 -0
- package/dist/goo-dot-matrix.js +591 -0
- package/dist/handmark.js +1 -1
- package/dist/hover-card.js +1 -1
- package/dist/hover-popover.js +1 -1
- package/dist/icon-chip.js +1 -1
- package/dist/icon-tooltip.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/instrument-chassis.js +1 -1
- package/dist/keyboard.js +1 -1
- package/dist/labeled-field.js +70 -60
- package/dist/metric-cell.js +1 -1
- package/dist/metric-stack.js +11 -2
- package/dist/motion-core.js +54 -32
- package/dist/motion-curves.js +11 -1
- package/dist/motion.js +46 -111
- package/dist/notification.js +1 -1
- package/dist/number-field.js +1 -1
- package/dist/pager-dots.js +2 -91
- package/dist/paper-backdrop.js +1 -1
- package/dist/paper-grid.d.ts +1 -0
- package/dist/paper-grid.js +788 -0
- package/dist/{presets-BW2b-fr1.js → presets-CvOUqtdY.js} +3 -3
- package/dist/{procedural-color.glsl-CIFsJhwI.js → procedural-color.wgsl-m7Zgv35j.js} +2 -2
- package/dist/progress.js +1 -1
- package/dist/pulse.js +1 -1
- package/dist/reactive.js +1 -1
- package/dist/{useCanvas2D-B8w_E3Rr.js → resolveCanvasColor-yPyIpJt9.js} +12 -2
- package/dist/scrollReader-DI1NWxUw.js +42 -0
- package/dist/scrolling-text.js +1 -1
- package/dist/search.js +160 -304
- package/dist/select.js +3 -3
- package/dist/selectable-chip.d.ts +1 -0
- package/dist/selectable-chip.js +65 -0
- package/dist/separator.js +1 -1
- package/dist/{sheet-tZMg0E0w.js → sheet-B2flBfLH.js} +2 -2
- package/dist/sheet.js +1 -1
- package/dist/sidebar.js +216 -114
- package/dist/slider.js +1 -1
- package/dist/sortable-list.js +1 -1
- package/dist/spectrum-walk-BVzA7Biz.js +33 -0
- package/dist/{springPresets-CFQGQfdl.js → springPresets-Ce7OYCm9.js} +12 -6
- package/dist/styles/animations.css +13 -3
- package/dist/styles/cards.css +69 -0
- package/dist/styles/completion-seal.css +131 -0
- package/dist/styles/components.css +2 -3
- package/dist/styles/configurator.css +55 -0
- package/dist/styles/critical-partition.mjs +33 -11
- package/dist/styles/deferred.css +2 -0
- package/dist/styles/dock/cta-seat.css +87 -0
- package/dist/styles/dock/density.css +153 -0
- package/dist/styles/dock/layers.css +55 -7
- package/dist/styles/dock/morph-bridge.css +54 -18
- package/dist/styles/dock/morph.css +41 -33
- package/dist/styles/dock/overflow.css +12 -0
- package/dist/styles/dock/search.css +68 -0
- package/dist/styles/dock/shape.css +124 -0
- package/dist/styles/dock/shell.css +23 -5
- package/dist/styles/dock/stack-rail.css +264 -0
- package/dist/styles/dock-controls/dark-mode-toggle.css +17 -4
- package/dist/styles/dock-controls/icon-button.css +14 -0
- package/dist/styles/dock.css +11 -1
- package/dist/styles/glass/accent-tone.css +66 -0
- package/dist/styles/glass/control-surfaces.css +167 -0
- package/dist/styles/glass/ladder.css +67 -17
- package/dist/styles/glass/rim.css +19 -9
- package/dist/styles/glass/surfaces.css +69 -148
- package/dist/styles/glass.css +10 -0
- package/dist/styles/index.css +15 -0
- package/dist/styles/scroll-chrome.css +123 -0
- package/dist/styles/scroll-driven.css +38 -0
- package/dist/styles/segmented-tabs.css +50 -14
- package/dist/styles/theme/bridges.css +22 -0
- package/dist/styles/theme/radius.css +18 -1
- package/dist/styles/tokens/color-radius.css +13 -3
- package/dist/styles/tokens/dark-arm.css +39 -6
- package/dist/styles/tokens/glass-deep.css +28 -3
- package/dist/styles/tokens/glass-fx.css +44 -1
- package/dist/styles/tokens/glass.css +91 -31
- package/dist/styles/tokens/light-dark.css +1 -1
- package/dist/styles/tokens/offsets.css +27 -0
- package/dist/styles/tokens/property-regs.css +133 -0
- package/dist/styles/tokens/scale-paper.css +73 -29
- package/dist/styles/tokens/scheme-motion.css +44 -6
- package/dist/styles/tokens/sizing-config.css +110 -0
- package/dist/styles/tokens/sizing.css +55 -104
- package/dist/styles/tokens.css +5 -0
- package/dist/styles/typography/semantic.css +18 -5
- package/dist/styles/utilities/a11y-overrides.css +20 -5
- package/dist/styles/utilities/base-misc.css +52 -0
- package/dist/styles/utilities/btn.css +14 -3
- package/dist/styles/utilities/components.css +31 -6
- package/dist/styles/utilities/metal.css +26 -0
- package/dist/switch.js +1 -1
- package/dist/tabs.js +8 -8
- package/dist/timeline.js +1 -1
- package/dist/toast.js +1 -1
- package/dist/toggle-chip.js +10 -10
- package/dist/toggle-group.js +1 -1
- package/dist/tooltip.js +1 -1
- package/dist/typewriter.js +1 -1
- package/dist/uniformBridgeWGPU-CtAKl45L.js +1204 -0
- package/dist/{useAnimatedNumber-BfUq2bUM.js → useAnimatedNumber-CLrxicG9.js} +1 -1
- package/dist/{useConfiguratorState-DNlOh6c8.js → useConfiguratorState-4xblKfwd.js} +25 -24
- package/dist/useControlSize-SH1UmJCi.js +9 -0
- package/dist/useDockCtaReceive-DfFkmgL1.js +82 -0
- package/dist/{useDragMorph-DgxnsVJz.js → useDragMorph-BUgAC-zK.js} +4 -4
- package/dist/useFuzzySearch-DIhcYtcw.js +177 -0
- package/dist/useGpuSubstrate-4pTcp6mX.js +294 -0
- package/dist/{useLiquidPress-kfb4KX79.js → useLiquidPress-BooG97RY.js} +2 -2
- package/dist/usePointerVelocityField-QLsy3_kv.js +91 -0
- package/dist/useScrollChrome-D66AVP7C.js +258 -0
- package/dist/{useSpringMount-q1amq1SJ.js → useSpringMount-BWDnKIwh.js} +1 -1
- package/dist/useSpringPress-B1-Czp-V.js +36 -0
- package/dist/useViewTransition-CUI1nAgn.js +95 -0
- package/dist/{vendor-CKmzio-i.js → vendor-B2qOlYY3.js} +24 -11
- package/dist/virtual.d.ts +1 -0
- package/dist/virtual.js +225 -0
- package/dist/watercolor-dot.js +116 -73
- package/package.json +127 -7
- package/src/styles/animations.css +13 -3
- package/src/styles/cards.css +69 -0
- package/src/styles/completion-seal.css +131 -0
- package/src/styles/configurator.css +55 -0
- package/src/styles/critical-partition.mjs +33 -11
- package/src/styles/dock/cta-seat.css +87 -0
- package/src/styles/dock/density.css +153 -0
- package/src/styles/dock/layers.css +55 -7
- package/src/styles/dock/morph-bridge.css +54 -18
- package/src/styles/dock/morph.css +41 -33
- package/src/styles/dock/overflow.css +12 -0
- package/src/styles/dock/search.css +68 -0
- package/src/styles/dock/shape.css +124 -0
- package/src/styles/dock/shell.css +23 -5
- package/src/styles/dock/stack-rail.css +264 -0
- package/src/styles/dock-controls/dark-mode-toggle.css +17 -4
- package/src/styles/dock-controls/icon-button.css +14 -0
- package/src/styles/dock.css +11 -1
- package/src/styles/glass/accent-tone.css +66 -0
- package/src/styles/glass/control-surfaces.css +167 -0
- package/src/styles/glass/ladder.css +67 -17
- package/src/styles/glass/rim.css +19 -9
- package/src/styles/glass/surfaces.css +69 -148
- package/src/styles/glass.css +10 -0
- package/src/styles/index.css +15 -0
- package/src/styles/scroll-chrome.css +123 -0
- package/src/styles/scroll-driven.css +38 -0
- package/src/styles/segmented-tabs.css +50 -14
- package/src/styles/theme/bridges.css +22 -0
- package/src/styles/theme/radius.css +18 -1
- package/src/styles/tokens/color-radius.css +13 -3
- package/src/styles/tokens/dark-arm.css +39 -6
- package/src/styles/tokens/glass-deep.css +28 -3
- package/src/styles/tokens/glass-fx.css +44 -1
- package/src/styles/tokens/glass.css +91 -31
- package/src/styles/tokens/light-dark.css +1 -1
- package/src/styles/tokens/offsets.css +27 -0
- package/src/styles/tokens/property-regs.css +133 -0
- package/src/styles/tokens/scale-paper.css +73 -29
- package/src/styles/tokens/scheme-motion.css +44 -6
- package/src/styles/tokens/sizing-config.css +110 -0
- package/src/styles/tokens/sizing.css +55 -104
- package/src/styles/tokens.css +5 -0
- package/src/styles/typography/semantic.css +18 -5
- package/src/styles/utilities/a11y-overrides.css +20 -5
- package/src/styles/utilities/base-misc.css +52 -0
- package/src/styles/utilities/btn.css +14 -3
- package/src/styles/utilities/components.css +31 -6
- package/src/styles/utilities/metal.css +26 -0
- package/dist/ContextMenuContent-uWnVxDab.js +0 -85
- package/dist/DialogFooter-BZNX5aVr.js +0 -165
- package/dist/HoverCardContent-b2uaAMRR.js +0 -83
- package/dist/Input-h9v5LeXf.js +0 -55
- package/dist/NumberFieldContent-Cq7EzX-U.js +0 -138
- package/dist/Separator-pKF0oA4M.js +0 -37
- package/dist/Switch-CwYNf8bo.js +0 -47
- package/dist/TooltipProvider-rzvnXz60.js +0 -104
- package/dist/color-DweYl7pE.js +0 -86
- package/dist/components/custom/constellation/composables/useConstellationPointer.d.ts +0 -35
- package/dist/components/custom/constellation/constellationDraw.d.ts +0 -30
- package/dist/components/custom/dock/DockRail.vue.d.ts +0 -89
- package/dist/createCanvasLifecycle-CHD5XrDW.js +0 -82
- package/dist/procedural-color.wgsl-CToRHugY.js +0 -224
- package/dist/resolveCanvasColor-CUyHr5Uu.js +0 -11
- package/dist/styles/dock/rail-extend.css +0 -397
- package/dist/usePointerVelocityField-JbRd5CrM.js +0 -137
- package/dist/useRAFLoop-UYa4zoiN.js +0 -109
- package/dist/useSpringPress-BsqPr7FJ.js +0 -34
- package/src/styles/dock/rail-extend.css +0 -397
- /package/dist/{FadingScroll-DI6hQhT9.js → FadingScroll-DLRbH5Xr.js} +0 -0
- /package/dist/{HoverPopover-CbqbNwgU.js → HoverPopover-BcIxvyqZ.js} +0 -0
- /package/dist/{InstrumentChassis-Bx0F_q5g.js → InstrumentChassis-CxsHSyMj.js} +0 -0
- /package/dist/{PaperBackdrop-Vf3tlpvd.js → PaperBackdrop-CqwjnfLv.js} +0 -0
- /package/dist/{Progress-DctG61iZ.js → Progress-CnqB7gLm.js} +0 -0
- /package/dist/{ScrollingText-yOpBzFYq.js → ScrollingText-CTZbA_cG.js} +0 -0
- /package/dist/{SelectGroup-DwwjicPY.js → SelectGroup-BFiod7X2.js} +0 -0
- /package/dist/{compile-CQEFRTmx.js → compile-nZ1xVYTp.js} +0 -0
- /package/dist/{constants-BPOqYJAm.js → constants--C2DkLW8.js} +0 -0
- /package/dist/{math-BINYmg5z.js → math-Eb0w3LqU.js} +0 -0
- /package/dist/{prng-Za0Rmgag.js → prng-B-d9eYX8.js} +0 -0
- /package/dist/{slider-DVb4HXU-.js → slider-2A0rPn79.js} +0 -0
- /package/dist/{useGlobalDark-C28t0VWJ.js → useGlobalDark-CmjB9E32.js} +0 -0
- /package/dist/{useIntersectionPause-Bj4sPkMh.js → useIntersectionPause-Dbozzjgm.js} +0 -0
- /package/dist/{useInterval-CvK1mL92.js → useInterval-CNdua40W.js} +0 -0
- /package/dist/{useKeyboardShortcuts-BXWXOZ-9.js → useKeyboardShortcuts-BPRp33Im.js} +0 -0
- /package/dist/{useLiquidFlex-mZPMiNXh.js → useLiquidFlex-UmA6LMZu.js} +0 -0
- /package/dist/{useScrollProgress-D7bYU2RK.js → useScrollProgress-c3yxmH6a.js} +0 -0
- /package/dist/{useSortable-DHjtZSEd.js → useSortable-BVqlJRBR.js} +0 -0
- /package/dist/{useTextHighlight-CWEi25hf.js → useTextHighlight-NmBM5V_4.js} +0 -0
- /package/dist/{vReveal-Czsb7zQC.js → vReveal-D9k0jADx.js} +0 -0
- /package/dist/{vSpecular-CQFmLNzA.js → vSpecular-EX7loENl.js} +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { OklchStop } from "../../../composables/color";
|
|
2
|
+
/** Compile-time dot cap — mirrors the WGSL/GLSL instance-buffer array bound. */
|
|
3
|
+
export declare const MAX_DOTS = 4000;
|
|
4
|
+
/** Compile-time palette cap — mirrors the WGSL `MAX_DOT_STOPS` #define. */
|
|
5
|
+
export declare const MAX_DOT_STOPS = 4;
|
|
6
|
+
/** Pointer interaction mode — a repel pushes dots off the surface, attract pulls them in. */
|
|
7
|
+
export type DotPointerMode = "repel" | "attract";
|
|
8
|
+
/**
|
|
9
|
+
* The full author schema — the studio's `useConfiguratorState` model. Every field is a
|
|
10
|
+
* tunable the demo configurator drives; the composable resolves it into the uniform table.
|
|
11
|
+
* A NEW schema (no prior `dot-matrix`, no MIGRATION row).
|
|
12
|
+
*/
|
|
13
|
+
export interface DotMatrixConfig {
|
|
14
|
+
/** Dot count on the sphere surface (500–MAX_DOTS; the reference's fine field). */
|
|
15
|
+
dotCount: number;
|
|
16
|
+
/** Sphere radius as a fraction of the view min-dimension (0.2–0.9). */
|
|
17
|
+
radius: number;
|
|
18
|
+
/** Base dot billboard radius in px @ 1× (DPR-aware → crisp). */
|
|
19
|
+
dotSize: number;
|
|
20
|
+
/** The subtle resting opacity (0–1). */
|
|
21
|
+
baseOpacity: number;
|
|
22
|
+
/** Depth-fade strength (0–1; high = strong translucent-shell read). */
|
|
23
|
+
depthFade: number;
|
|
24
|
+
/** The slow dignified Y-spin in rad/s (0–0.3). */
|
|
25
|
+
rotationSpeed: number;
|
|
26
|
+
/** The rotation-axis tilt in degrees (a tilted globe reads more alive; ~23°). */
|
|
27
|
+
axisTilt: number;
|
|
28
|
+
/** The globe count (1 default; the reference two-globe composition is 2). */
|
|
29
|
+
spheres: 1 | 2;
|
|
30
|
+
/** The sub-perceptual breathing radius-pulse depth (0 default; demo 0.02). */
|
|
31
|
+
breathing: number;
|
|
32
|
+
/** The dot-color ramp (the demo themes it mono-white); resolved via the ColorResolver. */
|
|
33
|
+
palette: OklchStop[];
|
|
34
|
+
/** The ground color (the demo sets near-black; default transparent). */
|
|
35
|
+
background: OklchStop | "transparent";
|
|
36
|
+
/** Pointer parallax + repel + accel-burst (the §T7 interaction). */
|
|
37
|
+
interactive: boolean;
|
|
38
|
+
/** repel ↔ attract (the dimple direction). */
|
|
39
|
+
pointerMode: DotPointerMode;
|
|
40
|
+
/** The pointer-parallax depth (0–0.3; the screen-center tracks the cursor). */
|
|
41
|
+
parallax: number;
|
|
42
|
+
/** ONE static frame then park under `prefers-reduced-motion: reduce`. */
|
|
43
|
+
respectReducedMotion: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The warm-cream identity palette (the library default — NOT teal). A two-stop warm-amber
|
|
47
|
+
* ramp over the warm-cream foreground family, mirroring the dot-flow `WARM_IDENTITY_PALETTE`.
|
|
48
|
+
* A consumer (the demo) themes it mono-warm-white-on-near-black through a PRESET, never a
|
|
49
|
+
* token edit.
|
|
50
|
+
*/
|
|
51
|
+
export declare const WARM_IDENTITY_PALETTE: OklchStop[];
|
|
52
|
+
/**
|
|
53
|
+
* The shipped warm-identity default config — the §T5 SUBTLE + CALM register: ONE calm
|
|
54
|
+
* warm-cream globe of fine dots on a transparent ground (the glass card shows through),
|
|
55
|
+
* slowly rotating on a tilted axis. The depth-fade carries the sphere read; the second
|
|
56
|
+
* sphere + the breathing + the near-black ground are DEMO presets (presets-in-consumers).
|
|
57
|
+
*/
|
|
58
|
+
export declare const DEFAULT_DOT_MATRIX_CONFIG: DotMatrixConfig;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as DotMatrix } from "./DotMatrix.vue";
|
|
2
|
+
export { useDotMatrix, type DotMatrixHandle, type UseDotMatrixOptions, } from "./composables/useDotMatrix";
|
|
3
|
+
export { type DotMatrixConfig, type DotPointerMode, DEFAULT_DOT_MATRIX_CONFIG, WARM_IDENTITY_PALETTE, MAX_DOTS, MAX_DOT_STOPS, } from "./constants";
|
|
4
|
+
export { type Vec3, type Mat3, type FacingFade, fibonacciDot, facingFade, spinMatrix, applyMat3, breathRadius, GOLDEN_RATIO, GOLDEN_ANGLE, FACING_LO, FACING_HI, SIZE_TAPER_BASE, SIZE_TAPER_GAIN, } from "./composables/dotMatrixField";
|
|
5
|
+
export type { OklchStop } from "../../../composables/color";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** The instanced-billboard VERTEX shader (gl_VertexID quad + instanced dot attribute). */
|
|
2
|
+
export declare const DOT_MATRIX_VERT_GLSL = "#version 300 es\nprecision highp float;\n\n#define MAX_DOT_STOPS 4\n#define GOLDEN_ANGLE 2.399963229728653\n\n// The static quad corner (6 verts: two triangles) + the instanced per-dot data.\nin vec2 aCorner; // billboard-local [-1,1]\nin vec4 aDot; // (unitPos.xyz, sphereIdx) \u2014 instanced (divisor 1)\n\nuniform vec4 uU0; // (resX, resY, dpr, time)\nuniform vec4 uU1; // (radius, dotSize, baseOpacity, aspect)\nuniform vec4 uU2; // (facingLo, facingHi, sizeLo, sizeHi)\nuniform vec4 uU3; // (parallax, pointerPush, pointerBloom, pointerActive)\nuniform vec4 uU4; // (pointerX, pointerY, sphere2Scale, breathRadius)\nuniform vec4 uU5; // (sphere2OffsetX, sphere2OffsetY, hasBackground, _pad)\nuniform mat3 uSpin; // the slow tilted Y-rotation\n\nout vec2 vLocal; // [-1,1] billboard-local for the SDF circle\nout float vBright; // facing-driven brightness\nout float vAlpha; // facing-driven opacity\nout float vTone; // palette tone (0 = bright cream near-front, 1 = amber rim)\n\nfloat facingTerm(vec3 n) {\n return clamp(n.z * 0.5 + 0.5, 0.0, 1.0); // 1 = dead-front\n}\n\nvoid main() {\n vec3 unitPos = aDot.xyz;\n float sphereIdx = aDot.w;\n\n float breath = uU4.w;\n float sphereScale = uU1.x;\n vec2 sphereOffset = vec2(0.0);\n if (sphereIdx > 0.5) {\n sphereScale = uU1.x * uU4.z;\n sphereOffset = vec2(uU5.x, uU5.y);\n }\n\n // The rotated surface normal = spin \u00B7 unitPos (the \u00A7T2 facing source).\n vec3 n = uSpin * unitPos;\n float facing = facingTerm(n);\n\n // Pointer-repel/attract dimple (the \u00A7T7 local perturbation).\n float pAct = uU3.w;\n vec2 pointerNdc = vec2(uU4.x * 2.0 - 1.0, 1.0 - uU4.y * 2.0);\n vec2 screenN = n.xy * sphereScale + sphereOffset;\n vec2 toPointer = screenN - pointerNdc;\n float pd = length(toPointer);\n float dimple = exp(-pd * pd * 18.0) * uU3.y * pAct;\n vec2 lift = n.xy * dimple;\n\n vec2 parallaxOff = pointerNdc * uU3.x * pAct;\n vec2 center2d = n.xy * sphereScale * breath + sphereOffset + lift + parallaxOff;\n\n // The depth-of-field size taper + the accel-burst bloom scale.\n float sizeTaper = uU2.z + uU2.w * facing;\n float burstScale = 1.0 + uU3.z * exp(-pd * pd * 12.0);\n float dotR = uU1.y * sizeTaper * burstScale;\n\n float offX = aCorner.x * dotR;\n float offY = aCorner.y * dotR;\n\n float facingOpacity = uU2.x + uU2.y * facing;\n float burstBright = 1.0 + uU3.z * 0.8 * exp(-pd * pd * 12.0);\n\n vLocal = aCorner;\n vBright = facingOpacity * burstBright;\n vAlpha = clamp(uU1.z * facingOpacity * burstBright, 0.0, 1.0);\n // The palette tone reads the DEPTH (near-front bright cream \u2192 rim amber) so the depth-shell\n // reads tonally on BOTH a dark AND a light ground.\n vTone = clamp(1.0 - facing, 0.0, 1.0);\n\n // The whole sphere + quad is built in a SQUARE space (so the globe stays circular); the\n // final clip-space x divides by aspect so a wide canvas does not squash it into an ellipse.\n float aspect = max(uU1.w, 1e-4);\n gl_Position = vec4((center2d.x + offX) / aspect, center2d.y + offY, 0.0, 1.0);\n}";
|
|
3
|
+
/** The crisp fwidth-SDF dot fragment (the ONE AA canon; splices the shared color chunk). */
|
|
4
|
+
export declare const DOT_MATRIX_FRAG_GLSL = "#version 300 es\nprecision highp float;\n\n#define MAX_DOT_STOPS 4\n\nin vec2 vLocal;\nin float vBright;\nin float vAlpha;\nin float vTone;\nout vec4 fragColor;\n\nuniform vec4 uBg; // (background.rgb, hasBackground)\nuniform int uStopCount;\nuniform vec3 uPalette[MAX_DOT_STOPS]; // linear-sRGB stops\n\nconst mat2 FBM_ROT = mat2(0.8, 0.6, -0.6, 0.8);\n\n\nfloat srgbToLinearCh(float c) {\n return c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);\n}\nvec3 srgbToLinear(vec3 c) {\n return vec3(srgbToLinearCh(c.r), srgbToLinearCh(c.g), srgbToLinearCh(c.b));\n}\n\nfloat linearToSrgbCh(float c) {\n return c <= 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1.0 / 2.4) - 0.055;\n}\nvec3 linearToSrgb(vec3 c) {\n return vec3(linearToSrgbCh(c.r), linearToSrgbCh(c.g), linearToSrgbCh(c.b));\n}\n\n// value.js LINEAR_SRGB_TO_LMS (constants.ts), row-major; written here as GLSL\n// columns (= the transpose) so mat3 * vec3 evaluates the row-major M\u00B7v.\nconst mat3 LINEAR_SRGB_TO_LMS = mat3(\n 0.4122214708, 0.2119034982, 0.0883024619,\n 0.5363325363, 0.6806995451, 0.2817188376,\n 0.0514459929, 0.1073969566, 0.6299787005\n);\n\n// value.js srgbToOKLab's INLINE LMS\u2192OKLab coefficients (gamut.ts lines 295-297 \u2014\n// these differ at the ~1e-9 digit from LMS_TO_OKLAB_MATRIX; use the inline ones to\n// mirror the exact value.js path), row-major \u2192 GLSL columns.\nconst mat3 LMS_TO_OKLAB = mat3(\n 0.2104542553, 1.9779984951, 0.0259040371,\n 0.7936177850, -2.4285922050, 0.7827717662,\n -0.0040720468, 0.4505937099, -0.8086757660\n);\n\n// value.js OKLAB_TO_LMS_COEFF (constants.ts), row-major \u2192 GLSL columns. Rows:\n// l = [1, 0.3963377774, 0.2158037573], m = [1, -0.1055613458, -0.0638541728],\n// s = [1, -0.0894841775, -1.2914855480].\nconst mat3 OKLAB_TO_LMS = mat3(\n 1.0, 1.0, 1.0,\n 0.3963377774, -0.1055613458, -0.0894841775,\n 0.2158037573, -0.0638541728, -1.2914855480\n);\n\n// value.js LMS_TO_LINEAR_SRGB (constants.ts), row-major \u2192 GLSL columns.\nconst mat3 LMS_TO_LINEAR_SRGB = mat3(\n 4.0767416621, -1.2684380046, -0.0041960863,\n -3.3077115913, 2.6097574011, -0.7034186147,\n 0.2309699292, -0.3413193965, 1.7076147010\n);\n\n// Gamma sRGB \u2192 raw OKLab (L, a, b). Mirrors value.js srgbToOKLab.\nvec3 srgbToOklab(vec3 c) {\n vec3 lin = srgbToLinear(c);\n vec3 lms = LINEAR_SRGB_TO_LMS * lin;\n vec3 lmsCbrt = sign(lms) * pow(abs(lms), vec3(1.0 / 3.0));\n return LMS_TO_OKLAB * lmsCbrt;\n}\n\n// Raw OKLab (L, a, b) \u2192 linear sRGB. Mirrors value.js oklabToLinearSRGB.\nvec3 oklabToLinearSrgb(vec3 lab) {\n vec3 lms_ = OKLAB_TO_LMS * lab;\n vec3 lms = lms_ * lms_ * lms_;\n return LMS_TO_LINEAR_SRGB * lms;\n}\n\n// OKLab \u2192 OKLCh: H in RADIANS. Mirrors value.js rawOklabToOklch (which returns\n// degrees; we stay in radians and only fold to [0, 2pi)).\nvec3 oklabToOklch(vec3 lab) {\n float C = length(lab.yz);\n float H = atan(lab.z, lab.y);\n if (H < 0.0) H += 2.0 * PI;\n return vec3(lab.x, C, H);\n}\n\n// OKLCh (H radians) \u2192 OKLab. Mirrors value.js rawOklchToOklab.\nvec3 oklchToOklab(vec3 lch) {\n return vec3(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));\n}\n\nvec3 samplePaletteLin(float t) {\n if (uStopCount <= 1) return uPalette[0];\n float n = float(uStopCount);\n float ft = clamp(t, 0.0, 1.0) * (n - 1.0);\n int i0 = int(floor(ft));\n int i1 = min(i0 + 1, uStopCount - 1);\n float f = ft - float(i0);\n vec3 lmsA = LINEAR_SRGB_TO_LMS * uPalette[i0];\n vec3 lmsB = LINEAR_SRGB_TO_LMS * uPalette[i1];\n vec3 labA = LMS_TO_OKLAB * (sign(lmsA) * pow(abs(lmsA), vec3(1.0 / 3.0)));\n vec3 labB = LMS_TO_OKLAB * (sign(lmsB) * pow(abs(lmsB), vec3(1.0 / 3.0)));\n return oklabToLinearSrgb(mix(labA, labB, f));\n}\n\nvoid main() {\n // The crisp fwidth-smoothstep SDF circle (the ONE AA canon; ~1px band at any DPR).\n float d = length(vLocal) - 1.0;\n float aa = max(fwidth(d), 1e-4);\n float coverage = 1.0 - smoothstep(-aa, aa, d);\n if (coverage < 0.002) discard;\n\n vec3 lin = samplePaletteLin(vTone) * clamp(vBright, 0.0, 1.6);\n float alpha = vAlpha * coverage;\n vec3 rgb = clamp(linearToSrgb(lin), vec3(0.0), vec3(1.0));\n fragColor = vec4(rgb * alpha, alpha);\n}";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const DOT_MATRIX_WGSL = "\nconst PI: f32 = 3.141592653589793;\nconst TAU: f32 = 6.283185307179586;\nconst MAX_DOT_STOPS: i32 = 4;\n// The golden-angle constant (transcribes dotMatrixField.ts GOLDEN_ANGLE = PI*(3-sqrt5)).\nconst GOLDEN_ANGLE: f32 = 2.399963229728653;\n\nstruct Dot {\n // (unitPos.xyz, sphereIdx)\n data: vec4<f32>,\n};\n\n// \u2500\u2500 Render uniforms (the typed-struct source-of-truth \u2014 see uniformBridgeWGPU.ts) \u2500\u2500\nstruct Uniforms {\n // u0: (uResolutionX, uResolutionY, uDpr, uTime)\n u0: vec4<f32>,\n // u1: (uRadius, uDotSize, uBaseOpacity, uAspect)\n u1: vec4<f32>,\n // u2: (uFacingLo, uFacingHi, uSizeLo, uSizeHi)\n u2: vec4<f32>,\n // u3: (uParallax, uPointerPush, uPointerBloom, uPointerActive)\n u3: vec4<f32>,\n // u4: (uPointerX, uPointerY, uSphere2Scale, uBreathRadius)\n u4: vec4<f32>,\n // u5: (uSphere2OffsetX, uSphere2OffsetY, uHasBackground, _pad)\n u5: vec4<f32>,\n spin: mat3x3<f32>,\n // ints: (uStopCount, uDotCount, uSpheres, _pad)\n ints: vec4<i32>,\n // bg: (background.rgb, _pad)\n bg: vec4<f32>,\n palette: array<vec4<f32>, 4>,\n};\n\n@group(0) @binding(0) var<uniform> u: Uniforms;\n@group(0) @binding(1) var<storage, read> dots: array<Dot>;\n\n\nfn srgbToLinearCh(c: f32) -> f32 {\n if (c <= 0.04045) { return c / 12.92; }\n return pow((c + 0.055) / 1.055, 2.4);\n}\nfn srgbToLinear(c: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(srgbToLinearCh(c.r), srgbToLinearCh(c.g), srgbToLinearCh(c.b));\n}\n\nfn linearToSrgbCh(c: f32) -> f32 {\n if (c <= 0.0031308) { return c * 12.92; }\n return 1.055 * pow(c, 1.0 / 2.4) - 0.055;\n}\nfn linearToSrgb(c: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(linearToSrgbCh(c.r), linearToSrgbCh(c.g), linearToSrgbCh(c.b));\n}\n\n// value.js LINEAR_SRGB_TO_LMS, row-major \u2192 WGSL columns (= the transpose).\nconst LINEAR_SRGB_TO_LMS: mat3x3<f32> = mat3x3<f32>(\n 0.4122214708, 0.2119034982, 0.0883024619,\n 0.5363325363, 0.6806995451, 0.2817188376,\n 0.0514459929, 0.1073969566, 0.6299787005\n);\n\n// value.js srgbToOKLab's INLINE LMS\u2192OKLab coefficients, row-major \u2192 WGSL columns.\nconst LMS_TO_OKLAB: mat3x3<f32> = mat3x3<f32>(\n 0.2104542553, 1.9779984951, 0.0259040371,\n 0.7936177850, -2.4285922050, 0.7827717662,\n -0.0040720468, 0.4505937099, -0.8086757660\n);\n\n// value.js OKLAB_TO_LMS_COEFF, row-major \u2192 WGSL columns.\nconst OKLAB_TO_LMS: mat3x3<f32> = mat3x3<f32>(\n 1.0, 1.0, 1.0,\n 0.3963377774, -0.1055613458, -0.0894841775,\n 0.2158037573, -0.0638541728, -1.2914855480\n);\n\n// value.js LMS_TO_LINEAR_SRGB, row-major \u2192 WGSL columns.\nconst LMS_TO_LINEAR_SRGB: mat3x3<f32> = mat3x3<f32>(\n 4.0767416621, -1.2684380046, -0.0041960863,\n -3.3077115913, 2.6097574011, -0.7034186147,\n 0.2309699292, -0.3413193965, 1.7076147010\n);\n\nfn cbrt3(v: vec3<f32>) -> vec3<f32> {\n return sign(v) * pow(abs(v), vec3<f32>(1.0 / 3.0));\n}\n\n// Gamma sRGB \u2192 raw OKLab (L, a, b). Mirrors value.js srgbToOKLab.\nfn srgbToOklab(c: vec3<f32>) -> vec3<f32> {\n let lin = srgbToLinear(c);\n let lms = LINEAR_SRGB_TO_LMS * lin;\n return LMS_TO_OKLAB * cbrt3(lms);\n}\n\n// Raw OKLab (L, a, b) \u2192 linear sRGB. Mirrors value.js oklabToLinearSRGB.\nfn oklabToLinearSrgb(lab: vec3<f32>) -> vec3<f32> {\n let lms_ = OKLAB_TO_LMS * lab;\n let lms = lms_ * lms_ * lms_;\n return LMS_TO_LINEAR_SRGB * lms;\n}\n\n// OKLab \u2192 OKLCh: H in RADIANS, folded to [0, 2pi). Mirrors value.js rawOklabToOklch.\nfn oklabToOklch(lab: vec3<f32>) -> vec3<f32> {\n let C = length(lab.yz);\n var H = atan2(lab.z, lab.y);\n if (H < 0.0) { H = H + 2.0 * PI; }\n return vec3<f32>(lab.x, C, H);\n}\n\n// OKLCh (H radians) \u2192 OKLab. Mirrors value.js rawOklchToOklab.\nfn oklchToOklab(lch: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));\n}\n\n// The \u00A7T2 depth-fade (transcribes dotMatrixField.ts facingFade): the rotated-normal's z\n// \u2192 a SOFT facing term \u2192 opacity + size ramps. NOT a binary back-face cull.\nfn facingTerm(n: vec3<f32>) -> f32 {\n return clamp(n.z * 0.5 + 0.5, 0.0, 1.0); // 1 = dead-front, 0 = dead-back\n}\n\n// Sample the multi-stop palette (linear-sRGB stops, OKLab mix). t in [0,1].\nfn samplePaletteLin(t: f32) -> vec3<f32> {\n let stopCount = u.ints.x;\n if (stopCount <= 1) { return u.palette[0].rgb; }\n let n = f32(stopCount);\n let ft = clamp(t, 0.0, 1.0) * (n - 1.0);\n let i0 = i32(floor(ft));\n let i1 = min(i0 + 1, stopCount - 1);\n let f = ft - f32(i0);\n let labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * u.palette[i0].rgb);\n let labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * u.palette[i1].rgb);\n return oklabToLinearSrgb(mix(labA, labB, f));\n}\n\nstruct VSOut {\n @builtin(position) pos: vec4<f32>,\n @location(0) local: vec2<f32>, // [-1,1] billboard-local coords for the SDF circle\n @location(1) bright: f32, // facing-driven brightness [0, ~1.6]\n @location(2) alpha: f32, // facing-driven opacity\n @location(3) tone: f32, // palette tone (0 = bright cream near-front, 1 = amber rim)\n};\n\n@vertex\nfn vs_main(\n @builtin(vertex_index) vi: u32,\n @builtin(instance_index) ii: u32,\n) -> VSOut {\n // Two-triangle quad corners in billboard-local space (camera-facing by construction).\n var corners = array<vec2<f32>, 6>(\n vec2<f32>(-1.0, -1.0), vec2<f32>(1.0, -1.0), vec2<f32>(-1.0, 1.0),\n vec2<f32>(-1.0, 1.0), vec2<f32>(1.0, -1.0), vec2<f32>(1.0, 1.0),\n );\n let local = corners[vi];\n\n let dot = dots[ii].data;\n var unitPos = dot.xyz; // the STATIC phyllotaxis position (JS-computed)\n let sphereIdx = dot.w;\n\n // The breathing radius pulse (transcribes breathRadius \u2014 1 at rest).\n let breath = u.u4.w;\n // Per-sphere offset/scale (the reference two-globe composition).\n var sphereScale = u.u1.x; // uRadius\n var sphereOffset = vec2<f32>(0.0, 0.0);\n if (sphereIdx > 0.5) {\n sphereScale = u.u1.x * u.u4.z; // uRadius * uSphere2Scale\n sphereOffset = vec2<f32>(u.u5.x, u.u5.y); // uSphere2Offset\n }\n\n // The rotated surface NORMAL = spin \u00B7 unitPos (the \u00A7T2 facing source). The spin matrix\n // is the slow tilted Y-rotation (dotMatrixField.ts spinMatrix).\n let n = u.spin * unitPos;\n let facing = facingTerm(n);\n\n // Pointer-repel/attract \u2014 a soft Gaussian dimple lifts the dot radially off the surface\n // near the cursor (the \u00A7T7 local perturbation). The pointer is in NDC (-1..1); a repel\n // (push>0) pushes the dot OUT, an attract (push<0) pulls IN. Velocity scales the push.\n let pAct = u.u3.w;\n let pointerNdc = vec2<f32>(u.u4.x * 2.0 - 1.0, 1.0 - u.u4.y * 2.0);\n let screenN = n.xy * sphereScale + sphereOffset;\n let toPointer = screenN - pointerNdc;\n let pd = length(toPointer);\n let dimple = exp(-pd * pd * 18.0) * u.u3.y * pAct; // soft Gaussian falloff \u00D7 push\n // Lift along the rotated normal's screen projection (radially through the shell).\n let lift = n.xy * dimple;\n\n // Project the rotated normal to the screen (orthographic \u2014 the \u00A7T5 flat hero look),\n // scaled by the sphere radius + the breathing, plus the per-sphere offset + the dimple\n // lift + the pointer-parallax screen-center track.\n let parallaxOff = (pointerNdc) * u.u3.x * pAct; // uParallax \u00B7 pointer \u00B7 active\n let center2d = n.xy * sphereScale * breath + sphereOffset + lift + parallaxOff;\n\n // The depth-of-field dot-size taper (transcribes facingFade size): 0.6 + 0.4\u00B7facing,\n // plus the accel-burst bloom scale near the cursor.\n let sizeTaper = u.u2.z + u.u2.w * facing;\n let burstScale = 1.0 + u.u3.z * exp(-pd * pd * 12.0);\n let dotR = u.u1.y * sizeTaper * burstScale; // uDotSize \u00B7 taper \u00B7 burst\n\n let offX = local.x * dotR;\n let offY = local.y * dotR;\n\n // The opacity ramp (transcribes facingFade opacity): facingLo + facingHi\u00B7facing, scaled\n // by the base opacity + a faint burst brightness lift near the cursor.\n let facingOpacity = u.u2.x + u.u2.y * facing; // facingLo + facingHi\u00B7facing\n let burstBright = 1.0 + u.u3.z * 0.8 * exp(-pd * pd * 12.0);\n\n // The whole sphere + quad is built in a SQUARE space (so the globe stays circular); the\n // final clip-space x divides by aspect so a wide canvas does not squash it into an\n // ellipse (aspect \u2265 1 \u2192 x shrinks; aspect < 1 \u2192 x grows). This keeps the dot quads round\n // AND the sphere circular in PIXELS regardless of the canvas aspect.\n let aspect = max(u.u1.w, 1e-4);\n let clipX = (center2d.x + offX) / aspect;\n let clipY = center2d.y + offY;\n\n var out: VSOut;\n out.pos = vec4<f32>(clipX, clipY, 0.0, 1.0);\n out.local = local;\n out.bright = facingOpacity * burstBright;\n out.alpha = clamp(u.u1.z * facingOpacity * burstBright, 0.0, 1.0);\n // The palette tone reads the DEPTH (not the opacity): the near-front samples the bright\n // cream stop[0] (tone 0), the rim/far the darker amber stop (tone \u2192 1), so the depth-shell\n // reads TONALLY on BOTH a dark AND a light ground (a light-ground globe can't lean on the\n // opacity fade alone \u2014 over a light card a faded dot reads brighter, inverting the shell).\n out.tone = clamp(1.0 - facing, 0.0, 1.0);\n return out;\n}\n\n@fragment\nfn fs_main(in: VSOut) -> @location(0) vec4<f32> {\n // The crisp fwidth-smoothstep SDF circle (the ONE AA canon \u2014 the band is ~1px wide at\n // any DPR/zoom, so fine sub-2px dots stay crisp). d = |uv| - 1; aa = fwidth(d).\n let d = length(in.local) - 1.0;\n let aa = max(fwidth(d), 1e-4);\n let coverage = 1.0 - smoothstep(-aa, aa, d);\n if (coverage < 0.002) { discard; }\n\n // The palette tints the dot by DEPTH (near-front cream \u2192 rim amber); the brightness lights\n // the core. The near hemisphere reads as the bright warm-cream stop, the rim/far fading to\n // the darker amber \u2014 the translucent dot-shell on both grounds.\n let lin = samplePaletteLin(in.tone) * clamp(in.bright, 0.0, 1.6);\n let alpha = in.alpha * coverage;\n let rgb = clamp(linearToSrgb(lin), vec3<f32>(0.0), vec3<f32>(1.0));\n // Premultiplied-alpha output (the translucent dot-shell additive over the clear).\n return vec4<f32>(rgb * alpha, alpha);\n}\n";
|
|
@@ -20,11 +20,11 @@ type __VLS_ModelProps = {
|
|
|
20
20
|
modelValue?: EasingPickerValue;
|
|
21
21
|
};
|
|
22
22
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
23
|
-
declare var
|
|
23
|
+
declare var __VLS_78: {
|
|
24
24
|
value: EasingPickerValue;
|
|
25
25
|
};
|
|
26
26
|
type __VLS_Slots = {} & {
|
|
27
|
-
footer?: (props: typeof
|
|
27
|
+
footer?: (props: typeof __VLS_78) => any;
|
|
28
28
|
};
|
|
29
29
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
30
30
|
"update:modelValue": (value: EasingPickerValue | undefined) => any;
|
|
@@ -47,6 +47,11 @@ export interface UseEasingPickerReturn {
|
|
|
47
47
|
easingFn: ComputedRef<EasingFn>;
|
|
48
48
|
/** The complete re-parseable readout literal for the active mode. */
|
|
49
49
|
readout: ComputedRef<string>;
|
|
50
|
+
/** Whether the steps-mode readout round-trips through value.js `parseSteps`
|
|
51
|
+
* back to the live (n, term) — the boundary-law proof that the painted
|
|
52
|
+
* staircase IS a re-parseable value.js literal, not a hand-rolled string
|
|
53
|
+
* the catalogue cannot read back. `true` in bezier mode (no steps literal). */
|
|
54
|
+
reparseOk: ComputedRef<boolean>;
|
|
50
55
|
/** The full v-model payload (mode + css + fn + raw params). */
|
|
51
56
|
value: ComputedRef<EasingPickerValue>;
|
|
52
57
|
/** Two SVG-space handle coords `[{x,y},{x,y}]` (bezier mode). */
|
|
@@ -45,9 +45,20 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
|
45
45
|
expandLabel: string;
|
|
46
46
|
collapseLabel: string;
|
|
47
47
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
|
|
48
|
+
'expand-trigger'?: (props: {
|
|
49
|
+
expand: () => void;
|
|
50
|
+
label: string;
|
|
51
|
+
}) => any;
|
|
52
|
+
} & {
|
|
48
53
|
default?: (props: {
|
|
49
54
|
fullscreen: boolean;
|
|
50
55
|
}) => any;
|
|
56
|
+
} & {
|
|
57
|
+
'fullscreen-chrome'?: (props: {
|
|
58
|
+
collapse: () => void;
|
|
59
|
+
label: string;
|
|
60
|
+
fullscreen: boolean;
|
|
61
|
+
}) => any;
|
|
51
62
|
} & {
|
|
52
63
|
default?: (props: {
|
|
53
64
|
fullscreen: boolean;
|
|
@@ -1,61 +1,54 @@
|
|
|
1
|
-
import type { ColorResolver } from "../../../composables/color";
|
|
1
|
+
import type { ColorResolver, OklchStop } from "../../../composables/color";
|
|
2
|
+
import { type BasisComponent } from "./math";
|
|
3
|
+
import type { FourierFieldConfig } from "./constants";
|
|
2
4
|
/**
|
|
3
|
-
* FourierField — a Fourier epicycle field on
|
|
4
|
-
* primitive to Aurora and
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* FourierField — a Fourier epicycle field on the GPU substrate (BC.W-VIZ-FOURIER), a
|
|
6
|
+
* sibling primitive to Aurora, GooBlob, and DotFlowField. A chain of rotating circles
|
|
7
|
+
* stacked tip-to-tail draws the reconstructing partial-sum curve; a glowing comet head
|
|
8
|
+
* leads the fading trail. WebGPU-FIRST: the compute pass writes the partial-sum curve +
|
|
9
|
+
* the epicycle chain tips, the fullscreen-fragment render pass composites the SDF field; a
|
|
10
|
+
* WebGL2 GLSL twin is the genuinely-absent-tail fallback (the §E "WebGPU everywhere"
|
|
11
|
+
* mandate — the Canvas2D renderer is RETIRED). It composes `useFourierField` → the
|
|
12
|
+
* `createGpuSubstrate` picker over the ONE canvas lifecycle leaf (offscreen-pause, live-PRM
|
|
13
|
+
* freeze, consumer-owned DPR) and the SHARED `usePointerVelocityField` (the pointer SCRUBS
|
|
14
|
+
* the reconstruction).
|
|
10
15
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* `defaultBlobColorResolver` from `@mkbabb/glass-ui/color` so a `var()` /
|
|
14
|
-
* `light-dark()` token, an `oklch()` / `hsl()` / hex string all resolve. A
|
|
15
|
-
* `var()` token is first resolved to a concrete `rgb()` against the host's
|
|
16
|
-
* inherited color-scheme, then re-resolved on a color change AND on a dark-mode
|
|
17
|
-
* toggle so the field retints with the theme.
|
|
16
|
+
* The DEFAULT palette is the warm-cream library identity (`--viz-fourier` warm-amber); a
|
|
17
|
+
* demo Teal/cool preset stays demo-LOCAL (presets-in-consumers — never a library token).
|
|
18
18
|
*
|
|
19
|
-
* `variant` is
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* BB.W-CARVE3 — the ~475-line renderer lives in `composables/useFourierField.ts`
|
|
25
|
-
* (the colocation symmetry Aurora/`useAurora.ts`, GooBlob/`useMetaballRenderer.ts`
|
|
26
|
-
* and Constellation/`useConstellation.ts` already carry). The SFC stays thin: the
|
|
27
|
-
* props, the two template refs, and the single `useFourierField(props, …)` call.
|
|
19
|
+
* The `variant: "hero"|"final"` prop is RETIRED (BC.W-VIZ-FOURIER — the bundles fold into
|
|
20
|
+
* config presets, MIGRATION row). An ambient-background consumer passes `color` (+ the
|
|
21
|
+
* `colorResolver`) for a thin warm default preserving the recessive look; the studio passes
|
|
22
|
+
* the full `config` + `spectrum` + `getPalette`.
|
|
28
23
|
*/
|
|
29
24
|
type __VLS_Props = {
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
/**
|
|
25
|
+
/** The full author config (the studio's `useConfiguratorState` model). Defaults to the warm identity. */
|
|
26
|
+
config?: FourierFieldConfig;
|
|
27
|
+
/** An explicit CPU-minted spectrum (a curated shape's DFT). When absent, a seeded elliptic spectrum is generated. */
|
|
28
|
+
spectrum?: readonly BasisComponent[];
|
|
29
|
+
/** Resolve the curve palette as OKLCh (the studio themes it). When absent, `color`/`config.palette` is used. */
|
|
30
|
+
getPalette?: () => OklchStop[];
|
|
31
|
+
/** Ambient-consumer color seam — a `var()`/`light-dark()` token or a literal; derives a warm 2-stop palette. */
|
|
32
|
+
color?: string;
|
|
33
|
+
/** The color resolver (the GooBlob/Aurora seam) — required when `color` is a `var()` token. */
|
|
34
|
+
colorResolver?: ColorResolver;
|
|
35
|
+
/** Extra seed mixed into the generated elliptic spectrum PRNG. Default "". */
|
|
37
36
|
seed?: string;
|
|
38
|
-
/**
|
|
37
|
+
/** Paint ONE static deterministic best-frame and never animate (the capture lever). Default false. */
|
|
39
38
|
freeze?: boolean;
|
|
40
|
-
/** Outer loudness envelope (the
|
|
41
|
-
* resolved `peakAlpha`/`headGlowAlpha` at the PAINT layer (a per-LAYER
|
|
42
|
-
* multiply, not a uniform CSS opacity). Default 1 (the bundle's resting
|
|
43
|
-
* loudness); clamped [0, 2] — the field's ~2 upper bound lets a hero push
|
|
44
|
-
* brighter than the recessed default without runaway. */
|
|
39
|
+
/** Outer loudness envelope (scales the per-layer alpha). When set, overrides `config.intensity`; clamped [0,2]. */
|
|
45
40
|
intensity?: number;
|
|
46
|
-
/** OPTIONAL injected clock — a getter returning the loop parameter `t ∈ [0,1)`.
|
|
47
|
-
* When BOUND, the render reads `clock()` (a controllable studio clock: pause,
|
|
48
|
-
* scrub, speed); when ABSENT (the ambient face), the autonomous
|
|
49
|
-
* `(now / durationMs) % 1` frame-time loop is the DEFAULT. `freeze` /
|
|
50
|
-
* `prefers-reduced-motion` still short-circuit to `frozenT` regardless — the
|
|
51
|
-
* ambient bundle is unchanged. The SOLE additive seam (BA.W-FOURIER-STUDIO). */
|
|
52
|
-
clock?: () => number;
|
|
53
41
|
};
|
|
54
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
55
|
-
|
|
42
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
43
|
+
backend: () => import("../../../composables/glass/webgpu").GpuBackend;
|
|
44
|
+
pause: () => void;
|
|
45
|
+
resume: () => void;
|
|
46
|
+
wake: () => void;
|
|
47
|
+
renderAt: (timeSec: number) => void;
|
|
48
|
+
setHeadT: (t: number) => void;
|
|
49
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
56
50
|
seed: string;
|
|
57
51
|
freeze: boolean;
|
|
58
|
-
intensity: number;
|
|
59
52
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
60
53
|
declare const _default: typeof __VLS_export;
|
|
61
54
|
export default _default;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { WebGLCanvasFrame } from "../../../../composables/glass/webgl/useWebGLCanvas";
|
|
2
|
+
import type { OklchStop } from "../../../../composables/color";
|
|
3
|
+
import { type FourierFieldConfig } from "../constants";
|
|
4
|
+
import { type BasisComponent } from "../math";
|
|
5
|
+
export interface FourierGLSetupDeps {
|
|
6
|
+
canvas: HTMLCanvasElement;
|
|
7
|
+
config: FourierFieldConfig;
|
|
8
|
+
getSpectrum: () => readonly BasisComponent[];
|
|
9
|
+
getPalette: () => OklchStop[];
|
|
10
|
+
getHeadT: () => number;
|
|
11
|
+
shouldContinue: () => boolean;
|
|
12
|
+
onFrame?: (timeSec: number) => void;
|
|
13
|
+
}
|
|
14
|
+
/** Build the `setupGL(gl)` callback the `createGpuSubstrate` WebGL2 path invokes. */
|
|
15
|
+
export declare function createFourierGLSetup(deps: FourierGLSetupDeps): (gl: WebGL2RenderingContext) => WebGLCanvasFrame;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { WebGPUCanvasFrame } from "../../../../composables/glass/webgpu/useWebGPUCanvas";
|
|
2
|
+
import type { OklchStop } from "../../../../composables/color";
|
|
3
|
+
import { type FourierFieldConfig } from "../constants";
|
|
4
|
+
import type { BasisComponent } from "../math";
|
|
5
|
+
export interface FourierWGPUSetupDeps {
|
|
6
|
+
canvas: HTMLCanvasElement;
|
|
7
|
+
config: FourierFieldConfig;
|
|
8
|
+
/** The CPU-minted spectrum (re-read each frame so a source-swap reaches the buffer). */
|
|
9
|
+
getSpectrum: () => readonly BasisComponent[];
|
|
10
|
+
/** The resolved (ColorResolver) palette stops as OKLCh — re-read each frame so a live edit reaches the buffer. */
|
|
11
|
+
getPalette: () => OklchStop[];
|
|
12
|
+
/** The single loop parameter `head_t ∈ [0,1)` (the ONE keyframes.js clock). */
|
|
13
|
+
getHeadT: () => number;
|
|
14
|
+
/** Demand-gate (the renderer's quiescence layer — substrate-agnostic). */
|
|
15
|
+
shouldContinue: () => boolean;
|
|
16
|
+
/** The per-frame pointer hook — useFourierField advances the shared pointer field here. */
|
|
17
|
+
onFrame?: (timeSec: number) => void;
|
|
18
|
+
}
|
|
19
|
+
/** Build the fourier-field `setupWGPU(device, context, format)` callback. */
|
|
20
|
+
export declare function createFourierWGPUSetup(deps: FourierWGPUSetupDeps): (device: GPUDevice, context: GPUCanvasContext, format: GPUTextureFormat) => WebGPUCanvasFrame;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { OklchStop } from "../../../../composables/color";
|
|
2
|
+
import { type BasisComponent } from "../math";
|
|
3
|
+
/** One phasor lane in the storage buffer: (re, im, index, _pad). */
|
|
4
|
+
export declare const FOURIER_PHASOR_BYTES = 16;
|
|
5
|
+
export declare const FOURIER_COMPUTE_UNIFORM_BYTES = 32;
|
|
6
|
+
export interface FourierUniformScratch {
|
|
7
|
+
buffer: ArrayBuffer;
|
|
8
|
+
f32: Float32Array;
|
|
9
|
+
i32: Int32Array;
|
|
10
|
+
}
|
|
11
|
+
export declare function createFourierComputeScratch(): FourierUniformScratch;
|
|
12
|
+
/** Pack the compute uniforms in place. */
|
|
13
|
+
export declare function packFourierComputeUniforms(scratch: FourierUniformScratch, headT: number, trailArc: number, harmonicN: number, epicycleArmN: number, sampleCount: number, phasorCount: number): FourierUniformScratch;
|
|
14
|
+
export declare const FOURIER_RENDER_UNIFORM_BYTES: number;
|
|
15
|
+
export declare function createFourierRenderScratch(): FourierUniformScratch;
|
|
16
|
+
/** The model→clip fit transform (center + uniform scale) — computed once per spectrum. */
|
|
17
|
+
export interface FourierFit {
|
|
18
|
+
centerX: number;
|
|
19
|
+
centerY: number;
|
|
20
|
+
/** The uniform scale s such that (model − center)·s maps the curve into clip [-1,1] with margin. */
|
|
21
|
+
scale: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Stable view-fit: sample the FULL reconstruction once over the period, bound its bbox,
|
|
25
|
+
* and derive the center + a margin-padded uniform scale. The render's fullscreen pass
|
|
26
|
+
* inverts this transform per fragment so the curve never clips and the scale is fixed.
|
|
27
|
+
*/
|
|
28
|
+
export declare function computeFourierFit(spectrum: readonly BasisComponent[]): FourierFit;
|
|
29
|
+
/**
|
|
30
|
+
* Convert a CSS-px stroke width to MODEL units (the shader's space). The fit `scale` maps
|
|
31
|
+
* model → clip; clip spans [-1,1] over the min CSS dimension → cssPx-per-clip = canvasCssMin/2.
|
|
32
|
+
* model-per-cssPx = (1/scale)·(2/canvasCssMin).
|
|
33
|
+
*/
|
|
34
|
+
export declare function trailWidthToModel(trailWidthPx: number, scale: number, canvasCssMin: number): number;
|
|
35
|
+
/** Pack the render uniforms in place. */
|
|
36
|
+
export declare function packFourierRenderUniforms(scratch: FourierUniformScratch, fit: FourierFit, aspect: number, trailWidthModel: number, peakAlpha: number, headGlowAlpha: number, trailFadeExp: number, trailFloor: number, intensity: number, showEpicycles: boolean, rainbowChain: boolean, sampleCount: number, armCount: number, palette: OklchStop[]): FourierUniformScratch;
|
|
37
|
+
/**
|
|
38
|
+
* Pack the phasor storage table (re, im, index, _pad) from the CPU-minted spectrum. The
|
|
39
|
+
* WGSL SUMS this per frame — it is the ONLY spectrum upload (no WGSL-side mint).
|
|
40
|
+
*/
|
|
41
|
+
export declare function packPhasorTable(spectrum: readonly BasisComponent[]): Float32Array;
|
|
@@ -1,39 +1,42 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import { type
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
variant: "hero" | "final";
|
|
21
|
-
/** Base CSS color (any form the resolver understands; a `var()`/`light-dark()` token resolves against the host). */
|
|
22
|
-
color: string;
|
|
23
|
-
/** REQUIRED color seam — resolves a concrete color to a gamma-sRGB [r,g,b] triple in [0,1]. */
|
|
24
|
-
colorResolver: ColorResolver;
|
|
25
|
-
/** Extra seed mixed into the spectrum PRNG for a unique-but-reproducible curve. */
|
|
26
|
-
seed: string;
|
|
27
|
-
/** When true, paint ONE static deterministic best-frame and never animate (the capture/export lever). */
|
|
28
|
-
freeze: boolean;
|
|
29
|
-
/** Outer loudness envelope (the Aurora `opacityCeiling` shape). Scales the resolved alphas at the PAINT layer; clamped [0, 2]. */
|
|
30
|
-
intensity: number;
|
|
31
|
-
/** OPTIONAL injected clock — a getter returning the loop parameter `t ∈ [0,1)` (the studio's controllable clock). */
|
|
32
|
-
clock?: () => number;
|
|
1
|
+
import { type Ref } from "vue";
|
|
2
|
+
import { type GpuBackend } from "../../../../composables/glass/webgpu/useGpuSubstrate";
|
|
3
|
+
import type { OklchStop } from "../../../../composables/color";
|
|
4
|
+
import type { FourierFieldConfig } from "../constants";
|
|
5
|
+
import type { BasisComponent } from "../math";
|
|
6
|
+
export interface UseFourierFieldOptions {
|
|
7
|
+
config: FourierFieldConfig;
|
|
8
|
+
/** The active phasor spectrum (CPU-minted; re-read each frame so a source-swap reaches the buffer). */
|
|
9
|
+
getSpectrum: () => readonly BasisComponent[];
|
|
10
|
+
/** Resolve the curve-color palette as OKLCh (the demo themes it; default warm-identity). */
|
|
11
|
+
getPalette: () => OklchStop[];
|
|
12
|
+
/** When true, hold the deterministic best-frame and never advance (the capture / freeze lever). */
|
|
13
|
+
freeze?: () => boolean;
|
|
14
|
+
/** The static deterministic best-frame parameter under `freeze`/PRM. Default 0.34. */
|
|
15
|
+
frozenT?: number;
|
|
16
|
+
/** Base forward period for one full traversal at 1× speed, in seconds. Default 16. */
|
|
17
|
+
periodS?: number;
|
|
18
|
+
/** `"capture"` → renderAt-only (the deterministic π capture path). Default `"live"`. */
|
|
19
|
+
mode?: "live" | "capture";
|
|
33
20
|
}
|
|
34
|
-
/** The
|
|
35
|
-
export interface
|
|
36
|
-
|
|
37
|
-
|
|
21
|
+
/** The uniform handle a consumer wires its lifecycle against (backend-agnostic). */
|
|
22
|
+
export interface FourierFieldHandle {
|
|
23
|
+
/** The resolved backend (`"webgpu"` where supported, else the WebGL2 GLSL fallback). */
|
|
24
|
+
readonly backend: GpuBackend;
|
|
25
|
+
/** Park the loop (the WCAG-2.2.2 pause seam — `DockBackgroundToggle` wires this). */
|
|
26
|
+
pause: () => void;
|
|
27
|
+
/** Re-arm the loop. */
|
|
28
|
+
resume: () => void;
|
|
29
|
+
/** Re-arm a parked loop on demand. */
|
|
30
|
+
wake: () => void;
|
|
31
|
+
/** Draw one frame out-of-loop (capture / thumbnail). */
|
|
32
|
+
renderAt: (timeSec: number) => void;
|
|
33
|
+
/** The live `prefers-reduced-motion: reduce` state. */
|
|
34
|
+
readonly reducedMotion: boolean;
|
|
35
|
+
/** The current loop parameter `head_t ∈ [0,1)` (the scrubber reads/writes it). */
|
|
36
|
+
readonly headT: number;
|
|
37
|
+
/** Scrub the clock directly (the transport scrubber / a pointer drag). */
|
|
38
|
+
setHeadT: (t: number) => void;
|
|
39
|
+
/** Tear down the renderer + release GPU/GL resources. */
|
|
40
|
+
dispose: () => void;
|
|
38
41
|
}
|
|
39
|
-
export declare function useFourierField(
|
|
42
|
+
export declare function useFourierField(canvasRef: Ref<HTMLCanvasElement | null>, options: UseFourierFieldOptions): FourierFieldHandle;
|
|
@@ -1,7 +1,64 @@
|
|
|
1
|
+
import type { OklchStop } from "../../../composables/color";
|
|
1
2
|
/**
|
|
2
|
-
* Curve-sampling resolution for the stable view-fit bbox pass — the renderer
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Curve-sampling resolution for the stable view-fit bbox pass — the renderer samples the
|
|
4
|
+
* epicycle curve this many times once at mount to size it to the canvas with a fixed
|
|
5
|
+
* margin (so the curve never clips and the scale is constant across the run). 720 = one
|
|
6
|
+
* sample per half-degree of the unit period.
|
|
6
7
|
*/
|
|
7
8
|
export declare const FOURIER_FIT_SAMPLES = 720;
|
|
9
|
+
/**
|
|
10
|
+
* The phasor-table uniform ceiling — the WGSL `MAX_PHASORS` #define. The configurator's
|
|
11
|
+
* harmonic count maxes here; a >64-term custom trace books a storage-buffer widen (cheap —
|
|
12
|
+
* the flow-field already uses a storage buffer). The curated ℱ/heart/star set + the
|
|
13
|
+
* generated elliptic spectrum all sit under it.
|
|
14
|
+
*/
|
|
15
|
+
export declare const MAX_PHASORS = 64;
|
|
16
|
+
/**
|
|
17
|
+
* The comet-curve sample ceiling — the storage-buffer array bound. The compute pass
|
|
18
|
+
* writes the partial-sum curve point at `M` samples back along the period from the head;
|
|
19
|
+
* the render pass reads them as the comet polyline. 384 gives a smooth bold stroke.
|
|
20
|
+
*/
|
|
21
|
+
export declare const MAX_CURVE_SAMPLES = 384;
|
|
22
|
+
/** The palette-stop ceiling — the WGSL `MAX_FOURIER_STOPS` #define. */
|
|
23
|
+
export declare const MAX_FOURIER_STOPS = 4;
|
|
24
|
+
/**
|
|
25
|
+
* The full author schema — the studio's `useConfiguratorState` model. Every field is a
|
|
26
|
+
* tunable the demo configurator drives; the composable resolves it into the uniform table.
|
|
27
|
+
*/
|
|
28
|
+
export interface FourierFieldConfig {
|
|
29
|
+
/** The active phasor spectrum source key — `"elliptic"` (generated) or a curated shape key. */
|
|
30
|
+
source: string;
|
|
31
|
+
/** TRUNCATE the partial sum — the harmonic count N (1..min(spectrum.length, MAX_PHASORS)). */
|
|
32
|
+
harmonics: number;
|
|
33
|
+
/** Draw the rotating epicycle chain (orthogonal to N). */
|
|
34
|
+
showEpicycles: boolean;
|
|
35
|
+
/** How many chain arms to draw (1..N; ≤ the harmonic count). */
|
|
36
|
+
epicycleArms: number;
|
|
37
|
+
/** Paint the chain as a warm-anchored hue sweep vs one analogous hue. */
|
|
38
|
+
rainbowChain: boolean;
|
|
39
|
+
/** Comet-body length as a fraction of the period (0.15..1.0). */
|
|
40
|
+
trailArc: number;
|
|
41
|
+
/** Comet stroke weight in CSS px (1..6). */
|
|
42
|
+
trailWidth: number;
|
|
43
|
+
/** Outer loudness envelope (per-layer alpha multiply, 0..2). */
|
|
44
|
+
intensity: number;
|
|
45
|
+
/** Character of the generated elliptic spectrum (0.05..0.4 — smooth ellipse → crinkled). */
|
|
46
|
+
harmonicScale: number;
|
|
47
|
+
/** Clock speed multiplier (0.25/0.5/1/2). */
|
|
48
|
+
speed: number;
|
|
49
|
+
/** The curve-color ramp (the library viz palette; warm default). Resolved via the ColorResolver. */
|
|
50
|
+
palette: OklchStop[];
|
|
51
|
+
/** ONE static frame then park under `prefers-reduced-motion: reduce`. */
|
|
52
|
+
respectReducedMotion: boolean;
|
|
53
|
+
/** Pointer scrubs `head_t` + a flick injects clock momentum (the W-VIZ-INTERACTION consume). */
|
|
54
|
+
interactive: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The warm-cream identity palette (the library default — NOT teal). A two-stop warm-amber
|
|
58
|
+
* ramp over the warm-cream foreground family, resolved via the ColorResolver. The chain's
|
|
59
|
+
* rainbow sweep is warm-anchored over THIS base; a consumer (the demo) themes it through a
|
|
60
|
+
* preset, never a token edit.
|
|
61
|
+
*/
|
|
62
|
+
export declare const WARM_IDENTITY_PALETTE: OklchStop[];
|
|
63
|
+
/** The shipped warm-identity default config. */
|
|
64
|
+
export declare const DEFAULT_FOURIER_CONFIG: FourierFieldConfig;
|
|
@@ -1,26 +1,31 @@
|
|
|
1
|
-
import type { ColorResolver } from "../../../composables/color";
|
|
1
|
+
import type { ColorResolver, OklchStop } from "../../../composables/color";
|
|
2
|
+
import type { FourierFieldConfig } from "./constants";
|
|
3
|
+
import type { BasisComponent } from "./math";
|
|
2
4
|
export { default as FourierField } from "./FourierField.vue";
|
|
3
5
|
export { comp, positionsAt, partialSumAt, dftFromPoints, makeEllipticSpectrum, type BasisComponent, type EllipticSpectrumOptions, } from "./math";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
|
|
6
|
+
export { DEFAULT_FOURIER_CONFIG, WARM_IDENTITY_PALETTE, MAX_PHASORS, MAX_CURVE_SAMPLES, type FourierFieldConfig, } from "./constants";
|
|
7
|
+
export { useFourierField, type FourierFieldHandle, type UseFourierFieldOptions, } from "./composables/useFourierField";
|
|
8
|
+
/**
|
|
9
|
+
* The props a consumer forwards when wrapping `<FourierField>` (the GPU-substrate epicycle
|
|
10
|
+
* field; ships via `/fourier-field`). Mirrors the component's inline `defineProps` shape (an
|
|
11
|
+
* SFC cannot export its inline props type). BC.W-VIZ-FOURIER — the `variant: "hero"|"final"`
|
|
12
|
+
* enum is RETIRED (folds into config presets); the renderer is the WGSL-primary GPU substrate.
|
|
13
|
+
*/
|
|
12
14
|
export interface FourierFieldProps {
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
/**
|
|
15
|
+
/** The full author config (the studio's `useConfiguratorState` model). Defaults to the warm identity. */
|
|
16
|
+
config?: FourierFieldConfig;
|
|
17
|
+
/** An explicit CPU-minted spectrum (a curated shape's DFT). When absent, a seeded elliptic spectrum is generated. */
|
|
18
|
+
spectrum?: readonly BasisComponent[];
|
|
19
|
+
/** Resolve the curve palette as OKLCh (the studio themes it). */
|
|
20
|
+
getPalette?: () => OklchStop[];
|
|
21
|
+
/** Ambient-consumer color seam — a `var()`/`light-dark()` token or a literal; derives a warm palette. */
|
|
22
|
+
color?: string;
|
|
23
|
+
/** The color resolver (the GooBlob/Aurora seam) — required when `color` is a `var()` token. */
|
|
24
|
+
colorResolver?: ColorResolver;
|
|
25
|
+
/** Extra seed mixed into the generated elliptic spectrum PRNG. Default "". */
|
|
20
26
|
seed?: string;
|
|
21
27
|
/** Paint ONE static deterministic best-frame and never animate (the capture lever). Default false. */
|
|
22
28
|
freeze?: boolean;
|
|
23
|
-
/** Outer loudness envelope (the
|
|
24
|
-
* resolved `peakAlpha`/`headGlowAlpha` at the paint layer. Default 1; clamped [0, 2]. */
|
|
29
|
+
/** Outer loudness envelope (scales the per-layer alpha). Overrides `config.intensity` when set; clamped [0, 2]. */
|
|
25
30
|
intensity?: number;
|
|
26
31
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const FOURIER_FIELD_COMPUTE_WGSL = "\nconst MAX_PHASORS: i32 = 64;\nconst TAU: f32 = 6.283185307179586;\n\nstruct Phasor {\n // (re, im, index, _pad)\n data: vec4<f32>,\n};\n\n// \u2500\u2500 Compute uniforms (the typed-struct source-of-truth \u2014 see uniformBridgeWGPU.ts) \u2500\u2500\nstruct ComputeUniforms {\n // c0: (headT, trailArc, _pad, _pad)\n c0: vec4<f32>,\n // ints: (harmonicN, epicycleArmN, sampleCount, phasorCount)\n ints: vec4<i32>,\n};\n\n@group(0) @binding(0) var<uniform> u: ComputeUniforms;\n@group(0) @binding(1) var<storage, read> phasors: array<Phasor>;\n// curveSamples[i] = (x, y, age, _pad)\n@group(0) @binding(2) var<storage, read_write> curveSamples: array<vec4<f32>>;\n// chainTips[k] = (x, y, _pad, _pad) \u2014 the running tip after stacking phasor k\n@group(0) @binding(3) var<storage, read_write> chainTips: array<vec4<f32>>;\n\n// The PARTIAL-SUM curve point at parameter t over the first n phasors \u2014 the WGSL\n// transcription of math.ts:78-95 (partialSumAt). EXACTLY:\n// c += vec2(re\u00B7cos \u2212 im\u00B7sin, re\u00B7sin + im\u00B7cos) with angle = TAU\u00B7index\u00B7t.\nfn partialSumAt(t: f32, n: i32) -> vec2<f32> {\n var c = vec2<f32>(0.0, 0.0);\n let phasorCount = u.ints.w;\n let lim = min(n, phasorCount);\n for (var i = 0; i < MAX_PHASORS; i = i + 1) {\n if (i >= lim) { break; }\n let p = phasors[i].data;\n let re = p.x;\n let im = p.y;\n let index = p.z;\n let angle = TAU * index * t;\n let cs = cos(angle);\n let sn = sin(angle);\n c = c + vec2<f32>(re * cs - im * sn, re * sn + im * cs);\n }\n return c;\n}\n\n// The epicycle chain tip after stacking the first k phasors at head_t \u2014 the WGSL\n// transcription of math.ts:41-60 (positionsAt, read at the running tip). The running tip\n// after phasor (k\u22121) is exactly the partial sum over the first k terms.\nfn epicycleChainTip(t: f32, k: i32) -> vec2<f32> {\n return partialSumAt(t, k);\n}\n\n@compute @workgroup_size(64)\nfn cs_main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let i = i32(gid.x);\n let headT = u.c0.x;\n let trailArc = u.c0.y;\n let harmonicN = u.ints.x;\n let armN = u.ints.y;\n let sampleCount = u.ints.z;\n\n // \u2500\u2500 The comet body samples \u2500\u2500\n if (i < sampleCount) {\n // age: 0 at the oldest tail (i = sampleCount\u22121), 1 at the head (i = 0).\n let denom = max(f32(sampleCount - 1), 1.0);\n let frac = f32(i) / denom; // 0 = head, 1 = tail\n let age = 1.0 - frac; // 1 = head, 0 = tail\n // sample back along the period from the head by trailArc.\n var t = headT - trailArc * frac;\n t = t - floor(t); // fract \u2192 [0,1)\n let pt = partialSumAt(t, harmonicN);\n curveSamples[i] = vec4<f32>(pt.x, pt.y, age, 0.0);\n }\n\n // \u2500\u2500 The epicycle chain tips (k = 0..armN, capped to harmonicN) \u2500\u2500\n // chainTips[0] is the origin; chainTips[k] is the tip after phasor (k\u22121).\n let armLim = min(armN, harmonicN);\n if (i <= armLim && i <= MAX_PHASORS) {\n let tip = epicycleChainTip(headT, i);\n chainTips[i] = vec4<f32>(tip.x, tip.y, 0.0, 0.0);\n }\n}\n";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** The full-screen-triangle vertex shader (the aurora/concentric pattern). */
|
|
2
|
+
export declare const FOURIER_FIELD_VERT_GLSL = "#version 300 es\nin vec2 aPosition;\nout vec2 vClip;\nvoid main() {\n vClip = aPosition;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n";
|
|
3
|
+
/** The fragment SDF — the GLSL twin of fourier-field.render.wgsl.ts's fs_main. */
|
|
4
|
+
export declare const FOURIER_FIELD_FRAG_GLSL = "#version 300 es\nprecision highp float;\n\n#define MAX_CURVE_SAMPLES 256\n#define MAX_PHASORS 64\n\nin vec2 vClip;\nout vec4 fragColor;\n\nuniform vec4 uFit; // (centerX, centerY, scale, aspect)\nuniform vec4 uTrail; // (trailWidth, peakAlpha, headGlowAlpha, trailFadeExp)\nuniform vec4 uEnv; // (trailFloor, intensity, showEpicycles, rainbowChain)\nuniform int uSampleCount;\nuniform int uArmCount;\nuniform int uStopCount;\nuniform vec3 uPalette[4]; // linear-sRGB stops\n// curveSamples[i] = (x, y, age) in MODEL space; chainTips[k] = (x, y) in MODEL space.\nuniform vec3 uCurve[MAX_CURVE_SAMPLES];\nuniform vec2 uChain[MAX_PHASORS];\n\nconst float PI = 3.141592653589793;\n\n\nfloat srgbToLinearCh(float c) {\n return c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);\n}\nvec3 srgbToLinear(vec3 c) {\n return vec3(srgbToLinearCh(c.r), srgbToLinearCh(c.g), srgbToLinearCh(c.b));\n}\n\nfloat linearToSrgbCh(float c) {\n return c <= 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1.0 / 2.4) - 0.055;\n}\nvec3 linearToSrgb(vec3 c) {\n return vec3(linearToSrgbCh(c.r), linearToSrgbCh(c.g), linearToSrgbCh(c.b));\n}\n\n// value.js LINEAR_SRGB_TO_LMS (constants.ts), row-major; written here as GLSL\n// columns (= the transpose) so mat3 * vec3 evaluates the row-major M\u00B7v.\nconst mat3 LINEAR_SRGB_TO_LMS = mat3(\n 0.4122214708, 0.2119034982, 0.0883024619,\n 0.5363325363, 0.6806995451, 0.2817188376,\n 0.0514459929, 0.1073969566, 0.6299787005\n);\n\n// value.js srgbToOKLab's INLINE LMS\u2192OKLab coefficients (gamut.ts lines 295-297 \u2014\n// these differ at the ~1e-9 digit from LMS_TO_OKLAB_MATRIX; use the inline ones to\n// mirror the exact value.js path), row-major \u2192 GLSL columns.\nconst mat3 LMS_TO_OKLAB = mat3(\n 0.2104542553, 1.9779984951, 0.0259040371,\n 0.7936177850, -2.4285922050, 0.7827717662,\n -0.0040720468, 0.4505937099, -0.8086757660\n);\n\n// value.js OKLAB_TO_LMS_COEFF (constants.ts), row-major \u2192 GLSL columns. Rows:\n// l = [1, 0.3963377774, 0.2158037573], m = [1, -0.1055613458, -0.0638541728],\n// s = [1, -0.0894841775, -1.2914855480].\nconst mat3 OKLAB_TO_LMS = mat3(\n 1.0, 1.0, 1.0,\n 0.3963377774, -0.1055613458, -0.0894841775,\n 0.2158037573, -0.0638541728, -1.2914855480\n);\n\n// value.js LMS_TO_LINEAR_SRGB (constants.ts), row-major \u2192 GLSL columns.\nconst mat3 LMS_TO_LINEAR_SRGB = mat3(\n 4.0767416621, -1.2684380046, -0.0041960863,\n -3.3077115913, 2.6097574011, -0.7034186147,\n 0.2309699292, -0.3413193965, 1.7076147010\n);\n\n// Gamma sRGB \u2192 raw OKLab (L, a, b). Mirrors value.js srgbToOKLab.\nvec3 srgbToOklab(vec3 c) {\n vec3 lin = srgbToLinear(c);\n vec3 lms = LINEAR_SRGB_TO_LMS * lin;\n vec3 lmsCbrt = sign(lms) * pow(abs(lms), vec3(1.0 / 3.0));\n return LMS_TO_OKLAB * lmsCbrt;\n}\n\n// Raw OKLab (L, a, b) \u2192 linear sRGB. Mirrors value.js oklabToLinearSRGB.\nvec3 oklabToLinearSrgb(vec3 lab) {\n vec3 lms_ = OKLAB_TO_LMS * lab;\n vec3 lms = lms_ * lms_ * lms_;\n return LMS_TO_LINEAR_SRGB * lms;\n}\n\n// OKLab \u2192 OKLCh: H in RADIANS. Mirrors value.js rawOklabToOklch (which returns\n// degrees; we stay in radians and only fold to [0, 2pi)).\nvec3 oklabToOklch(vec3 lab) {\n float C = length(lab.yz);\n float H = atan(lab.z, lab.y);\n if (H < 0.0) H += 2.0 * PI;\n return vec3(lab.x, C, H);\n}\n\n// OKLCh (H radians) \u2192 OKLab. Mirrors value.js rawOklchToOklab.\nvec3 oklchToOklab(vec3 lch) {\n return vec3(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));\n}\n\n// Negative-safe cube root (the WGSL chunk's cbrt3 twin; the GLSL chunk inlines it).\nvec3 cbrt3(vec3 v) { return sign(v) * pow(abs(v), vec3(1.0 / 3.0)); }\n\nvec3 samplePaletteLin(float t) {\n if (uStopCount <= 1) return uPalette[0];\n float n = float(uStopCount);\n float ft = clamp(t, 0.0, 1.0) * (n - 1.0);\n int i0 = int(floor(ft));\n int i1 = min(i0 + 1, uStopCount - 1);\n float f = ft - float(i0);\n vec3 labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * uPalette[i0]);\n vec3 labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * uPalette[i1]);\n return oklabToLinearSrgb(mix(labA, labB, f));\n}\n\nvec3 chainColorLin(float seg, bool rainbow) {\n vec3 baseLin = uPalette[0];\n if (!rainbow) return baseLin;\n vec3 lab = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * baseLin);\n vec3 lch = oklabToOklch(lab);\n float hueShift = mix(-0.45, 1.15, clamp(seg, 0.0, 1.0));\n vec3 lifted = vec3(0.66, max(lch.y, 0.14), lch.z + hueShift);\n return oklabToLinearSrgb(oklchToOklab(lifted));\n}\n\nfloat segDist(vec2 p, vec2 a, vec2 b) {\n vec2 pa = p - a;\n vec2 ba = b - a;\n float h = clamp(dot(pa, ba) / max(dot(ba, ba), 1e-8), 0.0, 1.0);\n return length(pa - ba * h);\n}\n\nvoid main() {\n vec2 center = uFit.xy;\n float scale = max(uFit.z, 1e-6);\n float aspect = max(uFit.w, 1e-4);\n // clip \u2192 model (the inverse of model\u2192clip fit).\n vec2 p = center + vec2(vClip.x * aspect, vClip.y) / scale;\n\n float aa = max(fwidth(p.x) + fwidth(p.y), 1e-5) * 0.75;\n float trailWidth = uTrail.x; // already in model units (packed CPU-side)\n float peak = uTrail.y * uEnv.y;\n float headGlow = uTrail.z * uEnv.y;\n float fadeExp = uTrail.w;\n float trailFloor = uEnv.x;\n bool showEpicycles = uEnv.z > 0.5;\n bool rainbow = uEnv.w > 0.5;\n float halfW = trailWidth * 0.5;\n\n vec4 accum = vec4(0.0);\n\n if (showEpicycles && uArmCount >= 1) {\n for (int k = 0; k < MAX_PHASORS; k++) {\n if (k >= uArmCount) break;\n vec2 a = uChain[k];\n vec2 b = uChain[k + 1];\n float seg = float(k) / max(float(uArmCount - 1), 1.0);\n vec3 lin = chainColorLin(seg, rainbow);\n float radius = length(b - a);\n float dRing = abs(length(p - a) - radius);\n float ringW = max(halfW * 0.45, aa);\n float ringMask = (1.0 - smoothstep(ringW, ringW + aa, dRing)) * 0.5;\n float dArm = segDist(p, a, b);\n float armMask = 1.0 - smoothstep(halfW * 0.55, halfW * 0.55 + aa, dArm);\n float dotR = max(halfW * 0.7, aa * 2.0);\n float dDot = length(p - a);\n float dotMask = 1.0 - smoothstep(dotR, dotR + aa, dDot);\n float m = clamp(max(max(ringMask, armMask), dotMask), 0.0, 1.0) * peak * 0.7;\n vec3 rgb = clamp(linearToSrgb(lin), vec3(0.0), vec3(1.0));\n accum = vec4(rgb * m, m) + accum * (1.0 - m);\n }\n }\n\n for (int i = 0; i < MAX_CURVE_SAMPLES; i++) {\n if (i >= uSampleCount - 1) break;\n vec3 sa = uCurve[i];\n vec3 sb = uCurve[i + 1];\n float d = segDist(p, sa.xy, sb.xy);\n float cover = 1.0 - smoothstep(halfW, halfW + aa, d);\n if (cover < 0.002) continue;\n float age = max(sa.z, sb.z);\n float a = peak * pow(age, fadeExp);\n a = max(a, peak * trailFloor) * cover;\n vec3 lin = samplePaletteLin(1.0 - age * 0.4);\n vec3 rgb = clamp(linearToSrgb(lin), vec3(0.0), vec3(1.0));\n accum = vec4(rgb * a, a) + accum * (1.0 - a);\n }\n\n if (uSampleCount >= 1) {\n vec2 head = uCurve[0].xy;\n float dHead = length(p - head);\n float coreR = halfW * 1.5;\n float haloR = coreR * 3.0;\n vec3 headRgb = clamp(linearToSrgb(samplePaletteLin(0.0)), vec3(0.0), vec3(1.0));\n float halo = (1.0 - smoothstep(0.0, haloR, dHead)) * headGlow * 0.35;\n accum = vec4(headRgb * halo, halo) + accum * (1.0 - halo);\n float core = (1.0 - smoothstep(coreR, coreR + aa, dHead)) * headGlow;\n accum = vec4(headRgb * core, core) + accum * (1.0 - core);\n float spec = (1.0 - smoothstep(coreR * 0.4, coreR * 0.4 + aa, dHead)) * headGlow * 0.9;\n accum = vec4(vec3(1.0) * spec, spec) + accum * (1.0 - spec);\n }\n\n fragColor = accum;\n}\n";
|