@mkbabb/glass-ui 4.0.1 → 4.2.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-DlVP2evz.js} +72 -53
- package/dist/{CommandShortcut-DvZNQ_HF.js → CommandShortcut-By-VQcLO.js} +25 -14
- package/dist/{ConfiguratorRow-BR4l-ixA.js → ConfiguratorRow-YMXdINHx.js} +14 -14
- package/dist/ContextMenuContent-CMWn6huB.js +90 -0
- package/dist/{ContextMenuSubContent-xol4sD2q.js → ContextMenuSubContent-DvwWCUc0.js} +16 -16
- package/dist/{DataTable-CuKwF7wr.js → DataTable-C4tG3eIJ.js} +4 -4
- package/dist/DialogContent-D8U9ZfWS.js +121 -0
- package/dist/DialogFooter-DoLy0ewI.js +80 -0
- package/dist/DialogScrollContent-BMekN7gq.js +93 -0
- package/dist/{FadingScroll-DI6hQhT9.js → FadingScroll-P8B30rAD.js} +1 -1
- package/dist/HoverCardContent-DAmGYglo.js +88 -0
- package/dist/{HoverPopover-CbqbNwgU.js → HoverPopover-DYpBOzzF.js} +1 -1
- package/dist/{IconChip-BTD-nay5.js → IconChip-CQa7XZYc.js} +7 -5
- package/dist/{IconTooltip-Bl8gFZ8d.js → IconTooltip-_df8M3xm.js} +1 -1
- package/dist/Input-CyU4_hIC.js +57 -0
- package/dist/{MetricBadge-RHdBP72w.js → MetricBadge-DQt_dGah.js} +1 -1
- package/dist/{Notification-VUwexFUf.js → Notification-BlSPJhtZ.js} +4 -4
- package/dist/NumberFieldContent-Z3VxGu_6.js +140 -0
- package/dist/PagerDots-CYlqVFd4.js +196 -0
- package/dist/PaperBackdrop-DYWgrnh8.js +42 -0
- package/dist/{PopoverContent-DL7E6vJP.js → PopoverContent-BuKyHZSz.js} +2 -2
- package/dist/{Progress-DctG61iZ.js → Progress-C9SsdwIZ.js} +1 -1
- package/dist/{ScrollingText-yOpBzFYq.js → ScrollingText-DY3W1Jfh.js} +2 -2
- package/dist/SelectScrollDownButton-3mFHX_R-.js +260 -0
- package/dist/{SelectSeparator-DXswVdRz.js → SelectSeparator-CNRGG7Ew.js} +1 -1
- package/dist/Separator-Cf9-JFgi.js +44 -0
- package/dist/Switch-uf-UKPA2.js +49 -0
- package/dist/{Toaster-Bw4xR8xV.js → Toaster-ozrsR4mP.js} +2 -2
- package/dist/{ToggleGroupItem-pEM9vIhs.js → ToggleGroupItem-BpzaVzNm.js} +6 -6
- package/dist/TooltipProvider-QQVM_80r.js +109 -0
- package/dist/animated-digit.js +2 -2
- package/dist/api/index.d.ts +16 -32
- package/dist/api/types-extra.d.ts +33 -0
- package/dist/api.js +2 -2
- package/dist/aurora.js +629 -269
- package/dist/badge-Bt14yURi.js +72 -0
- package/dist/badge.js +1 -1
- package/dist/border-progress.js +49 -57
- package/dist/button-D1W9PrzI.js +130 -0
- package/dist/button.js +1 -1
- package/dist/canvas.js +2 -3
- package/dist/card.js +1 -1
- package/dist/carousel.js +235 -106
- package/dist/chipVariants-BJQ0I2kB.js +18 -0
- package/dist/collapsible.js +1 -1
- package/dist/color-B9jZdhJX.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/glSetup.d.ts +1 -1
- package/dist/components/custom/aurora/composables/runtime.d.ts +12 -0
- package/dist/components/custom/aurora/composables/uniformBridgeWGPU.d.ts +12 -3
- package/dist/components/custom/aurora/composables/wgpuSetup.d.ts +8 -0
- package/dist/components/custom/aurora/constants/presets.d.ts +47 -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/aurora/index.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/Concentric.vue.d.ts +15 -12
- package/dist/components/custom/concentric/composables/concentricGLSetup.d.ts +12 -0
- package/dist/components/custom/concentric/composables/concentricWGPUSetup.d.ts +13 -0
- package/dist/components/custom/concentric/composables/levelField.d.ts +50 -0
- package/dist/components/custom/concentric/composables/uniformBridgeWGPU.d.ts +7 -3
- package/dist/components/custom/concentric/composables/useConcentric.d.ts +3 -3
- package/dist/components/custom/concentric/constants.d.ts +69 -24
- 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/configurator/Configurator.vue.d.ts +23 -2
- package/dist/components/custom/configurator/index.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/DockDropdownTrigger.vue.d.ts +4 -3
- package/dist/components/custom/dock/DockIconButton.vue.d.ts +22 -0
- package/dist/components/custom/dock/DockPopoverTrigger.vue.d.ts +19 -0
- package/dist/components/custom/dock/DockStack.vue.d.ts +78 -0
- package/dist/components/custom/dock/GlassDock.vue.d.ts +21 -3
- package/dist/components/custom/dock/composables/dockMorphContext.d.ts +18 -32
- package/dist/components/custom/dock/composables/dockMorphMeasure.d.ts +78 -67
- package/dist/components/custom/dock/composables/index.d.ts +3 -0
- package/dist/components/custom/dock/composables/railProjection.d.ts +45 -0
- package/dist/components/custom/dock/composables/useDockContextSilhouette.d.ts +192 -0
- package/dist/components/custom/dock/composables/useDockFission.d.ts +158 -0
- package/dist/components/custom/dock/composables/useDockItemDrag.d.ts +18 -0
- package/dist/components/custom/dock/composables/useDockSearch.d.ts +85 -0
- package/dist/components/custom/dock/composables/useDockShellProps.d.ts +49 -0
- package/dist/components/custom/dock/constants.d.ts +32 -17
- package/dist/components/custom/dock/index.d.ts +8 -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 +69 -6
- package/dist/components/custom/dot-flow-field/composables/flowGLProgram.d.ts +8 -0
- package/dist/components/custom/dot-flow-field/composables/flowSetupGL.d.ts +9 -0
- package/dist/components/custom/dot-flow-field/composables/flowSetupGLFlow.d.ts +12 -0
- package/dist/components/custom/dot-flow-field/composables/flowSetupWGPU.d.ts +7 -0
- package/dist/components/custom/dot-flow-field/composables/uniformBridgeWGPU.d.ts +50 -9
- package/dist/components/custom/dot-flow-field/composables/useDotFlowField.d.ts +6 -5
- package/dist/components/custom/dot-flow-field/composables/useFlowParticles.d.ts +23 -9
- package/dist/components/custom/dot-flow-field/constants.d.ts +92 -20
- 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 +31 -18
- package/dist/components/custom/dot-flow-field/shaders/flow-field.render.wgsl.d.ts +2 -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 +61 -0
- package/dist/components/custom/dot-matrix/composables/useDotMatrix.d.ts +34 -0
- package/dist/components/custom/dot-matrix/composables/useDotSphere.d.ts +34 -0
- package/dist/components/custom/dot-matrix/constants.d.ts +72 -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 +44 -47
- package/dist/components/custom/fourier-field/composables/fourierFieldGLSetup.d.ts +24 -0
- package/dist/components/custom/fourier-field/composables/fourierFieldWGPUSetup.d.ts +31 -0
- package/dist/components/custom/fourier-field/composables/uniformBridgeWGPU.d.ts +56 -0
- package/dist/components/custom/fourier-field/composables/useFourierField.d.ts +61 -37
- package/dist/components/custom/fourier-field/constants.d.ts +114 -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/composables/easing.d.ts +1 -0
- package/dist/components/custom/goo-blob/composables/useBlobSatellites.d.ts +1 -0
- package/dist/components/custom/goo-blob/constants.d.ts +26 -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 +86 -1
- 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 +79 -0
- package/dist/components/custom/goo-dot-matrix/composables/uniformBridgeWGPU.d.ts +45 -0
- package/dist/components/custom/goo-dot-matrix/composables/useGooDotMatrix.d.ts +31 -0
- package/dist/components/custom/goo-dot-matrix/constants.d.ts +115 -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 +13 -0
- package/dist/components/custom/goo-dot-matrix/shaders/goo-dot.wgsl.d.ts +4 -0
- package/dist/components/custom/goo-filter/GooFilter.vue.d.ts +22 -0
- package/dist/components/custom/goo-filter/index.d.ts +1 -0
- package/dist/components/custom/handmark/brush.d.ts +17 -17
- package/dist/components/custom/handmark/constants.d.ts +28 -8
- package/dist/components/custom/handmark/geometry.d.ts +34 -1
- package/dist/components/custom/handmark/index.d.ts +1 -1
- package/dist/components/custom/icon-chip/types.d.ts +10 -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-backdrop/PaperBackdrop.vue.d.ts +18 -0
- package/dist/components/custom/paper-grid/PaperGrid.vue.d.ts +42 -0
- package/dist/components/custom/paper-grid/composables/paperGrid.d.ts +105 -0
- package/dist/components/custom/paper-grid/composables/paperGridGLSetup.d.ts +18 -0
- package/dist/components/custom/paper-grid/composables/paperGridWGPUSetup.d.ts +21 -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 +95 -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/chipVariants.d.ts +39 -0
- package/dist/components/custom/selectable-chip/index.d.ts +2 -0
- package/dist/components/custom/selectable-chip/selectableChipVariants.d.ts +15 -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 +28 -2
- package/dist/components/custom/timeline/ScrubberTimeline.vue.d.ts +16 -0
- package/dist/components/custom/timeline/geometry.d.ts +0 -8
- package/dist/components/custom/toggle-chip/index.d.ts +15 -4
- package/dist/components/custom/watercolor-dot/WatercolorDot.vue.d.ts +32 -17
- 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/_shared/useSurfaceAxis.d.ts +17 -3
- package/dist/components/ui/badge/Badge.vue.d.ts +14 -0
- package/dist/components/ui/badge/index.d.ts +1 -0
- package/dist/components/ui/button/Button.vue.d.ts +1 -0
- package/dist/components/ui/button/index.d.ts +1 -1
- package/dist/components/ui/card/Card.vue.d.ts +46 -1
- package/dist/components/ui/card/ScrollCard.vue.d.ts +1 -1
- package/dist/components/ui/card/index.d.ts +1 -1
- package/dist/components/ui/carousel/CarouselContent.vue.d.ts +2 -4
- 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/dialog/DialogContent.vue.d.ts +9 -0
- package/dist/components/ui/drawer/Drawer.vue.d.ts +33 -14
- package/dist/components/ui/drawer/constants.d.ts +8 -6
- package/dist/components/ui/drawer/index.d.ts +12 -2
- 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 +12 -0
- package/dist/components/ui/slider/Slider.vue.d.ts +9 -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/dom/index.d.ts +1 -0
- package/dist/composables/dom/useDragVelocity.d.ts +46 -0
- package/dist/composables/glass/useVizChoreography.d.ts +123 -0
- package/dist/composables/glass/wave/index.d.ts +4 -0
- package/dist/composables/glass/wave/waveField.d.ts +115 -0
- package/dist/composables/glass/wave/waveField.glsl.d.ts +1 -0
- package/dist/composables/glass/wave/waveField.wgsl.d.ts +1 -0
- package/dist/composables/glass/webgl/createCanvasLifecycle.d.ts +105 -2
- package/dist/composables/glass/webgl/shaders/flow.wgsl.d.ts +1 -0
- package/dist/composables/glass/webgl/useWebGLCanvas.d.ts +40 -2
- package/dist/composables/glass/webgpu/index.d.ts +2 -1
- package/dist/composables/glass/webgpu/useGpuSubstrate.d.ts +65 -7
- package/dist/composables/glass/webgpu/useWebGPUCanvas.d.ts +50 -2
- package/dist/composables/glass/webgpu/webgpuDevice.d.ts +42 -0
- package/dist/composables/motion/core/index.d.ts +7 -0
- package/dist/composables/motion/core/useHaptic.d.ts +48 -0
- package/dist/composables/motion/core/writeVelocityWeight.d.ts +31 -0
- package/dist/composables/motion/index.d.ts +2 -0
- package/dist/composables/motion/scrollReader.d.ts +25 -0
- package/dist/composables/motion/springPresets.d.ts +19 -1
- package/dist/composables/motion/suite.d.ts +2 -2
- package/dist/composables/motion/useBloomUp.d.ts +97 -0
- package/dist/composables/motion/useCelebrationBurst.d.ts +50 -0
- package/dist/composables/motion/useCharStagger.d.ts +44 -0
- package/dist/composables/motion/useDockCtaReceive.d.ts +29 -22
- package/dist/composables/motion/useGooMorph.d.ts +72 -0
- package/dist/composables/motion/useLiquidFlex.d.ts +18 -0
- package/dist/composables/motion/useLiquidMorph.d.ts +108 -0
- package/dist/composables/motion/useLiquidPress.d.ts +12 -0
- package/dist/composables/motion/useLiquidReveal.d.ts +7 -4
- package/dist/composables/motion/useMorphField.d.ts +157 -0
- package/dist/composables/motion/useScrollChrome.d.ts +58 -0
- package/dist/composables/motion/useScrollPin.d.ts +49 -0
- package/dist/composables/motion/useScrollScene.d.ts +67 -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 +552 -309
- 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 +2 -2
- package/dist/createCanvasLifecycle-CuCrGRfq.js +173 -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 +1320 -631
- package/dist/dockContext-gFVS2gMg.js +18 -0
- package/dist/dom.js +7 -6
- package/dist/dot-flow-field.js +1268 -387
- package/dist/dot-matrix.d.ts +1 -0
- package/dist/dot-matrix.js +774 -0
- package/dist/dotMatrixField-CRO0ZFk4.js +48 -0
- package/dist/drawer.js +106 -96
- package/dist/{dropdown-menu-CofSZuk8.js → dropdown-menu-CCfcCQ68.js} +83 -79
- package/dist/dropdown-menu.js +1 -1
- package/dist/easing.js +188 -176
- package/dist/expandable-container.js +43 -21
- package/dist/fading-scroll.js +1 -1
- package/dist/flow.glsl-DqEGRpl4.js +4 -0
- package/dist/forms.js +64 -62
- package/dist/fourier-field.js +1069 -178
- package/dist/fourier-math.js +1 -1
- package/dist/glass-panel.js +2 -2
- package/dist/glass-ui.css +1 -1
- package/dist/glass-ui.js +164 -119
- package/dist/goo-blob.js +175 -1230
- package/dist/goo-dot-matrix.d.ts +1 -0
- package/dist/goo-dot-matrix.js +811 -0
- package/dist/handmark.js +137 -94
- package/dist/header-ribbon.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 +5 -0
- package/dist/instrument-chassis.js +1 -1
- package/dist/keyboard.js +1 -1
- package/dist/label.js +1 -1
- package/dist/labeled-field.js +70 -60
- package/dist/metric-badge.js +1 -1
- package/dist/metric-cell.js +1 -1
- package/dist/metric-stack.js +12 -3
- package/dist/motion-core.js +59 -34
- package/dist/motion-curves.js +30 -14
- package/dist/motion.js +231 -96
- 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 +761 -0
- package/dist/paperGrid-CXCSMbZ1.js +191 -0
- package/dist/popover.js +1 -1
- package/dist/{presets-BW2b-fr1.js → presets-QvYgnFIZ.js} +14 -13
- package/dist/{procedural-color.glsl-CIFsJhwI.js → procedural-color.wgsl-C1Y5PkM6.js} +2 -2
- package/dist/progress.js +1 -1
- package/dist/pulse.js +2 -2
- package/dist/reactive.js +2 -2
- package/dist/{useCanvas2D-B8w_E3Rr.js → resolveCanvasColor-DsSJk06I.js} +16 -6
- package/dist/scrollReader-rc3Ns_NM.js +42 -0
- package/dist/scrolling-text.js +1 -1
- package/dist/search.js +162 -306
- package/dist/select.js +3 -3
- package/dist/selectable-chip.d.ts +1 -0
- package/dist/selectable-chip.js +48 -0
- package/dist/separator.js +1 -1
- package/dist/{sheet-tZMg0E0w.js → sheet-DUCIoOe0.js} +4 -4
- package/dist/sheet.js +1 -1
- package/dist/sidebar.js +216 -114
- package/dist/slider-CcICPe3u.js +149 -0
- package/dist/slider.js +1 -1
- package/dist/sortable-list.js +3 -3
- package/dist/spectrum-walk-cBNSx_zm.js +33 -0
- package/dist/springPresets-DfoQ6XRY.js +64 -0
- package/dist/stacked-icons.js +54 -39
- package/dist/styles/animations.css +13 -3
- package/dist/styles/cards.css +271 -2
- package/dist/styles/completion-seal.css +131 -0
- package/dist/styles/components.css +1 -4
- package/dist/styles/configurator.css +221 -1
- package/dist/styles/critical-partition.mjs +66 -11
- package/dist/styles/deferred.css +4 -0
- package/dist/styles/dock/adaptive-legibility.css +119 -0
- package/dist/styles/dock/cta-seat.css +87 -0
- package/dist/styles/dock/density.css +167 -6
- package/dist/styles/dock/fission-bridge.css +552 -0
- package/dist/styles/dock/layers.css +90 -78
- package/dist/styles/dock/morph-bridge.css +67 -18
- package/dist/styles/dock/morph.css +57 -118
- package/dist/styles/dock/overflow.css +12 -0
- package/dist/styles/dock/search.css +68 -0
- package/dist/styles/dock/shape.css +250 -0
- package/dist/styles/dock/shell.css +24 -8
- package/dist/styles/dock/stack-rail.css +352 -0
- package/dist/styles/dock-controls/dark-mode-toggle.css +17 -4
- package/dist/styles/dock-controls/icon-button.css +46 -0
- package/dist/styles/dock-controls/triggers.css +23 -1
- package/dist/styles/dock-controls.css +18 -0
- package/dist/styles/dock.css +27 -2
- package/dist/styles/drawer.css +166 -0
- package/dist/styles/glass/accent-tone.css +66 -0
- package/dist/styles/glass/control-surfaces.css +167 -0
- package/dist/styles/glass/glass-atom.css +244 -0
- package/dist/styles/glass/glass-capsule.css +143 -0
- package/dist/styles/glass/glass-chip.css +215 -0
- package/dist/styles/glass/ladder.css +67 -17
- package/dist/styles/glass/liquid-enter.css +252 -0
- package/dist/styles/glass/liquid-morph.css +850 -0
- package/dist/styles/glass/material.css +70 -1
- package/dist/styles/glass/reveal.css +22 -2
- package/dist/styles/glass/rim.css +31 -9
- package/dist/styles/glass/surfaces.css +81 -150
- package/dist/styles/glass.css +21 -0
- package/dist/styles/icon-chip.css +45 -0
- package/dist/styles/index.css +26 -0
- package/dist/styles/jubilance.css +65 -0
- package/dist/styles/motion/morph-field.css +229 -0
- package/dist/styles/paper.css +230 -14
- package/dist/styles/scroll-choreography.css +135 -78
- package/dist/styles/scroll-chrome.css +123 -0
- package/dist/styles/scroll-driven.css +38 -0
- package/dist/styles/segmented-tabs.css +110 -40
- package/dist/styles/select.css +151 -0
- package/dist/styles/theme/bridges.css +22 -0
- package/dist/styles/theme/radius.css +18 -1
- package/dist/styles/tokens/color-radius.css +14 -4
- package/dist/styles/tokens/dark-arm.css +94 -12
- package/dist/styles/tokens/glass-deep.css +33 -4
- package/dist/styles/tokens/glass-fx.css +122 -1
- package/dist/styles/tokens/glass.css +226 -34
- package/dist/styles/tokens/light-dark.css +3 -3
- package/dist/styles/tokens/offsets.css +27 -0
- package/dist/styles/tokens/property-regs.css +277 -0
- package/dist/styles/tokens/scale-paper.css +86 -30
- package/dist/styles/tokens/scheme-motion.css +106 -133
- package/dist/styles/tokens/scheme-spring.css +239 -0
- package/dist/styles/tokens/scroll-tokens.css +15 -15
- package/dist/styles/tokens/shadow.css +73 -13
- package/dist/styles/tokens/sizing-config.css +110 -0
- package/dist/styles/tokens/sizing.css +55 -104
- package/dist/styles/tokens.css +14 -2
- 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 +84 -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 +199 -182
- package/dist/timeline.js +241 -206
- package/dist/toast.js +1 -1
- package/dist/toggle-chip.js +14 -41
- package/dist/toggle-group.js +1 -1
- package/dist/tooltip.js +1 -1
- package/dist/typewriter.js +2 -2
- package/dist/uniformBridgeWGPU-BCse1SHU.js +1268 -0
- package/dist/{useAnimatedNumber-BfUq2bUM.js → useAnimatedNumber-BntskVdQ.js} +1 -1
- package/dist/{useConfiguratorState-DNlOh6c8.js → useConfiguratorState-22BcULzF.js} +41 -38
- package/dist/useControlSize-DAZ062x7.js +9 -0
- package/dist/useDockCtaReceive-DX7RDb6_.js +88 -0
- package/dist/{useDragMorph-DgxnsVJz.js → useDragMorph-DGLSewwB.js} +4 -4
- package/dist/useDragVelocity-CjcfX3dA.js +57 -0
- package/dist/useFuzzySearch-0fTYOhS4.js +177 -0
- package/dist/useGooMorph-Cs13NgYL.js +104 -0
- package/dist/useGpuSubstrate-Ceet70xq.js +347 -0
- package/dist/useHaptic-CPz5BT9I.js +134 -0
- package/dist/{useLiquidFlex-mZPMiNXh.js → useLiquidFlex-Cc6PjVJD.js} +8 -3
- package/dist/useLiquidPress-CtOQ8Z0_.js +43 -0
- package/dist/useMorphField-ogBM7ubT.js +141 -0
- package/dist/usePointerVelocityField-BrkqZFhj.js +91 -0
- package/dist/useScrollChrome-JuImi1DM.js +258 -0
- package/dist/{useSpringMount-q1amq1SJ.js → useSpringMount-DFxtzmkR.js} +1 -1
- package/dist/useSpringPress-VM9RgVq3.js +36 -0
- package/dist/{useSurfaceAxis-g0NloYEF.js → useSurfaceAxis-Ci7Dnaw2.js} +1 -1
- package/dist/{useTouchGate-CBZTD4SD.js → useTouchGate-B1Lf9XqN.js} +1 -1
- 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 +107 -74
- package/dist/writeVelocityWeight-Bh83xZfs.js +19 -0
- package/package.json +140 -9
- package/src/styles/animations.css +13 -3
- package/src/styles/cards.css +271 -2
- package/src/styles/completion-seal.css +131 -0
- package/src/styles/configurator.css +221 -1
- package/src/styles/critical-partition.mjs +66 -11
- package/src/styles/dock/adaptive-legibility.css +119 -0
- package/src/styles/dock/cta-seat.css +87 -0
- package/src/styles/dock/density.css +167 -6
- package/src/styles/dock/fission-bridge.css +552 -0
- package/src/styles/dock/layers.css +90 -78
- package/src/styles/dock/morph-bridge.css +67 -18
- package/src/styles/dock/morph.css +57 -118
- package/src/styles/dock/overflow.css +12 -0
- package/src/styles/dock/search.css +68 -0
- package/src/styles/dock/shape.css +250 -0
- package/src/styles/dock/shell.css +24 -8
- package/src/styles/dock/stack-rail.css +352 -0
- package/src/styles/dock-controls/dark-mode-toggle.css +17 -4
- package/src/styles/dock-controls/icon-button.css +46 -0
- package/src/styles/dock-controls/triggers.css +23 -1
- package/src/styles/dock-controls.css +18 -0
- package/src/styles/dock.css +27 -2
- package/src/styles/drawer.css +164 -0
- package/src/styles/glass/accent-tone.css +66 -0
- package/src/styles/glass/control-surfaces.css +167 -0
- package/src/styles/glass/glass-atom.css +244 -0
- package/src/styles/glass/glass-capsule.css +143 -0
- package/src/styles/glass/glass-chip.css +215 -0
- package/src/styles/glass/ladder.css +67 -17
- package/src/styles/glass/liquid-enter.css +252 -0
- package/src/styles/glass/liquid-morph.css +850 -0
- package/src/styles/glass/material.css +70 -1
- package/src/styles/glass/reveal.css +22 -2
- package/src/styles/glass/rim.css +31 -9
- package/src/styles/glass/surfaces.css +81 -150
- package/src/styles/glass.css +21 -0
- package/src/styles/icon-chip.css +45 -0
- package/src/styles/index.css +26 -0
- package/src/styles/jubilance.css +65 -0
- package/src/styles/motion/morph-field.css +229 -0
- package/src/styles/paper.css +230 -14
- package/src/styles/scroll-choreography.css +135 -78
- package/src/styles/scroll-chrome.css +123 -0
- package/src/styles/scroll-driven.css +38 -0
- package/src/styles/segmented-tabs.css +110 -36
- package/src/styles/select.css +151 -0
- package/src/styles/theme/bridges.css +22 -0
- package/src/styles/theme/radius.css +18 -1
- package/src/styles/tokens/color-radius.css +14 -4
- package/src/styles/tokens/dark-arm.css +94 -12
- package/src/styles/tokens/glass-deep.css +33 -4
- package/src/styles/tokens/glass-fx.css +122 -1
- package/src/styles/tokens/glass.css +226 -34
- package/src/styles/tokens/light-dark.css +3 -3
- package/src/styles/tokens/offsets.css +27 -0
- package/src/styles/tokens/property-regs.css +277 -0
- package/src/styles/tokens/scale-paper.css +86 -30
- package/src/styles/tokens/scheme-motion.css +106 -133
- package/src/styles/tokens/scheme-spring.css +239 -0
- package/src/styles/tokens/scroll-tokens.css +15 -15
- package/src/styles/tokens/shadow.css +73 -13
- package/src/styles/tokens/sizing-config.css +110 -0
- package/src/styles/tokens/sizing.css +55 -104
- package/src/styles/tokens.css +14 -2
- 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 +84 -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/DialogContent-DcKK8k9i.js +0 -103
- 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/PaperBackdrop-Vf3tlpvd.js +0 -31
- package/dist/SelectScrollDownButton-CrA8F0iV.js +0 -252
- package/dist/Separator-pKF0oA4M.js +0 -37
- package/dist/Switch-CwYNf8bo.js +0 -47
- package/dist/TooltipProvider-rzvnXz60.js +0 -104
- package/dist/badge-D9XWW4GT.js +0 -53
- package/dist/button-DYCUa-tH.js +0 -126
- package/dist/color-DweYl7pE.js +0 -86
- package/dist/components/custom/concentric/composables/ringField.d.ts +0 -44
- 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/dockContext-BNfyPLe9.js +0 -17
- package/dist/procedural-color.wgsl-CToRHugY.js +0 -224
- package/dist/resolveCanvasColor-CUyHr5Uu.js +0 -11
- package/dist/slider-DVb4HXU-.js +0 -142
- package/dist/springPresets-CFQGQfdl.js +0 -40
- package/dist/styles/dock/rail-extend.css +0 -397
- package/dist/useLiquidPress-kfb4KX79.js +0 -39
- 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/{CollapsibleContent-68dEXIAl.js → CollapsibleContent-D7UNsXQr.js} +0 -0
- /package/dist/{InstrumentChassis-Bx0F_q5g.js → InstrumentChassis-UUJX0-mW.js} +0 -0
- /package/dist/{Label-C2ejNWeC.js → Label-B_HPqi_q.js} +0 -0
- /package/dist/{ModalOverlay-D1VrWyoi.js → ModalOverlay-DfAf7o15.js} +0 -0
- /package/dist/{SelectGroup-DwwjicPY.js → SelectGroup-Dcczq44n.js} +0 -0
- /package/dist/{_plugin-vue_export-helper-C1je1s0u.js → _plugin-vue_export-helper-gLzyemvl.js} +0 -0
- /package/dist/{compile-CQEFRTmx.js → compile-INR_tPk_.js} +0 -0
- /package/dist/{constants-BPOqYJAm.js → constants-BWj7DkMn.js} +0 -0
- /package/dist/{createContext-CpBNTRMI.js → createContext-Cd23P9j0.js} +0 -0
- /package/dist/{math-BINYmg5z.js → math-5RcIgCB4.js} +0 -0
- /package/dist/{menuItemVariants-D8VNHq22.js → menuItemVariants-DAXquKja.js} +0 -0
- /package/dist/{prng-Za0Rmgag.js → prng-B5tIXTtj.js} +0 -0
- /package/dist/{useGlobalDark-C28t0VWJ.js → useGlobalDark-B4HO9LXG.js} +0 -0
- /package/dist/{useIntersectionPause-Bj4sPkMh.js → useIntersectionPause-DO8Vl4gs.js} +0 -0
- /package/dist/{useInterval-CvK1mL92.js → useInterval-BVUI-sez.js} +0 -0
- /package/dist/{useKeyboardShortcuts-BXWXOZ-9.js → useKeyboardShortcuts-BEut54Tk.js} +0 -0
- /package/dist/{useResizeObserver-Bpoi7tRE.js → useResizeObserver-DdEn3v2f.js} +0 -0
- /package/dist/{useResolveTokenColor-vAylyR0x.js → useResolveTokenColor-ChOnCckA.js} +0 -0
- /package/dist/{useScrollProgress-D7bYU2RK.js → useScrollProgress-A0M6qRl7.js} +0 -0
- /package/dist/{useSortable-DHjtZSEd.js → useSortable-DQV_UNDw.js} +0 -0
- /package/dist/{useTextHighlight-CWEi25hf.js → useTextHighlight-Bma3UlKA.js} +0 -0
- /package/dist/{useTimer-BHJOKr35.js → useTimer-BBLGPXR8.js} +0 -0
- /package/dist/{useUserInvalidAria-y5namzeE.js → useUserInvalidAria-EmmwWPOl.js} +0 -0
- /package/dist/{useViewportReady-anbac3m6.js → useViewportReady-C9pYnn7K.js} +0 -0
- /package/dist/{vReveal-Czsb7zQC.js → vReveal-CT1KtwZA.js} +0 -0
- /package/dist/{vSpecular-CQFmLNzA.js → vSpecular-EX7loENl.js} +0 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { t as e } from "./cn-DJXf4yaB.js";
|
|
2
|
+
import { computed as t, createCommentVNode as n, createElementBlock as r, defineComponent as i, normalizeClass as a, onMounted as o, openBlock as s, readonly as c, ref as l, toDisplayString as u, toRef as d, unref as f, watch as p } from "vue";
|
|
3
|
+
//#region src/components/custom/completion-seal/composables/useCompletionSeal.ts
|
|
4
|
+
function m() {
|
|
5
|
+
return typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
6
|
+
}
|
|
7
|
+
function h(e) {
|
|
8
|
+
if (e != null) return typeof e == "function" ? e() : e.value;
|
|
9
|
+
}
|
|
10
|
+
function g(e = {}) {
|
|
11
|
+
let { play: n, respectReducedMotion: r = !0 } = e, i = l(!1), a = l(!1), s = t(() => r && m());
|
|
12
|
+
function u() {
|
|
13
|
+
if (s.value) {
|
|
14
|
+
i.value = !1, a.value = !0;
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
i.value = !1, typeof requestAnimationFrame == "function" ? requestAnimationFrame(() => {
|
|
18
|
+
i.value = !0, a.value = !0;
|
|
19
|
+
}) : (i.value = !0, a.value = !0);
|
|
20
|
+
}
|
|
21
|
+
return n == null ? o(u) : (o(() => {
|
|
22
|
+
h(n) && u();
|
|
23
|
+
}), p(() => h(n), (e, t) => {
|
|
24
|
+
e && !t && u();
|
|
25
|
+
})), {
|
|
26
|
+
playing: c(i),
|
|
27
|
+
drawn: c(a),
|
|
28
|
+
reduced: c(s),
|
|
29
|
+
draw: u
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
var _ = "0 0 64 64", v = {
|
|
33
|
+
check: "M16 33 L28 45 L48 19",
|
|
34
|
+
wordmark: "M14 30 L26 42 L50 16 M14 50 L50 50"
|
|
35
|
+
}, y = {
|
|
36
|
+
cx: 32,
|
|
37
|
+
cy: 32,
|
|
38
|
+
r: 24
|
|
39
|
+
}, b = [
|
|
40
|
+
"data-shape",
|
|
41
|
+
"data-play",
|
|
42
|
+
"data-drawn"
|
|
43
|
+
], x = ["viewBox"], S = [
|
|
44
|
+
"cx",
|
|
45
|
+
"cy",
|
|
46
|
+
"r"
|
|
47
|
+
], C = ["d"], w = {
|
|
48
|
+
key: 0,
|
|
49
|
+
class: "sr-only"
|
|
50
|
+
}, T = /* @__PURE__ */ i({
|
|
51
|
+
name: "CompletionSeal",
|
|
52
|
+
__name: "CompletionSeal",
|
|
53
|
+
props: {
|
|
54
|
+
shape: {},
|
|
55
|
+
label: {},
|
|
56
|
+
play: { type: Boolean },
|
|
57
|
+
class: {}
|
|
58
|
+
},
|
|
59
|
+
setup(i) {
|
|
60
|
+
let o = i, c = t(() => o.shape ?? "check"), l = t(() => c.value === "wordmark" ? v.wordmark : v.check), { playing: p, drawn: m } = g({ play: o.play === void 0 ? void 0 : d(o, "play") });
|
|
61
|
+
return (t, i) => (s(), r("div", {
|
|
62
|
+
class: a(["completion-seal", f(e)(o.class)]),
|
|
63
|
+
"data-shape": c.value,
|
|
64
|
+
"data-play": f(p) ? "" : void 0,
|
|
65
|
+
"data-drawn": f(m) ? "" : void 0,
|
|
66
|
+
role: "status",
|
|
67
|
+
"aria-live": "polite"
|
|
68
|
+
}, [(s(), r("svg", {
|
|
69
|
+
class: "completion-seal__svg",
|
|
70
|
+
viewBox: f(_),
|
|
71
|
+
"aria-hidden": "true",
|
|
72
|
+
focusable: "false"
|
|
73
|
+
}, [c.value === "ring" ? (s(), r("circle", {
|
|
74
|
+
key: 0,
|
|
75
|
+
class: "completion-seal__mark",
|
|
76
|
+
cx: f(y).cx,
|
|
77
|
+
cy: f(y).cy,
|
|
78
|
+
r: f(y).r,
|
|
79
|
+
pathLength: "100"
|
|
80
|
+
}, null, 8, S)) : (s(), r("path", {
|
|
81
|
+
key: 1,
|
|
82
|
+
class: "completion-seal__mark",
|
|
83
|
+
d: l.value,
|
|
84
|
+
pathLength: "100"
|
|
85
|
+
}, null, 8, C))], 8, x)), o.label ? (s(), r("span", w, u(o.label), 1)) : n("", !0)], 10, b));
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
//#endregion
|
|
89
|
+
export { T as CompletionSeal, g as useCompletionSeal };
|
|
@@ -52,11 +52,16 @@ type __VLS_Props = {
|
|
|
52
52
|
* - `"css"` — never arm WebGL; the `paletteToCssGradient` placeholder
|
|
53
53
|
* stays the permanent surface (the warm wash composites, it just
|
|
54
54
|
* does not animate).
|
|
55
|
-
* - `"auto"` (default) —
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* `"
|
|
59
|
-
*
|
|
55
|
+
* - `"auto"` (default) — resolves to `"webgl"` on every device EXCEPT a
|
|
56
|
+
* detected SOFTWARE renderer (SwiftShader / llvmpipe / MS Basic Render),
|
|
57
|
+
* which falls to `"css"` (the page-wedging-software-raster guard, the only
|
|
58
|
+
* surviving `"css"` signal). BC.W-VIZ-AURORA (T1) RETIRED the dead-static
|
|
59
|
+
* `hardwareConcurrency <= 4` / `saveData` / `reduced-motion` falls: a
|
|
60
|
+
* 2026-capable low-core / throttled tab no longer gets a frozen gradient
|
|
61
|
+
* (the "renders SLOW" defect root), and reduced-motion is handled SOLELY by
|
|
62
|
+
* the substrate's live `matchMedia` freeze (one static frame then park,
|
|
63
|
+
* re-arms on un-reduce). Resolved once at setup; SSR / missing-API safe
|
|
64
|
+
* (assumes capable → `"webgl"` when the probes are unavailable).
|
|
60
65
|
*/
|
|
61
66
|
renderMode?: AuroraRenderMode;
|
|
62
67
|
/**
|
|
@@ -60,6 +60,19 @@ export interface DeriveAuroraOptions {
|
|
|
60
60
|
* fold that makes the oil/oil-pastel mediums read as mixed paint. Default 0.
|
|
61
61
|
*/
|
|
62
62
|
temperatureShift?: number;
|
|
63
|
+
/**
|
|
64
|
+
* BC.W-VIZ-AURORA (A7) — the additive DERIVE-path hue-EXCLUSION axis (the
|
|
65
|
+
* speedtest-AX cross-repo fold). Named OKLCh hue bands (each `[startDeg, endDeg]`,
|
|
66
|
+
* wrap-around supported via `start > end`) that EVERY derived stop's hue must fall
|
|
67
|
+
* OUTSIDE. The mechanism that makes "teal-on-navy is GONE" enforceable in the DERIVE
|
|
68
|
+
* path, not just the static default — a consumer deriving a palette FROM any seed
|
|
69
|
+
* can never re-introduce a purged band (e.g. `avoidHues: [[170, 200]]` excludes the
|
|
70
|
+
* teal arc by construction). The exclusion RE-ROUTES the walked hue to the nearest
|
|
71
|
+
* band EDGE (preserving L/C — no chroma flatten); it is NOT a post-hoc desaturate.
|
|
72
|
+
* Additive + default-unset → byte-identical derive (the `WarpMode`-additive-widen
|
|
73
|
+
* precedent: `proof:aurora-atoms-roundtrip` stays GREEN by construction).
|
|
74
|
+
*/
|
|
75
|
+
avoidHues?: readonly (readonly [number, number])[];
|
|
63
76
|
}
|
|
64
77
|
/**
|
|
65
78
|
* Seed ONE color into a harmonious, gamut-safe N-stop aurora palette.
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import type { UniformLocations } from "./glSetup";
|
|
12
12
|
import { type CursorState } from "./cursorModel";
|
|
13
13
|
import type { AuroraConfig } from "../constants/presets";
|
|
14
|
+
import type { UsePointerVelocityField } from "../../../../composables/motion/usePointerVelocityField";
|
|
14
15
|
export interface FrameLoopDeps {
|
|
15
16
|
gl: WebGL2RenderingContext;
|
|
16
17
|
prog: WebGLProgram;
|
|
@@ -20,6 +21,14 @@ export interface FrameLoopDeps {
|
|
|
20
21
|
getConfig: () => AuroraConfig;
|
|
21
22
|
/** Reduced-motion intent — parks the loop after one static frame. */
|
|
22
23
|
getReducedMotion: () => boolean;
|
|
24
|
+
/**
|
|
25
|
+
* BC.W-VIZ-AURORA (T5) — the shared viz-pointer-physics field (BB.B4). FED
|
|
26
|
+
* `tick(deltaMs)` from THIS frame callback (the one-loop discipline — the field owns
|
|
27
|
+
* NO own rAF); the renderer reads `acceleration` for the iOS-27 gel snap-back. The
|
|
28
|
+
* existing cursorModel velocity/burst stays the byte-faithful baseline; the accel
|
|
29
|
+
* term is the additive fold.
|
|
30
|
+
*/
|
|
31
|
+
pointerField: UsePointerVelocityField;
|
|
23
32
|
}
|
|
24
33
|
export interface FrameLoop {
|
|
25
34
|
/** Advance the cursor easing THEN draw — the per-frame step. */
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* shader-uniform boundary: a NEW uniform name must be added here, and the cache is
|
|
10
10
|
* keyed off it, so a fresh uniform always gets a location slot.
|
|
11
11
|
*/
|
|
12
|
-
export declare const UNIFORM_NAMES: readonly ["uTime", "uPalette", "uStopCount", "uNucleiCount", "uNucleiPos", "uNucleiRadius", "uNucleiPaletteBias", "uNucleiValueBias", "uNucleiDriftRadius", "uNucleiDriftPhase", "uNucleiElong", "uNucleiAngle", "uSoftmaxBeta", "uValueVariance", "uWarpAmount", "uWarpScale", "uWarpDrift", "uWarpMode", "uNoiseOctaves", "uMedium", "uHuePath", "uFlowPattern", "uFlowFocal", "uFlowAngle", "uFlowCurl", "uCursor", "uCursorStrength", "uCursorRadius", "uCursorVelocity", "uCursorBurst", "uStrokeAmount", "uStrokeScale", "uStrokeAnisotropy", "uStrokeLayers", "uStrokeMode", "uStrokeOrient", "uLightDir", "uLightColor", "uWetEdge", "uGranulation", "uImpasto", "uBrokenColor", "uCanvasGrain", "uNucleiDrift", "uPaletteDrift", "uBreathDepth", "uBreathPeriod", "uSaturation", "uPaperGrain", "uAlpha"];
|
|
12
|
+
export declare const UNIFORM_NAMES: readonly ["uTime", "uPalette", "uStopCount", "uNucleiCount", "uNucleiPos", "uNucleiRadius", "uNucleiPaletteBias", "uNucleiValueBias", "uNucleiDriftRadius", "uNucleiDriftPhase", "uNucleiElong", "uNucleiAngle", "uSoftmaxBeta", "uValueVariance", "uWarpAmount", "uWarpScale", "uWarpDrift", "uWarpMode", "uNoiseOctaves", "uMedium", "uHuePath", "uFlowPattern", "uFlowFocal", "uFlowAngle", "uFlowCurl", "uCursor", "uCursorStrength", "uCursorRadius", "uCursorVelocity", "uCursorBurst", "uStrokeAmount", "uStrokeScale", "uStrokeAnisotropy", "uStrokeLayers", "uStrokeMode", "uStrokeOrient", "uLightDir", "uLightColor", "uWetEdge", "uGranulation", "uImpasto", "uBrokenColor", "uCanvasGrain", "uNucleiDrift", "uPaletteDrift", "uBreathDepth", "uBreathPeriod", "uSaturation", "uPaperGrain", "uAlpha", "uVividness"];
|
|
13
13
|
export type UniformName = (typeof UNIFORM_NAMES)[number];
|
|
14
14
|
export type UniformLocations = Record<UniformName, WebGLUniformLocation | null>;
|
|
15
15
|
export interface GlProgram {
|
|
@@ -102,6 +102,18 @@ export interface AuroraRuntimeOptions {
|
|
|
102
102
|
export interface AuroraRuntime extends Omit<AuroraInstance, "pause" | "resume"> {
|
|
103
103
|
pause(reason?: SuspendReason): void;
|
|
104
104
|
resume(reason?: SuspendReason): void;
|
|
105
|
+
/**
|
|
106
|
+
* BC.W-VIZ-AURORA (T2) — the device-resolved arm PROMISE. On the WebGPU
|
|
107
|
+
* backend `renderAt`/`arm` are NO-OPS until `armAsync()` resolves the async
|
|
108
|
+
* adapter→device→configure→setup prelude (`useGpuSubstrate.armAsync` tries
|
|
109
|
+
* WebGPU then falls to the WebGL2 net). A CAPTURE consumer (`renderAt(t)` +
|
|
110
|
+
* `toDataURL`) MUST `await armAsync()` before the first `renderAt` — the
|
|
111
|
+
* synchronous `arm()` cannot guarantee the WebGPU device is present, so a
|
|
112
|
+
* synchronous `renderAt` right after `createAurora(…,{mode:"capture"})` paints
|
|
113
|
+
* a BLANK frame (the dead-preview defect). Resolves once the backend is armed;
|
|
114
|
+
* the WebGL2 fallback resolves immediately. Idempotent + safe post-dispose.
|
|
115
|
+
*/
|
|
116
|
+
armAsync(): Promise<void>;
|
|
105
117
|
/**
|
|
106
118
|
* AW.W8.1 — feed a pointer delta into the velocity-reactive flow (a fast flick →
|
|
107
119
|
* a transient swirl-burst). The PRM early-out lives here: the injection is
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* scalars0 : vec4<f32> off 0 (uTime, uSoftmaxBeta, uValueVariance, uWarpAmount)
|
|
14
14
|
* scalars1 : vec4<f32> off 16 (uWarpScale, uWarpDrift, uSaturation, uPaperGrain)
|
|
15
15
|
* scalars2 : vec4<f32> off 32 (uAlpha, uNucleiDrift, uPaletteDrift, uBreathDepth)
|
|
16
|
-
* scalars3 : vec4<f32> off 48 (uBreathPeriod, uCursorStrength, uCursorRadius,
|
|
16
|
+
* scalars3 : vec4<f32> off 48 (uBreathPeriod, uCursorStrength, uCursorRadius, uVividness)
|
|
17
17
|
* cursor : vec4<f32> off 64 (uCursor.x, uCursor.y, _, _)
|
|
18
18
|
* ints0 : vec4<i32> off 80 (uStopCount, uNucleiCount, uWarpMode, uNoiseOctaves)
|
|
19
19
|
* ints1 : vec4<i32> off 96 (uMedium, uHuePath, _, _)
|
|
@@ -21,7 +21,16 @@
|
|
|
21
21
|
* nuc0 : array<vec4<f32>, 6> off 240 (pos.x, pos.y, radius, paletteBias)
|
|
22
22
|
* nuc1 : array<vec4<f32>, 6> off 336 (valueBias, driftRadius, driftPhase, elong)
|
|
23
23
|
* nuc2 : array<vec4<f32>, 6> off 432 (angle, _, _, _)
|
|
24
|
-
*
|
|
24
|
+
* scalars4 : vec4<f32> off 528 (uStrokeAmount, uStrokeScale, uStrokeAnisotropy, uCanvasGrain)
|
|
25
|
+
* scalars5 : vec4<f32> off 544 (uWetEdge, uGranulation, uBrokenColor, uKuwaharaQ)
|
|
26
|
+
* kuwahara : vec4<f32> off 560 (uKuwaharaRadius, uKuwaharaSectors, _, _)
|
|
27
|
+
* total : 576 bytes (16-aligned)
|
|
28
|
+
*
|
|
29
|
+
* BC.W-VIZ-AURORA (T4) — the painterly-medium scalar lanes (scalars4/scalars5/kuwahara)
|
|
30
|
+
* are APPENDED after the arrays, so EVERY pre-existing offset is byte-identical and the
|
|
31
|
+
* smooth-default parity capture is byte-equivalent (these lanes pack 0 on a smooth config).
|
|
32
|
+
* The WGSL `Uniforms` struct (`aurora.wgsl.ts`) carries the SAME three trailing lanes —
|
|
33
|
+
* the typed-struct lockstep: a one-sided add reds the parity-ΔE.
|
|
25
34
|
*
|
|
26
35
|
* Y-origin: config authoring is CSS-top-origin (0 = top); the bridge flips Y at the
|
|
27
36
|
* uniform boundary (`flipY`), exactly as the GLSL `uniformBridge` does.
|
|
@@ -29,7 +38,7 @@
|
|
|
29
38
|
import { type AuroraConfig } from "../constants/presets";
|
|
30
39
|
import type { CursorState } from "./cursorModel";
|
|
31
40
|
/** The total uniform-buffer byte size (16-aligned). */
|
|
32
|
-
export declare const AURORA_WGPU_UNIFORM_BYTES =
|
|
41
|
+
export declare const AURORA_WGPU_UNIFORM_BYTES = 576;
|
|
33
42
|
/**
|
|
34
43
|
* The packed scratch buffer + the dual ArrayBuffer views. A slider drag refills this
|
|
35
44
|
* in place (no per-frame allocation) — mirroring the GLSL bridge's pre-allocated
|
|
@@ -15,11 +15,19 @@
|
|
|
15
15
|
import type { WebGPUCanvasFrame } from "../../../../composables/glass/webgpu/useWebGPUCanvas";
|
|
16
16
|
import { type CursorState } from "./cursorModel";
|
|
17
17
|
import type { AuroraConfig } from "../constants/presets";
|
|
18
|
+
import type { UsePointerVelocityField } from "../../../../composables/motion/usePointerVelocityField";
|
|
18
19
|
export interface AuroraWGPUSetupDeps {
|
|
19
20
|
canvas: HTMLCanvasElement;
|
|
20
21
|
cursor: CursorState;
|
|
21
22
|
getConfig: () => AuroraConfig;
|
|
22
23
|
getReducedMotion: () => boolean;
|
|
24
|
+
/**
|
|
25
|
+
* BC.W-VIZ-AURORA (T5) — the shared viz-pointer-physics field (BB.B4). FED
|
|
26
|
+
* `tick(deltaMs)` from the WGPU frame callback (the SAME field instance the WebGL2
|
|
27
|
+
* loop feeds — one source, no own rAF); the renderer reads `acceleration` for the
|
|
28
|
+
* iOS-27 gel snap-back.
|
|
29
|
+
*/
|
|
30
|
+
pointerField: UsePointerVelocityField;
|
|
23
31
|
}
|
|
24
32
|
/**
|
|
25
33
|
* Build the aurora `setupWGPU(device, context, format)` callback. Closes over the
|
|
@@ -115,6 +115,16 @@ export interface AuroraConfig {
|
|
|
115
115
|
impasto: number;
|
|
116
116
|
brokenColor: number;
|
|
117
117
|
canvasGrain: number;
|
|
118
|
+
/**
|
|
119
|
+
* BC.W-VIZ-AURORA (T4) — the anisotropic-Kuwahara painterly-finish knobs (the
|
|
120
|
+
* `medium:"kuwahara"` register; the WGSL primary's keystone). Optional; omitted =
|
|
121
|
+
* the recipe defaults (radius 0.010 procedural-patch units, q 4.0 the SOFT
|
|
122
|
+
* variance-weight exponent). Sectors are fixed at 8 (the soft-blend overlap floor —
|
|
123
|
+
* not an authoring axis). These ride the appended WGSL `kuwahara`/`scalars5` struct
|
|
124
|
+
* lanes; a smooth/non-kuwahara config leaves them at the default (a no-op).
|
|
125
|
+
*/
|
|
126
|
+
kuwaharaRadius?: number;
|
|
127
|
+
kuwaharaQ?: number;
|
|
118
128
|
/**
|
|
119
129
|
* AW.W4.2 — the impasto relight direction (the movable directional source the
|
|
120
130
|
* accumulated paint-height field catches). Optional; omitted = upper-left
|
|
@@ -139,6 +149,20 @@ export interface AuroraConfig {
|
|
|
139
149
|
saturation: number;
|
|
140
150
|
paperGrain: number;
|
|
141
151
|
alpha: number;
|
|
152
|
+
/**
|
|
153
|
+
* BD.W-AUR-VIVIDNESS — the §3 chroma FLOOR (the warm-field vividness contract).
|
|
154
|
+
* Optional; omitted = `DEFAULT_VIVIDNESS` (1 — high, the library's vivid identity).
|
|
155
|
+
* A shader-resident OKLab chroma-floor lifts any pale zone toward `VIVID_TARGET`
|
|
156
|
+
* (mode-scaled in the shader) so the field never resolves toward gray BEHIND glass
|
|
157
|
+
* — the literal fix for the "missing colorful field → gray glass" defect. The lift
|
|
158
|
+
* is HUE-PRESERVING (scales chroma along the zone's existing OKLab direction); below
|
|
159
|
+
* `VIVID_EPS` the hue is precision noise, so the floor synthesizes along the WARM
|
|
160
|
+
* anchor (`VIVID_WARM_ANCHOR`) — NEVER teal/navy, the warm-floor guarantee. A
|
|
161
|
+
* deliberately-pale hero surface opts OUT with `vividness: 0` (the new lanes write 0,
|
|
162
|
+
* so a `vividness:0` config is byte-identical to the pre-floor render — the gated
|
|
163
|
+
* identity move). Range 0..1.
|
|
164
|
+
*/
|
|
165
|
+
vividness?: number;
|
|
142
166
|
/**
|
|
143
167
|
* AW.W6/W8 — the pointer/scroll interactivity opt-in (default OFF — the wispy-sky
|
|
144
168
|
* default stays static). W6 declares the SHAPE; W8 wires the cursor-as-light /
|
|
@@ -166,6 +190,14 @@ export interface AuroraInstance extends AuroraCursorApi {
|
|
|
166
190
|
* 24). A no-op once armed or once `dispose()` has run.
|
|
167
191
|
*/
|
|
168
192
|
arm(): void;
|
|
193
|
+
/**
|
|
194
|
+
* BC.W-VIZ-AURORA (T2) — the device-resolved arm PROMISE. On the WebGPU
|
|
195
|
+
* backend `renderAt`/`arm` are no-ops until this resolves the async
|
|
196
|
+
* adapter→device→configure→setup prelude. A CAPTURE consumer (thumbnail bake)
|
|
197
|
+
* MUST `await armAsync()` before the first `renderAt` or the frame is BLANK
|
|
198
|
+
* (the dead-preview defect). The WebGL2 fallback resolves immediately.
|
|
199
|
+
*/
|
|
200
|
+
armAsync(): Promise<void>;
|
|
169
201
|
update(cfg: AuroraConfig): void;
|
|
170
202
|
/** Render a single deterministic frame at time `t` (seconds). Used for thumbnail bakes. */
|
|
171
203
|
renderAt(timeSec: number): void;
|
|
@@ -176,6 +208,21 @@ export interface AuroraInstance extends AuroraCursorApi {
|
|
|
176
208
|
}
|
|
177
209
|
export declare const MAX_NUCLEI = 6;
|
|
178
210
|
export declare const MAX_STOPS = 8;
|
|
211
|
+
/**
|
|
212
|
+
* The default `vividness` for a bare `<Aurora>` — HIGH (the library's vivid identity).
|
|
213
|
+
* This INVERTS the pre-floor status quo: vivid is the default, pale is the explicit
|
|
214
|
+
* `vividness: 0` opt-out. The literal §3 fix — a warm glass plate over the default field
|
|
215
|
+
* now reads transmissive-not-gray because the field carries chroma.
|
|
216
|
+
*/
|
|
217
|
+
export declare const DEFAULT_VIVIDNESS = 1;
|
|
218
|
+
/**
|
|
219
|
+
* The per-fragment OKLab chroma the floor lifts a pale zone TOWARD at `vividness:1`
|
|
220
|
+
* (the shader scales this by a mode factor — a dim/dark field needs more chroma to read
|
|
221
|
+
* vivid through glass). Tuned so the lifted DEFAULT field clears the §3 transmissive
|
|
222
|
+
* floor (mean OKLab chroma ≥ 0.045) with headroom; a vivid zone above this is untouched.
|
|
223
|
+
* Mirrored as `VIVID_TARGET` in the GLSL + WGSL twins.
|
|
224
|
+
*/
|
|
225
|
+
export declare const VIVID_TARGET = 0.115;
|
|
179
226
|
/**
|
|
180
227
|
* A neutral starting point for consumers that build their own config from scratch.
|
|
181
228
|
* Not a themed preset — the demo's 11 authored presets override every field.
|
|
@@ -59,12 +59,22 @@ export interface ResolveRenderModeOptions {
|
|
|
59
59
|
* would arm WebGL. The single ESCAPE is `options.forceWebGLUnderSoftwareRaster`
|
|
60
60
|
* (default `false` — the guard is the safe default).
|
|
61
61
|
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
62
|
+
* BC.W-VIZ-AURORA (T1) — the DEAD-STATIC `"auto"` fall is RETIRED. The
|
|
63
|
+
* `lowConcurrency` (`hardwareConcurrency <= 4`) and `saveData` heuristics are
|
|
64
|
+
* GONE: they predate the offscreen-park + the `AV_AURORA_DPR_MAX` sub-2× cap +
|
|
65
|
+
* the demand-gate that make a full-viewport aurora cheap, and `<= 4` is
|
|
66
|
+
* false-positive-prone in 2026 (a capable base-M-series laptop / a throttled VM
|
|
67
|
+
* tab reports 4 logical cores → it got a FROZEN static gradient that reads as
|
|
68
|
+
* "the aurora is broken", USER-DEFECTS §E "renders SLOW"). So `"auto"` arms the
|
|
69
|
+
* GPU on every Chrome-113/Safari-26/Firefox-141 device.
|
|
70
|
+
*
|
|
71
|
+
* Reduced-motion is handled SOLELY by the substrate's live `matchMedia` freeze
|
|
72
|
+
* (`createCanvasLifecycle` paints ONE static frame then parks, and re-arms on
|
|
73
|
+
* un-reduce) — NOT a render-mode fall (the old `"css"` fall never armed WebGL,
|
|
74
|
+
* so an un-reduce mid-session could never wake it; the substrate freeze does).
|
|
75
|
+
* The ONLY `"css"` signal that remains is the genuine software-raster GUARD
|
|
76
|
+
* (the universal first leg above) — and even that is subsumed by
|
|
77
|
+
* `BC.W-WEBGPU-EVERYWHERE`'s try-WebGPU-then-rebuild-WebGL2 picker.
|
|
68
78
|
*
|
|
69
79
|
* THE CAPABLE PATH IS BYTE-UNTOUCHED: `isSoftwareWebGLRenderer()` returns `false`
|
|
70
80
|
* on a real GPU (or a null probe — never a false downgrade), so a forced
|
|
@@ -73,8 +83,6 @@ export interface ResolveRenderModeOptions {
|
|
|
73
83
|
* SSR / missing-API safe: if `navigator` / `window` / the probes are
|
|
74
84
|
* unavailable we ASSUME a capable device and resolve `"webgl"` (the warm wash
|
|
75
85
|
* still composites either way — the only question is whether it animates).
|
|
76
|
-
* `navigator.connection` is non-standard, so it is feature-probed via an
|
|
77
|
-
* optional-chained cast rather than a typed accessor.
|
|
78
86
|
*
|
|
79
87
|
* Called ONCE at component setup — the device tier is a mount-time decision,
|
|
80
88
|
* not a reactive one (a connection-type flip mid-session does not re-resolve;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const AURORA_MEDIUMS_WGSL = "\n// \u2500\u2500 Painterly luma + medium scalar accessors \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst W_LUMA: vec3<f32> = vec3<f32>(0.2126, 0.7152, 0.0722);\n\nfn mStrokeAmount() -> f32 { return u.scalars4.x; }\nfn mStrokeScale() -> f32 { return u.scalars4.y; }\nfn mStrokeAnisotropy() -> f32 { return u.scalars4.z; }\nfn mCanvasGrain() -> f32 { return u.scalars4.w; }\nfn mWetEdge() -> f32 { return u.scalars5.x; }\nfn mGranulation() -> f32 { return u.scalars5.y; }\nfn mBrokenColor() -> f32 { return u.scalars5.z; }\nfn mKuwaharaQ() -> f32 { return u.scalars5.w; }\nfn mKuwaharaRadius() -> f32 { return u.kuwahara.x; }\n\n// \u2500\u2500 Base color re-sample (the edge-mask operator the mediums Sobel/sector-sample) \u2500\u2500\n// The WGSL twin of mediums.glsl.ts sampleBase: warp -> nuclei field -> palette -> value.\nfn sampleBase(p: vec2<f32>, t: f32) -> vec3<f32> {\n let pw = domainWarp(p, t);\n let nf = nucleiField(pw, t);\n var c = samplePalette(nf.paletteId);\n c = c * (1.0 + u.scalars0.z * nf.valueMod);\n return c;\n}\n\n// \u2500\u2500 Broken color (hue + chroma jitter at constant OKLCh L) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfn brokenColorJitter(c: vec3<f32>, hueSeed: f32, valueSeed: f32, strength: f32) -> vec3<f32> {\n let amt = clamp(mBrokenColor() * strength, 0.0, 1.0);\n if (amt <= 0.001) { return c; }\n var lch = oklabToOklch(linOklab(c));\n lch.z = lch.z + (hueSeed - 0.5) * (32.0 * PI / 180.0) * amt;\n lch.y = max(lch.y * (1.0 + (valueSeed - 0.5) * 0.28 * amt), 0.0);\n return max(oklabToLinearSrgb(oklchToOklab(lch)), vec3<f32>(0.0));\n}\n\n// \u2500\u2500 Structure-tensor / edge-tangent-flow (AW.W4.1; the WGSL twin) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Returns vec3(tangent.x, tangent.y, A) \u2014 the minor-eigenvector edge-tangent + coherence.\nfn structureTensorField(p: vec2<f32>, t: f32, fallbackDir: vec2<f32>) -> vec3<f32> {\n let e = 0.0035;\n let l00 = dot(sampleBase(p + vec2<f32>(-e, -e), t), W_LUMA);\n let l10 = dot(sampleBase(p + vec2<f32>(0.0, -e), t), W_LUMA);\n let l20 = dot(sampleBase(p + vec2<f32>( e, -e), t), W_LUMA);\n let l01 = dot(sampleBase(p + vec2<f32>(-e, 0.0), t), W_LUMA);\n let l21 = dot(sampleBase(p + vec2<f32>( e, 0.0), t), W_LUMA);\n let l02 = dot(sampleBase(p + vec2<f32>(-e, e), t), W_LUMA);\n let l12 = dot(sampleBase(p + vec2<f32>(0.0, e), t), W_LUMA);\n let l22 = dot(sampleBase(p + vec2<f32>( e, e), t), W_LUMA);\n let Gx = (l20 + 2.0 * l21 + l22) - (l00 + 2.0 * l01 + l02);\n let Gy = (l02 + 2.0 * l12 + l22) - (l00 + 2.0 * l10 + l20);\n let Jxx = Gx * Gx;\n let Jyy = Gy * Gy;\n let Jxy = Gx * Gy;\n let tr = Jxx + Jyy;\n let disc = sqrt(max((Jxx - Jyy) * (Jxx - Jyy) + 4.0 * Jxy * Jxy, 0.0));\n let lambdaMaj = 0.5 * (tr + disc);\n let lambdaMin = 0.5 * (tr - disc);\n var tangent: vec2<f32>;\n if (disc < 1e-7) {\n tangent = fallbackDir;\n } else {\n let theta = 0.5 * atan2(2.0 * Jxy, Jxx - Jyy);\n tangent = vec2<f32>(-sin(theta), cos(theta));\n }\n var A = (lambdaMaj - lambdaMin) / (lambdaMaj + lambdaMin + 1e-6);\n A = clamp(A, 0.0, 1.0);\n if (dot(tangent, fallbackDir) < 0.0) { tangent = -tangent; }\n let blendW = pow(A, 0.28);\n let dir = normalize(mix(fallbackDir, tangent, blendW) + vec2<f32>(1e-6, 1e-6));\n return vec3<f32>(dir, A);\n}\n\n// \u2500\u2500 Flow field (the WGSL twin \u2014 the simple flow seed the medium fallback dirs use) \u2500\u2500\nfn flowField(p: vec2<f32>, t: f32) -> vec2<f32> {\n // Curl-noise-driven swirl (the medium-default dir; the full radial/swirl/diagonal\n // dispatch rides uniforms the WGSL struct does not carry \u2014 the procedural mediums\n // use this multi/curl seed as the fallback the structure tensor relaxes toward).\n let n = fbm(p * 2.0 + vec2<f32>(t * 0.02, t * 0.02));\n let a = n * 6.2831853;\n var dir = vec2<f32>(cos(a), sin(a));\n // Cursor swirl bias (matches the GLSL flow cursor term \u2014 the steady attraction).\n let cursorStrength = u.scalars3.y;\n let cursorRadius = u.scalars3.z;\n let cursor = u.cursor.xy;\n if (cursorStrength > 0.001) {\n let toCur = cursor - p;\n let d = length(toCur);\n let r = max(cursorRadius, 0.01);\n let w = exp(-(d * d) / (r * r * 0.5));\n let tangent = vec2<f32>(-toCur.y, toCur.x) / max(d, 1e-4);\n let a0 = atan2(dir.y, dir.x);\n let a1 = atan2(tangent.y, tangent.x);\n var da = a1 - a0;\n da = atan2(sin(da), cos(da));\n let aa = a0 + da * w * cursorStrength;\n dir = vec2<f32>(cos(aa), sin(aa));\n }\n return dir;\n}\n\n// \u2500\u2500 Watercolor \u2014 wet-edge cauliflowers + granulation + wash banding \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfn mediumWatercolor(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n var col = col0;\n let eps = 0.004;\n let cx1 = sampleBase(p + vec2<f32>(eps, 0.0), t);\n let cx2 = sampleBase(p - vec2<f32>(eps, 0.0), t);\n let cy1 = sampleBase(p + vec2<f32>(0.0, eps), t);\n let cy2 = sampleBase(p - vec2<f32>(0.0, eps), t);\n let gx = dot(cx1 - cx2, W_LUMA);\n let gy = dot(cy1 - cy2, W_LUMA);\n let edge = sqrt(gx * gx + gy * gy) / (2.0 * eps);\n let mask = smoothstep(0.0, 2.5, edge);\n col = col * mix(1.0, 0.78, mask * mWetEdge());\n\n let paper = 0.5 * vnoise(p * 160.0) + 0.5 * vnoise(p * 360.0);\n let pigLoad = 1.0 - dot(col, W_LUMA);\n col = col * (1.0 - mGranulation() * pigLoad * (paper - 0.5));\n\n let band = fbm(vec2<f32>(p.x * 1.5, p.y * 0.4));\n col = col * (1.0 + 0.04 * (band - 0.5));\n return col;\n}\n\n// \u2500\u2500 Pastel \u2014 anisotropic stroke noise along the flow + tooth grain \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfn mediumPastel(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n var col = col0;\n let flow = flowField(p, t);\n let perp = vec2<f32>(-flow.y, flow.x);\n let strokeScale = mStrokeScale();\n let along = dot(p, flow) * strokeScale;\n var across = dot(p, perp) * strokeScale;\n across = across + 0.03 * (vnoise(p * 260.0) - 0.5);\n\n let aniso = mix(1.0, 0.18, mStrokeAnisotropy());\n let stroke = fbm(vec2<f32>(along * aniso, across));\n col = col * mix(1.0, 0.82 + 0.32 * stroke, mStrokeAmount());\n\n let tooth = vnoise(p * 800.0);\n col = col * (1.0 - 0.08 * mStrokeAmount() * (tooth - 0.5));\n return col;\n}\n\n// \u2500\u2500 Crayon \u2014 DRY wax pigment on paper tooth (the tooth-multiply + scumble) \u2500\u2500\nfn mediumCrayon(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n let flow = structureTensorField(p, t, flowField(p, t)).xy;\n let ang = atan2(flow.y, flow.x);\n let ca = cos(-ang);\n let sa = sin(-ang);\n let pr = vec2<f32>(p.x * ca - p.y * sa, p.x * sa + p.y * ca);\n\n let aniso = mix(0.45, 0.95, mStrokeAnisotropy());\n let scale = max(mStrokeScale() * 1.6, 180.0);\n\n let t1 = vnoise(vec2<f32>(pr.x * scale * aniso, pr.y * scale));\n let t2 = vnoise(vec2<f32>(pr.x * scale * aniso * 0.4, pr.y * scale * 0.4) + vec2<f32>(11.0, 11.0));\n let t3 = vnoise(vec2<f32>(pr.x * scale * aniso * 2.1, pr.y * scale * 2.1) + vec2<f32>(23.0, 23.0));\n let tooth = 0.55 * t1 + 0.30 * t2 + 0.15 * t3;\n\n let pressure = clamp(mStrokeAmount(), 0.0, 1.0);\n let bite = mix(0.18, 0.46, pressure);\n var result = col0 * (1.0 - bite * (0.5 - tooth));\n\n let scumbleMask = smoothstep(0.42, 0.78, vnoise(vec2<f32>(pr.x * scale * 0.55, pr.y * scale * 0.22) + vec2<f32>(7.0, 7.0)));\n let scumbleCoverage = scumbleMask * pressure * 0.7;\n let paper = col0 * mix(0.80, 0.94, pressure);\n result = mix(paper, result, scumbleCoverage);\n\n let pigmentCell = floor(pr * max(scale * 0.18, 32.0));\n let pigmentMask = smoothstep(0.28, 0.82, vnoise(pr * scale * 0.21 + vec2<f32>(19.0, 19.0)));\n result = brokenColorJitter(\n result,\n hash21(pigmentCell + vec2<f32>(17.0, 17.0)),\n hash21(pigmentCell * 2.1 + vec2<f32>(31.0, 31.0)),\n 0.45 + 0.55 * pigmentMask\n );\n\n result = saturate3(result, 1.08);\n return result;\n}\n\n// \u2500\u2500 Kuwahara \u2014 the SOFT anisotropic generalized Kuwahara painterly finish \u2500\u2500\u2500\u2500\n// THE KEYSTONE (Kyprianidis 2010). Aurora is a PROCEDURAL field (no input texture) so the\n// operator runs over sampleBase directly: an elliptical kernel oriented along the structure\n// tensor (elongated along the edge-tangent, narrowed across by the anisotropy), 8 OVERLAPPING\n// sectors via SMOOTH gaussian-angular weights, blended by 1/(1+var^q) (the SOFT criterion \u2192\n// no 8-spoke pinwheel by construction). 4 rings \u00D7 8 angular taps = 32 procedural samples.\nfn mediumKuwahara(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n let stf = structureTensorField(p, t, flowField(p, t));\n let tangent = stf.xy;\n let A = stf.z;\n // The studio knob drives the patch radius; clamp into the procedural patch band.\n let radius = clamp(mKuwaharaRadius() + mStrokeScale() * 0.00018, 0.006, 0.024);\n let aniso = mix(1.0, 0.34, clamp(A, 0.0, 1.0));\n let ax = tangent;\n let ay = vec2<f32>(-tangent.y, tangent.x);\n\n // Per-sector weighted sums (8 sectors). WGSL has no runtime-indexed local arrays of\n // vectors as cleanly as GLSL, so unroll the sector accumulators explicitly.\n var mSum: array<vec3<f32>, 8>;\n var sSum: array<vec3<f32>, 8>;\n var wSum: array<f32, 8>;\n for (var i = 0; i < 8; i = i + 1) {\n mSum[i] = vec3<f32>(0.0);\n sSum[i] = vec3<f32>(0.0);\n wSum[i] = 0.0;\n }\n\n let RINGS = 4;\n let TAPS = 8;\n for (var r = 1; r <= RINGS; r = r + 1) {\n let rr = f32(r) / f32(RINGS);\n let radial = 1.0 - 0.6 * rr;\n for (var a = 0; a < TAPS; a = a + 1) {\n let ang = 6.2831853 * f32(a) / f32(TAPS);\n let dirE = ax * cos(ang) + ay * (sin(ang) * aniso);\n let off = dirE * (radius * rr);\n let c = sampleBase(p + off, t);\n for (var k = 0; k < 8; k = k + 1) {\n let sectorAng = 6.2831853 * f32(k) / 8.0;\n var d = ang - sectorAng;\n d = atan2(sin(d), cos(d));\n let sw = exp(-d * d * 2.2) * radial;\n mSum[k] = mSum[k] + c * sw;\n sSum[k] = sSum[k] + c * c * sw;\n wSum[k] = wSum[k] + sw;\n }\n }\n }\n\n let q = max(mKuwaharaQ(), 1.0);\n var accum = vec3<f32>(0.0);\n var accumW = 0.0;\n for (var k = 0; k < 8; k = k + 1) {\n let wk = max(wSum[k], 1e-4);\n let mean = mSum[k] / wk;\n let var3 = max(sSum[k] / wk - mean * mean, vec3<f32>(0.0));\n let variance = dot(var3, W_LUMA);\n let sectorW = 1.0 / (1.0 + pow(variance * 320.0, q));\n accum = accum + mean * sectorW;\n accumW = accumW + sectorW;\n }\n var result = accum / max(accumW, 1e-4);\n\n // Anchor in near-flat zones so the smoothing only bites at edges.\n let center = sampleBase(p, t);\n result = mix(center, result, clamp(0.35 + 0.65 * A, 0.0, 1.0));\n\n // Faint canvas tooth + pigment-saturation so the flattened patches read as oil paint.\n let tooth = vnoise(p * 300.0) - 0.5;\n result = result * (1.0 + tooth * 0.06 * mCanvasGrain());\n result = saturate3(result, 1.04);\n\n return mix(col0, result, clamp(mStrokeAmount(), 0.0, 1.0));\n}\n\n// \u2500\u2500 Medium dispatch (the WGSL twin of the GLSL main() if-ladder) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// uMedium: 0 smooth \u00B7 1 pastel \u00B7 2 watercolor \u00B7 3 oil \u00B7 4 crayon \u00B7 5 vangogh \u00B7\n// 6 oil-pastel \u00B7 7 kuwahara. The cheap peer mediums (pastel/watercolor/crayon) +\n// kuwahara port their own bodies; the oil/vangogh/oil-pastel STROKE cascade renders\n// the anisotropic-Kuwahara PAINTERLY finish here (a real oil-paint read, never the\n// smooth core \u2014 the \"NO FALLBACKS on Safari\" mandate; the full per-dab Starry-Night\n// stroke WGSL is the booked W-AURORA-WGPU-MEDIUMS-STROKES tail).\nfn applyMedium(col: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n let medium = u.ints1.x;\n if (medium == 1) { return mediumPastel(col, p, t); }\n if (medium == 2) { return mediumWatercolor(col, p, t); }\n if (medium == 4) { return mediumCrayon(col, p, t); }\n // oil(3) / vangogh(5) / oil-pastel(6) / kuwahara(7) all render the painterly\n // anisotropic-Kuwahara finish on the WGSL primary (the WebGL2 fallback carries the\n // full per-dab stroke cascade for oil/vangogh/oil-pastel).\n if (medium == 3 || medium == 5 || medium == 6 || medium == 7) {\n return mediumKuwahara(col, p, t);\n }\n return col;\n}\n";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AURORA_WGSL = "\nconst MAX_NUCLEI: i32 = 6;\nconst MAX_STOPS: i32 = 8;\nconst PI: f32 = 3.141592653589793;\n\n// \u2500\u2500 Uniforms (the typed-struct source-of-truth \u2014 see aurora.wgsl.uniforms.ts) \u2500\u2500\n// Scalars are packed into vec4 lanes to keep the std140/WGSL 16-byte struct alignment\n// trivial. nuc0[i] = (pos.x, pos.y, radius, paletteBias); nuc1[i] = (valueBias,\n// driftRadius, driftPhase, elong); nuc2[i] = (angle, _, _, _). palette[i].rgb is the\n// CPU-baked linear-sRGB stop.\nstruct Uniforms {\n // scalars0: (uTime, uSoftmaxBeta, uValueVariance, uWarpAmount)\n scalars0: vec4<f32>,\n // scalars1: (uWarpScale, uWarpDrift, uSaturation, uPaperGrain)\n scalars1: vec4<f32>,\n // scalars2: (uAlpha, uNucleiDrift, uPaletteDrift, uBreathDepth)\n scalars2: vec4<f32>,\n // scalars3: (uBreathPeriod, uCursorStrength, uCursorRadius, _pad)\n scalars3: vec4<f32>,\n // cursor: (uCursor.x, uCursor.y, _pad, _pad)\n cursor: vec4<f32>,\n // ints: (uStopCount, uNucleiCount, uWarpMode, uNoiseOctaves)\n ints0: vec4<i32>,\n // ints1: (uMedium, uHuePath, _, _)\n ints1: vec4<i32>,\n palette: array<vec4<f32>, 8>,\n nuc0: array<vec4<f32>, 6>,\n nuc1: array<vec4<f32>, 6>,\n nuc2: array<vec4<f32>, 6>,\n};\n\n@group(0) @binding(0) var<uniform> u: Uniforms;\n\n// \u2500\u2500 Authoring-scale \u2192 rad/sec lifts (byte-identical to aurora.frag.ts) \u2500\u2500\nconst K_NUCLEI: f32 = 14.0;\nconst K_PAL: f32 = 24.0;\nconst K_WARP: f32 = 5.0;\n\n// \u2500\u2500 Noise (aurora-local hash21/vnoise/fbm \u2014 legitimately divergent per AV.W2 \u00A73a) \u2500\u2500\nfn hash21(p0: vec2<f32>) -> f32 {\n var p = fract(p0 * vec2<f32>(123.34, 456.21));\n p = p + dot(p, p + 45.32);\n return fract(p.x * p.y);\n}\n\nfn hash22(p0: vec2<f32>) -> vec2<f32> {\n let p = vec2<f32>(dot(p0, vec2<f32>(127.1, 311.7)),\n dot(p0, vec2<f32>(269.5, 183.3)));\n return fract(sin(p) * 43758.5453);\n}\n\nfn vnoise(p: vec2<f32>) -> f32 {\n let i = floor(p);\n let f = fract(p);\n let uu = f * f * (3.0 - 2.0 * f);\n let a = hash21(i);\n let b = hash21(i + vec2<f32>(1.0, 0.0));\n let c = hash21(i + vec2<f32>(0.0, 1.0));\n let d = hash21(i + vec2<f32>(1.0, 1.0));\n return mix(mix(a, b, uu.x), mix(c, d, uu.x), uu.y);\n}\n\nconst FBM_ROT: mat2x2<f32> = mat2x2<f32>(0.8, 0.6, -0.6, 0.8);\n\nfn fbm(p0: vec2<f32>) -> f32 {\n var v = 0.0;\n var a = 0.5;\n var p = p0;\n let octaves = u.ints0.w;\n for (var i = 0; i < 5; i = i + 1) {\n if (i >= octaves) { break; }\n v = v + a * vnoise(p);\n p = FBM_ROT * p * 2.02;\n a = a * 0.5;\n }\n return v;\n}\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// value.js interpolateHue in the NORMALIZED-TURNS domain. methods: 0 shorter,\n// 1 longer, 2 increasing, 3 decreasing.\nfn interpolateHueTurns(h0: f32, h1: f32, t: f32, method: i32) -> f32 {\n let TAU = 2.0 * PI;\n var a = h0 / TAU;\n var b = h1 / TAU;\n let i = b - a;\n if (method == 0) { // shorter\n if (i > 0.5) { a = a + 1.0; } else if (i < -0.5) { b = b + 1.0; }\n } else if (method == 1) { // longer\n if (i > 0.0 && i < 0.5) { a = a + 1.0; } else if (i > -0.5 && i <= 0.0) { b = b + 1.0; }\n } else if (method == 2) { // increasing\n if (i < 0.0) { b = b + 1.0; }\n } else { // decreasing\n if (i > 0.0) { a = a + 1.0; }\n }\n var r = a + t * (b - a);\n r = fract(r); // fract is non-negative in WGSL\n return r * TAU; // back to radians\n}\n\n// Linear-sRGB endpoint pair \u2192 OKLab-rectangular interpolation \u2192 linear sRGB.\nfn mixPaletteOklab(linA: vec3<f32>, linB: vec3<f32>, t: f32) -> vec3<f32> {\n let labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linA);\n let labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linB);\n let lab = mix(labA, labB, t);\n return oklabToLinearSrgb(lab);\n}\n\n// Linear-sRGB endpoint pair \u2192 OKLCh hue-arc interpolation \u2192 linear sRGB.\nfn mixPaletteOklchArc(linA: vec3<f32>, linB: vec3<f32>, t: f32, method: i32) -> vec3<f32> {\n let labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linA);\n let labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linB);\n let lchA = oklabToOklch(labA);\n let lchB = oklabToOklch(labB);\n let L = mix(lchA.x, lchB.x, t);\n let C = mix(lchA.y, lchB.y, t);\n let H = interpolateHueTurns(lchA.z, lchB.z, t, method);\n return oklabToLinearSrgb(oklchToOklab(vec3<f32>(L, C, H)));\n}\n\n// The ramp dispatcher (the samplePalette splices it). tRaw is the raw inter-stop\n// parameter [0,1]; the smoothstep ease + the huePath branch live here so the ramp is\n// one source. increasing(2)/decreasing(3) take the OKLCh hue-arc; every other method\n// takes the OKLab-rectangular straight line.\nfn samplePaletteRamp(a: vec3<f32>, b: vec3<f32>, tRaw: f32, huePath: i32) -> vec3<f32> {\n let t = smoothstep(0.0, 1.0, tRaw);\n if (huePath == 2 || huePath == 3) {\n return mixPaletteOklchArc(a, b, t, huePath);\n }\n return mixPaletteOklab(a, b, t);\n}\n\n// Interleaved Gradient Noise (Jimenez) \u2014 display-space 1-LSB dither.\nfn ign(p: vec2<f32>) -> f32 {\n return fract(52.9829189 * fract(dot(p, vec2<f32>(0.06711056, 0.00583715))));\n}\n\n// Cellular / Worley f1.\nfn cellular(p: vec2<f32>) -> f32 {\n let i = floor(p);\n let f = fract(p);\n var m = 1e9;\n for (var y = -1; y <= 1; y = y + 1) {\n for (var x = -1; x <= 1; x = x + 1) {\n let g = vec2<f32>(f32(x), f32(y));\n let o = hash22(i + g);\n let r = g + o - f;\n m = min(m, dot(r, r));\n }\n }\n return sqrt(m);\n}\n\n// \u2500\u2500 Warp (Quilez double warp + the three warp modes + the cursor swirl) \u2500\u2500\nfn domainWarp(p: vec2<f32>, t: f32) -> vec2<f32> {\n let warpScale = u.scalars1.x;\n let warpDrift = u.scalars1.y;\n let warpAmount = u.scalars0.w;\n let warpMode = u.ints0.z;\n let cursorStrength = u.scalars3.y;\n let cursorRadius = u.scalars3.z;\n let cursor = u.cursor.xy;\n\n let q = vec2<f32>(fbm(p * warpScale + vec2<f32>(0.0, 0.0) + t * warpDrift * K_WARP),\n fbm(p * warpScale + vec2<f32>(5.2, 1.3) + t * warpDrift * K_WARP));\n let r = vec2<f32>(fbm(p * warpScale + 4.0 * q + vec2<f32>(1.7, 9.2)),\n fbm(p * warpScale + 4.0 * q + vec2<f32>(8.3, 2.8)));\n\n var warp = r;\n if (warpMode == 1) {\n // cellular \u2014 chunky territories\n let c1 = cellular(p * warpScale * 1.5 + vec2<f32>(t * warpDrift * K_WARP * 2.0, 0.0));\n let c2 = cellular(p * warpScale * 1.5 + vec2<f32>(11.0, 7.0 + t * warpDrift * K_WARP * 2.0));\n warp = vec2<f32>(c1, c2);\n } else if (warpMode == 2) {\n // hybrid \u2014 fbm + cellular averaged\n let c1 = cellular(p * warpScale * 1.2);\n let c2 = cellular(p * warpScale * 1.2 + vec2<f32>(11.0, 7.0));\n warp = mix(r, vec2<f32>(c1, c2), 0.5);\n }\n var warped = p + warpAmount * warp;\n\n // Cursor swirl \u2014 rotate p around the cursor with radial falloff.\n if (cursorStrength > 0.001) {\n let toP = p - cursor;\n let d = length(toP);\n let rr = max(cursorRadius, 0.01);\n let w = exp(-(d * d) / (rr * rr * 0.45));\n let ang = w * cursorStrength * 2.1;\n let ca = cos(ang);\n let sa = sin(ang);\n var rotated = vec2<f32>(ca * toP.x - sa * toP.y, sa * toP.x + ca * toP.y) + cursor;\n let pinch = w * cursorStrength * 0.08;\n rotated = mix(rotated, cursor, pinch);\n warped = mix(warped, rotated + warpAmount * warp * 0.7, w * cursorStrength);\n }\n return warped;\n}\n\n// \u2500\u2500 Palette LUT \u2500\u2500\nfn samplePalette(id0: f32) -> vec3<f32> {\n let id = clamp(id0, 0.0, 1.0);\n let stopCount = u.ints0.x;\n let scaled = id * f32(stopCount - 1);\n let i0 = i32(floor(scaled));\n let i1 = min(i0 + 1, stopCount - 1);\n let t = fract(scaled);\n return samplePaletteRamp(u.palette[i0].rgb, u.palette[i1].rgb, t, u.ints1.y);\n}\n\n// \u2500\u2500 Nuclei field (anisotropic Gaussian softmax + drift + palette drift) \u2500\u2500\nstruct NucleiResult { paletteId: f32, valueMod: f32 };\n\nfn nucleiField(p: vec2<f32>, t: f32) -> NucleiResult {\n let nucleiCount = u.ints0.y;\n let nucleiDrift = u.scalars2.y;\n let paletteDrift = u.scalars2.z;\n let softmaxBeta = u.scalars0.y;\n\n var accumBias = 0.0;\n var accumValue = 0.0;\n var accumW = 0.0;\n for (var i = 0; i < MAX_NUCLEI; i = i + 1) {\n if (i >= nucleiCount) { break; }\n let n0 = u.nuc0[i]; // pos.x, pos.y, radius, paletteBias\n let n1 = u.nuc1[i]; // valueBias, driftRadius, driftPhase, elong\n let angle = u.nuc2[i].x;\n let driftRadius = n1.y;\n let driftPhase = n1.z;\n let posI = n0.xy + driftRadius * vec2<f32>(\n cos(t * nucleiDrift * K_NUCLEI + driftPhase),\n sin(t * nucleiDrift * K_NUCLEI + driftPhase * 1.13)\n );\n let diff = p - posI;\n let ca = cos(angle);\n let sa = sin(angle);\n let local = vec2<f32>(ca * diff.x + sa * diff.y, -sa * diff.x + ca * diff.y);\n let along = local.x / max(n1.w, 0.01);\n let across = local.y;\n let d2 = along * along + across * across;\n let r = max(n0.z, 0.01);\n let w = exp(-softmaxBeta * d2 / (r * r));\n accumBias = accumBias + w * n0.w;\n accumValue = accumValue + w * n1.x;\n accumW = accumW + w;\n }\n var paletteId = accumBias / max(accumW, 1e-4);\n let valueMod = accumValue / max(accumW, 1e-4);\n\n let palAmp = clamp(paletteDrift * 6.0, 0.0, 0.06);\n paletteId = paletteId + palAmp * sin(t * paletteDrift * K_PAL);\n paletteId = clamp(paletteId, 0.0, 1.0);\n return NucleiResult(paletteId, valueMod);\n}\n\n// \u2500\u2500 Color utils (OKLCh saturation) \u2500\u2500\nfn linOklab(lin: vec3<f32>) -> vec3<f32> {\n let lms = LINEAR_SRGB_TO_LMS * lin;\n return LMS_TO_OKLAB * cbrt3(lms);\n}\n\nfn saturate3(c: vec3<f32>, amt: f32) -> vec3<f32> {\n var lch = oklabToOklch(linOklab(c));\n lch.y = max(lch.y * amt, 0.0);\n return max(oklabToLinearSrgb(oklchToOklab(lch)), vec3<f32>(0.0));\n}\n\n// \u2500\u2500 PBR-Neutral tonemap (named aces() in the GLSL \u2014 the tonemap slot) \u2500\u2500\nfn aces(color0: vec3<f32>) -> vec3<f32> {\n let startCompression = 0.8 - 0.04;\n let desaturation = 0.15;\n var color = color0;\n let x = min(color.r, min(color.g, color.b));\n var offset = 0.04;\n if (x < 0.08) { offset = x - 6.25 * x * x; }\n color = color - offset;\n let peak = max(color.r, max(color.g, color.b));\n if (peak < startCompression) { return clamp(color, vec3<f32>(0.0), vec3<f32>(1.0)); }\n let d = 1.0 - startCompression;\n let newPeak = 1.0 - d * d / (peak + d - startCompression);\n color = color * (newPeak / peak);\n let g = 1.0 - 1.0 / (desaturation * (peak - newPeak) + 1.0);\n return clamp(mix(color, newPeak * vec3<f32>(1.0), g), vec3<f32>(0.0), vec3<f32>(1.0));\n}\n\n// \u2500\u2500 Full-screen triangle vertex stage (the pilot idiom \u2014 no vertex buffer) \u2500\u2500\nstruct VSOut {\n @builtin(position) pos: vec4<f32>,\n @location(0) uv: vec2<f32>,\n};\n\n@vertex\nfn vs_main(@builtin(vertex_index) vi: u32) -> VSOut {\n // NDC corners of the covering triangle (-1,-1), (3,-1), (-1,3).\n var p = vec2<f32>(-1.0, -1.0);\n if (vi == 1u) { p = vec2<f32>(3.0, -1.0); }\n else if (vi == 2u) { p = vec2<f32>(-1.0, 3.0); }\n var out: VSOut;\n out.pos = vec4<f32>(p, 0.0, 1.0);\n // vUv = aPos * 0.5 + 0.5 (the aurora.vert convention).\n out.uv = p * 0.5 + 0.5;\n return out;\n}\n\n// \u2500\u2500 Fragment stage (the main() transcription) \u2500\u2500\n@fragment\nfn fs_main(in: VSOut) -> @location(0) vec4<f32> {\n let t = u.scalars0.x;\n let valueVariance = u.scalars0.z;\n let breathDepth = u.scalars2.w;\n let breathPeriod = u.scalars3.x;\n let saturation = u.scalars1.z;\n let paperGrain = u.scalars1.w;\n let alpha = u.scalars2.x;\n\n let uv = in.uv;\n let pN = uv;\n\n let p_warp = domainWarp(pN, t);\n\n let nf = nucleiField(p_warp, t);\n var col = samplePalette(nf.paletteId);\n col = col * (1.0 + valueVariance * nf.valueMod);\n\n // Breath \u2014 slow global luminance wobble.\n let breath = sin(t * 6.2831 / max(breathPeriod, 1.0));\n col = col * (1.0 + breathDepth * breath * 0.5);\n\n // The painterly mediums (uMedium 1-6) are the WebGL2 fallback's register; the WGSL\n // primary renders the smooth core for the default parity capture (the booked\n // W-AURORA-WGPU-MEDIUMS successor ports the painterly bodies).\n\n // Saturation trim.\n col = saturate3(col, saturation);\n\n // Tonemap + film grain.\n col = aces(col);\n // gl_FragCoord.xy \u2192 the device-pixel position (the WGSL @builtin(position)).\n let fragCoord = in.pos.xy;\n let grain = hash21(fragCoord + t * 17.0);\n col = col + (grain - 0.5) * paperGrain;\n\n col = clamp(col * 0.985 + 0.008, vec3<f32>(0.0), vec3<f32>(1.0));\n\n // MANDATORY OETF \u2014 closes the seam (the whole pipeline above runs in LINEAR).\n col = linearToSrgb(col);\n\n // 1-LSB triangular IGN dither in DISPLAY space, AFTER the OETF.\n col = col + (1.0 / 255.0) * (ign(fragCoord) - 0.5);\n\n // Premultiply on DISPLAY-space color (matches the WebGL2 path: OETF, then premul).\n return vec4<f32>(col * alpha, alpha);\n}\n";
|
|
1
|
+
export declare const AURORA_WGSL = "\nconst MAX_NUCLEI: i32 = 6;\nconst MAX_STOPS: i32 = 8;\nconst PI: f32 = 3.141592653589793;\n\n// \u2500\u2500 Uniforms (the typed-struct source-of-truth \u2014 see aurora.wgsl.uniforms.ts) \u2500\u2500\n// Scalars are packed into vec4 lanes to keep the std140/WGSL 16-byte struct alignment\n// trivial. nuc0[i] = (pos.x, pos.y, radius, paletteBias); nuc1[i] = (valueBias,\n// driftRadius, driftPhase, elong); nuc2[i] = (angle, _, _, _). palette[i].rgb is the\n// CPU-baked linear-sRGB stop.\nstruct Uniforms {\n // scalars0: (uTime, uSoftmaxBeta, uValueVariance, uWarpAmount)\n scalars0: vec4<f32>,\n // scalars1: (uWarpScale, uWarpDrift, uSaturation, uPaperGrain)\n scalars1: vec4<f32>,\n // scalars2: (uAlpha, uNucleiDrift, uPaletteDrift, uBreathDepth)\n scalars2: vec4<f32>,\n // scalars3: (uBreathPeriod, uCursorStrength, uCursorRadius, uVividness)\n // BD.W-AUR-VIVIDNESS \u2014 the .w pad lane now carries the \u00A73 chroma-floor strength.\n scalars3: vec4<f32>,\n // cursor: (uCursor.x, uCursor.y, _pad, _pad)\n cursor: vec4<f32>,\n // ints: (uStopCount, uNucleiCount, uWarpMode, uNoiseOctaves)\n ints0: vec4<i32>,\n // ints1: (uMedium, uHuePath, _, _)\n ints1: vec4<i32>,\n palette: array<vec4<f32>, 8>,\n nuc0: array<vec4<f32>, 6>,\n nuc1: array<vec4<f32>, 6>,\n nuc2: array<vec4<f32>, 6>,\n // BC.W-VIZ-AURORA (T4) \u2014 the painterly-medium scalar lanes. APPENDED after the\n // arrays so EVERY existing offset (and the smooth-default parity capture) is\n // byte-identical (these lanes are written 0 on a smooth config). scalars4:\n // (uStrokeAmount, uStrokeScale, uStrokeAnisotropy, uCanvasGrain). scalars5:\n // (uWetEdge, uGranulation, uBrokenColor, uKuwaharaQ). kuwahara: (uKuwaharaRadius,\n // uKuwaharaSectors, _, _) \u2014 the Kuwahara radius/sectors/q in lockstep with\n // packAuroraWGPUUniforms (the typed-struct discipline).\n scalars4: vec4<f32>,\n scalars5: vec4<f32>,\n kuwahara: vec4<f32>,\n};\n\n@group(0) @binding(0) var<uniform> u: Uniforms;\n\n// \u2500\u2500 Authoring-scale \u2192 rad/sec lifts (byte-identical to aurora.frag.ts) \u2500\u2500\nconst K_NUCLEI: f32 = 14.0;\nconst K_PAL: f32 = 24.0;\nconst K_WARP: f32 = 5.0;\n\n// \u2500\u2500 Noise (aurora-local hash21/vnoise/fbm \u2014 legitimately divergent per AV.W2 \u00A73a) \u2500\u2500\nfn hash21(p0: vec2<f32>) -> f32 {\n var p = fract(p0 * vec2<f32>(123.34, 456.21));\n p = p + dot(p, p + 45.32);\n return fract(p.x * p.y);\n}\n\nfn hash22(p0: vec2<f32>) -> vec2<f32> {\n let p = vec2<f32>(dot(p0, vec2<f32>(127.1, 311.7)),\n dot(p0, vec2<f32>(269.5, 183.3)));\n return fract(sin(p) * 43758.5453);\n}\n\nfn vnoise(p: vec2<f32>) -> f32 {\n let i = floor(p);\n let f = fract(p);\n let uu = f * f * (3.0 - 2.0 * f);\n let a = hash21(i);\n let b = hash21(i + vec2<f32>(1.0, 0.0));\n let c = hash21(i + vec2<f32>(0.0, 1.0));\n let d = hash21(i + vec2<f32>(1.0, 1.0));\n return mix(mix(a, b, uu.x), mix(c, d, uu.x), uu.y);\n}\n\nconst FBM_ROT: mat2x2<f32> = mat2x2<f32>(0.8, 0.6, -0.6, 0.8);\n\nfn fbm(p0: vec2<f32>) -> f32 {\n var v = 0.0;\n var a = 0.5;\n var p = p0;\n let octaves = u.ints0.w;\n for (var i = 0; i < 5; i = i + 1) {\n if (i >= octaves) { break; }\n v = v + a * vnoise(p);\n p = FBM_ROT * p * 2.02;\n a = a * 0.5;\n }\n return v;\n}\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// value.js interpolateHue in the NORMALIZED-TURNS domain. methods: 0 shorter,\n// 1 longer, 2 increasing, 3 decreasing.\nfn interpolateHueTurns(h0: f32, h1: f32, t: f32, method: i32) -> f32 {\n let TAU = 2.0 * PI;\n var a = h0 / TAU;\n var b = h1 / TAU;\n let i = b - a;\n if (method == 0) { // shorter\n if (i > 0.5) { a = a + 1.0; } else if (i < -0.5) { b = b + 1.0; }\n } else if (method == 1) { // longer\n if (i > 0.0 && i < 0.5) { a = a + 1.0; } else if (i > -0.5 && i <= 0.0) { b = b + 1.0; }\n } else if (method == 2) { // increasing\n if (i < 0.0) { b = b + 1.0; }\n } else { // decreasing\n if (i > 0.0) { a = a + 1.0; }\n }\n var r = a + t * (b - a);\n r = fract(r); // fract is non-negative in WGSL\n return r * TAU; // back to radians\n}\n\n// Linear-sRGB endpoint pair \u2192 OKLab-rectangular interpolation \u2192 linear sRGB.\nfn mixPaletteOklab(linA: vec3<f32>, linB: vec3<f32>, t: f32) -> vec3<f32> {\n let labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linA);\n let labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linB);\n let lab = mix(labA, labB, t);\n return oklabToLinearSrgb(lab);\n}\n\n// Linear-sRGB endpoint pair \u2192 OKLCh hue-arc interpolation \u2192 linear sRGB.\nfn mixPaletteOklchArc(linA: vec3<f32>, linB: vec3<f32>, t: f32, method: i32) -> vec3<f32> {\n let labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linA);\n let labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * linB);\n let lchA = oklabToOklch(labA);\n let lchB = oklabToOklch(labB);\n let L = mix(lchA.x, lchB.x, t);\n let C = mix(lchA.y, lchB.y, t);\n let H = interpolateHueTurns(lchA.z, lchB.z, t, method);\n return oklabToLinearSrgb(oklchToOklab(vec3<f32>(L, C, H)));\n}\n\n// The ramp dispatcher (the samplePalette splices it). tRaw is the raw inter-stop\n// parameter [0,1]; the smoothstep ease + the huePath branch live here so the ramp is\n// one source. increasing(2)/decreasing(3) take the OKLCh hue-arc; every other method\n// takes the OKLab-rectangular straight line.\nfn samplePaletteRamp(a: vec3<f32>, b: vec3<f32>, tRaw: f32, huePath: i32) -> vec3<f32> {\n let t = smoothstep(0.0, 1.0, tRaw);\n if (huePath == 2 || huePath == 3) {\n return mixPaletteOklchArc(a, b, t, huePath);\n }\n return mixPaletteOklab(a, b, t);\n}\n\n// Interleaved Gradient Noise (Jimenez) \u2014 display-space 1-LSB dither.\nfn ign(p: vec2<f32>) -> f32 {\n return fract(52.9829189 * fract(dot(p, vec2<f32>(0.06711056, 0.00583715))));\n}\n\n// Cellular / Worley f1.\nfn cellular(p: vec2<f32>) -> f32 {\n let i = floor(p);\n let f = fract(p);\n var m = 1e9;\n for (var y = -1; y <= 1; y = y + 1) {\n for (var x = -1; x <= 1; x = x + 1) {\n let g = vec2<f32>(f32(x), f32(y));\n let o = hash22(i + g);\n let r = g + o - f;\n m = min(m, dot(r, r));\n }\n }\n return sqrt(m);\n}\n\n// \u2500\u2500 Warp (Quilez double warp + the three warp modes + the cursor swirl) \u2500\u2500\nfn domainWarp(p: vec2<f32>, t: f32) -> vec2<f32> {\n let warpScale = u.scalars1.x;\n let warpDrift = u.scalars1.y;\n let warpAmount = u.scalars0.w;\n let warpMode = u.ints0.z;\n let cursorStrength = u.scalars3.y;\n let cursorRadius = u.scalars3.z;\n let cursor = u.cursor.xy;\n\n let q = vec2<f32>(fbm(p * warpScale + vec2<f32>(0.0, 0.0) + t * warpDrift * K_WARP),\n fbm(p * warpScale + vec2<f32>(5.2, 1.3) + t * warpDrift * K_WARP));\n let r = vec2<f32>(fbm(p * warpScale + 4.0 * q + vec2<f32>(1.7, 9.2)),\n fbm(p * warpScale + 4.0 * q + vec2<f32>(8.3, 2.8)));\n\n var warp = r;\n if (warpMode == 1) {\n // cellular \u2014 chunky territories\n let c1 = cellular(p * warpScale * 1.5 + vec2<f32>(t * warpDrift * K_WARP * 2.0, 0.0));\n let c2 = cellular(p * warpScale * 1.5 + vec2<f32>(11.0, 7.0 + t * warpDrift * K_WARP * 2.0));\n warp = vec2<f32>(c1, c2);\n } else if (warpMode == 2) {\n // hybrid \u2014 fbm + cellular averaged\n let c1 = cellular(p * warpScale * 1.2);\n let c2 = cellular(p * warpScale * 1.2 + vec2<f32>(11.0, 7.0));\n warp = mix(r, vec2<f32>(c1, c2), 0.5);\n }\n var warped = p + warpAmount * warp;\n\n // Cursor swirl \u2014 rotate p around the cursor with radial falloff.\n if (cursorStrength > 0.001) {\n let toP = p - cursor;\n let d = length(toP);\n let rr = max(cursorRadius, 0.01);\n let w = exp(-(d * d) / (rr * rr * 0.45));\n let ang = w * cursorStrength * 2.1;\n let ca = cos(ang);\n let sa = sin(ang);\n var rotated = vec2<f32>(ca * toP.x - sa * toP.y, sa * toP.x + ca * toP.y) + cursor;\n let pinch = w * cursorStrength * 0.08;\n rotated = mix(rotated, cursor, pinch);\n warped = mix(warped, rotated + warpAmount * warp * 0.7, w * cursorStrength);\n }\n return warped;\n}\n\n// \u2500\u2500 Palette LUT \u2500\u2500\nfn samplePalette(id0: f32) -> vec3<f32> {\n let id = clamp(id0, 0.0, 1.0);\n let stopCount = u.ints0.x;\n let scaled = id * f32(stopCount - 1);\n let i0 = i32(floor(scaled));\n let i1 = min(i0 + 1, stopCount - 1);\n let t = fract(scaled);\n return samplePaletteRamp(u.palette[i0].rgb, u.palette[i1].rgb, t, u.ints1.y);\n}\n\n// \u2500\u2500 Nuclei field (anisotropic Gaussian softmax + drift + palette drift) \u2500\u2500\nstruct NucleiResult { paletteId: f32, valueMod: f32 };\n\nfn nucleiField(p: vec2<f32>, t: f32) -> NucleiResult {\n let nucleiCount = u.ints0.y;\n let nucleiDrift = u.scalars2.y;\n let paletteDrift = u.scalars2.z;\n let softmaxBeta = u.scalars0.y;\n\n var accumBias = 0.0;\n var accumValue = 0.0;\n var accumW = 0.0;\n for (var i = 0; i < MAX_NUCLEI; i = i + 1) {\n if (i >= nucleiCount) { break; }\n let n0 = u.nuc0[i]; // pos.x, pos.y, radius, paletteBias\n let n1 = u.nuc1[i]; // valueBias, driftRadius, driftPhase, elong\n let angle = u.nuc2[i].x;\n let driftRadius = n1.y;\n let driftPhase = n1.z;\n let posI = n0.xy + driftRadius * vec2<f32>(\n cos(t * nucleiDrift * K_NUCLEI + driftPhase),\n sin(t * nucleiDrift * K_NUCLEI + driftPhase * 1.13)\n );\n let diff = p - posI;\n let ca = cos(angle);\n let sa = sin(angle);\n let local = vec2<f32>(ca * diff.x + sa * diff.y, -sa * diff.x + ca * diff.y);\n let along = local.x / max(n1.w, 0.01);\n let across = local.y;\n let d2 = along * along + across * across;\n let r = max(n0.z, 0.01);\n let w = exp(-softmaxBeta * d2 / (r * r));\n accumBias = accumBias + w * n0.w;\n accumValue = accumValue + w * n1.x;\n accumW = accumW + w;\n }\n var paletteId = accumBias / max(accumW, 1e-4);\n let valueMod = accumValue / max(accumW, 1e-4);\n\n let palAmp = clamp(paletteDrift * 6.0, 0.0, 0.06);\n paletteId = paletteId + palAmp * sin(t * paletteDrift * K_PAL);\n paletteId = clamp(paletteId, 0.0, 1.0);\n return NucleiResult(paletteId, valueMod);\n}\n\n// \u2500\u2500 Color utils (OKLCh saturation) \u2500\u2500\nfn linOklab(lin: vec3<f32>) -> vec3<f32> {\n let lms = LINEAR_SRGB_TO_LMS * lin;\n return LMS_TO_OKLAB * cbrt3(lms);\n}\n\nfn saturate3(c: vec3<f32>, amt: f32) -> vec3<f32> {\n var lch = oklabToOklch(linOklab(c));\n lch.y = max(lch.y * amt, 0.0);\n return max(oklabToLinearSrgb(oklchToOklab(lch)), vec3<f32>(0.0));\n}\n\n// BD.W-AUR-VIVIDNESS \u2014 the \u00A73 chroma FLOOR, the WGSL twin of the GLSL vividnessFloor.\n// OKLab chroma lifted toward the floor, hue + L preserved; below VIVID_EPS the (a,b)\n// direction is precision noise so the lift synthesizes along the WARM anchor (amber,\n// both components positive) \u2014 never teal/navy. vividness (scalars3.w) == 0 is a no-op\n// (the byte-identity opt-out). Mode factor lifts a dim field a touch (read through glass).\nconst VIVID_TARGET: f32 = 0.115;\nconst VIVID_EPS: f32 = 0.012;\nconst VIVID_WARM_ANCHOR: vec2<f32> = vec2<f32>(0.34202, 0.93969);\nfn vividnessFloor(c: vec3<f32>, vividness: f32) -> vec3<f32> {\n if (vividness <= 0.0001) { return c; }\n var lab = linOklab(c);\n let C = length(lab.yz);\n let modeLift = mix(1.18, 1.0, clamp(lab.x * 1.4, 0.0, 1.0));\n let Cmin = vividness * VIVID_TARGET * modeLift;\n var hueDir = VIVID_WARM_ANCHOR;\n if (C > VIVID_EPS) { hueDir = lab.yz / C; }\n let yz = hueDir * max(C, Cmin);\n lab = vec3<f32>(lab.x, yz.x, yz.y);\n return max(oklabToLinearSrgb(lab), vec3<f32>(0.0));\n}\n\n// \u2500\u2500 PBR-Neutral tonemap (named aces() in the GLSL \u2014 the tonemap slot) \u2500\u2500\nfn aces(color0: vec3<f32>) -> vec3<f32> {\n let startCompression = 0.8 - 0.04;\n let desaturation = 0.15;\n var color = color0;\n let x = min(color.r, min(color.g, color.b));\n var offset = 0.04;\n if (x < 0.08) { offset = x - 6.25 * x * x; }\n color = color - offset;\n let peak = max(color.r, max(color.g, color.b));\n if (peak < startCompression) { return clamp(color, vec3<f32>(0.0), vec3<f32>(1.0)); }\n let d = 1.0 - startCompression;\n let newPeak = 1.0 - d * d / (peak + d - startCompression);\n color = color * (newPeak / peak);\n let g = 1.0 - 1.0 / (desaturation * (peak - newPeak) + 1.0);\n return clamp(mix(color, newPeak * vec3<f32>(1.0), g), vec3<f32>(0.0), vec3<f32>(1.0));\n}\n\n// \u2500\u2500 BC.W-VIZ-AURORA (T4) \u2014 the painterly-medium bodies (the keystone WGSL port) \u2500\u2500\n// Spliced HERE, after every helper the mediums consume is defined (domainWarp,\n// nucleiField, samplePalette, linOklab, saturate3, oklabToOklch/oklchToOklab,\n// hash21/vnoise/fbm) and before the vertex/fragment stages. applyMedium(col,p,t)\n// is the dispatch the fragment stage calls.\n\n// \u2500\u2500 Painterly luma + medium scalar accessors \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst W_LUMA: vec3<f32> = vec3<f32>(0.2126, 0.7152, 0.0722);\n\nfn mStrokeAmount() -> f32 { return u.scalars4.x; }\nfn mStrokeScale() -> f32 { return u.scalars4.y; }\nfn mStrokeAnisotropy() -> f32 { return u.scalars4.z; }\nfn mCanvasGrain() -> f32 { return u.scalars4.w; }\nfn mWetEdge() -> f32 { return u.scalars5.x; }\nfn mGranulation() -> f32 { return u.scalars5.y; }\nfn mBrokenColor() -> f32 { return u.scalars5.z; }\nfn mKuwaharaQ() -> f32 { return u.scalars5.w; }\nfn mKuwaharaRadius() -> f32 { return u.kuwahara.x; }\n\n// \u2500\u2500 Base color re-sample (the edge-mask operator the mediums Sobel/sector-sample) \u2500\u2500\n// The WGSL twin of mediums.glsl.ts sampleBase: warp -> nuclei field -> palette -> value.\nfn sampleBase(p: vec2<f32>, t: f32) -> vec3<f32> {\n let pw = domainWarp(p, t);\n let nf = nucleiField(pw, t);\n var c = samplePalette(nf.paletteId);\n c = c * (1.0 + u.scalars0.z * nf.valueMod);\n return c;\n}\n\n// \u2500\u2500 Broken color (hue + chroma jitter at constant OKLCh L) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfn brokenColorJitter(c: vec3<f32>, hueSeed: f32, valueSeed: f32, strength: f32) -> vec3<f32> {\n let amt = clamp(mBrokenColor() * strength, 0.0, 1.0);\n if (amt <= 0.001) { return c; }\n var lch = oklabToOklch(linOklab(c));\n lch.z = lch.z + (hueSeed - 0.5) * (32.0 * PI / 180.0) * amt;\n lch.y = max(lch.y * (1.0 + (valueSeed - 0.5) * 0.28 * amt), 0.0);\n return max(oklabToLinearSrgb(oklchToOklab(lch)), vec3<f32>(0.0));\n}\n\n// \u2500\u2500 Structure-tensor / edge-tangent-flow (AW.W4.1; the WGSL twin) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Returns vec3(tangent.x, tangent.y, A) \u2014 the minor-eigenvector edge-tangent + coherence.\nfn structureTensorField(p: vec2<f32>, t: f32, fallbackDir: vec2<f32>) -> vec3<f32> {\n let e = 0.0035;\n let l00 = dot(sampleBase(p + vec2<f32>(-e, -e), t), W_LUMA);\n let l10 = dot(sampleBase(p + vec2<f32>(0.0, -e), t), W_LUMA);\n let l20 = dot(sampleBase(p + vec2<f32>( e, -e), t), W_LUMA);\n let l01 = dot(sampleBase(p + vec2<f32>(-e, 0.0), t), W_LUMA);\n let l21 = dot(sampleBase(p + vec2<f32>( e, 0.0), t), W_LUMA);\n let l02 = dot(sampleBase(p + vec2<f32>(-e, e), t), W_LUMA);\n let l12 = dot(sampleBase(p + vec2<f32>(0.0, e), t), W_LUMA);\n let l22 = dot(sampleBase(p + vec2<f32>( e, e), t), W_LUMA);\n let Gx = (l20 + 2.0 * l21 + l22) - (l00 + 2.0 * l01 + l02);\n let Gy = (l02 + 2.0 * l12 + l22) - (l00 + 2.0 * l10 + l20);\n let Jxx = Gx * Gx;\n let Jyy = Gy * Gy;\n let Jxy = Gx * Gy;\n let tr = Jxx + Jyy;\n let disc = sqrt(max((Jxx - Jyy) * (Jxx - Jyy) + 4.0 * Jxy * Jxy, 0.0));\n let lambdaMaj = 0.5 * (tr + disc);\n let lambdaMin = 0.5 * (tr - disc);\n var tangent: vec2<f32>;\n if (disc < 1e-7) {\n tangent = fallbackDir;\n } else {\n let theta = 0.5 * atan2(2.0 * Jxy, Jxx - Jyy);\n tangent = vec2<f32>(-sin(theta), cos(theta));\n }\n var A = (lambdaMaj - lambdaMin) / (lambdaMaj + lambdaMin + 1e-6);\n A = clamp(A, 0.0, 1.0);\n if (dot(tangent, fallbackDir) < 0.0) { tangent = -tangent; }\n let blendW = pow(A, 0.28);\n let dir = normalize(mix(fallbackDir, tangent, blendW) + vec2<f32>(1e-6, 1e-6));\n return vec3<f32>(dir, A);\n}\n\n// \u2500\u2500 Flow field (the WGSL twin \u2014 the simple flow seed the medium fallback dirs use) \u2500\u2500\nfn flowField(p: vec2<f32>, t: f32) -> vec2<f32> {\n // Curl-noise-driven swirl (the medium-default dir; the full radial/swirl/diagonal\n // dispatch rides uniforms the WGSL struct does not carry \u2014 the procedural mediums\n // use this multi/curl seed as the fallback the structure tensor relaxes toward).\n let n = fbm(p * 2.0 + vec2<f32>(t * 0.02, t * 0.02));\n let a = n * 6.2831853;\n var dir = vec2<f32>(cos(a), sin(a));\n // Cursor swirl bias (matches the GLSL flow cursor term \u2014 the steady attraction).\n let cursorStrength = u.scalars3.y;\n let cursorRadius = u.scalars3.z;\n let cursor = u.cursor.xy;\n if (cursorStrength > 0.001) {\n let toCur = cursor - p;\n let d = length(toCur);\n let r = max(cursorRadius, 0.01);\n let w = exp(-(d * d) / (r * r * 0.5));\n let tangent = vec2<f32>(-toCur.y, toCur.x) / max(d, 1e-4);\n let a0 = atan2(dir.y, dir.x);\n let a1 = atan2(tangent.y, tangent.x);\n var da = a1 - a0;\n da = atan2(sin(da), cos(da));\n let aa = a0 + da * w * cursorStrength;\n dir = vec2<f32>(cos(aa), sin(aa));\n }\n return dir;\n}\n\n// \u2500\u2500 Watercolor \u2014 wet-edge cauliflowers + granulation + wash banding \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfn mediumWatercolor(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n var col = col0;\n let eps = 0.004;\n let cx1 = sampleBase(p + vec2<f32>(eps, 0.0), t);\n let cx2 = sampleBase(p - vec2<f32>(eps, 0.0), t);\n let cy1 = sampleBase(p + vec2<f32>(0.0, eps), t);\n let cy2 = sampleBase(p - vec2<f32>(0.0, eps), t);\n let gx = dot(cx1 - cx2, W_LUMA);\n let gy = dot(cy1 - cy2, W_LUMA);\n let edge = sqrt(gx * gx + gy * gy) / (2.0 * eps);\n let mask = smoothstep(0.0, 2.5, edge);\n col = col * mix(1.0, 0.78, mask * mWetEdge());\n\n let paper = 0.5 * vnoise(p * 160.0) + 0.5 * vnoise(p * 360.0);\n let pigLoad = 1.0 - dot(col, W_LUMA);\n col = col * (1.0 - mGranulation() * pigLoad * (paper - 0.5));\n\n let band = fbm(vec2<f32>(p.x * 1.5, p.y * 0.4));\n col = col * (1.0 + 0.04 * (band - 0.5));\n return col;\n}\n\n// \u2500\u2500 Pastel \u2014 anisotropic stroke noise along the flow + tooth grain \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfn mediumPastel(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n var col = col0;\n let flow = flowField(p, t);\n let perp = vec2<f32>(-flow.y, flow.x);\n let strokeScale = mStrokeScale();\n let along = dot(p, flow) * strokeScale;\n var across = dot(p, perp) * strokeScale;\n across = across + 0.03 * (vnoise(p * 260.0) - 0.5);\n\n let aniso = mix(1.0, 0.18, mStrokeAnisotropy());\n let stroke = fbm(vec2<f32>(along * aniso, across));\n col = col * mix(1.0, 0.82 + 0.32 * stroke, mStrokeAmount());\n\n let tooth = vnoise(p * 800.0);\n col = col * (1.0 - 0.08 * mStrokeAmount() * (tooth - 0.5));\n return col;\n}\n\n// \u2500\u2500 Crayon \u2014 DRY wax pigment on paper tooth (the tooth-multiply + scumble) \u2500\u2500\nfn mediumCrayon(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n let flow = structureTensorField(p, t, flowField(p, t)).xy;\n let ang = atan2(flow.y, flow.x);\n let ca = cos(-ang);\n let sa = sin(-ang);\n let pr = vec2<f32>(p.x * ca - p.y * sa, p.x * sa + p.y * ca);\n\n let aniso = mix(0.45, 0.95, mStrokeAnisotropy());\n let scale = max(mStrokeScale() * 1.6, 180.0);\n\n let t1 = vnoise(vec2<f32>(pr.x * scale * aniso, pr.y * scale));\n let t2 = vnoise(vec2<f32>(pr.x * scale * aniso * 0.4, pr.y * scale * 0.4) + vec2<f32>(11.0, 11.0));\n let t3 = vnoise(vec2<f32>(pr.x * scale * aniso * 2.1, pr.y * scale * 2.1) + vec2<f32>(23.0, 23.0));\n let tooth = 0.55 * t1 + 0.30 * t2 + 0.15 * t3;\n\n let pressure = clamp(mStrokeAmount(), 0.0, 1.0);\n let bite = mix(0.18, 0.46, pressure);\n var result = col0 * (1.0 - bite * (0.5 - tooth));\n\n let scumbleMask = smoothstep(0.42, 0.78, vnoise(vec2<f32>(pr.x * scale * 0.55, pr.y * scale * 0.22) + vec2<f32>(7.0, 7.0)));\n let scumbleCoverage = scumbleMask * pressure * 0.7;\n let paper = col0 * mix(0.80, 0.94, pressure);\n result = mix(paper, result, scumbleCoverage);\n\n let pigmentCell = floor(pr * max(scale * 0.18, 32.0));\n let pigmentMask = smoothstep(0.28, 0.82, vnoise(pr * scale * 0.21 + vec2<f32>(19.0, 19.0)));\n result = brokenColorJitter(\n result,\n hash21(pigmentCell + vec2<f32>(17.0, 17.0)),\n hash21(pigmentCell * 2.1 + vec2<f32>(31.0, 31.0)),\n 0.45 + 0.55 * pigmentMask\n );\n\n result = saturate3(result, 1.08);\n return result;\n}\n\n// \u2500\u2500 Kuwahara \u2014 the SOFT anisotropic generalized Kuwahara painterly finish \u2500\u2500\u2500\u2500\n// THE KEYSTONE (Kyprianidis 2010). Aurora is a PROCEDURAL field (no input texture) so the\n// operator runs over sampleBase directly: an elliptical kernel oriented along the structure\n// tensor (elongated along the edge-tangent, narrowed across by the anisotropy), 8 OVERLAPPING\n// sectors via SMOOTH gaussian-angular weights, blended by 1/(1+var^q) (the SOFT criterion \u2192\n// no 8-spoke pinwheel by construction). 4 rings \u00D7 8 angular taps = 32 procedural samples.\nfn mediumKuwahara(col0: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n let stf = structureTensorField(p, t, flowField(p, t));\n let tangent = stf.xy;\n let A = stf.z;\n // The studio knob drives the patch radius; clamp into the procedural patch band.\n let radius = clamp(mKuwaharaRadius() + mStrokeScale() * 0.00018, 0.006, 0.024);\n let aniso = mix(1.0, 0.34, clamp(A, 0.0, 1.0));\n let ax = tangent;\n let ay = vec2<f32>(-tangent.y, tangent.x);\n\n // Per-sector weighted sums (8 sectors). WGSL has no runtime-indexed local arrays of\n // vectors as cleanly as GLSL, so unroll the sector accumulators explicitly.\n var mSum: array<vec3<f32>, 8>;\n var sSum: array<vec3<f32>, 8>;\n var wSum: array<f32, 8>;\n for (var i = 0; i < 8; i = i + 1) {\n mSum[i] = vec3<f32>(0.0);\n sSum[i] = vec3<f32>(0.0);\n wSum[i] = 0.0;\n }\n\n let RINGS = 4;\n let TAPS = 8;\n for (var r = 1; r <= RINGS; r = r + 1) {\n let rr = f32(r) / f32(RINGS);\n let radial = 1.0 - 0.6 * rr;\n for (var a = 0; a < TAPS; a = a + 1) {\n let ang = 6.2831853 * f32(a) / f32(TAPS);\n let dirE = ax * cos(ang) + ay * (sin(ang) * aniso);\n let off = dirE * (radius * rr);\n let c = sampleBase(p + off, t);\n for (var k = 0; k < 8; k = k + 1) {\n let sectorAng = 6.2831853 * f32(k) / 8.0;\n var d = ang - sectorAng;\n d = atan2(sin(d), cos(d));\n let sw = exp(-d * d * 2.2) * radial;\n mSum[k] = mSum[k] + c * sw;\n sSum[k] = sSum[k] + c * c * sw;\n wSum[k] = wSum[k] + sw;\n }\n }\n }\n\n let q = max(mKuwaharaQ(), 1.0);\n var accum = vec3<f32>(0.0);\n var accumW = 0.0;\n for (var k = 0; k < 8; k = k + 1) {\n let wk = max(wSum[k], 1e-4);\n let mean = mSum[k] / wk;\n let var3 = max(sSum[k] / wk - mean * mean, vec3<f32>(0.0));\n let variance = dot(var3, W_LUMA);\n let sectorW = 1.0 / (1.0 + pow(variance * 320.0, q));\n accum = accum + mean * sectorW;\n accumW = accumW + sectorW;\n }\n var result = accum / max(accumW, 1e-4);\n\n // Anchor in near-flat zones so the smoothing only bites at edges.\n let center = sampleBase(p, t);\n result = mix(center, result, clamp(0.35 + 0.65 * A, 0.0, 1.0));\n\n // Faint canvas tooth + pigment-saturation so the flattened patches read as oil paint.\n let tooth = vnoise(p * 300.0) - 0.5;\n result = result * (1.0 + tooth * 0.06 * mCanvasGrain());\n result = saturate3(result, 1.04);\n\n return mix(col0, result, clamp(mStrokeAmount(), 0.0, 1.0));\n}\n\n// \u2500\u2500 Medium dispatch (the WGSL twin of the GLSL main() if-ladder) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// uMedium: 0 smooth \u00B7 1 pastel \u00B7 2 watercolor \u00B7 3 oil \u00B7 4 crayon \u00B7 5 vangogh \u00B7\n// 6 oil-pastel \u00B7 7 kuwahara. The cheap peer mediums (pastel/watercolor/crayon) +\n// kuwahara port their own bodies; the oil/vangogh/oil-pastel STROKE cascade renders\n// the anisotropic-Kuwahara PAINTERLY finish here (a real oil-paint read, never the\n// smooth core \u2014 the \"NO FALLBACKS on Safari\" mandate; the full per-dab Starry-Night\n// stroke WGSL is the booked W-AURORA-WGPU-MEDIUMS-STROKES tail).\nfn applyMedium(col: vec3<f32>, p: vec2<f32>, t: f32) -> vec3<f32> {\n let medium = u.ints1.x;\n if (medium == 1) { return mediumPastel(col, p, t); }\n if (medium == 2) { return mediumWatercolor(col, p, t); }\n if (medium == 4) { return mediumCrayon(col, p, t); }\n // oil(3) / vangogh(5) / oil-pastel(6) / kuwahara(7) all render the painterly\n // anisotropic-Kuwahara finish on the WGSL primary (the WebGL2 fallback carries the\n // full per-dab stroke cascade for oil/vangogh/oil-pastel).\n if (medium == 3 || medium == 5 || medium == 6 || medium == 7) {\n return mediumKuwahara(col, p, t);\n }\n return col;\n}\n\n\n// \u2500\u2500 Full-screen triangle vertex stage (the pilot idiom \u2014 no vertex buffer) \u2500\u2500\nstruct VSOut {\n @builtin(position) pos: vec4<f32>,\n @location(0) uv: vec2<f32>,\n};\n\n@vertex\nfn vs_main(@builtin(vertex_index) vi: u32) -> VSOut {\n // NDC corners of the covering triangle (-1,-1), (3,-1), (-1,3).\n var p = vec2<f32>(-1.0, -1.0);\n if (vi == 1u) { p = vec2<f32>(3.0, -1.0); }\n else if (vi == 2u) { p = vec2<f32>(-1.0, 3.0); }\n var out: VSOut;\n out.pos = vec4<f32>(p, 0.0, 1.0);\n // vUv = aPos * 0.5 + 0.5 (the aurora.vert convention).\n out.uv = p * 0.5 + 0.5;\n return out;\n}\n\n// \u2500\u2500 Fragment stage (the main() transcription) \u2500\u2500\n@fragment\nfn fs_main(in: VSOut) -> @location(0) vec4<f32> {\n let t = u.scalars0.x;\n let valueVariance = u.scalars0.z;\n let breathDepth = u.scalars2.w;\n let breathPeriod = u.scalars3.x;\n let saturation = u.scalars1.z;\n let paperGrain = u.scalars1.w;\n let alpha = u.scalars2.x;\n let vividness = u.scalars3.w;\n\n let uv = in.uv;\n let pN = uv;\n\n let p_warp = domainWarp(pN, t);\n\n let nf = nucleiField(p_warp, t);\n var col = samplePalette(nf.paletteId);\n col = col * (1.0 + valueVariance * nf.valueMod);\n\n // Breath \u2014 slow global luminance wobble.\n let breath = sin(t * 6.2831 / max(breathPeriod, 1.0));\n col = col * (1.0 + breathDepth * breath * 0.5);\n\n // BC.W-VIZ-AURORA (T4) \u2014 the painterly-medium dispatch. uMedium 0 (smooth) is a\n // no-op pass-through so the DEFAULT smooth config is byte-identical to the prior\n // WGSL primary (the parity capture); uMedium 1-7 render the ported painterly\n // bodies (pastel/watercolor/crayon/kuwahara) or the anisotropic-Kuwahara finish\n // (oil/vangogh/oil-pastel) \u2014 never a silent smooth degrade on Safari 26.\n col = applyMedium(col, pN, t);\n\n // Saturation trim.\n col = saturate3(col, saturation);\n\n // BD.W-AUR-VIVIDNESS \u2014 the \u00A73 chroma floor (warm-anchored, hue-preserving). The WGSL\n // twin of the GLSL call; vividness:0 is a no-op so the smooth/pale default stays gated.\n col = vividnessFloor(col, vividness);\n\n // Tonemap + film grain.\n col = aces(col);\n // gl_FragCoord.xy \u2192 the device-pixel position (the WGSL @builtin(position)).\n let fragCoord = in.pos.xy;\n let grain = hash21(fragCoord + t * 17.0);\n col = col + (grain - 0.5) * paperGrain;\n\n col = clamp(col * 0.985 + 0.008, vec3<f32>(0.0), vec3<f32>(1.0));\n\n // MANDATORY OETF \u2014 closes the seam (the whole pipeline above runs in LINEAR).\n col = linearToSrgb(col);\n\n // 1-LSB triangular IGN dither in DISPLAY space, AFTER the OETF.\n col = col + (1.0 / 255.0) * (ign(fragCoord) - 0.5);\n\n // Premultiply on DISPLAY-space color (matches the WebGL2 path: OETF, then premul).\n return vec4<f32>(col * alpha, alpha);\n}\n";
|
|
@@ -5,7 +5,7 @@ export type { UseAuroraReturn } from "./composables/useAurora";
|
|
|
5
5
|
export { useCursorInteraction } from "./composables/useCursorInteraction";
|
|
6
6
|
export { createAurora } from "./composables/runtime";
|
|
7
7
|
export type { AuroraRuntimeMode, AuroraRuntimeOptions } from "./composables/runtime";
|
|
8
|
-
export { DEFAULT_AURORA_CONFIG, PAPER_WASH_GROUND, MAX_NUCLEI, MAX_STOPS, type AuroraConfig, type AuroraCursorApi, type AuroraFlow, type AuroraInstance, type AuroraInteractivity, type AuroraMedium, type AuroraNucleus, type FlowPattern, type OklchStop, type StrokeMode, type StrokeOrient, type WarpMode, } from "./constants/presets";
|
|
8
|
+
export { DEFAULT_AURORA_CONFIG, PAPER_WASH_GROUND, DEFAULT_VIVIDNESS, VIVID_TARGET, MAX_NUCLEI, MAX_STOPS, type AuroraConfig, type AuroraCursorApi, type AuroraFlow, type AuroraInstance, type AuroraInteractivity, type AuroraMedium, type AuroraNucleus, type FlowPattern, type OklchStop, type StrokeMode, type StrokeOrient, type WarpMode, } from "./constants/presets";
|
|
9
9
|
export { resolveAtoms, configToAtoms, nucleiPrior, DEFAULT_ATOMS, type AuroraAtoms, type AuroraMotionAtom, type AuroraZones, type AuroraZoneArrangement, type AuroraMediumAtom, type AuroraInteractivityAtom, } from "./composables/atoms";
|
|
10
10
|
export { cssToOklch, deriveAurora, flattenPalette, hexToOklchStop, oklchStopToHex, oklchToLinear, paletteToCssGradient, } from "./composables/color";
|
|
11
11
|
export { auroraFallbackGround, sampleAuroraField, nucleiFieldStatic, relativeLuminance, type AuroraFallbackGround, type AuroraFallbackGroundOptions, type AuroraGroundMetrics, } from "./composables/auroraFallbackGround";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type OklchStop } from "../../../../composables/color";
|
|
2
|
+
/**
|
|
3
|
+
* Walk the anchor ramp to the single OKLCh stop at parameter `t` (0..1) via the
|
|
4
|
+
* shorter-hue arc — the segment is located, then value.js's `mixColors` runs the
|
|
5
|
+
* OKLCh/shorter-hue perceptual mix at the in-segment fraction (the single-point
|
|
6
|
+
* twin of `sampleColorRamp`; ONE color source — value.js). L/C lerp in OKLCh and
|
|
7
|
+
* the hue walks the SHORTER arc, so the warm→cool midpoint keeps its chroma.
|
|
8
|
+
*
|
|
9
|
+
* Deterministic + DOM-free (SSR-safe; mirrors `deriveBlobPalette`).
|
|
10
|
+
*/
|
|
11
|
+
export declare function spectrumAt(stops: readonly OklchStop[], t: number): OklchStop;
|
|
12
|
+
/**
|
|
13
|
+
* Walk a CONCRETE-anchor ramp to `count` evenly-spaced HEX stops — the perceptual
|
|
14
|
+
* (OKLCH/shorter-hue) cold path. The caller (`spectrumStops` in the sync shell) has
|
|
15
|
+
* already screened out `var(--…)` ramps, so every stop here is a CONCRETE CSS color
|
|
16
|
+
* the leaf's `cssToOklch` parses to OKLCh; the walk carries no chroma trough.
|
|
17
|
+
*
|
|
18
|
+
* Each adjacent anchor pair is one `sampleColorRamp` segment (the value.js grid
|
|
19
|
+
* sampler walked SHORTER-hue in OKLCh); the per-segment grids concatenate (shared
|
|
20
|
+
* boundary deduped) into one continuous `count`-stop ramp. The endpoints anchor the
|
|
21
|
+
* input exactly; the hue walks the shorter arc end-to-end, so no segment greys out.
|
|
22
|
+
*
|
|
23
|
+
* @returns one HEX (`#rrggbb`) per stop.
|
|
24
|
+
*/
|
|
25
|
+
export declare function walkConcreteSpectrum(stops: readonly string[], count: number): string[];
|
|
@@ -1,22 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
/** A consumer-supplied callback the COLD path calls once the perceptual walk resolves. */
|
|
2
|
+
export type SpectrumUpgrade = (stops: string[]) => void;
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Produce `samples` evenly-spaced HEX/CSS stops across the anchor ramp — the conic
|
|
5
|
+
* gradient's color stops. CSS `var(--…)` tokens (the LIBRARY-default brand ramp) are
|
|
6
|
+
* passed through UNTOUCHED (they resolve in the cascade at paint — the value.js-free
|
|
7
|
+
* fast path). CONCRETE color anchors return the synchronous interim immediately AND,
|
|
8
|
+
* when `onUpgrade` is supplied, load `./spectrum-walk` and upgrade to the OKLCH/
|
|
9
|
+
* shorter-hue perceptual walk once the dynamic chunk resolves.
|
|
8
10
|
*
|
|
9
|
-
*
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Produce `samples` evenly-spaced HEX stops across the anchor ramp — the conic
|
|
14
|
-
* gradient's color stops, carrying no chroma trough across the sweep. The anchor
|
|
15
|
-
* stops are CSS color strings parsed via the leaf's `cssToOklch`; CSS `var(--…)`
|
|
16
|
-
* tokens (the LIBRARY-default brand ramp) are passed through UNTOUCHED (they
|
|
17
|
-
* resolve in the cascade at paint — the helper only walks CONCRETE color anchors).
|
|
11
|
+
* `spectrumStops` is SYNCHRONOUS (the SFC's `computed` cannot await). The dynamic
|
|
12
|
+
* boundary lives INSIDE it (the value.js branch fires `import()` and returns the
|
|
13
|
+
* synchronous interim), never on the export signature.
|
|
18
14
|
*
|
|
19
|
-
* @returns one
|
|
20
|
-
*
|
|
15
|
+
* @returns one stop per sample — `var()` strings for a token ramp, the raw anchors
|
|
16
|
+
* for the concrete-anchor synchronous interim (upgraded to HEX via `onUpgrade`).
|
|
21
17
|
*/
|
|
22
|
-
export declare function spectrumStops(stops: readonly string[], samples?: number): string[];
|
|
18
|
+
export declare function spectrumStops(stops: readonly string[], samples?: number, onUpgrade?: SpectrumUpgrade): string[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as BorderProgress } from "./BorderProgress.vue";
|
|
2
2
|
export type { BorderProgressProps } from "./BorderProgress.vue";
|
|
3
3
|
export type { BorderProgressCoverage, BorderProgressMilestone, BorderProgressMilestoneEvent, } from "./constants";
|
|
4
|
-
export {
|
|
4
|
+
export { spectrumStops, type SpectrumUpgrade } from "./composables/useBorderSpectrum";
|