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.
Files changed (192) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +101 -0
  3. package/bin/index.js +19 -0
  4. package/docs/README.md +18 -0
  5. package/docs/api/CLI.md +44 -0
  6. package/docs/api/renderers.md +80 -0
  7. package/docs/api/sketch.md +216 -0
  8. package/docs/api/triggers.md +101 -0
  9. package/docs/guide/about.md +16 -0
  10. package/docs/guide/exports.md +86 -0
  11. package/docs/guide/external-dependencies.md +22 -0
  12. package/docs/guide/getting-started.md +113 -0
  13. package/docs/guide/hot-shader-reloading.md +20 -0
  14. package/docs/guide/shortcuts.md +12 -0
  15. package/docs/guide/triggers.png +0 -0
  16. package/docs/guide/using-triggers.md +39 -0
  17. package/examples/cube-three.js +34 -0
  18. package/examples/ellipse-p5.js +26 -0
  19. package/examples/icon.fs +96 -0
  20. package/examples/icon.js +63 -0
  21. package/examples/icon.png +0 -0
  22. package/examples/icon.transparent.png +0 -0
  23. package/examples/package-lock.json +40 -0
  24. package/examples/package.json +15 -0
  25. package/examples/shape-2d.js +45 -0
  26. package/examples/shape-three.js +49 -0
  27. package/examples/shape-tree.fs +3 -0
  28. package/package.json +37 -0
  29. package/screenshot.png +0 -0
  30. package/src/cli/db.js +17 -0
  31. package/src/cli/index.js +198 -0
  32. package/src/cli/log.js +26 -0
  33. package/src/cli/plugins/check-dependencies.js +77 -0
  34. package/src/cli/plugins/db.js +12 -0
  35. package/src/cli/plugins/hot-shader-reload.js +86 -0
  36. package/src/cli/plugins/hot-sketch-reload.js +39 -0
  37. package/src/cli/plugins/screenshot.js +31 -0
  38. package/src/cli/server.js +140 -0
  39. package/src/cli/templates/2d.js +15 -0
  40. package/src/cli/templates/fragment.fs +10 -0
  41. package/src/cli/templates/fragment.js +18 -0
  42. package/src/cli/templates/index.js +24 -0
  43. package/src/cli/templates/p5.js +13 -0
  44. package/src/cli/templates/three-fragment.js +53 -0
  45. package/src/cli/templates/three-orthographic.js +23 -0
  46. package/src/cli/templates/three-perspective.js +20 -0
  47. package/src/cli/ws.js +92 -0
  48. package/src/client/app/App.svelte +8 -0
  49. package/src/client/app/client.js +68 -0
  50. package/src/client/app/components/IconCross.svelte +29 -0
  51. package/src/client/app/components/Init.svelte +13 -0
  52. package/src/client/app/components/KeyBinding.svelte +32 -0
  53. package/src/client/app/inputs/Input.js +15 -0
  54. package/src/client/app/inputs/Keyboard.js +21 -0
  55. package/src/client/app/inputs/MIDI.js +144 -0
  56. package/src/client/app/inputs/Mouse.js +5 -0
  57. package/src/client/app/inputs/Webcam.js +98 -0
  58. package/src/client/app/lib/canvas-recorder/CanvasRecorder.js +88 -0
  59. package/src/client/app/lib/canvas-recorder/FFMPEGRecorder.js +56 -0
  60. package/src/client/app/lib/canvas-recorder/FrameRecorder.js +40 -0
  61. package/src/client/app/lib/canvas-recorder/GIFRecorder.js +52 -0
  62. package/src/client/app/lib/canvas-recorder/MP4Recorder.js +46 -0
  63. package/src/client/app/lib/canvas-recorder/WebMRecorder.js +30 -0
  64. package/src/client/app/lib/canvas-recorder/mp4.js +20 -0
  65. package/src/client/app/lib/canvas-recorder/mp4.wasm +0 -0
  66. package/src/client/app/lib/canvas-recorder/utils.js +22 -0
  67. package/src/client/app/lib/gl/Geometry.js +39 -0
  68. package/src/client/app/lib/gl/Program.js +130 -0
  69. package/src/client/app/lib/gl/Renderer.js +148 -0
  70. package/src/client/app/lib/gl/Texture.js +114 -0
  71. package/src/client/app/lib/gl/index.js +109 -0
  72. package/src/client/app/lib/gl/utils.js +5 -0
  73. package/src/client/app/lib/helpers/frameDebounce.js +40 -0
  74. package/src/client/app/lib/loader/index.js +20 -0
  75. package/src/client/app/lib/loader/loadImage.js +19 -0
  76. package/src/client/app/lib/loader/loadScript.js +14 -0
  77. package/src/client/app/lib/paper-sizes.js +104 -0
  78. package/src/client/app/lib/presets.js +12 -0
  79. package/src/client/app/lib/tempo/Analyser.js +165 -0
  80. package/src/client/app/lib/tempo/Range.js +97 -0
  81. package/src/client/app/lib/tempo/index.js +138 -0
  82. package/src/client/app/modules/AudioAnalyser/Range.svelte +93 -0
  83. package/src/client/app/modules/AudioAnalyser/Spectrum.svelte +31 -0
  84. package/src/client/app/modules/AudioAnalyser.svelte +70 -0
  85. package/src/client/app/modules/Console/ConsoleLine.svelte +254 -0
  86. package/src/client/app/modules/Console.svelte +82 -0
  87. package/src/client/app/modules/Exports.svelte +105 -0
  88. package/src/client/app/modules/MidiPanel.svelte +106 -0
  89. package/src/client/app/modules/Monitor.svelte +62 -0
  90. package/src/client/app/modules/Params.svelte +112 -0
  91. package/src/client/app/renderers/2DRenderer.js +5 -0
  92. package/src/client/app/renderers/FragmentRenderer.js +62 -0
  93. package/src/client/app/renderers/OGLRenderer.js +0 -0
  94. package/src/client/app/renderers/P5Renderer.js +39 -0
  95. package/src/client/app/renderers/THREERenderer.js +128 -0
  96. package/src/client/app/stores/audioAnalysis.js +10 -0
  97. package/src/client/app/stores/console.js +76 -0
  98. package/src/client/app/stores/errors.js +25 -0
  99. package/src/client/app/stores/exports.js +28 -0
  100. package/src/client/app/stores/index.js +2 -0
  101. package/src/client/app/stores/layout.js +187 -0
  102. package/src/client/app/stores/multisampling.js +16 -0
  103. package/src/client/app/stores/props.js +44 -0
  104. package/src/client/app/stores/renderers.js +60 -0
  105. package/src/client/app/stores/rendering.js +111 -0
  106. package/src/client/app/stores/sketches.js +40 -0
  107. package/src/client/app/stores/time.js +27 -0
  108. package/src/client/app/stores/utils.js +66 -0
  109. package/src/client/app/transitions/fade.js +17 -0
  110. package/src/client/app/transitions/index.js +12 -0
  111. package/src/client/app/transitions/splitX.js +16 -0
  112. package/src/client/app/transitions/splitY.js +16 -0
  113. package/src/client/app/triggers/Keyboard.js +95 -0
  114. package/src/client/app/triggers/MIDI.js +122 -0
  115. package/src/client/app/triggers/Mouse.js +96 -0
  116. package/src/client/app/triggers/Trigger.js +71 -0
  117. package/src/client/app/triggers/index.js +19 -0
  118. package/src/client/app/triggers/shared.js +37 -0
  119. package/src/client/app/ui/Build.svelte +96 -0
  120. package/src/client/app/ui/ErrorOverlay.svelte +130 -0
  121. package/src/client/app/ui/Field.svelte +262 -0
  122. package/src/client/app/ui/FieldGroup.svelte +103 -0
  123. package/src/client/app/ui/FieldSection.svelte +123 -0
  124. package/src/client/app/ui/FieldSpace.svelte +37 -0
  125. package/src/client/app/ui/FieldTrigger.svelte +263 -0
  126. package/src/client/app/ui/FieldTriggers.svelte +58 -0
  127. package/src/client/app/ui/FloatingParams.svelte +49 -0
  128. package/src/client/app/ui/Layout.svelte +50 -0
  129. package/src/client/app/ui/LayoutColumn.svelte +9 -0
  130. package/src/client/app/ui/LayoutComponent.svelte +279 -0
  131. package/src/client/app/ui/LayoutResizer.svelte +218 -0
  132. package/src/client/app/ui/LayoutRoot.svelte +11 -0
  133. package/src/client/app/ui/LayoutRow.svelte +9 -0
  134. package/src/client/app/ui/LayoutToolbar.svelte +264 -0
  135. package/src/client/app/ui/Module.svelte +154 -0
  136. package/src/client/app/ui/ModuleHeaderAction.svelte +87 -0
  137. package/src/client/app/ui/ModuleHeaderButton.svelte +21 -0
  138. package/src/client/app/ui/ModuleHeaderSelect.svelte +50 -0
  139. package/src/client/app/ui/ModuleRenderer.svelte +38 -0
  140. package/src/client/app/ui/OutputRenderer.svelte +149 -0
  141. package/src/client/app/ui/ParamsMultisampling.svelte +109 -0
  142. package/src/client/app/ui/ParamsOutput.svelte +139 -0
  143. package/src/client/app/ui/Preview.svelte +15 -0
  144. package/src/client/app/ui/SelectChevrons.svelte +25 -0
  145. package/src/client/app/ui/SketchRenderer.svelte +672 -0
  146. package/src/client/app/ui/SketchSelect.svelte +49 -0
  147. package/src/client/app/ui/fields/ButtonInput.svelte +54 -0
  148. package/src/client/app/ui/fields/CheckboxInput.svelte +70 -0
  149. package/src/client/app/ui/fields/ColorInput.svelte +187 -0
  150. package/src/client/app/ui/fields/FieldInputRow.svelte +13 -0
  151. package/src/client/app/ui/fields/ImageInput.svelte +145 -0
  152. package/src/client/app/ui/fields/Input.svelte +120 -0
  153. package/src/client/app/ui/fields/ListInput.svelte +106 -0
  154. package/src/client/app/ui/fields/NumberInput.svelte +114 -0
  155. package/src/client/app/ui/fields/ProgressInput.svelte +90 -0
  156. package/src/client/app/ui/fields/Select.svelte +116 -0
  157. package/src/client/app/ui/fields/TextInput.svelte +18 -0
  158. package/src/client/app/ui/fields/Vec2Input.svelte +5 -0
  159. package/src/client/app/ui/fields/Vec3Input.svelte +6 -0
  160. package/src/client/app/ui/fields/VectorInput.svelte +102 -0
  161. package/src/client/app/utils/canvas.utils.js +229 -0
  162. package/src/client/app/utils/color.utils.js +427 -0
  163. package/src/client/app/utils/file.utils.js +77 -0
  164. package/src/client/app/utils/glsl.utils.js +14 -0
  165. package/src/client/app/utils/glslErrors.js +154 -0
  166. package/src/client/app/utils/index.js +39 -0
  167. package/src/client/app/utils/math.utils.js +23 -0
  168. package/src/client/app/utils/props.utils.js +53 -0
  169. package/src/client/index.html +18 -0
  170. package/src/client/main.js +9 -0
  171. package/src/client/public/css/global.css +115 -0
  172. package/src/client/public/favicon.ico +0 -0
  173. package/src/client/public/fonts/Inter-Bold.woff2 +0 -0
  174. package/src/client/public/fonts/Inter-Italic.woff2 +0 -0
  175. package/src/client/public/fonts/Inter-Regular.woff2 +0 -0
  176. package/src/client/public/fonts/Inter-SemiBold.woff2 +0 -0
  177. package/src/client/public/fonts/JetBrainsMono-Regular.woff2 +0 -0
  178. package/src/client/public/icons/chevron-bottom.svg +3 -0
  179. package/src/client/public/icons/chevron-right.svg +3 -0
  180. package/src/client/public/icons/chevron-top.svg +3 -0
  181. package/src/client/public/icons/columns-horizontal.svg +4 -0
  182. package/src/client/public/icons/columns-vertical.svg +4 -0
  183. package/src/client/public/icons/folder-plus.svg +6 -0
  184. package/src/client/public/icons/lock.svg +4 -0
  185. package/src/client/public/icons/picture-in-picture.svg +4 -0
  186. package/src/client/public/icons/trash.svg +5 -0
  187. package/src/client/public/icons/trigger.svg +8 -0
  188. package/src/client/public/icons/unlock.svg +4 -0
  189. package/src/client/public/js/ffmpeg.min.js +2 -0
  190. package/src/client/public/js/ffmpeg.min.js.map +1 -0
  191. package/src/client/public/js/gif.js +2 -0
  192. package/src/client/public/js/gif.worker.js +2 -0
@@ -0,0 +1,148 @@
1
+ class Renderer {
2
+
3
+ constructor({
4
+ canvas = document.createElement('canvas'),
5
+ antialias = false,
6
+ alpha = true,
7
+ depth = false,
8
+ stencil = false,
9
+ premultipliedAlpha = false,
10
+ pixelRatio = window.devicePixelRatio,
11
+ webgl = 2,
12
+ }) {
13
+ let gl;
14
+ let attributes = {
15
+ depth,
16
+ stencil,
17
+ antialias,
18
+ alpha,
19
+ premultipliedAlpha,
20
+ preserveDrawingBuffer: true
21
+ };
22
+
23
+ this.canvas = canvas;
24
+
25
+ if (webgl === 2) gl = canvas.getContext('webgl2', attributes);
26
+ if (!gl) {
27
+ gl = canvas.getContext('webgl', attributes) || canvas.getContext('experimental-webgl', attributes);
28
+ }
29
+
30
+ this.gl = gl;
31
+
32
+ this.state = {
33
+ activeTextureUnit: 0,
34
+ textureUnits: [],
35
+ flipY: false,
36
+ viewport: { width: 0, height: 0 },
37
+ pixelRatio,
38
+ width: 0,
39
+ height: 0,
40
+ };
41
+ this.gl.state = this.state;
42
+ }
43
+
44
+ render({
45
+ geometry,
46
+ program,
47
+ primitiveType = this.gl.TRIANGLES,
48
+ offset = 0,
49
+ count = 3
50
+ }) {
51
+ if (program.needsUpdate) {
52
+ program.compile();
53
+ }
54
+
55
+ this.gl.clear(this.gl.COLOR_BUFFER_BIT);
56
+
57
+ this.gl.useProgram(program._program);
58
+
59
+ for (let attributeName in program.attributesLocations) {
60
+ let location = program.attributesLocations[attributeName];
61
+ let buffer = geometry.buffers[attributeName];
62
+
63
+ this.gl.enableVertexAttribArray(location);
64
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
65
+
66
+ const size = 2; // 2 components per iteration
67
+ const type = this.gl.FLOAT; // the data is 32bit floats
68
+ const normalize = false; // don't normalize the data
69
+ const stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position
70
+ const bufferOffset = 0; // start at the beginning of the buffer
71
+ this.gl.vertexAttribPointer(
72
+ location,
73
+ size,
74
+ type,
75
+ normalize,
76
+ stride,
77
+ bufferOffset
78
+ );
79
+ }
80
+
81
+ let textureUnit = -1;
82
+
83
+ for (let uniformName in program.uniforms) {
84
+ let location = program.uniformsLocations[uniformName];
85
+ if (location) {
86
+ let uniform = program.uniforms[uniformName];
87
+
88
+ if (uniform.type === 'float') {
89
+ this.gl.uniform1f(location, uniform.value);
90
+ } else if (uniform.type === 'vec2') {
91
+ this.gl.uniform2f(location, uniform.value[0], uniform.value[1]);
92
+ } else if (uniform.type === 'vec3') {
93
+ this.gl.uniform3f(location, uniform.value[0], uniform.value[1], uniform.value[2]);
94
+ } else if (uniform.type === 'vec4') {
95
+ this.gl.uniform4f(location, uniform.value[0], uniform.value[1], uniform.value[2], uniform.value[3]);
96
+ } else if (uniform.type === 'sampler2D') {
97
+ if (uniform.value) {
98
+ textureUnit = textureUnit + 1;
99
+ uniform.value.update(textureUnit);
100
+
101
+ this.gl.uniform1i(location, textureUnit);
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ this.gl.drawArrays(primitiveType, offset, count);
108
+ }
109
+
110
+ setPixelRatio(pixelRatio = this.state.pixelRatio) {
111
+ if (this.state.pixelRatio !== pixelRatio) {
112
+ this.state.pixelRatio = pixelRatio;
113
+ this.setSize();
114
+ }
115
+ }
116
+
117
+ setSize({ width = this.state.width, height = this.state.height } = {}) {
118
+ this.state.width = width;
119
+ this.state.height = height;
120
+
121
+ this.canvas.width = this.state.width * this.state.pixelRatio;
122
+ this.canvas.height = this.state.height * this.state.pixelRatio;
123
+
124
+ this.setViewport();
125
+ }
126
+
127
+ setViewport({ width = this.state.width, height = this.state.height } = {}) {
128
+ let w = Math.floor(width * this.state.pixelRatio);
129
+ let h = Math.floor(height * this.state.pixelRatio);
130
+
131
+ if (this.state.viewport.width !== w || this.state.viewport.height !== h) {
132
+ this.gl.viewport(0, 0, w, h);
133
+
134
+ this.state.viewport.width = w;
135
+ this.state.viewport.height = h;
136
+ }
137
+ }
138
+
139
+ destroy() {
140
+ let extension = this.gl.getExtension('WEBGL_lose_context');
141
+
142
+ if (extension) {
143
+ extension.loseContext();
144
+ }
145
+ }
146
+ }
147
+
148
+ export default Renderer;
@@ -0,0 +1,114 @@
1
+ import { isPowerOf2 } from "./utils";
2
+
3
+ const emptyPixel = new Uint8Array([0, 0, 0, 0]);
4
+
5
+ let TEXTURE_ID = 0;
6
+
7
+ class Texture {
8
+ constructor(gl, {
9
+ image,
10
+ name = '',
11
+ target = gl.TEXTURE_2D,
12
+ type = gl.UNSIGNED_BYTE,
13
+ wrapS = gl.CLAMP_TO_EDGE,
14
+ wrapT = gl.CLAMP_TO_EDGE,
15
+ generateMipmaps = true,
16
+ format = gl.RGBA,
17
+ internalFormat = format,
18
+ minFilter = generateMipmaps ? gl.NEAREST_MIPMAP_LINEAR : gl.LINEAR,
19
+ magFilter = gl.LINEAR,
20
+ // premultiplyAlpha = false,
21
+ // unpackAlignment = 4,
22
+ flipY = target === gl.TEXTURE_2D ? true : false,
23
+ // width = image ? image.width : null,
24
+ // height = image ? image.height : null
25
+ } = {}) {
26
+ this.gl = gl;
27
+ this.image = image;
28
+ this.name = name;
29
+ this.target = target;
30
+ this.type = type;
31
+ this.wrapS = wrapS;
32
+ this.wrapT = wrapT;
33
+ this.generateMipmaps = generateMipmaps;
34
+ this.format = format;
35
+ this.internalFormat = internalFormat;
36
+ this.minFilter = minFilter;
37
+ this.magFilter = magFilter;
38
+ this.flipY = flipY;
39
+ this.needsUpdate = true;
40
+
41
+ this.glTexture = this.gl.createTexture();
42
+ this.id = TEXTURE_ID++;
43
+ }
44
+
45
+ bind() {
46
+ if (this.gl.state.textureUnits[this.gl.state.activeTextureUnit] === this.id) return;
47
+
48
+ this.gl.bindTexture(this.target, this.glTexture);
49
+ this.gl.state.textureUnits[this.gl.state.activeTextureUnit] = this.id;
50
+ }
51
+
52
+ update(textureUnit = 0) {
53
+ if (this.needsUpdate || this.gl.state.textureUnits[textureUnit] !== this.id) {
54
+ if (this.gl.state.activeTextureUnit !== textureUnit) {
55
+ this.gl.state.activeTextureUnit = textureUnit;
56
+ this.gl.activeTexture(this.gl.TEXTURE0 + textureUnit);
57
+ }
58
+
59
+ this.bind();
60
+ }
61
+
62
+ if (!this.needsUpdate) return;
63
+
64
+ this.needsUpdate = false;
65
+
66
+ if (this.flipY !== this.gl.state.flipY) {
67
+ this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, this.flipY);
68
+ this.gl.state.flipY = this.flipY;
69
+ }
70
+
71
+ if (this.image && this.generateMipmaps) {
72
+ if (!isPowerOf2(this.image.width) || !isPowerOf2(this.image.height)) {
73
+ this.generateMipmaps = false;
74
+
75
+ this.wrapS = this.wrapT = this.gl.CLAMP_TO_EDGE;
76
+ this.minFilter = this.gl.LINEAR;
77
+ }
78
+ }
79
+
80
+ this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_S, this.wrapS);
81
+ this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_T, this.wrapT);
82
+ this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, this.minFilter);
83
+ this.gl.texParameteri(this.target, this.gl.TEXTURE_MAG_FILTER, this.magFilter);
84
+
85
+ if (this.image) {
86
+ this.gl.texImage2D(this.target, 0, this.internalFormat, this.format, this.type, this.image);
87
+
88
+ if (this.generateMipmaps) {
89
+ this.gl.generateMipmap(this.target);
90
+ }
91
+ } else {
92
+ this.gl.texImage2D(
93
+ this.target,
94
+ 0,
95
+ this.gl.RGBA,
96
+ 1,
97
+ 1,
98
+ 0,
99
+ this.gl.RGBA,
100
+ this.gl.UNSIGNED_BYTE,
101
+ emptyPixel
102
+ );
103
+ }
104
+ }
105
+
106
+ destroy() {
107
+ this.gl.deleteTexture(this.glTexture);
108
+ this.glTexture = null;
109
+ this.gl = null;
110
+ this.image = null;
111
+ }
112
+ }
113
+
114
+ export default Texture;
@@ -0,0 +1,109 @@
1
+ import Geometry from "./Geometry.js";
2
+ import Texture from "./Texture.js";
3
+ import Program, { defaultFragment, defaultVertex } from "./Program.js";
4
+ import Renderer from "./Renderer.js";
5
+
6
+ export { Geometry, Texture, Program, Renderer };
7
+
8
+ export function fragment({
9
+ canvas = document.createElement('canvas'),
10
+ shader = defaultFragment,
11
+ uniforms = {},
12
+ }) {
13
+ let _fragmentShader = shader;
14
+ let _vertexShader = defaultVertex;
15
+ let _uniforms = uniforms;
16
+
17
+ let renderer = new Renderer({
18
+ canvas,
19
+ });
20
+
21
+ let geometry = new Geometry(renderer.gl);
22
+ let program = new Program(renderer.gl, {
23
+ fragment: shader,
24
+ uniforms,
25
+ });
26
+
27
+ function render() {
28
+ renderer.render({ geometry, program });
29
+ }
30
+
31
+ let w, h, pr;
32
+
33
+ function resize({ width = w, height = h, pixelRatio = pr }) {
34
+ renderer.setPixelRatio(pixelRatio);
35
+ renderer.setSize({ width, height });
36
+
37
+ w = width;
38
+ h = height;
39
+ pr = pixelRatio;
40
+ }
41
+
42
+ function destroy() {
43
+ geometry.destroy();
44
+ renderer.destroy();
45
+ uniforms = null;
46
+ }
47
+
48
+ const frag = {
49
+ gl: renderer.gl,
50
+ program,
51
+
52
+ texture: (params = {}) => new Texture(gl, params),
53
+
54
+ resize,
55
+ render,
56
+ destroy,
57
+ };
58
+
59
+ Object.defineProperty(frag, 'shader', {
60
+ enumerable: true,
61
+ configurable: true,
62
+ get: () => {
63
+ return _fragmentShader;
64
+ },
65
+ set: (v) => {
66
+ _fragmentShader = v;
67
+ program.fragmentShader = _fragmentShader;
68
+ }
69
+ });
70
+
71
+ Object.defineProperty(frag, 'fragmentShader', {
72
+ enumerable: true,
73
+ configurable: true,
74
+ get: () => {
75
+ return _fragmentShader;
76
+ },
77
+ set: (v) => {
78
+ _fragmentShader = v;
79
+ program.fragmentShader = _fragmentShader;
80
+ }
81
+ });
82
+
83
+ Object.defineProperty(frag, 'vertexShader', {
84
+ enumerable: true,
85
+ configurable: true,
86
+ get: () => {
87
+ return _vertexShader;
88
+ },
89
+ set: (v) => {
90
+ _vertexShader = v;
91
+ program.vertexShader = _vertexShader;
92
+ }
93
+ });
94
+
95
+ Object.defineProperty(frag, 'uniforms', {
96
+ enumerable: true,
97
+ configurable: true,
98
+ get: () => {
99
+ return _uniforms;
100
+ },
101
+ set: (v) => {
102
+ _uniforms = v;
103
+ program.uniforms = _uniforms;
104
+ program.needsUpdate = true;
105
+ }
106
+ });
107
+
108
+ return frag;
109
+ }
@@ -0,0 +1,5 @@
1
+
2
+
3
+ export function isPowerOf2(value) {
4
+ return (value & (value - 1)) === 0;
5
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Run a function maximum once per frame
3
+ * @param {Function} fn
4
+ * @param {Number} timeout
5
+ * @returns {Function} debounced function
6
+ */
7
+ export default function frameDebounce(fn, timeout = 100){
8
+ let lastTime = performance.now();
9
+ let needCall = false;
10
+ let _raf;
11
+ let a;
12
+
13
+ function loop() {
14
+ const now = performance.now();
15
+
16
+ if (needCall) {
17
+ needCall = false;
18
+ lastTime = now;
19
+
20
+ fn.apply(this, a);
21
+ lastTime = now;
22
+ }
23
+
24
+ if (now - lastTime > timeout && _raf > -1) {
25
+ cancelAnimationFrame(_raf);
26
+ _raf = null;
27
+ } else {
28
+ _raf = requestAnimationFrame(loop);
29
+ }
30
+ }
31
+
32
+ return (...args) => {
33
+ needCall = true;
34
+ a = args;
35
+
36
+ if (!_raf) {
37
+ loop();
38
+ }
39
+ };
40
+ }
@@ -0,0 +1,20 @@
1
+ import { loadImage } from "./loadImage";
2
+
3
+ function getFileExtension(path) {
4
+ return path.match(/[^\\/]\.([^.\\/]+)$/);
5
+ }
6
+
7
+ function getLoader(extension) {
8
+ if (["jpeg", "jpg", "gif", "png", "webp"].includes(extension)) {
9
+ return loadImage;
10
+ }
11
+
12
+ return () => {};
13
+ }
14
+
15
+ export function load(url, options = { id: url }) {
16
+ const extension = getFileExtension(url);
17
+ const loader = options.loader || getLoader(extension);
18
+
19
+ return loader(url, options);
20
+ };
@@ -0,0 +1,19 @@
1
+ export function loadImage(url, { id = url, img = new Image() } = {}) {
2
+ return new Promise((resolve, reject) => {
3
+ function onLoad() {
4
+ img.removeEventListener('load', onLoad);
5
+ resolve(img);
6
+ }
7
+
8
+ function onError(error) {
9
+ img.removeEventListener('load', onLoad);
10
+ img.removeEventListener('error', onError);
11
+ reject(error);
12
+ }
13
+
14
+ img.addEventListener('load', onLoad);
15
+ img.addEventListener('error', onError);
16
+
17
+ img.src = url;
18
+ });
19
+ };
@@ -0,0 +1,14 @@
1
+ export function loadScript(src) {
2
+ return new Promise((resolve, reject) => {
3
+ const script = document.createElement('script');
4
+ script.onerror = (err) => {
5
+ reject(err);
6
+ };
7
+ script.onload = () => {
8
+ resolve();
9
+ }
10
+
11
+ script.src = src;
12
+ document.body.appendChild(script);
13
+ });
14
+ }
@@ -0,0 +1,104 @@
1
+ // https://github.com/mattdesl/canvas-sketch/blob/24f6bb2bbdfdfd72a698a0b8a0962ad843fb7688/lib/paper-sizes.js
2
+ const defaultUnits = 'mm';
3
+
4
+ const data = [
5
+ // Common Paper Sizes
6
+ // (Mostly North-American based)
7
+ [ 'postcard', 101.6, 152.4 ],
8
+ [ 'poster-small', 280, 430 ],
9
+ [ 'poster', 460, 610 ],
10
+ [ 'poster-large', 610, 910 ],
11
+ [ 'business-card', 50.8, 88.9 ],
12
+
13
+ // Photographic Print Paper Sizes
14
+ [ '2r', 64, 89 ],
15
+ [ '3r', 89, 127 ],
16
+ [ '4r', 102, 152 ],
17
+ [ '5r', 127, 178 ], // 5″x7″
18
+ [ '6r', 152, 203 ], // 6″x8″
19
+ [ '8r', 203, 254 ], // 8″x10″
20
+ [ '10r', 254, 305 ], // 10″x12″
21
+ [ '11r', 279, 356 ], // 11″x14″
22
+ [ '12r', 305, 381 ],
23
+
24
+ // Standard Paper Sizes
25
+ [ 'a0', 841, 1189 ],
26
+ [ 'a1', 594, 841 ],
27
+ [ 'a2', 420, 594 ],
28
+ [ 'a3', 297, 420 ],
29
+ [ 'a4', 210, 297 ],
30
+ [ 'a5', 148, 210 ],
31
+ [ 'a6', 105, 148 ],
32
+ [ 'a7', 74, 105 ],
33
+ [ 'a8', 52, 74 ],
34
+ [ 'a9', 37, 52 ],
35
+ [ 'a10', 26, 37 ],
36
+ [ '2a0', 1189, 1682 ],
37
+ [ '4a0', 1682, 2378 ],
38
+ [ 'b0', 1000, 1414 ],
39
+ [ 'b1', 707, 1000 ],
40
+ [ 'b1+', 720, 1020 ],
41
+ [ 'b2', 500, 707 ],
42
+ [ 'b2+', 520, 720 ],
43
+ [ 'b3', 353, 500 ],
44
+ [ 'b4', 250, 353 ],
45
+ [ 'b5', 176, 250 ],
46
+ [ 'b6', 125, 176 ],
47
+ [ 'b7', 88, 125 ],
48
+ [ 'b8', 62, 88 ],
49
+ [ 'b9', 44, 62 ],
50
+ [ 'b10', 31, 44 ],
51
+ [ 'b11', 22, 32 ],
52
+ [ 'b12', 16, 22 ],
53
+ [ 'c0', 917, 1297 ],
54
+ [ 'c1', 648, 917 ],
55
+ [ 'c2', 458, 648 ],
56
+ [ 'c3', 324, 458 ],
57
+ [ 'c4', 229, 324 ],
58
+ [ 'c5', 162, 229 ],
59
+ [ 'c6', 114, 162 ],
60
+ [ 'c7', 81, 114 ],
61
+ [ 'c8', 57, 81 ],
62
+ [ 'c9', 40, 57 ],
63
+ [ 'c10', 28, 40 ],
64
+ [ 'c11', 22, 32 ],
65
+ [ 'c12', 16, 22 ],
66
+
67
+ // Use inches for North American sizes,
68
+ // as it produces less float precision errors
69
+ [ 'half-letter', 5.5, 8.5, 'in' ],
70
+ [ 'letter', 8.5, 11, 'in' ],
71
+ [ 'legal', 8.5, 14, 'in' ],
72
+ [ 'junior-legal', 5, 8, 'in' ],
73
+ [ 'ledger', 11, 17, 'in' ],
74
+ [ 'tabloid', 11, 17, 'in' ],
75
+ [ 'ansi-a', 8.5, 11.0, 'in' ],
76
+ [ 'ansi-b', 11.0, 17.0, 'in' ],
77
+ [ 'ansi-c', 17.0, 22.0, 'in' ],
78
+ [ 'ansi-d', 22.0, 34.0, 'in' ],
79
+ [ 'ansi-e', 34.0, 44.0, 'in' ],
80
+ [ 'arch-a', 9, 12, 'in' ],
81
+ [ 'arch-b', 12, 18, 'in' ],
82
+ [ 'arch-c', 18, 24, 'in' ],
83
+ [ 'arch-d', 24, 36, 'in' ],
84
+ [ 'arch-e', 36, 48, 'in' ],
85
+ [ 'arch-e1', 30, 42, 'in' ],
86
+ [ 'arch-e2', 26, 38, 'in' ],
87
+ [ 'arch-e3', 27, 39, 'in' ]
88
+ ];
89
+
90
+ let dictionary = data.reduce((dict, preset) => {
91
+ const item = {
92
+ units: preset[3] || defaultUnits,
93
+ dimensions: [ preset[1], preset[2] ]
94
+ };
95
+
96
+ dict[preset[0]] = item;
97
+ dict[preset[0].replace(/-/g, ' ')] = item;
98
+
99
+ return dict;
100
+ }, {});
101
+
102
+ export default dictionary;
103
+
104
+ export const presets = Object.keys(dictionary);
@@ -0,0 +1,12 @@
1
+ import paperSizes from "./paper-sizes.js";
2
+ import convertLength from "convert-length";
3
+
4
+ export default Object.keys(paperSizes);
5
+
6
+ export function getDimensionsForPreset(preset, { pixelsPerInch }) {
7
+ const { dimensions, units } = paperSizes[preset];
8
+
9
+ return dimensions.map(n => {
10
+ return convertLength(n, units, "px", { pixelsPerInch });
11
+ });
12
+ }