diff --git a/README.md b/README.md index 5846aff..a342e46 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ default/ The Prototype starter models (logo, Svelte rune cube_diorama/ Blender Studio's Cube Diorama, split per object (CC0) khronos-sample-assets/ metadata only — model bytes are fetched straight from github.com/KhronosGroup/glTF-Sample-Assets (CC-BY 4.0) +backgrounds/ shader background presets: 5 fluid (CC0) + 8 Gradient (MIT, ShaderGradient-adapted) audio-essentials/ 23 CC0 sounds (Kenney + OpenGameArt), installable .zip nature-kit/ Nature & Terrain: 31 trees/plants/rocks/cliff/path/pond pieces (made with Meshy.ai, CC0) — see nature-kit/kit.md @@ -104,6 +105,9 @@ reading the ref they were built against. post-processed here (`tools/architecture-kit/`) — see its `attribution.html` and `kit.md`. - `props-kit/` — © theprototype, CC0; made with [Meshy.ai](https://www.meshy.ai) (paid plan: the output is ours) plus procedural pieces — see its `attribution.html` and `kit.md`. +- `backgrounds/` — shader background presets: the fluid set is © theprototype, CC0; the Gradient family's + parameter sets are adapted from [ShaderGradient](https://github.com/ruucm/shadergradient)'s presets, MIT + © ruucm, stone-skipper — see [backgrounds/ATTRIBUTION.md](backgrounds/ATTRIBUTION.md). - `audio-essentials/` — all CC0; per-file sources in [CREDITS.md](audio-essentials/CREDITS.md) (Kenney.nl, OpenGameArt). - `nature-kit/` — © theprototype, CC0; made with [Meshy.ai](https://www.meshy.ai) and diff --git a/backgrounds/ATTRIBUTION.md b/backgrounds/ATTRIBUTION.md new file mode 100644 index 0000000..9ce6297 --- /dev/null +++ b/backgrounds/ATTRIBUTION.md @@ -0,0 +1,31 @@ +# backgrounds/ — attribution + +- **Fluid set** (`mesh-gradient`, `silk-gradient`, `noise-flow`, `metaballs`, `grain-dither`) — © theprototype, + CC0 1.0. Our own shader graphs (core roadmap 65 M2). +- **Gradient family** (`ember-ribbon`, `violet-orb`, `mint-tide`, `glass-orbit`, `night-swell`, `indigo-bloom`, + `deep-space`, `tangerine-sea`; index rows with `"family": "Gradient"`) — the parameter sets are adapted from the + presets of **ShaderGradient** (https://github.com/ruucm/shadergradient, `packages/shadergradient/src/presets.ts`), + renamed and retuned for the app's Gradient lab node. They are therefore under ShaderGradient's MIT licence, below. + The node itself (a port of ShaderGradient's GLSL) lives in the core app, which carries the same notice on its + third-party licences page. + +All of these files are generated by `tools/backgrounds/build.cjs`. + +--- + +MIT License + +Copyright (c) ruucm (https://github.com/ruucm), stone-skipper (https://github.com/stone-skipper) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/backgrounds/deep-space.json b/backgrounds/deep-space.json new file mode 100644 index 0000000..0903139 --- /dev/null +++ b/backgrounds/deep-space.json @@ -0,0 +1,67 @@ +{ + "format": 1, + "domain": "background", + "name": "Deep space", + "preset": "deep-space", + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper", + "layer": { + "pointer": false, + "scroll": false + }, + "nodes": [ + { + "id": "lab", + "type": "gradientLab", + "position": { + "x": 80, + "y": 80 + }, + "data": { + "shape": "waterPlane", + "color1": "#5606ff", + "color2": "#fe8989", + "color3": "#000000", + "speed": 0.1, + "density": 1.1, + "strength": 2.4, + "frequency": 0, + "amplitude": 0, + "brightness": 1.1, + "lighting": "ambient", + "environment": "city", + "reflection": 0.1, + "azimuth": 180, + "polar": 115, + "distance": 3.9, + "zoom": 1, + "fov": 45, + "posX": -0.5, + "posY": 0.1, + "posZ": 0, + "rotX": 0, + "rotY": 0, + "rotZ": 235, + "grain": 0 + } + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 420, + "y": 120 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-lab.out-out.color", + "source": "lab", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/backgrounds/ember-ribbon.json b/backgrounds/ember-ribbon.json new file mode 100644 index 0000000..a7c6356 --- /dev/null +++ b/backgrounds/ember-ribbon.json @@ -0,0 +1,67 @@ +{ + "format": 1, + "domain": "background", + "name": "Ember ribbon", + "preset": "ember-ribbon", + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper", + "layer": { + "pointer": false, + "scroll": false + }, + "nodes": [ + { + "id": "lab", + "type": "gradientLab", + "position": { + "x": 80, + "y": 80 + }, + "data": { + "shape": "plane", + "color1": "#ff5005", + "color2": "#dbba95", + "color3": "#d0bce1", + "speed": 0.4, + "density": 1.3, + "strength": 4, + "frequency": 5.5, + "amplitude": 1, + "brightness": 1.2, + "lighting": "ambient", + "environment": "city", + "reflection": 0.1, + "azimuth": 180, + "polar": 90, + "distance": 3.6, + "zoom": 1, + "fov": 45, + "posX": -1.4, + "posY": 0, + "posZ": 0, + "rotX": 0, + "rotY": 10, + "rotZ": 50, + "grain": 1 + } + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 420, + "y": 120 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-lab.out-out.color", + "source": "lab", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/backgrounds/glass-orbit.json b/backgrounds/glass-orbit.json new file mode 100644 index 0000000..3417d4e --- /dev/null +++ b/backgrounds/glass-orbit.json @@ -0,0 +1,67 @@ +{ + "format": 1, + "domain": "background", + "name": "Glass orbit", + "preset": "glass-orbit", + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper", + "layer": { + "pointer": false, + "scroll": false + }, + "nodes": [ + { + "id": "lab", + "type": "gradientLab", + "position": { + "x": 80, + "y": 80 + }, + "data": { + "shape": "sphere", + "color1": "#73bfc4", + "color2": "#ff810a", + "color3": "#8da0ce", + "speed": 0.3, + "density": 0.8, + "strength": 0.3, + "frequency": 5.5, + "amplitude": 3.2, + "brightness": 0.8, + "lighting": "environment", + "environment": "city", + "reflection": 0.4, + "azimuth": 270, + "polar": 180, + "distance": 14, + "zoom": 15.1, + "fov": 45, + "posX": -0.1, + "posY": 0, + "posZ": 0, + "rotX": 0, + "rotY": 130, + "rotZ": 70, + "grain": 1 + } + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 420, + "y": 120 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-lab.out-out.color", + "source": "lab", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/backgrounds/grain-dither.json b/backgrounds/grain-dither.json new file mode 100644 index 0000000..fbf4f50 --- /dev/null +++ b/backgrounds/grain-dither.json @@ -0,0 +1,450 @@ +{ + "format": 1, + "domain": "background", + "name": "Grain & dither", + "preset": "grain-dither", + "layer": { + "pointer": true, + "scroll": false + }, + "nodes": [ + { + "id": "uv", + "type": "aspectUv", + "position": { + "x": 40, + "y": 40 + }, + "data": {} + }, + { + "id": "chan", + "type": "split", + "position": { + "x": 240, + "y": 40 + }, + "data": {} + }, + { + "id": "cloud", + "type": "fbm", + "position": { + "x": 240, + "y": 220 + }, + "data": { + "scale": 2, + "octaves": 4, + "lacunarity": 2, + "gain": 0.5 + } + }, + { + "id": "cloudAmt", + "type": "float", + "position": { + "x": 240, + "y": 400 + }, + "data": { + "value": 0.22 + } + }, + { + "id": "cloudS", + "type": "multiply", + "position": { + "x": 440, + "y": 260 + }, + "data": {} + }, + { + "id": "t", + "type": "add", + "position": { + "x": 620, + "y": 100 + }, + "data": {} + }, + { + "id": "ramp", + "type": "gradient", + "position": { + "x": 800, + "y": 80 + }, + "data": { + "colorA": "#2b1b4a", + "colorB": "#c4577a", + "colorC": "#ffc98a", + "mid": 0.42 + } + }, + { + "id": "ptr", + "type": "pointer", + "position": { + "x": 40, + "y": 560 + }, + "data": {} + }, + { + "id": "ptrUv", + "type": "aspectUv", + "position": { + "x": 240, + "y": 560 + }, + "data": {} + }, + { + "id": "dist", + "type": "distance", + "position": { + "x": 440, + "y": 520 + }, + "data": {} + }, + { + "id": "spotRise", + "type": "smoothstep", + "position": { + "x": 620, + "y": 460 + }, + "data": { + "edge0": 0, + "edge1": 0.35 + } + }, + { + "id": "spot", + "type": "oneMinus", + "position": { + "x": 660, + "y": 580 + }, + "data": {} + }, + { + "id": "spotAmt", + "type": "float", + "position": { + "x": 620, + "y": 680 + }, + "data": { + "value": 0.35 + } + }, + { + "id": "spotS", + "type": "multiply", + "position": { + "x": 800, + "y": 540 + }, + "data": {} + }, + { + "id": "lit", + "type": "add", + "position": { + "x": 1000, + "y": 200 + }, + "data": {} + }, + { + "id": "bayer", + "type": "bayer", + "position": { + "x": 1000, + "y": 420 + }, + "data": { + "scale": 2 + } + }, + { + "id": "half", + "type": "float", + "position": { + "x": 1000, + "y": 560 + }, + "data": { + "value": 0.5 + } + }, + { + "id": "centred", + "type": "subtract", + "position": { + "x": 1180, + "y": 440 + }, + "data": {} + }, + { + "id": "depth", + "type": "float", + "position": { + "x": 1180, + "y": 600 + }, + "data": { + "value": 0.16 + } + }, + { + "id": "dither", + "type": "multiply", + "position": { + "x": 1360, + "y": 460 + }, + "data": {} + }, + { + "id": "dithered", + "type": "add", + "position": { + "x": 1360, + "y": 220 + }, + "data": {} + }, + { + "id": "steps", + "type": "posterize", + "position": { + "x": 1540, + "y": 220 + }, + "data": { + "steps": 7 + } + }, + { + "id": "grain", + "type": "grain", + "position": { + "x": 1540, + "y": 420 + }, + "data": { + "amount": 0.05, + "size": 2, + "animate": 1 + } + }, + { + "id": "final", + "type": "add", + "position": { + "x": 1740, + "y": 260 + }, + "data": {} + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 1940, + "y": 260 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-uv.out-chan.value", + "source": "uv", + "sourceHandle": "out", + "target": "chan", + "targetHandle": "value" + }, + { + "id": "e-uv.out-cloud.uv", + "source": "uv", + "sourceHandle": "out", + "target": "cloud", + "targetHandle": "uv" + }, + { + "id": "e-cloud.out-cloudS.a", + "source": "cloud", + "sourceHandle": "out", + "target": "cloudS", + "targetHandle": "a" + }, + { + "id": "e-cloudAmt.out-cloudS.b", + "source": "cloudAmt", + "sourceHandle": "out", + "target": "cloudS", + "targetHandle": "b" + }, + { + "id": "e-chan.y-t.a", + "source": "chan", + "sourceHandle": "y", + "target": "t", + "targetHandle": "a" + }, + { + "id": "e-cloudS.out-t.b", + "source": "cloudS", + "sourceHandle": "out", + "target": "t", + "targetHandle": "b" + }, + { + "id": "e-t.out-ramp.t", + "source": "t", + "sourceHandle": "out", + "target": "ramp", + "targetHandle": "t" + }, + { + "id": "e-ptr.position-ptrUv.uv", + "source": "ptr", + "sourceHandle": "position", + "target": "ptrUv", + "targetHandle": "uv" + }, + { + "id": "e-uv.out-dist.a", + "source": "uv", + "sourceHandle": "out", + "target": "dist", + "targetHandle": "a" + }, + { + "id": "e-ptrUv.out-dist.b", + "source": "ptrUv", + "sourceHandle": "out", + "target": "dist", + "targetHandle": "b" + }, + { + "id": "e-dist.out-spotRise.a", + "source": "dist", + "sourceHandle": "out", + "target": "spotRise", + "targetHandle": "a" + }, + { + "id": "e-spotRise.out-spot.a", + "source": "spotRise", + "sourceHandle": "out", + "target": "spot", + "targetHandle": "a" + }, + { + "id": "e-spot.out-spotS.a", + "source": "spot", + "sourceHandle": "out", + "target": "spotS", + "targetHandle": "a" + }, + { + "id": "e-spotAmt.out-spotS.b", + "source": "spotAmt", + "sourceHandle": "out", + "target": "spotS", + "targetHandle": "b" + }, + { + "id": "e-ramp.out-lit.a", + "source": "ramp", + "sourceHandle": "out", + "target": "lit", + "targetHandle": "a" + }, + { + "id": "e-spotS.out-lit.b", + "source": "spotS", + "sourceHandle": "out", + "target": "lit", + "targetHandle": "b" + }, + { + "id": "e-bayer.out-centred.a", + "source": "bayer", + "sourceHandle": "out", + "target": "centred", + "targetHandle": "a" + }, + { + "id": "e-half.out-centred.b", + "source": "half", + "sourceHandle": "out", + "target": "centred", + "targetHandle": "b" + }, + { + "id": "e-centred.out-dither.a", + "source": "centred", + "sourceHandle": "out", + "target": "dither", + "targetHandle": "a" + }, + { + "id": "e-depth.out-dither.b", + "source": "depth", + "sourceHandle": "out", + "target": "dither", + "targetHandle": "b" + }, + { + "id": "e-lit.out-dithered.a", + "source": "lit", + "sourceHandle": "out", + "target": "dithered", + "targetHandle": "a" + }, + { + "id": "e-dither.out-dithered.b", + "source": "dither", + "sourceHandle": "out", + "target": "dithered", + "targetHandle": "b" + }, + { + "id": "e-dithered.out-steps.a", + "source": "dithered", + "sourceHandle": "out", + "target": "steps", + "targetHandle": "a" + }, + { + "id": "e-steps.out-final.a", + "source": "steps", + "sourceHandle": "out", + "target": "final", + "targetHandle": "a" + }, + { + "id": "e-grain.out-final.b", + "source": "grain", + "sourceHandle": "out", + "target": "final", + "targetHandle": "b" + }, + { + "id": "e-final.out-out.color", + "source": "final", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/backgrounds/index.json b/backgrounds/index.json new file mode 100644 index 0000000..01b9ed3 --- /dev/null +++ b/backgrounds/index.json @@ -0,0 +1,133 @@ +{ + "format": 1, + "title": "Fluid backgrounds", + "license": "CC0-1.0", + "presets": [ + { + "key": "mesh-gradient", + "label": "Mesh gradient", + "hint": "Four soft colours drifting into each other; the first one leans towards your pointer.", + "file": "mesh-gradient.json" + }, + { + "key": "silk-gradient", + "label": "Silk gradient", + "hint": "A tilted, slowly folding ribbon of colour in the style of modern product pages. Scrolling shifts the palette; the pointer nudges the folds.", + "file": "silk-gradient.json" + }, + { + "key": "noise-flow", + "label": "Noise flow", + "hint": "Contour lines streaming through warped noise, like wind on a weather map. The flow bends towards your pointer.", + "file": "noise-flow.json" + }, + { + "key": "metaballs", + "label": "Metaballs", + "hint": "Glossy blobs that melt into each other like a lava lamp; one of them follows your pointer.", + "file": "metaballs.json" + }, + { + "key": "grain-dither", + "label": "Grain & dither", + "hint": "A soft dusk gradient broken into retro dither steps with film grain on top; a pool of light follows your pointer.", + "file": "grain-dither.json" + }, + { + "key": "ember-ribbon", + "label": "Ember ribbon", + "hint": "A warm ribbon of orange, sand and lilac folding slowly across the frame, with a fine print grain.", + "file": "ember-ribbon.json", + "family": "Gradient", + "needs": [ + "gradientLab" + ], + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper" + }, + { + "key": "violet-orb", + "label": "Violet orb", + "hint": "Seen up close, a sphere of periwinkle and violet that twists into soft spirals.", + "file": "violet-orb.json", + "family": "Gradient", + "needs": [ + "gradientLab" + ], + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper" + }, + { + "key": "mint-tide", + "label": "Mint tide", + "hint": "Rolling swells of mint and aqua fading to white, like light under shallow water. No grain.", + "file": "mint-tide.json", + "family": "Gradient", + "needs": [ + "gradientLab" + ], + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper" + }, + { + "key": "glass-orbit", + "label": "Glass orbit", + "hint": "A glossy teal and amber sphere seen from below, catching soft reflections from a studio around it.", + "file": "glass-orbit.json", + "family": "Gradient", + "needs": [ + "gradientLab" + ], + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper" + }, + { + "key": "night-swell", + "label": "Night swell", + "hint": "Slate and lavender waves rising out of near black: a calm, dark backdrop.", + "file": "night-swell.json", + "family": "Gradient", + "needs": [ + "gradientLab" + ], + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper" + }, + { + "key": "indigo-bloom", + "label": "Indigo bloom", + "hint": "White and gold blooming out of deep indigo on a slowly turning sphere. No grain.", + "file": "indigo-bloom.json", + "family": "Gradient", + "needs": [ + "gradientLab" + ], + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper" + }, + { + "key": "deep-space", + "label": "Deep space", + "hint": "Electric violet and coral drifting through black, like a nebula. No grain.", + "file": "deep-space.json", + "family": "Gradient", + "needs": [ + "gradientLab" + ], + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper" + }, + { + "key": "tangerine-sea", + "label": "Tangerine sea", + "hint": "A sea of hot orange with rust-red troughs, seen low across its surface. No grain.", + "file": "tangerine-sea.json", + "family": "Gradient", + "needs": [ + "gradientLab" + ], + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper" + } + ] +} diff --git a/backgrounds/indigo-bloom.json b/backgrounds/indigo-bloom.json new file mode 100644 index 0000000..9956239 --- /dev/null +++ b/backgrounds/indigo-bloom.json @@ -0,0 +1,67 @@ +{ + "format": 1, + "domain": "background", + "name": "Indigo bloom", + "preset": "indigo-bloom", + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper", + "layer": { + "pointer": false, + "scroll": false + }, + "nodes": [ + { + "id": "lab", + "type": "gradientLab", + "position": { + "x": 80, + "y": 80 + }, + "data": { + "shape": "sphere", + "color1": "#ffffff", + "color2": "#ffbb00", + "color3": "#0700ff", + "speed": 0.1, + "density": 1.1, + "strength": 1, + "frequency": 5.5, + "amplitude": 1.4, + "brightness": 1.1, + "lighting": "ambient", + "environment": "city", + "reflection": 0.1, + "azimuth": 0, + "polar": 140, + "distance": 14, + "zoom": 17.3, + "fov": 45, + "posX": 0, + "posY": 0, + "posZ": 0, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "grain": 0 + } + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 420, + "y": 120 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-lab.out-out.color", + "source": "lab", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/backgrounds/mesh-gradient.json b/backgrounds/mesh-gradient.json new file mode 100644 index 0000000..2c92066 --- /dev/null +++ b/backgrounds/mesh-gradient.json @@ -0,0 +1,132 @@ +{ + "format": 1, + "domain": "background", + "name": "Mesh gradient", + "preset": "mesh-gradient", + "layer": { + "pointer": true, + "scroll": false + }, + "nodes": [ + { + "id": "uv", + "type": "aspectUv", + "position": { + "x": 40, + "y": 60 + }, + "data": {} + }, + { + "id": "ptr", + "type": "pointer", + "position": { + "x": 40, + "y": 220 + }, + "data": {} + }, + { + "id": "ptrUv", + "type": "aspectUv", + "position": { + "x": 240, + "y": 240 + }, + "data": {} + }, + { + "id": "mesh", + "type": "meshGradient", + "position": { + "x": 460, + "y": 80 + }, + "data": { + "colorA": "#ff7a9c", + "colorB": "#ffd58a", + "colorC": "#7a8cff", + "colorD": "#46d9c4", + "speed": 0.35, + "warp": 0.7, + "pull": 0.45, + "sharpness": 2.2 + } + }, + { + "id": "grain", + "type": "grain", + "position": { + "x": 460, + "y": 380 + }, + "data": { + "amount": 0.035, + "size": 1.5, + "animate": 1 + } + }, + { + "id": "mixed", + "type": "add", + "position": { + "x": 760, + "y": 160 + }, + "data": {} + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 980, + "y": 160 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-uv.out-mesh.uv", + "source": "uv", + "sourceHandle": "out", + "target": "mesh", + "targetHandle": "uv" + }, + { + "id": "e-ptr.position-ptrUv.uv", + "source": "ptr", + "sourceHandle": "position", + "target": "ptrUv", + "targetHandle": "uv" + }, + { + "id": "e-ptrUv.out-mesh.focus", + "source": "ptrUv", + "sourceHandle": "out", + "target": "mesh", + "targetHandle": "focus" + }, + { + "id": "e-mesh.out-mixed.a", + "source": "mesh", + "sourceHandle": "out", + "target": "mixed", + "targetHandle": "a" + }, + { + "id": "e-grain.out-mixed.b", + "source": "grain", + "sourceHandle": "out", + "target": "mixed", + "targetHandle": "b" + }, + { + "id": "e-mixed.out-out.color", + "source": "mixed", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/backgrounds/metaballs.json b/backgrounds/metaballs.json new file mode 100644 index 0000000..3989cc7 --- /dev/null +++ b/backgrounds/metaballs.json @@ -0,0 +1,308 @@ +{ + "format": 1, + "domain": "background", + "name": "Metaballs", + "preset": "metaballs", + "layer": { + "pointer": true, + "scroll": false + }, + "nodes": [ + { + "id": "uv", + "type": "aspectUv", + "position": { + "x": 40, + "y": 40 + }, + "data": {} + }, + { + "id": "ptr", + "type": "pointer", + "position": { + "x": 40, + "y": 220 + }, + "data": {} + }, + { + "id": "ptrUv", + "type": "aspectUv", + "position": { + "x": 240, + "y": 240 + }, + "data": {} + }, + { + "id": "blobs", + "type": "blobs", + "position": { + "x": 460, + "y": 60 + }, + "data": { + "count": 6, + "radius": 0.11, + "speed": 0.45, + "smoothness": 0.14, + "softness": 0.006, + "attractRadius": 0.085 + } + }, + { + "id": "chan", + "type": "split", + "position": { + "x": 260, + "y": 420 + }, + "data": {} + }, + { + "id": "bg", + "type": "gradient", + "position": { + "x": 700, + "y": 360 + }, + "data": { + "colorA": "#120a2a", + "colorB": "#1c1450", + "colorC": "#2a1a5e", + "mid": 0.5 + } + }, + { + "id": "fill", + "type": "gradient", + "position": { + "x": 700, + "y": 120 + }, + "data": { + "colorA": "#ff4fa3", + "colorB": "#ff9a5a", + "colorC": "#ffe46b", + "mid": 0.5 + } + }, + { + "id": "body", + "type": "mix", + "position": { + "x": 940, + "y": 200 + }, + "data": {} + }, + { + "id": "glowRise", + "type": "smoothstep", + "position": { + "x": 940, + "y": 420 + }, + "data": { + "edge0": 0, + "edge1": 0.16 + } + }, + { + "id": "glowW", + "type": "oneMinus", + "position": { + "x": 1000, + "y": 520 + }, + "data": {} + }, + { + "id": "glowAmt", + "type": "float", + "position": { + "x": 940, + "y": 560 + }, + "data": { + "value": 0.35 + } + }, + { + "id": "glow", + "type": "multiply", + "position": { + "x": 1140, + "y": 440 + }, + "data": {} + }, + { + "id": "glowCol", + "type": "color", + "position": { + "x": 1140, + "y": 600 + }, + "data": { + "value": "#ff6ad5" + } + }, + { + "id": "glowRgb", + "type": "multiply", + "position": { + "x": 1320, + "y": 460 + }, + "data": {} + }, + { + "id": "lit", + "type": "add", + "position": { + "x": 1500, + "y": 260 + }, + "data": {} + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 1700, + "y": 260 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-uv.out-blobs.uv", + "source": "uv", + "sourceHandle": "out", + "target": "blobs", + "targetHandle": "uv" + }, + { + "id": "e-ptr.position-ptrUv.uv", + "source": "ptr", + "sourceHandle": "position", + "target": "ptrUv", + "targetHandle": "uv" + }, + { + "id": "e-ptrUv.out-blobs.attract", + "source": "ptrUv", + "sourceHandle": "out", + "target": "blobs", + "targetHandle": "attract" + }, + { + "id": "e-uv.out-chan.value", + "source": "uv", + "sourceHandle": "out", + "target": "chan", + "targetHandle": "value" + }, + { + "id": "e-chan.y-bg.t", + "source": "chan", + "sourceHandle": "y", + "target": "bg", + "targetHandle": "t" + }, + { + "id": "e-chan.y-fill.t", + "source": "chan", + "sourceHandle": "y", + "target": "fill", + "targetHandle": "t" + }, + { + "id": "e-bg.out-body.a", + "source": "bg", + "sourceHandle": "out", + "target": "body", + "targetHandle": "a" + }, + { + "id": "e-fill.out-body.b", + "source": "fill", + "sourceHandle": "out", + "target": "body", + "targetHandle": "b" + }, + { + "id": "e-blobs.mask-body.t", + "source": "blobs", + "sourceHandle": "mask", + "target": "body", + "targetHandle": "t" + }, + { + "id": "e-blobs.sdf-glowRise.a", + "source": "blobs", + "sourceHandle": "sdf", + "target": "glowRise", + "targetHandle": "a" + }, + { + "id": "e-glowRise.out-glowW.a", + "source": "glowRise", + "sourceHandle": "out", + "target": "glowW", + "targetHandle": "a" + }, + { + "id": "e-glowW.out-glow.a", + "source": "glowW", + "sourceHandle": "out", + "target": "glow", + "targetHandle": "a" + }, + { + "id": "e-glowAmt.out-glow.b", + "source": "glowAmt", + "sourceHandle": "out", + "target": "glow", + "targetHandle": "b" + }, + { + "id": "e-glowCol.out-glowRgb.a", + "source": "glowCol", + "sourceHandle": "out", + "target": "glowRgb", + "targetHandle": "a" + }, + { + "id": "e-glow.out-glowRgb.b", + "source": "glow", + "sourceHandle": "out", + "target": "glowRgb", + "targetHandle": "b" + }, + { + "id": "e-body.out-lit.a", + "source": "body", + "sourceHandle": "out", + "target": "lit", + "targetHandle": "a" + }, + { + "id": "e-glowRgb.out-lit.b", + "source": "glowRgb", + "sourceHandle": "out", + "target": "lit", + "targetHandle": "b" + }, + { + "id": "e-lit.out-out.color", + "source": "lit", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/backgrounds/mint-tide.json b/backgrounds/mint-tide.json new file mode 100644 index 0000000..33e60d2 --- /dev/null +++ b/backgrounds/mint-tide.json @@ -0,0 +1,67 @@ +{ + "format": 1, + "domain": "background", + "name": "Mint tide", + "preset": "mint-tide", + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper", + "layer": { + "pointer": false, + "scroll": false + }, + "nodes": [ + { + "id": "lab", + "type": "gradientLab", + "position": { + "x": 80, + "y": 80 + }, + "data": { + "shape": "waterPlane", + "color1": "#94ffd1", + "color2": "#6bf5ff", + "color3": "#ffffff", + "speed": 0.2, + "density": 1.2, + "strength": 3.4, + "frequency": 0, + "amplitude": 0, + "brightness": 1.2, + "lighting": "ambient", + "environment": "city", + "reflection": 0.1, + "azimuth": 170, + "polar": 70, + "distance": 4.4, + "zoom": 1, + "fov": 45, + "posX": 0, + "posY": 0.9, + "posZ": -0.3, + "rotX": 45, + "rotY": 0, + "rotZ": 0, + "grain": 0 + } + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 420, + "y": 120 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-lab.out-out.color", + "source": "lab", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/backgrounds/night-swell.json b/backgrounds/night-swell.json new file mode 100644 index 0000000..84a83dc --- /dev/null +++ b/backgrounds/night-swell.json @@ -0,0 +1,67 @@ +{ + "format": 1, + "domain": "background", + "name": "Night swell", + "preset": "night-swell", + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper", + "layer": { + "pointer": false, + "scroll": false + }, + "nodes": [ + { + "id": "lab", + "type": "gradientLab", + "position": { + "x": 80, + "y": 80 + }, + "data": { + "shape": "waterPlane", + "color1": "#606080", + "color2": "#8d7dca", + "color3": "#212121", + "speed": 0.3, + "density": 1.5, + "strength": 1.5, + "frequency": 0, + "amplitude": 0, + "brightness": 1, + "lighting": "ambient", + "environment": "city", + "reflection": 0.1, + "azimuth": 180, + "polar": 80, + "distance": 2.8, + "zoom": 1, + "fov": 45, + "posX": 0, + "posY": 0, + "posZ": 0, + "rotX": 50, + "rotY": 0, + "rotZ": -60, + "grain": 1 + } + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 420, + "y": 120 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-lab.out-out.color", + "source": "lab", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/backgrounds/noise-flow.json b/backgrounds/noise-flow.json new file mode 100644 index 0000000..cd46119 --- /dev/null +++ b/backgrounds/noise-flow.json @@ -0,0 +1,400 @@ +{ + "format": 1, + "domain": "background", + "name": "Noise flow", + "preset": "noise-flow", + "layer": { + "pointer": true, + "scroll": false + }, + "nodes": [ + { + "id": "uv", + "type": "aspectUv", + "position": { + "x": 40, + "y": 40 + }, + "data": {} + }, + { + "id": "ptr", + "type": "pointer", + "position": { + "x": 40, + "y": 200 + }, + "data": {} + }, + { + "id": "ptrUv", + "type": "aspectUv", + "position": { + "x": 240, + "y": 220 + }, + "data": {} + }, + { + "id": "toward", + "type": "subtract", + "position": { + "x": 440, + "y": 160 + }, + "data": {} + }, + { + "id": "pullAmt", + "type": "float", + "position": { + "x": 440, + "y": 320 + }, + "data": { + "value": 0.08 + } + }, + { + "id": "pull", + "type": "multiply", + "position": { + "x": 640, + "y": 180 + }, + "data": {} + }, + { + "id": "bent", + "type": "add", + "position": { + "x": 640, + "y": 40 + }, + "data": {} + }, + { + "id": "warp", + "type": "domainWarp", + "position": { + "x": 840, + "y": 40 + }, + "data": { + "amount": 0.7, + "scale": 2.2, + "speed": 0.07 + } + }, + { + "id": "field", + "type": "fbm", + "position": { + "x": 1040, + "y": 40 + }, + "data": { + "scale": 2.6, + "octaves": 5, + "lacunarity": 2, + "gain": 0.5 + } + }, + { + "id": "bands", + "type": "float", + "position": { + "x": 1040, + "y": 220 + }, + "data": { + "value": 9 + } + }, + { + "id": "scaled", + "type": "multiply", + "position": { + "x": 1240, + "y": 60 + }, + "data": {} + }, + { + "id": "time", + "type": "time", + "position": { + "x": 1240, + "y": 220 + }, + "data": { + "speed": 0.25 + } + }, + { + "id": "moving", + "type": "subtract", + "position": { + "x": 1420, + "y": 100 + }, + "data": {} + }, + { + "id": "wrap", + "type": "fract", + "position": { + "x": 1600, + "y": 100 + }, + "data": {} + }, + { + "id": "half", + "type": "float", + "position": { + "x": 1600, + "y": 240 + }, + "data": { + "value": 0.5 + } + }, + { + "id": "centre", + "type": "subtract", + "position": { + "x": 1780, + "y": 120 + }, + "data": {} + }, + { + "id": "dist", + "type": "abs", + "position": { + "x": 1960, + "y": 120 + }, + "data": {} + }, + { + "id": "line", + "type": "smoothstep", + "position": { + "x": 2140, + "y": 120 + }, + "data": { + "edge0": 0.4, + "edge1": 0.5 + } + }, + { + "id": "ramp", + "type": "gradient", + "position": { + "x": 1960, + "y": 300 + }, + "data": { + "colorA": "#05070f", + "colorB": "#0f2b4a", + "colorC": "#1a6b7a", + "mid": 0.55 + } + }, + { + "id": "ink", + "type": "color", + "position": { + "x": 2140, + "y": 300 + }, + "data": { + "value": "#9ff6ff" + } + }, + { + "id": "mixed", + "type": "mix", + "position": { + "x": 2340, + "y": 200 + }, + "data": {} + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 2540, + "y": 200 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-ptr.position-ptrUv.uv", + "source": "ptr", + "sourceHandle": "position", + "target": "ptrUv", + "targetHandle": "uv" + }, + { + "id": "e-ptrUv.out-toward.a", + "source": "ptrUv", + "sourceHandle": "out", + "target": "toward", + "targetHandle": "a" + }, + { + "id": "e-uv.out-toward.b", + "source": "uv", + "sourceHandle": "out", + "target": "toward", + "targetHandle": "b" + }, + { + "id": "e-toward.out-pull.a", + "source": "toward", + "sourceHandle": "out", + "target": "pull", + "targetHandle": "a" + }, + { + "id": "e-pullAmt.out-pull.b", + "source": "pullAmt", + "sourceHandle": "out", + "target": "pull", + "targetHandle": "b" + }, + { + "id": "e-uv.out-bent.a", + "source": "uv", + "sourceHandle": "out", + "target": "bent", + "targetHandle": "a" + }, + { + "id": "e-pull.out-bent.b", + "source": "pull", + "sourceHandle": "out", + "target": "bent", + "targetHandle": "b" + }, + { + "id": "e-bent.out-warp.uv", + "source": "bent", + "sourceHandle": "out", + "target": "warp", + "targetHandle": "uv" + }, + { + "id": "e-warp.out-field.uv", + "source": "warp", + "sourceHandle": "out", + "target": "field", + "targetHandle": "uv" + }, + { + "id": "e-field.out-scaled.a", + "source": "field", + "sourceHandle": "out", + "target": "scaled", + "targetHandle": "a" + }, + { + "id": "e-bands.out-scaled.b", + "source": "bands", + "sourceHandle": "out", + "target": "scaled", + "targetHandle": "b" + }, + { + "id": "e-scaled.out-moving.a", + "source": "scaled", + "sourceHandle": "out", + "target": "moving", + "targetHandle": "a" + }, + { + "id": "e-time.out-moving.b", + "source": "time", + "sourceHandle": "out", + "target": "moving", + "targetHandle": "b" + }, + { + "id": "e-moving.out-wrap.a", + "source": "moving", + "sourceHandle": "out", + "target": "wrap", + "targetHandle": "a" + }, + { + "id": "e-wrap.out-centre.a", + "source": "wrap", + "sourceHandle": "out", + "target": "centre", + "targetHandle": "a" + }, + { + "id": "e-half.out-centre.b", + "source": "half", + "sourceHandle": "out", + "target": "centre", + "targetHandle": "b" + }, + { + "id": "e-centre.out-dist.a", + "source": "centre", + "sourceHandle": "out", + "target": "dist", + "targetHandle": "a" + }, + { + "id": "e-dist.out-line.a", + "source": "dist", + "sourceHandle": "out", + "target": "line", + "targetHandle": "a" + }, + { + "id": "e-field.out-ramp.t", + "source": "field", + "sourceHandle": "out", + "target": "ramp", + "targetHandle": "t" + }, + { + "id": "e-ramp.out-mixed.a", + "source": "ramp", + "sourceHandle": "out", + "target": "mixed", + "targetHandle": "a" + }, + { + "id": "e-ink.out-mixed.b", + "source": "ink", + "sourceHandle": "out", + "target": "mixed", + "targetHandle": "b" + }, + { + "id": "e-line.out-mixed.t", + "source": "line", + "sourceHandle": "out", + "target": "mixed", + "targetHandle": "t" + }, + { + "id": "e-mixed.out-out.color", + "source": "mixed", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/backgrounds/silk-gradient.json b/backgrounds/silk-gradient.json new file mode 100644 index 0000000..3ce6e49 --- /dev/null +++ b/backgrounds/silk-gradient.json @@ -0,0 +1,423 @@ +{ + "format": 1, + "domain": "background", + "name": "Silk gradient", + "preset": "silk-gradient", + "layer": { + "pointer": true, + "scroll": true + }, + "nodes": [ + { + "id": "uv", + "type": "aspectUv", + "position": { + "x": 40, + "y": 40 + }, + "data": {} + }, + { + "id": "ptr", + "type": "pointer", + "position": { + "x": 40, + "y": 200 + }, + "data": {} + }, + { + "id": "nudgeAmt", + "type": "float", + "position": { + "x": 40, + "y": 330 + }, + "data": { + "value": 0.06 + } + }, + { + "id": "nudge", + "type": "multiply", + "position": { + "x": 240, + "y": 220 + }, + "data": {} + }, + { + "id": "shifted", + "type": "add", + "position": { + "x": 240, + "y": 60 + }, + "data": {} + }, + { + "id": "tilt", + "type": "rotateUv", + "position": { + "x": 440, + "y": 60 + }, + "data": { + "angle": -14, + "speed": 0, + "center": [ + 0.5, + 0.5 + ] + } + }, + { + "id": "warp", + "type": "domainWarp", + "position": { + "x": 640, + "y": 60 + }, + "data": { + "amount": 0.55, + "scale": 1.4, + "speed": 0.05 + } + }, + { + "id": "chan", + "type": "split", + "position": { + "x": 840, + "y": 20 + }, + "data": {} + }, + { + "id": "folds", + "type": "fbm", + "position": { + "x": 840, + "y": 200 + }, + "data": { + "scale": 1.6, + "octaves": 3, + "lacunarity": 2, + "gain": 0.5 + } + }, + { + "id": "xw", + "type": "float", + "position": { + "x": 840, + "y": 380 + }, + "data": { + "value": 0.85 + } + }, + { + "id": "xs", + "type": "multiply", + "position": { + "x": 1040, + "y": 20 + }, + "data": {} + }, + { + "id": "fw", + "type": "float", + "position": { + "x": 1040, + "y": 380 + }, + "data": { + "value": 0.55 + } + }, + { + "id": "fs", + "type": "multiply", + "position": { + "x": 1040, + "y": 200 + }, + "data": {} + }, + { + "id": "scroll", + "type": "scroll", + "position": { + "x": 1040, + "y": 500 + }, + "data": {} + }, + { + "id": "sw", + "type": "float", + "position": { + "x": 1040, + "y": 620 + }, + "data": { + "value": 0.45 + } + }, + { + "id": "ss", + "type": "multiply", + "position": { + "x": 1240, + "y": 500 + }, + "data": {} + }, + { + "id": "t1", + "type": "add", + "position": { + "x": 1240, + "y": 100 + }, + "data": {} + }, + { + "id": "t", + "type": "add", + "position": { + "x": 1420, + "y": 160 + }, + "data": {} + }, + { + "id": "ramp", + "type": "gradient", + "position": { + "x": 1600, + "y": 120 + }, + "data": { + "colorA": "#1d2a7a", + "colorB": "#c23bd4", + "colorC": "#ffb067", + "mid": 0.48 + } + }, + { + "id": "cyan", + "type": "color", + "position": { + "x": 1600, + "y": 340 + }, + "data": { + "value": "#52e5ff" + } + }, + { + "id": "hl", + "type": "smoothstep", + "position": { + "x": 1600, + "y": 470 + }, + "data": { + "edge0": 0.62, + "edge1": 0.9 + } + }, + { + "id": "silk", + "type": "mix", + "position": { + "x": 1820, + "y": 200 + }, + "data": {} + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 2040, + "y": 200 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-ptr.position-nudge.a", + "source": "ptr", + "sourceHandle": "position", + "target": "nudge", + "targetHandle": "a" + }, + { + "id": "e-nudgeAmt.out-nudge.b", + "source": "nudgeAmt", + "sourceHandle": "out", + "target": "nudge", + "targetHandle": "b" + }, + { + "id": "e-uv.out-shifted.a", + "source": "uv", + "sourceHandle": "out", + "target": "shifted", + "targetHandle": "a" + }, + { + "id": "e-nudge.out-shifted.b", + "source": "nudge", + "sourceHandle": "out", + "target": "shifted", + "targetHandle": "b" + }, + { + "id": "e-shifted.out-tilt.uv", + "source": "shifted", + "sourceHandle": "out", + "target": "tilt", + "targetHandle": "uv" + }, + { + "id": "e-tilt.out-warp.uv", + "source": "tilt", + "sourceHandle": "out", + "target": "warp", + "targetHandle": "uv" + }, + { + "id": "e-warp.out-chan.value", + "source": "warp", + "sourceHandle": "out", + "target": "chan", + "targetHandle": "value" + }, + { + "id": "e-warp.out-folds.uv", + "source": "warp", + "sourceHandle": "out", + "target": "folds", + "targetHandle": "uv" + }, + { + "id": "e-chan.x-xs.a", + "source": "chan", + "sourceHandle": "x", + "target": "xs", + "targetHandle": "a" + }, + { + "id": "e-xw.out-xs.b", + "source": "xw", + "sourceHandle": "out", + "target": "xs", + "targetHandle": "b" + }, + { + "id": "e-folds.out-fs.a", + "source": "folds", + "sourceHandle": "out", + "target": "fs", + "targetHandle": "a" + }, + { + "id": "e-fw.out-fs.b", + "source": "fw", + "sourceHandle": "out", + "target": "fs", + "targetHandle": "b" + }, + { + "id": "e-scroll.progress-ss.a", + "source": "scroll", + "sourceHandle": "progress", + "target": "ss", + "targetHandle": "a" + }, + { + "id": "e-sw.out-ss.b", + "source": "sw", + "sourceHandle": "out", + "target": "ss", + "targetHandle": "b" + }, + { + "id": "e-xs.out-t1.a", + "source": "xs", + "sourceHandle": "out", + "target": "t1", + "targetHandle": "a" + }, + { + "id": "e-fs.out-t1.b", + "source": "fs", + "sourceHandle": "out", + "target": "t1", + "targetHandle": "b" + }, + { + "id": "e-t1.out-t.a", + "source": "t1", + "sourceHandle": "out", + "target": "t", + "targetHandle": "a" + }, + { + "id": "e-ss.out-t.b", + "source": "ss", + "sourceHandle": "out", + "target": "t", + "targetHandle": "b" + }, + { + "id": "e-t.out-ramp.t", + "source": "t", + "sourceHandle": "out", + "target": "ramp", + "targetHandle": "t" + }, + { + "id": "e-folds.out-hl.a", + "source": "folds", + "sourceHandle": "out", + "target": "hl", + "targetHandle": "a" + }, + { + "id": "e-ramp.out-silk.a", + "source": "ramp", + "sourceHandle": "out", + "target": "silk", + "targetHandle": "a" + }, + { + "id": "e-cyan.out-silk.b", + "source": "cyan", + "sourceHandle": "out", + "target": "silk", + "targetHandle": "b" + }, + { + "id": "e-hl.out-silk.t", + "source": "hl", + "sourceHandle": "out", + "target": "silk", + "targetHandle": "t" + }, + { + "id": "e-silk.out-out.color", + "source": "silk", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/backgrounds/tangerine-sea.json b/backgrounds/tangerine-sea.json new file mode 100644 index 0000000..d021a15 --- /dev/null +++ b/backgrounds/tangerine-sea.json @@ -0,0 +1,67 @@ +{ + "format": 1, + "domain": "background", + "name": "Tangerine sea", + "preset": "tangerine-sea", + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper", + "layer": { + "pointer": false, + "scroll": false + }, + "nodes": [ + { + "id": "lab", + "type": "gradientLab", + "position": { + "x": 80, + "y": 80 + }, + "data": { + "shape": "waterPlane", + "color1": "#ff6a1a", + "color2": "#c73c00", + "color3": "#fd4912", + "speed": 0.2, + "density": 1.8, + "strength": 3, + "frequency": 0, + "amplitude": 0, + "brightness": 1.2, + "lighting": "ambient", + "environment": "city", + "reflection": 0.1, + "azimuth": 180, + "polar": 95, + "distance": 2.4, + "zoom": 1, + "fov": 45, + "posX": 0, + "posY": -2.1, + "posZ": 0, + "rotX": 0, + "rotY": 0, + "rotZ": 225, + "grain": 0 + } + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 420, + "y": 120 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-lab.out-out.color", + "source": "lab", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/backgrounds/violet-orb.json b/backgrounds/violet-orb.json new file mode 100644 index 0000000..af60bd1 --- /dev/null +++ b/backgrounds/violet-orb.json @@ -0,0 +1,67 @@ +{ + "format": 1, + "domain": "background", + "name": "Violet orb", + "preset": "violet-orb", + "license": "MIT", + "attribution": "Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper", + "layer": { + "pointer": false, + "scroll": false + }, + "nodes": [ + { + "id": "lab", + "type": "gradientLab", + "position": { + "x": 80, + "y": 80 + }, + "data": { + "shape": "sphere", + "color1": "#809bd6", + "color2": "#910aff", + "color3": "#af38ff", + "speed": 0.3, + "density": 0.8, + "strength": 0.4, + "frequency": 5.5, + "amplitude": 7, + "brightness": 1.5, + "lighting": "ambient", + "environment": "city", + "reflection": 0.1, + "azimuth": 250, + "polar": 140, + "distance": 14, + "zoom": 12.5, + "fov": 45, + "posX": 0, + "posY": 0, + "posZ": 0, + "rotX": 0, + "rotY": 0, + "rotZ": 140, + "grain": 1 + } + }, + { + "id": "out", + "type": "backgroundOutput", + "position": { + "x": 420, + "y": 120 + }, + "data": {} + } + ], + "edges": [ + { + "id": "e-lab.out-out.color", + "source": "lab", + "sourceHandle": "out", + "target": "out", + "targetHandle": "color" + } + ] +} diff --git a/tools/backgrounds/build.cjs b/tools/backgrounds/build.cjs new file mode 100644 index 0000000..6275ea6 --- /dev/null +++ b/tools/backgrounds/build.cjs @@ -0,0 +1,410 @@ +#!/usr/bin/env node +// Builds backgrounds/*.json + backgrounds/index.json — the fluid shader BACKGROUND presets +// (core roadmap 65 M2). Each preset is an ORDINARY background-domain shader graph: the same +// document a person gets by building it node by node in the app's Shader editor (Background +// tab), so "delete a node and see what changes" is how the vocabulary is learnt. Positions +// are authored left-to-right because these are the first background graphs most people open. +// +// 65 gradient adds the GRADIENT family: eight looks close to ShaderGradient's well-known presets +// (github.com/ruucm/shadergradient, MIT © ruucm, stone-skipper — the parameter sets are adapted +// from its presets.ts, so those rows carry its licence; see backgrounds/ATTRIBUTION.md), each a +// two-node graph: the core's Gradient lab node into the Background output. Their index rows name +// the node in `needs`, so a build of the app without it never lists them. +// +// node tools/backgrounds/build.cjs writes the files +// node tools/backgrounds/build.cjs --check exits 1 when the committed files are stale +const fs = require('fs'); +const path = require('path'); + +const OUT = path.join(__dirname, '..', '..', 'backgrounds'); +/** the document format the app reads (core src/lib/backgroundPresets.js PRESET_FORMAT) */ +const FORMAT = 1; + +const node = (id, type, x, y, data = {}) => ({ id, type, position: { x, y }, data }); +// the editor's canonical edge id shape, handles included +const edge = (source, sourceHandle, target, targetHandle) => ({ + id: 'e-' + source + '.' + sourceHandle + '-' + target + '.' + targetHandle, + source, + sourceHandle, + target, + targetHandle +}); +const num = (id, value, x, y) => node(id, 'float', x, y, { value }); + +const PRESETS = [ + { + key: 'mesh-gradient', + label: 'Mesh gradient', + hint: 'Four soft colours drifting into each other; the first one leans towards your pointer.', + layer: { pointer: true, scroll: false }, + nodes: [ + node('uv', 'aspectUv', 40, 60), + node('ptr', 'pointer', 40, 220), + node('ptrUv', 'aspectUv', 240, 240), + node('mesh', 'meshGradient', 460, 80, { + colorA: '#ff7a9c', colorB: '#ffd58a', colorC: '#7a8cff', colorD: '#46d9c4', + speed: 0.35, warp: 0.7, pull: 0.45, sharpness: 2.2 + }), + node('grain', 'grain', 460, 380, { amount: 0.035, size: 1.5, animate: 1 }), + node('mixed', 'add', 760, 160), + node('out', 'backgroundOutput', 980, 160) + ], + edges: [ + edge('uv', 'out', 'mesh', 'uv'), + edge('ptr', 'position', 'ptrUv', 'uv'), + edge('ptrUv', 'out', 'mesh', 'focus'), + edge('mesh', 'out', 'mixed', 'a'), + edge('grain', 'out', 'mixed', 'b'), + edge('mixed', 'out', 'out', 'color') + ] + }, + { + key: 'silk-gradient', + label: 'Silk gradient', + hint: 'A tilted, slowly folding ribbon of colour in the style of modern product pages. Scrolling shifts the palette; the pointer nudges the folds.', + layer: { pointer: true, scroll: true }, + nodes: [ + node('uv', 'aspectUv', 40, 40), + node('ptr', 'pointer', 40, 200), + node('nudgeAmt', 'float', 40, 330, { value: 0.06 }), + node('nudge', 'multiply', 240, 220), + node('shifted', 'add', 240, 60), + node('tilt', 'rotateUv', 440, 60, { angle: -14, speed: 0, center: [0.5, 0.5] }), + node('warp', 'domainWarp', 640, 60, { amount: 0.55, scale: 1.4, speed: 0.05 }), + node('chan', 'split', 840, 20), + node('folds', 'fbm', 840, 200, { scale: 1.6, octaves: 3, lacunarity: 2, gain: 0.5 }), + node('xw', 'float', 840, 380, { value: 0.85 }), + node('xs', 'multiply', 1040, 20), + node('fw', 'float', 1040, 380, { value: 0.55 }), + node('fs', 'multiply', 1040, 200), + node('scroll', 'scroll', 1040, 500), + node('sw', 'float', 1040, 620, { value: 0.45 }), + node('ss', 'multiply', 1240, 500), + node('t1', 'add', 1240, 100), + node('t', 'add', 1420, 160), + node('ramp', 'gradient', 1600, 120, { colorA: '#1d2a7a', colorB: '#c23bd4', colorC: '#ffb067', mid: 0.48 }), + node('cyan', 'color', 1600, 340, { value: '#52e5ff' }), + node('hl', 'smoothstep', 1600, 470, { edge0: 0.62, edge1: 0.9 }), + node('silk', 'mix', 1820, 200), + node('out', 'backgroundOutput', 2040, 200) + ], + edges: [ + edge('ptr', 'position', 'nudge', 'a'), + edge('nudgeAmt', 'out', 'nudge', 'b'), + edge('uv', 'out', 'shifted', 'a'), + edge('nudge', 'out', 'shifted', 'b'), + edge('shifted', 'out', 'tilt', 'uv'), + edge('tilt', 'out', 'warp', 'uv'), + edge('warp', 'out', 'chan', 'value'), + edge('warp', 'out', 'folds', 'uv'), + edge('chan', 'x', 'xs', 'a'), + edge('xw', 'out', 'xs', 'b'), + edge('folds', 'out', 'fs', 'a'), + edge('fw', 'out', 'fs', 'b'), + edge('scroll', 'progress', 'ss', 'a'), + edge('sw', 'out', 'ss', 'b'), + edge('xs', 'out', 't1', 'a'), + edge('fs', 'out', 't1', 'b'), + edge('t1', 'out', 't', 'a'), + edge('ss', 'out', 't', 'b'), + edge('t', 'out', 'ramp', 't'), + edge('folds', 'out', 'hl', 'a'), + edge('ramp', 'out', 'silk', 'a'), + edge('cyan', 'out', 'silk', 'b'), + edge('hl', 'out', 'silk', 't'), + edge('silk', 'out', 'out', 'color') + ] + }, + { + key: 'noise-flow', + label: 'Noise flow', + hint: 'Contour lines streaming through warped noise, like wind on a weather map. The flow bends towards your pointer.', + layer: { pointer: true, scroll: false }, + nodes: [ + node('uv', 'aspectUv', 40, 40), + node('ptr', 'pointer', 40, 200), + node('ptrUv', 'aspectUv', 240, 220), + node('toward', 'subtract', 440, 160), + node('pullAmt', 'float', 440, 320, { value: 0.08 }), + node('pull', 'multiply', 640, 180), + node('bent', 'add', 640, 40), + node('warp', 'domainWarp', 840, 40, { amount: 0.7, scale: 2.2, speed: 0.07 }), + node('field', 'fbm', 1040, 40, { scale: 2.6, octaves: 5, lacunarity: 2, gain: 0.5 }), + node('bands', 'float', 1040, 220, { value: 9 }), + node('scaled', 'multiply', 1240, 60), + node('time', 'time', 1240, 220, { speed: 0.25 }), + node('moving', 'subtract', 1420, 100), + node('wrap', 'fract', 1600, 100), + node('half', 'float', 1600, 240, { value: 0.5 }), + node('centre', 'subtract', 1780, 120), + node('dist', 'abs', 1960, 120), + node('line', 'smoothstep', 2140, 120, { edge0: 0.4, edge1: 0.5 }), + node('ramp', 'gradient', 1960, 300, { colorA: '#05070f', colorB: '#0f2b4a', colorC: '#1a6b7a', mid: 0.55 }), + node('ink', 'color', 2140, 300, { value: '#9ff6ff' }), + node('mixed', 'mix', 2340, 200), + node('out', 'backgroundOutput', 2540, 200) + ], + edges: [ + edge('ptr', 'position', 'ptrUv', 'uv'), + edge('ptrUv', 'out', 'toward', 'a'), + edge('uv', 'out', 'toward', 'b'), + edge('toward', 'out', 'pull', 'a'), + edge('pullAmt', 'out', 'pull', 'b'), + edge('uv', 'out', 'bent', 'a'), + edge('pull', 'out', 'bent', 'b'), + edge('bent', 'out', 'warp', 'uv'), + edge('warp', 'out', 'field', 'uv'), + edge('field', 'out', 'scaled', 'a'), + edge('bands', 'out', 'scaled', 'b'), + edge('scaled', 'out', 'moving', 'a'), + edge('time', 'out', 'moving', 'b'), + edge('moving', 'out', 'wrap', 'a'), + edge('wrap', 'out', 'centre', 'a'), + edge('half', 'out', 'centre', 'b'), + edge('centre', 'out', 'dist', 'a'), + edge('dist', 'out', 'line', 'a'), + edge('field', 'out', 'ramp', 't'), + edge('ramp', 'out', 'mixed', 'a'), + edge('ink', 'out', 'mixed', 'b'), + edge('line', 'out', 'mixed', 't'), + edge('mixed', 'out', 'out', 'color') + ] + }, + { + key: 'metaballs', + label: 'Metaballs', + hint: 'Glossy blobs that melt into each other like a lava lamp; one of them follows your pointer.', + layer: { pointer: true, scroll: false }, + nodes: [ + node('uv', 'aspectUv', 40, 40), + node('ptr', 'pointer', 40, 220), + node('ptrUv', 'aspectUv', 240, 240), + node('blobs', 'blobs', 460, 60, { count: 6, radius: 0.11, speed: 0.45, smoothness: 0.14, softness: 0.006, attractRadius: 0.085 }), + node('chan', 'split', 260, 420), + node('bg', 'gradient', 700, 360, { colorA: '#120a2a', colorB: '#1c1450', colorC: '#2a1a5e', mid: 0.5 }), + node('fill', 'gradient', 700, 120, { colorA: '#ff4fa3', colorB: '#ff9a5a', colorC: '#ffe46b', mid: 0.5 }), + node('body', 'mix', 940, 200), + // GLSL leaves smoothstep undefined for edge0 >= edge1, so a falloff is One minus a rise + node('glowRise', 'smoothstep', 940, 420, { edge0: 0.0, edge1: 0.16 }), + node('glowW', 'oneMinus', 1000, 520), + node('glowAmt', 'float', 940, 560, { value: 0.35 }), + node('glow', 'multiply', 1140, 440), + node('glowCol', 'color', 1140, 600, { value: '#ff6ad5' }), + node('glowRgb', 'multiply', 1320, 460), + node('lit', 'add', 1500, 260), + node('out', 'backgroundOutput', 1700, 260) + ], + edges: [ + edge('uv', 'out', 'blobs', 'uv'), + edge('ptr', 'position', 'ptrUv', 'uv'), + edge('ptrUv', 'out', 'blobs', 'attract'), + edge('uv', 'out', 'chan', 'value'), + edge('chan', 'y', 'bg', 't'), + edge('chan', 'y', 'fill', 't'), + edge('bg', 'out', 'body', 'a'), + edge('fill', 'out', 'body', 'b'), + edge('blobs', 'mask', 'body', 't'), + edge('blobs', 'sdf', 'glowRise', 'a'), + edge('glowRise', 'out', 'glowW', 'a'), + edge('glowW', 'out', 'glow', 'a'), + edge('glowAmt', 'out', 'glow', 'b'), + edge('glowCol', 'out', 'glowRgb', 'a'), + edge('glow', 'out', 'glowRgb', 'b'), + edge('body', 'out', 'lit', 'a'), + edge('glowRgb', 'out', 'lit', 'b'), + edge('lit', 'out', 'out', 'color') + ] + }, + { + key: 'grain-dither', + label: 'Grain & dither', + hint: 'A soft dusk gradient broken into retro dither steps with film grain on top; a pool of light follows your pointer.', + layer: { pointer: true, scroll: false }, + nodes: [ + node('uv', 'aspectUv', 40, 40), + node('chan', 'split', 240, 40), + node('cloud', 'fbm', 240, 220, { scale: 2, octaves: 4, lacunarity: 2, gain: 0.5 }), + node('cloudAmt', 'float', 240, 400, { value: 0.22 }), + node('cloudS', 'multiply', 440, 260), + node('t', 'add', 620, 100), + node('ramp', 'gradient', 800, 80, { colorA: '#2b1b4a', colorB: '#c4577a', colorC: '#ffc98a', mid: 0.42 }), + node('ptr', 'pointer', 40, 560), + node('ptrUv', 'aspectUv', 240, 560), + node('dist', 'distance', 440, 520), + node('spotRise', 'smoothstep', 620, 460, { edge0: 0.0, edge1: 0.35 }), + node('spot', 'oneMinus', 660, 580), + node('spotAmt', 'float', 620, 680, { value: 0.35 }), + node('spotS', 'multiply', 800, 540), + node('lit', 'add', 1000, 200), + node('bayer', 'bayer', 1000, 420, { scale: 2 }), + node('half', 'float', 1000, 560, { value: 0.5 }), + node('centred', 'subtract', 1180, 440), + node('depth', 'float', 1180, 600, { value: 0.16 }), + node('dither', 'multiply', 1360, 460), + node('dithered', 'add', 1360, 220), + node('steps', 'posterize', 1540, 220, { steps: 7 }), + node('grain', 'grain', 1540, 420, { amount: 0.05, size: 2, animate: 1 }), + node('final', 'add', 1740, 260), + node('out', 'backgroundOutput', 1940, 260) + ], + edges: [ + edge('uv', 'out', 'chan', 'value'), + edge('uv', 'out', 'cloud', 'uv'), + edge('cloud', 'out', 'cloudS', 'a'), + edge('cloudAmt', 'out', 'cloudS', 'b'), + edge('chan', 'y', 't', 'a'), + edge('cloudS', 'out', 't', 'b'), + edge('t', 'out', 'ramp', 't'), + edge('ptr', 'position', 'ptrUv', 'uv'), + edge('uv', 'out', 'dist', 'a'), + edge('ptrUv', 'out', 'dist', 'b'), + edge('dist', 'out', 'spotRise', 'a'), + edge('spotRise', 'out', 'spot', 'a'), + edge('spot', 'out', 'spotS', 'a'), + edge('spotAmt', 'out', 'spotS', 'b'), + edge('ramp', 'out', 'lit', 'a'), + edge('spotS', 'out', 'lit', 'b'), + edge('bayer', 'out', 'centred', 'a'), + edge('half', 'out', 'centred', 'b'), + edge('centred', 'out', 'dither', 'a'), + edge('depth', 'out', 'dither', 'b'), + edge('lit', 'out', 'dithered', 'a'), + edge('dither', 'out', 'dithered', 'b'), + edge('dithered', 'out', 'steps', 'a'), + edge('steps', 'out', 'final', 'a'), + edge('grain', 'out', 'final', 'b'), + edge('final', 'out', 'out', 'color') + ] + } +]; + +// ---- the Gradient family (65 gradient) -------------------------------------------------------- +/** the Gradient lab node's params, mirroring core src/lib/gradientLabCore.js GRADIENT_PARAMS defaults + * (the app normalizes whatever a file holds, so a key left out only takes the default) */ +const LAB_DEFAULTS = { + shape: 'plane', color1: '#ff5005', color2: '#dbba95', color3: '#d0bce1', speed: 0.4, density: 1.3, strength: 4, + frequency: 5.5, amplitude: 1, brightness: 1.2, lighting: 'ambient', environment: 'city', reflection: 0.1, + azimuth: 180, polar: 90, distance: 3.6, zoom: 1, fov: 45, posX: -1.4, posY: 0, posZ: 0, rotX: 0, rotY: 10, rotZ: 50, grain: 1 +}; +const SPHERE = { shape: 'sphere', distance: 14, posX: 0, posY: 0, posZ: 0, rotX: 0, rotY: 0, rotZ: 0 }; +const WATER = { shape: 'waterPlane', amplitude: 0, frequency: 0, posX: 0, posY: 0, posZ: 0, rotX: 0, rotY: 0, rotZ: 0 }; +const GRADIENTS = [ + { + key: 'ember-ribbon', + label: 'Ember ribbon', + hint: 'A warm ribbon of orange, sand and lilac folding slowly across the frame, with a fine print grain.', + lab: { speed: 0.4, density: 1.3, strength: 4 } + }, + { + key: 'violet-orb', + label: 'Violet orb', + hint: 'Seen up close, a sphere of periwinkle and violet that twists into soft spirals.', + lab: { ...SPHERE, color1: '#809bd6', color2: '#910aff', color3: '#af38ff', azimuth: 250, polar: 140, zoom: 12.5, rotZ: 140, amplitude: 7, density: 0.8, speed: 0.3, strength: 0.4, brightness: 1.5 } + }, + { + key: 'mint-tide', + label: 'Mint tide', + hint: 'Rolling swells of mint and aqua fading to white, like light under shallow water. No grain.', + lab: { ...WATER, color1: '#94ffd1', color2: '#6bf5ff', color3: '#ffffff', azimuth: 170, polar: 70, distance: 4.4, posY: 0.9, posZ: -0.3, rotX: 45, density: 1.2, speed: 0.2, strength: 3.4, grain: 0 } + }, + { + key: 'glass-orbit', + label: 'Glass orbit', + hint: 'A glossy teal and amber sphere seen from below, catching soft reflections from a studio around it.', + lab: { ...SPHERE, color1: '#73bfc4', color2: '#ff810a', color3: '#8da0ce', lighting: 'environment', reflection: 0.4, azimuth: 270, polar: 180, zoom: 15.1, posX: -0.1, rotY: 130, rotZ: 70, amplitude: 3.2, density: 0.8, speed: 0.3, strength: 0.3, brightness: 0.8 } + }, + { + key: 'night-swell', + label: 'Night swell', + hint: 'Slate and lavender waves rising out of near black: a calm, dark backdrop.', + lab: { ...WATER, color1: '#606080', color2: '#8d7dca', color3: '#212121', azimuth: 180, polar: 80, distance: 2.8, rotX: 50, rotZ: -60, density: 1.5, speed: 0.3, strength: 1.5, brightness: 1 } + }, + { + key: 'indigo-bloom', + label: 'Indigo bloom', + hint: 'White and gold blooming out of deep indigo on a slowly turning sphere. No grain.', + lab: { ...SPHERE, color1: '#ffffff', color2: '#ffbb00', color3: '#0700ff', azimuth: 0, polar: 140, zoom: 17.3, amplitude: 1.4, density: 1.1, speed: 0.1, strength: 1, brightness: 1.1, grain: 0 } + }, + { + key: 'deep-space', + label: 'Deep space', + hint: 'Electric violet and coral drifting through black, like a nebula. No grain.', + lab: { ...WATER, color1: '#5606ff', color2: '#fe8989', color3: '#000000', azimuth: 180, polar: 115, distance: 3.9, posX: -0.5, posY: 0.1, rotZ: 235, density: 1.1, speed: 0.1, strength: 2.4, brightness: 1.1, grain: 0 } + }, + { + key: 'tangerine-sea', + label: 'Tangerine sea', + hint: 'A sea of hot orange with rust-red troughs, seen low across its surface. No grain.', + lab: { ...WATER, color1: '#ff6a1a', color2: '#c73c00', color3: '#fd4912', azimuth: 180, polar: 95, distance: 2.4, posY: -2.1, rotZ: 225, density: 1.8, speed: 0.2, strength: 3, brightness: 1.2, grain: 0 } + } +]; +const GRADIENT_LICENSE = 'MIT'; +const GRADIENT_ATTRIBUTION = 'Adapted from ShaderGradient presets (github.com/ruucm/shadergradient), MIT © ruucm, stone-skipper'; +for (const g of GRADIENTS) { + PRESETS.push({ + key: g.key, + label: g.label, + hint: g.hint, + family: 'Gradient', + needs: ['gradientLab'], + license: GRADIENT_LICENSE, + attribution: GRADIENT_ATTRIBUTION, + layer: { pointer: false, scroll: false }, + nodes: [node('lab', 'gradientLab', 80, 80, { ...LAB_DEFAULTS, ...g.lab }), node('out', 'backgroundOutput', 420, 120)], + edges: [edge('lab', 'out', 'out', 'color')] + }); +} + +function files() { + /** @type {Record} */ + const out = {}; + const index = { + format: FORMAT, + title: 'Fluid backgrounds', + license: 'CC0-1.0', + presets: PRESETS.map((p) => ({ + key: p.key, + label: p.label, + hint: p.hint, + file: p.key + '.json', + // 65 gradient: optional, additive within format 1 (core backgroundPresetsCore.normalizePresetIndex) + ...(p.family ? { family: p.family, needs: p.needs, license: p.license, attribution: p.attribution } : {}) + })) + }; + out['index.json'] = JSON.stringify(index, null, '\t') + '\n'; + for (const p of PRESETS) { + const doc = { + format: FORMAT, + domain: 'background', + name: p.label, + preset: p.key, + ...(p.license ? { license: p.license, attribution: p.attribution } : {}), + layer: p.layer, + nodes: p.nodes, + edges: p.edges + }; + out[p.key + '.json'] = JSON.stringify(doc, null, '\t') + '\n'; + } + return out; +} + +const check = process.argv.includes('--check'); +let stale = 0; +for (const [name, text] of Object.entries(files())) { + const target = path.join(OUT, name); + if (check) { + const have = fs.existsSync(target) ? fs.readFileSync(target, 'utf8') : ''; + if (have !== text) { + console.log('STALE ' + name); + stale++; + } + } else { + fs.mkdirSync(OUT, { recursive: true }); + fs.writeFileSync(target, text); + console.log('wrote backgrounds/' + name); + } +} +if (check) { + console.log(stale ? stale + ' stale file(s) — run node tools/backgrounds/build.cjs' : 'backgrounds/ up to date'); + process.exit(stale ? 1 : 0); +}