fragment-tools 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +101 -0
- package/bin/index.js +19 -0
- package/docs/README.md +18 -0
- package/docs/api/CLI.md +44 -0
- package/docs/api/renderers.md +80 -0
- package/docs/api/sketch.md +216 -0
- package/docs/api/triggers.md +101 -0
- package/docs/guide/about.md +16 -0
- package/docs/guide/exports.md +86 -0
- package/docs/guide/external-dependencies.md +22 -0
- package/docs/guide/getting-started.md +113 -0
- package/docs/guide/hot-shader-reloading.md +20 -0
- package/docs/guide/shortcuts.md +12 -0
- package/docs/guide/triggers.png +0 -0
- package/docs/guide/using-triggers.md +39 -0
- package/examples/cube-three.js +34 -0
- package/examples/ellipse-p5.js +26 -0
- package/examples/icon.fs +96 -0
- package/examples/icon.js +63 -0
- package/examples/icon.png +0 -0
- package/examples/icon.transparent.png +0 -0
- package/examples/package-lock.json +40 -0
- package/examples/package.json +15 -0
- package/examples/shape-2d.js +45 -0
- package/examples/shape-three.js +49 -0
- package/examples/shape-tree.fs +3 -0
- package/package.json +37 -0
- package/screenshot.png +0 -0
- package/src/cli/db.js +17 -0
- package/src/cli/index.js +198 -0
- package/src/cli/log.js +26 -0
- package/src/cli/plugins/check-dependencies.js +77 -0
- package/src/cli/plugins/db.js +12 -0
- package/src/cli/plugins/hot-shader-reload.js +86 -0
- package/src/cli/plugins/hot-sketch-reload.js +39 -0
- package/src/cli/plugins/screenshot.js +31 -0
- package/src/cli/server.js +140 -0
- package/src/cli/templates/2d.js +15 -0
- package/src/cli/templates/fragment.fs +10 -0
- package/src/cli/templates/fragment.js +18 -0
- package/src/cli/templates/index.js +24 -0
- package/src/cli/templates/p5.js +13 -0
- package/src/cli/templates/three-fragment.js +53 -0
- package/src/cli/templates/three-orthographic.js +23 -0
- package/src/cli/templates/three-perspective.js +20 -0
- package/src/cli/ws.js +92 -0
- package/src/client/app/App.svelte +8 -0
- package/src/client/app/client.js +68 -0
- package/src/client/app/components/IconCross.svelte +29 -0
- package/src/client/app/components/Init.svelte +13 -0
- package/src/client/app/components/KeyBinding.svelte +32 -0
- package/src/client/app/inputs/Input.js +15 -0
- package/src/client/app/inputs/Keyboard.js +21 -0
- package/src/client/app/inputs/MIDI.js +144 -0
- package/src/client/app/inputs/Mouse.js +5 -0
- package/src/client/app/inputs/Webcam.js +98 -0
- package/src/client/app/lib/canvas-recorder/CanvasRecorder.js +88 -0
- package/src/client/app/lib/canvas-recorder/FFMPEGRecorder.js +56 -0
- package/src/client/app/lib/canvas-recorder/FrameRecorder.js +40 -0
- package/src/client/app/lib/canvas-recorder/GIFRecorder.js +52 -0
- package/src/client/app/lib/canvas-recorder/MP4Recorder.js +46 -0
- package/src/client/app/lib/canvas-recorder/WebMRecorder.js +30 -0
- package/src/client/app/lib/canvas-recorder/mp4.js +20 -0
- package/src/client/app/lib/canvas-recorder/mp4.wasm +0 -0
- package/src/client/app/lib/canvas-recorder/utils.js +22 -0
- package/src/client/app/lib/gl/Geometry.js +39 -0
- package/src/client/app/lib/gl/Program.js +130 -0
- package/src/client/app/lib/gl/Renderer.js +148 -0
- package/src/client/app/lib/gl/Texture.js +114 -0
- package/src/client/app/lib/gl/index.js +109 -0
- package/src/client/app/lib/gl/utils.js +5 -0
- package/src/client/app/lib/helpers/frameDebounce.js +40 -0
- package/src/client/app/lib/loader/index.js +20 -0
- package/src/client/app/lib/loader/loadImage.js +19 -0
- package/src/client/app/lib/loader/loadScript.js +14 -0
- package/src/client/app/lib/paper-sizes.js +104 -0
- package/src/client/app/lib/presets.js +12 -0
- package/src/client/app/lib/tempo/Analyser.js +165 -0
- package/src/client/app/lib/tempo/Range.js +97 -0
- package/src/client/app/lib/tempo/index.js +138 -0
- package/src/client/app/modules/AudioAnalyser/Range.svelte +93 -0
- package/src/client/app/modules/AudioAnalyser/Spectrum.svelte +31 -0
- package/src/client/app/modules/AudioAnalyser.svelte +70 -0
- package/src/client/app/modules/Console/ConsoleLine.svelte +254 -0
- package/src/client/app/modules/Console.svelte +82 -0
- package/src/client/app/modules/Exports.svelte +105 -0
- package/src/client/app/modules/MidiPanel.svelte +106 -0
- package/src/client/app/modules/Monitor.svelte +62 -0
- package/src/client/app/modules/Params.svelte +112 -0
- package/src/client/app/renderers/2DRenderer.js +5 -0
- package/src/client/app/renderers/FragmentRenderer.js +62 -0
- package/src/client/app/renderers/OGLRenderer.js +0 -0
- package/src/client/app/renderers/P5Renderer.js +39 -0
- package/src/client/app/renderers/THREERenderer.js +128 -0
- package/src/client/app/stores/audioAnalysis.js +10 -0
- package/src/client/app/stores/console.js +76 -0
- package/src/client/app/stores/errors.js +25 -0
- package/src/client/app/stores/exports.js +28 -0
- package/src/client/app/stores/index.js +2 -0
- package/src/client/app/stores/layout.js +187 -0
- package/src/client/app/stores/multisampling.js +16 -0
- package/src/client/app/stores/props.js +44 -0
- package/src/client/app/stores/renderers.js +60 -0
- package/src/client/app/stores/rendering.js +111 -0
- package/src/client/app/stores/sketches.js +40 -0
- package/src/client/app/stores/time.js +27 -0
- package/src/client/app/stores/utils.js +66 -0
- package/src/client/app/transitions/fade.js +17 -0
- package/src/client/app/transitions/index.js +12 -0
- package/src/client/app/transitions/splitX.js +16 -0
- package/src/client/app/transitions/splitY.js +16 -0
- package/src/client/app/triggers/Keyboard.js +95 -0
- package/src/client/app/triggers/MIDI.js +122 -0
- package/src/client/app/triggers/Mouse.js +96 -0
- package/src/client/app/triggers/Trigger.js +71 -0
- package/src/client/app/triggers/index.js +19 -0
- package/src/client/app/triggers/shared.js +37 -0
- package/src/client/app/ui/Build.svelte +96 -0
- package/src/client/app/ui/ErrorOverlay.svelte +130 -0
- package/src/client/app/ui/Field.svelte +262 -0
- package/src/client/app/ui/FieldGroup.svelte +103 -0
- package/src/client/app/ui/FieldSection.svelte +123 -0
- package/src/client/app/ui/FieldSpace.svelte +37 -0
- package/src/client/app/ui/FieldTrigger.svelte +263 -0
- package/src/client/app/ui/FieldTriggers.svelte +58 -0
- package/src/client/app/ui/FloatingParams.svelte +49 -0
- package/src/client/app/ui/Layout.svelte +50 -0
- package/src/client/app/ui/LayoutColumn.svelte +9 -0
- package/src/client/app/ui/LayoutComponent.svelte +279 -0
- package/src/client/app/ui/LayoutResizer.svelte +218 -0
- package/src/client/app/ui/LayoutRoot.svelte +11 -0
- package/src/client/app/ui/LayoutRow.svelte +9 -0
- package/src/client/app/ui/LayoutToolbar.svelte +264 -0
- package/src/client/app/ui/Module.svelte +154 -0
- package/src/client/app/ui/ModuleHeaderAction.svelte +87 -0
- package/src/client/app/ui/ModuleHeaderButton.svelte +21 -0
- package/src/client/app/ui/ModuleHeaderSelect.svelte +50 -0
- package/src/client/app/ui/ModuleRenderer.svelte +38 -0
- package/src/client/app/ui/OutputRenderer.svelte +149 -0
- package/src/client/app/ui/ParamsMultisampling.svelte +109 -0
- package/src/client/app/ui/ParamsOutput.svelte +139 -0
- package/src/client/app/ui/Preview.svelte +15 -0
- package/src/client/app/ui/SelectChevrons.svelte +25 -0
- package/src/client/app/ui/SketchRenderer.svelte +672 -0
- package/src/client/app/ui/SketchSelect.svelte +49 -0
- package/src/client/app/ui/fields/ButtonInput.svelte +54 -0
- package/src/client/app/ui/fields/CheckboxInput.svelte +70 -0
- package/src/client/app/ui/fields/ColorInput.svelte +187 -0
- package/src/client/app/ui/fields/FieldInputRow.svelte +13 -0
- package/src/client/app/ui/fields/ImageInput.svelte +145 -0
- package/src/client/app/ui/fields/Input.svelte +120 -0
- package/src/client/app/ui/fields/ListInput.svelte +106 -0
- package/src/client/app/ui/fields/NumberInput.svelte +114 -0
- package/src/client/app/ui/fields/ProgressInput.svelte +90 -0
- package/src/client/app/ui/fields/Select.svelte +116 -0
- package/src/client/app/ui/fields/TextInput.svelte +18 -0
- package/src/client/app/ui/fields/Vec2Input.svelte +5 -0
- package/src/client/app/ui/fields/Vec3Input.svelte +6 -0
- package/src/client/app/ui/fields/VectorInput.svelte +102 -0
- package/src/client/app/utils/canvas.utils.js +229 -0
- package/src/client/app/utils/color.utils.js +427 -0
- package/src/client/app/utils/file.utils.js +77 -0
- package/src/client/app/utils/glsl.utils.js +14 -0
- package/src/client/app/utils/glslErrors.js +154 -0
- package/src/client/app/utils/index.js +39 -0
- package/src/client/app/utils/math.utils.js +23 -0
- package/src/client/app/utils/props.utils.js +53 -0
- package/src/client/index.html +18 -0
- package/src/client/main.js +9 -0
- package/src/client/public/css/global.css +115 -0
- package/src/client/public/favicon.ico +0 -0
- package/src/client/public/fonts/Inter-Bold.woff2 +0 -0
- package/src/client/public/fonts/Inter-Italic.woff2 +0 -0
- package/src/client/public/fonts/Inter-Regular.woff2 +0 -0
- package/src/client/public/fonts/Inter-SemiBold.woff2 +0 -0
- package/src/client/public/fonts/JetBrainsMono-Regular.woff2 +0 -0
- package/src/client/public/icons/chevron-bottom.svg +3 -0
- package/src/client/public/icons/chevron-right.svg +3 -0
- package/src/client/public/icons/chevron-top.svg +3 -0
- package/src/client/public/icons/columns-horizontal.svg +4 -0
- package/src/client/public/icons/columns-vertical.svg +4 -0
- package/src/client/public/icons/folder-plus.svg +6 -0
- package/src/client/public/icons/lock.svg +4 -0
- package/src/client/public/icons/picture-in-picture.svg +4 -0
- package/src/client/public/icons/trash.svg +5 -0
- package/src/client/public/icons/trigger.svg +8 -0
- package/src/client/public/icons/unlock.svg +4 -0
- package/src/client/public/js/ffmpeg.min.js +2 -0
- package/src/client/public/js/ffmpeg.min.js.map +1 -0
- package/src/client/public/js/gif.js +2 -0
- package/src/client/public/js/gif.worker.js +2 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#### <sup>[fragment](../../README.md) → [Documentation](../README.md) → [Guide](../README.md#guide) → Exports</sup>
|
|
2
|
+
<br>
|
|
3
|
+
|
|
4
|
+
# Exports
|
|
5
|
+
|
|
6
|
+
`fragment` provides different ways to export sketches, whereas it's for communication or archive purposes. It currently supports image, video and live exports.
|
|
7
|
+
|
|
8
|
+
Settings of the `Exports` module are saved in localStorage so they will be kept between working sessions as long as `fragment` starts on the same URL/port.
|
|
9
|
+
|
|
10
|
+
## Export an image
|
|
11
|
+
|
|
12
|
+
`fragment` can export .png, .webp and .jpeg files.
|
|
13
|
+
|
|
14
|
+
You can change `encoding`, `quality` and `pixelsPerInch` in the module settings.
|
|
15
|
+
|
|
16
|
+
The size of the image used when exporting will be the current one used for display. If you want to create hi-res exports, make sure to change the `dimensions` or `pixelRatio` of the canvas before doing so.
|
|
17
|
+
|
|
18
|
+
> ⚠️ `pixelsPerInch` doesn't actually changed the resolution of the final exports, it only changes file metadata so it doesn't appear as a 72dpi file when opened in other softwares.
|
|
19
|
+
|
|
20
|
+
If you need to export a sketch for impression, set `canvasSize` in Params to `preset`. Select the size you want in the new `preset` dropdown and set `pixelsPerInch` to `300` before exporting.
|
|
21
|
+
|
|
22
|
+
Type `Cmd+S` on Mac or `Ctrl+S` on Windows to save a screenshot with selected settings into your working folder.
|
|
23
|
+
|
|
24
|
+
## Export a video
|
|
25
|
+
|
|
26
|
+
`fragment` can export .mp4, .gif, .webm videos and frame sequences.
|
|
27
|
+
|
|
28
|
+
You can change the `framerate`, the `encoding` and the `quality` of the recording in the module settings.
|
|
29
|
+
|
|
30
|
+
If `useDuration` is `true` and a sketch exports a [duration](../api/sketch.md#duration) property, the recording will stop once `fragment` has exported enough frames to compose the recording at specified framerate. This can be useful to export loop-based sketchs.
|
|
31
|
+
|
|
32
|
+
If `loopCount` is greater than 1, the recording will stop once fragment has enough frames to compose the recording for a final duration equals to sketchDuration*loopCount. This can be useful to export loop-based sketchs with variations between loops.
|
|
33
|
+
|
|
34
|
+
> ⚠️ The `framerate` used for recording can be different from sketch [fps](../api/sketch.md#duration) property.
|
|
35
|
+
|
|
36
|
+
## Export a live version
|
|
37
|
+
|
|
38
|
+
A sketch can be built into static files (html, js, css) to be deployed anywhere online.
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
fragment ./sketch.js --build
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The static build can be configured from the sketch file by exporting a `buildConfig` object.
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
export let buildConfig = {
|
|
48
|
+
backgroundColor: "red",
|
|
49
|
+
dimensions: [256, 256],
|
|
50
|
+
gui: {
|
|
51
|
+
position: "float",
|
|
52
|
+
align: "left",
|
|
53
|
+
size: 0.4,
|
|
54
|
+
output: false,
|
|
55
|
+
},
|
|
56
|
+
styles: /* css */`
|
|
57
|
+
:root {
|
|
58
|
+
--color-active: red;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
canvas {
|
|
62
|
+
box-shadow: 0px 2px 12px -2px rgba(0, 0, 0, 0.35);
|
|
63
|
+
}
|
|
64
|
+
}`
|
|
65
|
+
};
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
| name | type | effect | default |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| `backgroundColor` | `string` | Change the background color when canvas is not full size | `inherit` |
|
|
71
|
+
| `dimensions` | `number[2]` | Change the dimensions of the canvas | Viewport size |
|
|
72
|
+
| `canvasSize`| `string` | Change the resizing method of the canvas. Can be `window`, `fixed`, `scale`, `preset`, `aspect-ratio` | `window` |
|
|
73
|
+
| `pixelRatio` | `number\|function` | Change the pixel ratio of the canvas. | `1` |
|
|
74
|
+
| `gui` | `bool` | Display gui | `false` |
|
|
75
|
+
| `gui.position` | `string` | Change gui appearance. Can be `fixed` or `float` | `float` |
|
|
76
|
+
| `gui.align` | `string` | Change gui position. Can be `left` or `right` | `right` |
|
|
77
|
+
| `gui.size` | `string\|number` | Change gui width. Can be a percentage or a number between 0 and 1 | `0.3`
|
|
78
|
+
| `gui.output` | `string\|number` | Display canvasSize and dimensions fields in gui | `false` |
|
|
79
|
+
| `gui.hidden` | `boolean` | Hide gui on start | `false` |
|
|
80
|
+
| `styles` | `string` | Inject styles in document | `false` |
|
|
81
|
+
|
|
82
|
+
A built sketch can be previewed on dev mode by typing `p`.
|
|
83
|
+
|
|
84
|
+
## Change the filename
|
|
85
|
+
|
|
86
|
+
By default, `fragment` will use the sketch filename and a timestamp to name your export like `sketch.js.2022.05.27-08.30.00.[extension]`. See [filenamePattern](../api/sketch.md#filenamepattern) to change this behavior.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#### <sup>[fragment](../../README.md) → [Documentation](../README.md) → [Guide](../README.md#guide) → External dependencies</sup>
|
|
2
|
+
<br>
|
|
3
|
+
|
|
4
|
+
# External dependencies
|
|
5
|
+
|
|
6
|
+
You can manage dependencies of your project like you would do on a traditional `npm` project, [vite](https://vitejs.dev/) will bundle them on the fly on the first render of your sketch.
|
|
7
|
+
|
|
8
|
+
## Example
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
# Install a package from npmjs.com
|
|
12
|
+
npm install my-project-dependency
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
// sketch.js
|
|
17
|
+
import dependency from "my-project-dependency";
|
|
18
|
+
|
|
19
|
+
export let init = () => {
|
|
20
|
+
// use `dependency` here
|
|
21
|
+
};
|
|
22
|
+
```
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#### <sup>[fragment](../../README.md) → [Documentation](../README.md) → [Guide](../README.md#guide) → Getting started</sup>
|
|
2
|
+
<br>
|
|
3
|
+
|
|
4
|
+
# Getting started
|
|
5
|
+
|
|
6
|
+
## Create a sketch
|
|
7
|
+
|
|
8
|
+
In your terminal, type the following command to create a new sketch based on the 2D template.
|
|
9
|
+
```
|
|
10
|
+
fragment ./sketch.js --new --template=2d
|
|
11
|
+
```
|
|
12
|
+
Check [Templates docs](../api/CLI.md#templates) to see which templates are also available.
|
|
13
|
+
|
|
14
|
+
Open `sketch.js` recently created in your favorite code editor. The file should looks like this:
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
export let props = {};
|
|
18
|
+
|
|
19
|
+
export let init = ({ context, width, height }) => {
|
|
20
|
+
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export let update = ({ context, width, height, time, deltaTime }) => {
|
|
24
|
+
context.clearRect(0, 0, width, height);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export let resize = ({ width, height }) => {
|
|
28
|
+
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export let rendering = "2d";
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Draw a circle
|
|
35
|
+
|
|
36
|
+
Let's start by drawing a centered circle on the canvas. Because we used the `2d` template, the `update` function exposes a `context` param, which can be used to draw. See [CanvasRenderingContext2D docs](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D) if you want to know more about what can be done with `context`.
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
export let update = ({ context, width, height }) => {
|
|
40
|
+
// set the fill color to black
|
|
41
|
+
context.fillStyle = '#000000';
|
|
42
|
+
// draw a rectangle covering the entire canvas
|
|
43
|
+
context.fillRect(0, 0, width, height);
|
|
44
|
+
|
|
45
|
+
// choose a radius for your canvas
|
|
46
|
+
const radius = 20;
|
|
47
|
+
|
|
48
|
+
// change the fill color to blue
|
|
49
|
+
context.fillStyle = '#0000ff';
|
|
50
|
+
// draw the circle
|
|
51
|
+
context.beginPath();
|
|
52
|
+
context.arc(width * 0.5, height * 0.5, radius, 0, 2 * Math.PI, false);
|
|
53
|
+
// fill the previous path drawing with the current fillStyle
|
|
54
|
+
context.fill();
|
|
55
|
+
};
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Create a GUI
|
|
59
|
+
|
|
60
|
+
In order to quickly create controls on the screen, `fragment` checks for an existing `props` object exported from your sketch. The controls will be built based on the type of values in the `props` object.
|
|
61
|
+
|
|
62
|
+
Let's create our first prop `radius`.
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
export let props = {
|
|
66
|
+
radius: {
|
|
67
|
+
value: 20,
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export let update = () => {
|
|
72
|
+
// draw background
|
|
73
|
+
context.fillStyle = '#000000';
|
|
74
|
+
context.fillRect(0, 0, width, height);
|
|
75
|
+
|
|
76
|
+
const radius = props.radius.value; // get value from props object available in the scope
|
|
77
|
+
|
|
78
|
+
context.fillStyle = '#0000ff';
|
|
79
|
+
context.beginPath();
|
|
80
|
+
context.arc(width * 0.5, height * 0.5, radius, 0, 2 * Math.PI, false);
|
|
81
|
+
context.fill();
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
You should see a new input field under `Parameters` labelled `radius`. Try changing the value, the canvas will redraw according to your new value. That's great but it's not ideal to manually enter a new value each time.
|
|
86
|
+
|
|
87
|
+
Each `prop` can have a special property `params`. If the `[propName].value` is a `number`, then `params` can accept three new properties `min`, `max` and `step`.
|
|
88
|
+
|
|
89
|
+
Let's add them:
|
|
90
|
+
```js
|
|
91
|
+
export let props = {
|
|
92
|
+
radius: {
|
|
93
|
+
value: 20,
|
|
94
|
+
params: {
|
|
95
|
+
min: 1,
|
|
96
|
+
max: 200,
|
|
97
|
+
step: 1,
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
A slider should have appeared after saving the sketch file next to the previous input. Now if you click and drag on the slider, you should see your circle changing live.
|
|
104
|
+
|
|
105
|
+
Congrats, you made your first sketch in `fragment`!
|
|
106
|
+
|
|
107
|
+
If you want to know more about `props` and what can be done with it, check out the [SketchProps](../api/sketch.md#sketchprops) section of the documentation.
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
## Next steps
|
|
111
|
+
|
|
112
|
+
- [Using triggers](./using-triggers.md)
|
|
113
|
+
- [Exporting a sketch](./exports.md)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#### <sup>[fragment](../../README.md) → [Documentation](../README.md) → [Guide](../README.md#guide) → Hot shader reloading</sup>
|
|
2
|
+
<br>
|
|
3
|
+
|
|
4
|
+
# Hot shader reloading
|
|
5
|
+
|
|
6
|
+
Instead of using built-in HMR features of [vite](https://vitejs.dev/), `fragment` has its own way of reloading shaders when it encounters files with the following extensions:
|
|
7
|
+
- `.glsl`
|
|
8
|
+
- `.fs`
|
|
9
|
+
- `.vs`
|
|
10
|
+
- `.vert`
|
|
11
|
+
- `.frag`
|
|
12
|
+
|
|
13
|
+
## With `rendering="three"`
|
|
14
|
+
|
|
15
|
+
When using [three.js](https://threejs.org/) rendering, `fragment` will traverse the `scene` provided in the params to see if the file recently saved has a filepath that matches a `fragmentShader` or `vertexShader` provided to a `ShaderMaterial` or a `RawShaderMaterial`.
|
|
16
|
+
If you're using your own `Scene` instance, `fragment` will not be able to retrieve the materials currently in use and will reload the whole sketch instead.
|
|
17
|
+
|
|
18
|
+
## With `rendering="fragment"`
|
|
19
|
+
|
|
20
|
+
The single WebGLProgram displayed is recompiled on the fly.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#### <sup>[fragment](../../README.md) → [Documentation](../README.md) → [Guide](../README.md#guide) → Shortcuts</sup>
|
|
2
|
+
|
|
3
|
+
# Shortcuts
|
|
4
|
+
|
|
5
|
+
| shortcut | action |
|
|
6
|
+
|---|---|
|
|
7
|
+
|`Cmd/Ctrl + S`| Capture canvas
|
|
8
|
+
|`Cmd/Ctrl + Shift + S`| Record canvas
|
|
9
|
+
|`r`| Reload sketch
|
|
10
|
+
|`w`| Modify layout
|
|
11
|
+
|`Space`| Pause rendering
|
|
12
|
+
|`p`| Toggle Preview mode
|
|
Binary file
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#### <sup>[fragment](../../README.md) → [Documentation](../README.md) → [Guide](../README.md#guide) → Using triggers</sup>
|
|
2
|
+
|
|
3
|
+
# Using triggers
|
|
4
|
+
|
|
5
|
+
Triggers are functions you can call imperatively from your sketch file to make it *interactive*. They can also be assigned on a prop through the UI.
|
|
6
|
+
|
|
7
|
+
## From a sketch
|
|
8
|
+
|
|
9
|
+
Instead of setting up the listener manually:
|
|
10
|
+
```js
|
|
11
|
+
export let init = ({ canvas }) => {
|
|
12
|
+
canvas.addEventListener('click', (event) => {
|
|
13
|
+
console.log("canvas clicked");
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
You can import and use them in your sketch:
|
|
19
|
+
```js
|
|
20
|
+
import { onClick } from "@fragment/triggers";
|
|
21
|
+
|
|
22
|
+
export let init = ({ canvas }) => {
|
|
23
|
+
onClick((event) => {
|
|
24
|
+
console.log("canvas clicked");
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
See [Triggers API docs](../api/triggers.md) for usage.
|
|
30
|
+
|
|
31
|
+
## From the UI
|
|
32
|
+
|
|
33
|
+
Triggers can also added on specific type of fields from the UI, by clicking on the label of a field. Triggers can only be added when the type of a prop is a `function` or a number with `params: { min, max }`.
|
|
34
|
+
|
|
35
|
+
They are saved in localStorage so they persist between refreshs. This is useful when you want to quickly test or prototype values.
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
The dot on the left shows if a trigger is active or not. You can toggle activity by clicking on it.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
import * as THREE from "three";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
let camera;
|
|
6
|
+
let mesh;
|
|
7
|
+
|
|
8
|
+
export let init = ({ scene, width, height }) => {
|
|
9
|
+
camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
|
|
10
|
+
camera.position.z = 3;
|
|
11
|
+
camera.lookAt(new THREE.Vector3());
|
|
12
|
+
|
|
13
|
+
mesh = new THREE.Mesh(
|
|
14
|
+
new THREE.BoxBufferGeometry(1, 1, 1),
|
|
15
|
+
new THREE.MeshBasicMaterial({
|
|
16
|
+
color: 0xFF0000,
|
|
17
|
+
wireframe: true,
|
|
18
|
+
})
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
scene.add(mesh);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export let update = ({ renderer, scene, time, deltaTime }) => {
|
|
25
|
+
mesh.rotation.y += 0.01;
|
|
26
|
+
renderer.render(scene, camera);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export let resize = ({ width, height }) => {
|
|
30
|
+
camera.aspect = width / height;
|
|
31
|
+
camera.updateProjectionMatrix();
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export let rendering = "three";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import p5 from "p5";
|
|
2
|
+
|
|
3
|
+
export let props = {
|
|
4
|
+
radius: {
|
|
5
|
+
value: 100,
|
|
6
|
+
params: {
|
|
7
|
+
min: 10,
|
|
8
|
+
max: 200,
|
|
9
|
+
step: 1,
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export let fps = 0;
|
|
15
|
+
|
|
16
|
+
export let setup = ({ p, width, height }) => {};
|
|
17
|
+
|
|
18
|
+
export let draw = ({ p, width, height }) => {
|
|
19
|
+
p.background(255, 0, 0);
|
|
20
|
+
|
|
21
|
+
const radius = props.radius.value;
|
|
22
|
+
|
|
23
|
+
p.ellipse(width * 0.5, height * 0.5, radius, radius);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export let rendering = "p5";
|
package/examples/icon.fs
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#version 300 es
|
|
2
|
+
|
|
3
|
+
precision highp float;
|
|
4
|
+
|
|
5
|
+
uniform float uTime;
|
|
6
|
+
uniform vec2 uResolution;
|
|
7
|
+
uniform float uRadius;
|
|
8
|
+
uniform float uShift;
|
|
9
|
+
|
|
10
|
+
in vec2 vUv;
|
|
11
|
+
out vec4 FragColor;
|
|
12
|
+
|
|
13
|
+
float aastep(float threshold, float value) {
|
|
14
|
+
// #ifdef GL_OES_standard_derivatives
|
|
15
|
+
float afwidth = length(vec2(dFdx(value), dFdy(value))) * 0.70710678118654757;
|
|
16
|
+
return smoothstep(threshold-afwidth, threshold+afwidth, value);
|
|
17
|
+
// #else
|
|
18
|
+
// return step(threshold, value);
|
|
19
|
+
// #endif
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
float disc(vec2 st, float radius) {
|
|
23
|
+
return 1. - aastep(radius, length(st - vec2(0.5)));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
float disc(vec2 st, float radius, vec2 center) {
|
|
27
|
+
return 1. - aastep(radius, length(st - center));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
void main() {
|
|
31
|
+
float gridFactor = 40.;
|
|
32
|
+
|
|
33
|
+
float borderRadius = uRadius;
|
|
34
|
+
float c = 0.;
|
|
35
|
+
c += disc(vUv, borderRadius, vec2(1. - borderRadius, 1. - borderRadius));
|
|
36
|
+
c += disc(vUv, borderRadius, vec2(borderRadius, 1. - borderRadius));
|
|
37
|
+
c += disc(vUv, borderRadius, vec2(borderRadius, borderRadius));
|
|
38
|
+
c += disc(vUv, borderRadius, vec2(1. - borderRadius, borderRadius));
|
|
39
|
+
|
|
40
|
+
float q = 0.;
|
|
41
|
+
float qv = min(step(borderRadius, vUv.x), step(vUv.x, 1. - borderRadius));
|
|
42
|
+
float qh = min(step(borderRadius, vUv.y), step(vUv.y, 1. - borderRadius));
|
|
43
|
+
|
|
44
|
+
q = max(qh, qv);
|
|
45
|
+
q = clamp(q, 0., 1.);
|
|
46
|
+
c += q;
|
|
47
|
+
c = clamp(c, 0., 1.);
|
|
48
|
+
|
|
49
|
+
float t = 1.;
|
|
50
|
+
|
|
51
|
+
vec3 color = vec3(0.);
|
|
52
|
+
|
|
53
|
+
vec2 grid = vUv * 41.;
|
|
54
|
+
vec2 uvp = fract(grid);
|
|
55
|
+
|
|
56
|
+
float colIndex = floor(grid.x);
|
|
57
|
+
float rowIndex = floor(grid.y);
|
|
58
|
+
float pattern = 0.;
|
|
59
|
+
|
|
60
|
+
float c1 = mod(colIndex, 2.) > 0. ? 1. : 0.;
|
|
61
|
+
float c2 = mod(colIndex + 1., 2.) > 0. ? 1. : 0.;
|
|
62
|
+
float r1 = mod(rowIndex, 2.) > 0. ? 1. : 0.;
|
|
63
|
+
float r2 = mod(rowIndex + 1., 2.) > 0. ? 1. : 0.;
|
|
64
|
+
|
|
65
|
+
pattern = r1 * c1;
|
|
66
|
+
pattern += c2 * r2;
|
|
67
|
+
pattern = 1. - pattern;
|
|
68
|
+
|
|
69
|
+
float gradient = 1. - mod(floor(vUv.x * (gridFactor * 2. + 1.)), 2.) > 0. ? 0. : 1.;
|
|
70
|
+
|
|
71
|
+
vec2 p0 = vec2(0.5);
|
|
72
|
+
vec2 p1 = p0 + (1. / (gridFactor * 2. + 1.)) * 7. * t;
|
|
73
|
+
vec2 p2 = p0 - (1. / (gridFactor * 2. + 1.)) * 7. * t;
|
|
74
|
+
|
|
75
|
+
float r = (1. / gridFactor * 10.) * t;
|
|
76
|
+
|
|
77
|
+
float ra1 = disc(vUv, r, p2);
|
|
78
|
+
float ra2 = disc(vUv, r, p0);
|
|
79
|
+
float ra3 = disc(vUv, r, p1);
|
|
80
|
+
|
|
81
|
+
ra1 *= gradient;
|
|
82
|
+
ra2 *= (1. - gradient);
|
|
83
|
+
ra3 *= gradient;
|
|
84
|
+
|
|
85
|
+
pattern *= 1. - c;
|
|
86
|
+
pattern += 0.9 * (1. - c);
|
|
87
|
+
|
|
88
|
+
color += vec3(1., 0., 0.) * ra1;
|
|
89
|
+
color += vec3(0., 1., 0.) * ra2;
|
|
90
|
+
color += vec3(0., 0., 1.) * ra3;
|
|
91
|
+
|
|
92
|
+
float alpha = 1.;
|
|
93
|
+
alpha *= c;
|
|
94
|
+
|
|
95
|
+
FragColor = vec4(color, alpha);
|
|
96
|
+
}
|
package/examples/icon.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import fragmentShader from "./icon.fs";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export let props = {
|
|
5
|
+
radius: {
|
|
6
|
+
value: 0.1,
|
|
7
|
+
params: {
|
|
8
|
+
min: 0,
|
|
9
|
+
max: 0.5,
|
|
10
|
+
step: 0.01,
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
shift: {
|
|
14
|
+
value: 0.05,
|
|
15
|
+
params: {
|
|
16
|
+
min: 0,
|
|
17
|
+
max: 1,
|
|
18
|
+
step: 0.001,
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
progress: {
|
|
22
|
+
value: 0,
|
|
23
|
+
params: {
|
|
24
|
+
min: 0,
|
|
25
|
+
max: 1,
|
|
26
|
+
step: 0.001,
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
let uniforms = {
|
|
32
|
+
uTime: { value: 0, type: "float" },
|
|
33
|
+
uRadius: { value: props.radius.value, type: "float" },
|
|
34
|
+
uShift: { value: props.shift.value, type: "float" },
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export let fps = 0;
|
|
38
|
+
|
|
39
|
+
export let init = ({ frag }) => {
|
|
40
|
+
frag.uniforms = uniforms;
|
|
41
|
+
frag.shader = fragmentShader;
|
|
42
|
+
frag.vertexShader = `#version 300 es
|
|
43
|
+
in vec4 position;
|
|
44
|
+
in vec2 uv;
|
|
45
|
+
|
|
46
|
+
out vec2 vUv;
|
|
47
|
+
|
|
48
|
+
void main(){
|
|
49
|
+
vUv = uv;
|
|
50
|
+
gl_Position = position;
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export let update = ({ frag, deltaTime }) => {
|
|
56
|
+
uniforms.uTime.value += deltaTime;
|
|
57
|
+
uniforms.uRadius.value = props.radius.value;
|
|
58
|
+
uniforms.uShift.value = props.shift.value;
|
|
59
|
+
|
|
60
|
+
frag.render();
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export let rendering = "fragment";
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fragment-examples",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"lockfileVersion": 2,
|
|
5
|
+
"requires": true,
|
|
6
|
+
"packages": {
|
|
7
|
+
"": {
|
|
8
|
+
"name": "fragment-examples",
|
|
9
|
+
"version": "1.0.0",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"p5": "^1.4.1",
|
|
13
|
+
"three": "^0.140.2"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {}
|
|
16
|
+
},
|
|
17
|
+
"node_modules/p5": {
|
|
18
|
+
"version": "1.4.2",
|
|
19
|
+
"resolved": "https://registry.npmjs.org/p5/-/p5-1.4.2.tgz",
|
|
20
|
+
"integrity": "sha512-J5zqZ/l1NIbJSuNr/FH9nDYgBRg7/NubStNPnx1fQCMSAgxI6peKDHs9i5iaG9EuwbJzjuG6/5bX/D0lqqrP9A=="
|
|
21
|
+
},
|
|
22
|
+
"node_modules/three": {
|
|
23
|
+
"version": "0.140.2",
|
|
24
|
+
"resolved": "https://registry.npmjs.org/three/-/three-0.140.2.tgz",
|
|
25
|
+
"integrity": "sha512-DdT/AHm/TbZXEhQKQpGt5/iSgBrmXpjU26FNtj1KhllVPTKj1eG4X/ShyD5W2fngE+I1s1wa4ttC4C3oCJt7Ag=="
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"p5": {
|
|
30
|
+
"version": "1.4.2",
|
|
31
|
+
"resolved": "https://registry.npmjs.org/p5/-/p5-1.4.2.tgz",
|
|
32
|
+
"integrity": "sha512-J5zqZ/l1NIbJSuNr/FH9nDYgBRg7/NubStNPnx1fQCMSAgxI6peKDHs9i5iaG9EuwbJzjuG6/5bX/D0lqqrP9A=="
|
|
33
|
+
},
|
|
34
|
+
"three": {
|
|
35
|
+
"version": "0.140.2",
|
|
36
|
+
"resolved": "https://registry.npmjs.org/three/-/three-0.140.2.tgz",
|
|
37
|
+
"integrity": "sha512-DdT/AHm/TbZXEhQKQpGt5/iSgBrmXpjU26FNtj1KhllVPTKj1eG4X/ShyD5W2fngE+I1s1wa4ttC4C3oCJt7Ag=="
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fragment-examples",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"p5": "^1.4.1",
|
|
7
|
+
"three": "^0.140.2"
|
|
8
|
+
},
|
|
9
|
+
"devDependencies": {},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "fragment ./circle-2d.js"
|
|
12
|
+
},
|
|
13
|
+
"author": "Raphaël Améaume",
|
|
14
|
+
"license": "MIT"
|
|
15
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export let props = {
|
|
2
|
+
background: {
|
|
3
|
+
value: "#0057B8",
|
|
4
|
+
},
|
|
5
|
+
fill: {
|
|
6
|
+
value: "#FFD700",
|
|
7
|
+
},
|
|
8
|
+
size: {
|
|
9
|
+
value: 256,
|
|
10
|
+
params: {
|
|
11
|
+
min: 64,
|
|
12
|
+
max: 512
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
shape: {
|
|
16
|
+
value: "circle",
|
|
17
|
+
params: {
|
|
18
|
+
options: ["circle", "square"]
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export let fps = 0;
|
|
24
|
+
|
|
25
|
+
export let update = ({ context, width, height }) => {
|
|
26
|
+
// draw background
|
|
27
|
+
context.fillStyle = props.background.value;
|
|
28
|
+
context.fillRect(0, 0, width, height);
|
|
29
|
+
|
|
30
|
+
// draw circle
|
|
31
|
+
const shape = props.shape.value;
|
|
32
|
+
const size = props.size.value;
|
|
33
|
+
|
|
34
|
+
context.fillStyle = props.fill.value;
|
|
35
|
+
|
|
36
|
+
if (shape === "circle") {
|
|
37
|
+
context.beginPath();
|
|
38
|
+
context.arc(width * 0.5, height * 0.5, size, 0, 2 * Math.PI, false);
|
|
39
|
+
context.fill();
|
|
40
|
+
} else if (shape === "square") {
|
|
41
|
+
context.fillRect(width * 0.5 - size, height * 0.5 - size, size * 2, size * 2);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export let rendering = "2d";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
import * as THREE from "three";
|
|
3
|
+
|
|
4
|
+
import fragmentShader from "./shape-tree.fs";
|
|
5
|
+
|
|
6
|
+
let camera;
|
|
7
|
+
let mesh;
|
|
8
|
+
|
|
9
|
+
export let init = ({ scene, width, height }) => {
|
|
10
|
+
camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
|
|
11
|
+
camera.position.z = 3;
|
|
12
|
+
camera.lookAt(new THREE.Vector3());
|
|
13
|
+
|
|
14
|
+
mesh = new THREE.Mesh(
|
|
15
|
+
new THREE.PlaneBufferGeometry(1, 1),
|
|
16
|
+
new THREE.ShaderMaterial({
|
|
17
|
+
vertexShader: `
|
|
18
|
+
void main() {
|
|
19
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.);
|
|
20
|
+
}
|
|
21
|
+
`,
|
|
22
|
+
fragmentShader:
|
|
23
|
+
`
|
|
24
|
+
void main() {
|
|
25
|
+
gl_FragColor = vec4(0., 1., 0., 1.);
|
|
26
|
+
}
|
|
27
|
+
`,
|
|
28
|
+
wireframe: true,
|
|
29
|
+
}),
|
|
30
|
+
// new THREE.MeshBasicMaterial({
|
|
31
|
+
// color: 0xFF0000,
|
|
32
|
+
// wireframe: true,
|
|
33
|
+
// })
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
scene.add(mesh);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export let update = ({ renderer, scene, time, deltaTime }) => {
|
|
40
|
+
mesh.rotation.y += 0.01;
|
|
41
|
+
renderer.render(scene, camera);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export let resize = ({ width, height }) => {
|
|
45
|
+
camera.aspect = width / height;
|
|
46
|
+
camera.updateProjectionMatrix();
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export let rendering = "three";
|