chroma-noise 0.0.5 → 0.0.6

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.
@@ -1,9 +1,8 @@
1
1
  <script lang="ts">
2
2
  import frag from './fragment.txt?raw';
3
3
  import { onMount, onDestroy } from 'svelte';
4
+ import { hexToRgb, isBrowser, createGradientWorker, getTargetSize } from './index.js';
4
5
  import type { Warp, Grain, GradientOptions } from './index.js';
5
- import { hexToRgb, isBrowser } from './utils.js';
6
- import gradientWorker from './gradient.worker.js?worker&module';
7
6
 
8
7
  let {
9
8
  points = [],
@@ -16,6 +15,8 @@
16
15
  seed = Math.random(),
17
16
  currentState = $bindable('loading'),
18
17
  class: c = '',
18
+ resolution = {},
19
+ blendMode = 'legacy',
19
20
  ...rest
20
21
  }: GradientOptions = $props();
21
22
 
@@ -27,11 +28,13 @@
27
28
 
28
29
  let canvas: HTMLCanvasElement | undefined = $state();
29
30
  let worker: Worker | undefined = $state();
30
- let frame: number;
31
- let running = true;
31
+ let running = $state(false);
32
32
  let lastTime = 0;
33
33
  let animTime = 0;
34
+ let frame: number | null = null;
35
+ let currentCanvasSize = $state({ width: 0, height: 0 });
34
36
 
37
+ let lastUniforms = $state<Record<string, any>>({});
35
38
 
36
39
  function updateUniforms() {
37
40
  if (!worker) return;
@@ -45,55 +48,80 @@
45
48
  posArr.set([points[i].x, points[i].y], i * 2);
46
49
  }
47
50
 
48
- worker.postMessage({
49
- type: 'updateUniforms',
50
- uniforms: {
51
- u_colors: colorsArr,
52
- u_positions: posArr,
53
- u_count: Math.min(points.length, maxPoints),
54
- u_radius: radius,
55
- u_intensity: intensity,
56
- u_warpMode: warp.mode,
57
- u_warpSize: warp.size,
58
- u_warpAmount: warp.amount,
59
- u_grainAmount: grain.amount,
60
- u_grainSize: grain.size,
61
- u_seed: seed
51
+ const newUniforms = {
52
+ u_colors: colorsArr,
53
+ u_positions: posArr,
54
+ u_count: Math.min(points.length, maxPoints),
55
+ u_radius: radius,
56
+ u_intensity: intensity,
57
+ u_warpMode: Number(warp.mode),
58
+ u_warpSize: warp.size,
59
+ u_warpAmount: warp.amount,
60
+ u_grainAmount: grain.amount,
61
+ u_grainSize: grain.size,
62
+ u_seed: seed,
63
+ u_blendMode: blendMode === 'new' ? 0 : 1
64
+ };
65
+
66
+ const changedUniforms: Record<string, any> = {};
67
+ for (const [key, value] of Object.entries(newUniforms)) {
68
+ if (JSON.stringify(lastUniforms[key]) !== JSON.stringify(value)) {
69
+ changedUniforms[key] = value;
62
70
  }
63
- });
64
- }
71
+ }
65
72
 
66
- function updateResolution() {
67
- if (!worker || !canvas) return;
68
- const dpr = Math.max(1, window.devicePixelRatio || 1);
69
- const width = Math.floor(canvas.clientWidth * dpr);
70
- const height = Math.floor(canvas.clientHeight * dpr);
71
- worker.postMessage({
72
- type: 'updateUniforms',
73
- uniforms: {
74
- u_resolution: [width, height]
75
- }
76
- });
73
+ if (Object.keys(changedUniforms).length > 0) {
74
+ worker.postMessage({
75
+ type: 'updateUniforms',
76
+ uniforms: changedUniforms
77
+ });
78
+ lastUniforms = { ...newUniforms };
79
+ }
77
80
  }
78
81
 
79
- function render(time: number) {
80
- if (worker) {
81
- if (lastTime === 0) lastTime = time;
82
- const dt = (time - lastTime) * 0.001;
83
- lastTime = time;
84
- animTime += dt * speed;
82
+ function resizeCanvasToDisplaySize() {
83
+ if (!canvas || !worker) return;
84
+
85
+ const { width, height } = getTargetSize(canvas, resolution);
85
86
 
87
+ if (currentCanvasSize.width !== width || currentCanvasSize.height !== height) {
88
+ currentCanvasSize = { width, height };
86
89
  worker.postMessage({
87
- type: 'render',
88
- time: animTime
90
+ type: 'resize',
91
+ width,
92
+ height
89
93
  });
94
+ }
95
+ }
90
96
 
91
- if (running) {
92
- currentState = 'playing';
93
- frame = requestAnimationFrame(render);
94
- } else {
95
- currentState = 'paused';
96
- }
97
+ $effect(() => {
98
+ if (worker) {
99
+ updateUniforms();
100
+ }
101
+ });
102
+
103
+ $effect(() => {
104
+ if (worker) {
105
+ resizeCanvasToDisplaySize();
106
+ }
107
+ });
108
+
109
+ function render(time: number) {
110
+ if (!worker) return;
111
+
112
+ if (lastTime === 0) lastTime = time;
113
+ const dt = (time - lastTime) * 0.001;
114
+ lastTime = time;
115
+ animTime += dt * speed;
116
+
117
+ worker.postMessage({
118
+ type: 'render',
119
+ time: animTime
120
+ });
121
+
122
+ if (running) {
123
+ currentState = 'playing';
124
+ frame = requestAnimationFrame(render);
97
125
  }
98
126
  }
99
127
 
@@ -101,52 +129,45 @@
101
129
  if (!canvas || !isBrowser()) return;
102
130
  currentState = 'loading';
103
131
 
104
- worker = new gradientWorker();
105
-
106
- worker.onmessage = (event: MessageEvent) => {
107
- const { type } = event.data;
108
- if (type === 'ready') {
109
- updateUniforms();
110
- currentState = 'playing';
111
- } else if (type === 'rendering') {
112
- currentState = 'playing';
113
- } else if (type === 'paused') {
114
- currentState = 'paused';
115
- } else if (type === 'error') {
116
- console.error('Worker error:', event.data.error);
117
- currentState = 'paused';
118
- }
119
- };
120
-
121
- const dpr = Math.max(1, window.devicePixelRatio || 1);
122
- const width = Math.floor(canvas.clientWidth * dpr);
123
- const height = Math.floor(canvas.clientHeight * dpr);
124
- canvas.width = width;
125
- canvas.height = height;
126
-
127
- try {
128
- const offscreenCanvas = canvas.transferControlToOffscreen();
129
- worker.postMessage({
130
- type: 'init',
131
- offscreenCanvas,
132
- fragShader: frag,
133
- speed
134
- }, [offscreenCanvas]);
132
+ worker = createGradientWorker();
135
133
 
136
- const resizeObserver = new ResizeObserver(() => {
137
- updateResolution();
138
- });
139
- resizeObserver.observe(canvas);
140
- frame = requestAnimationFrame(render);
141
- } catch (error) {
142
- console.error('Could not transfer canvas to worker: ', error);
134
+ worker.onmessage = (event: MessageEvent) => {
135
+ const { type } = event.data;
136
+ if (type === 'ready') {
137
+ updateUniforms();
138
+ currentState = 'playing';
139
+ frame = requestAnimationFrame(render);
140
+ } else if (type === 'error') {
141
+ console.error('Worker error:', event.data.error);
142
+ currentState = 'paused';
143
143
  }
144
+ };
145
+
146
+ const { width, height } = getTargetSize(canvas, resolution);
147
+ currentCanvasSize = { width, height };
148
+
149
+ try {
150
+ const offscreenCanvas = canvas.transferControlToOffscreen();
151
+ worker.postMessage(
152
+ {
153
+ type: 'init',
154
+ offscreenCanvas,
155
+ fragShader: frag
156
+ },
157
+ [offscreenCanvas]
158
+ );
159
+ worker.postMessage({ type: 'resize', width, height });
160
+ running = true;
161
+ } catch (error) {
162
+ console.error('Could not transfer canvas to worker: ', error);
163
+ }
144
164
  });
145
165
 
146
166
  onDestroy(() => {
147
167
  running = false;
148
168
  if (!isBrowser()) return;
149
-
169
+
170
+ if (frame) cancelAnimationFrame(frame);
150
171
  if (worker) {
151
172
  worker.postMessage({ type: 'destroy' });
152
173
  worker.terminate();
@@ -154,16 +175,25 @@
154
175
  });
155
176
 
156
177
  $effect(() => {
157
- if(worker && (points.length || radius || intensity || warp || grain || seed)) {
178
+ if (worker && (points.length || radius || intensity || warp || grain || seed)) {
158
179
  updateUniforms();
159
180
  }
160
181
  });
161
182
  </script>
162
183
 
163
- <canvas bind:this={canvas} {...rest} class="{c} {currentState}"></canvas>
184
+ <canvas bind:this={canvas} {...rest} class="{currentState} {c}"></canvas>
164
185
 
165
186
  <style>
166
- canvas { width: 100%; height: 100%; display: block; transition: opacity 1s ease-out }
167
- canvas.loading { opacity: 0; }
168
- canvas.playing { opacity: 1; }
187
+ canvas {
188
+ width: 100%;
189
+ height: 100%;
190
+ display: block;
191
+ transition: opacity 1s ease-out;
192
+ }
193
+ canvas.loading {
194
+ opacity: 0;
195
+ }
196
+ canvas.playing {
197
+ opacity: 1;
198
+ }
169
199
  </style>
package/dist/fragment.txt CHANGED
@@ -17,6 +17,7 @@ uniform int u_warpMode;
17
17
  uniform float u_warpSize;
18
18
  uniform float u_warpAmount;
19
19
  uniform float u_seed;
20
+ uniform int u_blendMode;
20
21
 
21
22
  vec3 permute(vec3 x) {
22
23
  return mod(((x * 34.0) + 1.0) * x, 289.0);
@@ -136,6 +137,10 @@ void main() {
136
137
 
137
138
  float g = grain(gl_FragCoord.xy / u_resolution.xy);
138
139
 
140
+ float radiusToUse = (u_blendMode == 0)
141
+ ? u_radius * min(u_resolution.x / u_resolution.y, 1.0)
142
+ : u_radius;
143
+
139
144
  vec3 accum = vec3(0.0);
140
145
  float totalWeight = 0.0;
141
146
  for (int i = 0; i < MAX_POINTS; ++i) {
@@ -143,7 +148,7 @@ void main() {
143
148
  vec2 diff = uv - u_positions[i];
144
149
  diff.x *= u_resolution.x / u_resolution.y;
145
150
  float d = length(diff);
146
- float w = exp(- (d * d) / (u_radius * u_radius));
151
+ float w = exp(- (d * d) / (radiusToUse * radiusToUse));
147
152
  w = pow(w, max(0.001, u_intensity));
148
153
  accum += u_colors[i] * w;
149
154
  totalWeight += w;
@@ -57,13 +57,18 @@ self.onmessage = (event) => {
57
57
  case 'updateUniforms': {
58
58
  const { uniforms: newUniforms } = event.data;
59
59
  if (newUniforms) {
60
- currentUniforms = newUniforms;
60
+ console.log('Worker received uniforms:', newUniforms);
61
+ currentUniforms = {
62
+ ...currentUniforms,
63
+ ...newUniforms
64
+ };
65
+ console.log('Current uniforms after update:', currentUniforms);
61
66
  }
62
67
  break;
63
68
  }
64
69
  case 'resize': {
65
- const { width, height, dpr } = event.data;
66
- if (gl && width && height && dpr) {
70
+ const { width, height } = event.data;
71
+ if (gl && width && height) {
67
72
  const scaledWidth = Math.floor(width);
68
73
  const scaledHeight = Math.floor(height);
69
74
  gl.canvas.width = scaledWidth;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export { default as Gradient } from './Gradient.svelte';
2
2
  export type * from './types.js';
3
3
  export * from './utils.js';
4
+ export { createGradientWorker } from './workerFactory.js';
5
+ export type { Resolution, BlendMode } from './types.js';
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { default as Gradient } from './Gradient.svelte';
2
2
  export * from './utils.js';
3
+ export { createGradientWorker } from './workerFactory.js';
package/dist/types.d.ts CHANGED
@@ -30,6 +30,21 @@ export interface Grain {
30
30
  size?: number;
31
31
  }
32
32
  export type shaderState = 'loading' | 'playing' | 'paused';
33
+ /**
34
+ * Blend modes for gradient rendering
35
+ */
36
+ export type BlendMode = 'new' | 'legacy';
37
+ /** Configuration for resolution. */
38
+ export interface Resolution {
39
+ /** Canvas resolution width, default: canvas.clientWidth */
40
+ width?: number;
41
+ /** Canvas resolution height, default: canvas.clientHeight */
42
+ height?: number;
43
+ /** Canvas resolution modifier, default: 1, min: 0.01, max: 2 */
44
+ modifier?: number;
45
+ /** Determines whether to use DPR, default: false */
46
+ useDPR?: boolean;
47
+ }
33
48
  /**
34
49
  * Configuration for the gradient.
35
50
  */
@@ -54,6 +69,10 @@ export interface GradientOptions {
54
69
  currentState?: shaderState;
55
70
  /** Class applied to the canvas element **/
56
71
  class?: string;
72
+ /** Resolution settings */
73
+ resolution?: Resolution;
74
+ /** Blend mode for gradient rendering */
75
+ blendMode?: BlendMode;
57
76
  }
58
77
  export interface RenderMessage {
59
78
  type: 'init' | 'render' | 'resize' | 'updateUniforms' | 'destroy';
package/dist/utils.d.ts CHANGED
@@ -1,15 +1,17 @@
1
1
  export declare function hexToRgb(hex: string): [number, number, number];
2
- export declare const SHADER_UNIFORMS: readonly ["u_resolution", "u_time", "u_count", "u_colors", "u_positions", "u_radius", "u_intensity", "u_warpMode", "u_warpSize", "u_warpAmount", "u_grainAmount", "u_grainSize", "u_seed"];
2
+ export declare const SHADER_UNIFORMS: readonly ["u_resolution", "u_time", "u_count", "u_colors", "u_positions", "u_radius", "u_intensity", "u_warpMode", "u_warpSize", "u_warpAmount", "u_grainAmount", "u_grainSize", "u_seed", "u_blendMode"];
3
3
  export declare const VERTEX_SHADER = "attribute vec2 a_pos;void main() {gl_Position = vec4(a_pos, 0.0, 1.0);}";
4
4
  export declare const FULLSCREEN_QUAD: Float32Array<ArrayBuffer>;
5
5
  export declare function createShader(gl: WebGL2RenderingContext | WebGLRenderingContext, type: number, src: string): WebGLShader;
6
6
  export declare function createProgram(gl: WebGL2RenderingContext | WebGLRenderingContext, vsSrc: string, fsSrc: string): WebGLProgram;
7
7
  export declare function getUniform(gl: WebGL2RenderingContext | WebGLRenderingContext, program: WebGLProgram, name: string): WebGLUniformLocation;
8
8
  export declare function setupQuadBuffer(gl: WebGL2RenderingContext | WebGLRenderingContext, program: WebGLProgram): void;
9
- export declare function getCanvasSize(canvas: HTMLCanvasElement): {
9
+ /**
10
+ * Calculate target canvas size based on resolution settings
11
+ */
12
+ export declare function getTargetSize(canvas: HTMLCanvasElement, resolution: import('./types.js').Resolution): {
10
13
  width: number;
11
14
  height: number;
12
- dpr: number;
13
15
  };
14
16
  export declare const isBrowser: () => boolean;
15
17
  /**
package/dist/utils.js CHANGED
@@ -21,7 +21,8 @@ export const SHADER_UNIFORMS = [
21
21
  'u_warpAmount',
22
22
  'u_grainAmount',
23
23
  'u_grainSize',
24
- 'u_seed'
24
+ 'u_seed',
25
+ 'u_blendMode'
25
26
  ];
26
27
  export const VERTEX_SHADER = `attribute vec2 a_pos;void main() {gl_Position = vec4(a_pos, 0.0, 1.0);}`;
27
28
  export const FULLSCREEN_QUAD = new Float32Array([-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);
@@ -64,11 +65,34 @@ export function setupQuadBuffer(gl, program) {
64
65
  gl.enableVertexAttribArray(a_pos);
65
66
  gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0);
66
67
  }
67
- export function getCanvasSize(canvas) {
68
+ /**
69
+ * Calculate target canvas size based on resolution settings
70
+ */
71
+ export function getTargetSize(canvas, resolution) {
68
72
  const dpr = Math.max(1, window.devicePixelRatio || 1);
69
- const width = Math.floor(canvas.clientWidth * dpr);
70
- const height = Math.floor(canvas.clientHeight * dpr);
71
- return { width, height, dpr };
73
+ const clientWidth = canvas.clientWidth;
74
+ const clientHeight = canvas.clientHeight;
75
+ let width = clientWidth;
76
+ let height = clientHeight;
77
+ if (resolution.width !== undefined) {
78
+ width = resolution.width;
79
+ }
80
+ if (resolution.height !== undefined) {
81
+ height = resolution.height;
82
+ }
83
+ if (resolution.modifier !== undefined) {
84
+ const modifier = Math.max(0.01, Math.min(2.0, resolution.modifier));
85
+ width = width * modifier;
86
+ height = height * modifier;
87
+ }
88
+ if (resolution.useDPR !== false) {
89
+ width = width * dpr;
90
+ height = height * dpr;
91
+ }
92
+ return {
93
+ width: Math.floor(width),
94
+ height: Math.floor(height)
95
+ };
72
96
  }
73
97
  export const isBrowser = () => typeof window !== 'undefined' && typeof document !== 'undefined';
74
98
  /**
@@ -86,7 +110,8 @@ export const UNIFORM_TYPES = {
86
110
  u_warpAmount: 'f32',
87
111
  u_grainAmount: 'f32',
88
112
  u_grainSize: 'f32',
89
- u_seed: 'f32'
113
+ u_seed: 'f32',
114
+ u_blendMode: 'i32'
90
115
  };
91
116
  /**
92
117
  * Set a WebGL uniform based on its type
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Worker factory that creates a gradient rendering worker as a Blob
3
+ * This approach ensures the worker works correctly
4
+ */
5
+ export declare function createGradientWorker(): Worker;
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Worker factory that creates a gradient rendering worker as a Blob
3
+ * This approach ensures the worker works correctly
4
+ */
5
+ export function createGradientWorker() {
6
+ const workerCode = `
7
+ const SHADER_UNIFORMS = [
8
+ 'u_resolution',
9
+ 'u_time',
10
+ 'u_count',
11
+ 'u_colors',
12
+ 'u_positions',
13
+ 'u_radius',
14
+ 'u_intensity',
15
+ 'u_warpMode',
16
+ 'u_warpSize',
17
+ 'u_warpAmount',
18
+ 'u_grainAmount',
19
+ 'u_grainSize',
20
+ 'u_seed'
21
+ ];
22
+
23
+ const VERTEX_SHADER = 'attribute vec2 a_pos;void main() {gl_Position = vec4(a_pos, 0.0, 1.0);}';
24
+ const FULLSCREEN_QUAD = new Float32Array([-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);
25
+
26
+ const UNIFORM_TYPES = {
27
+ u_resolution: 'vec2',
28
+ u_colors: 'vec3f',
29
+ u_positions: 'vec2f',
30
+ u_count: 'i32',
31
+ u_warpMode: 'i32',
32
+ u_radius: 'f32',
33
+ u_intensity: 'f32',
34
+ u_warpSize: 'f32',
35
+ u_warpAmount: 'f32',
36
+ u_grainAmount: 'f32',
37
+ u_grainSize: 'f32',
38
+ u_seed: 'f32'
39
+ };
40
+
41
+ let gl = null;
42
+ let program = null;
43
+ let uniforms = {};
44
+ let currentUniforms = {};
45
+
46
+ function createShader(gl, type, src) {
47
+ const s = gl.createShader(type);
48
+ gl.shaderSource(s, src);
49
+ gl.compileShader(s);
50
+ if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) {
51
+ const error = gl.getShaderInfoLog(s);
52
+ gl.deleteShader(s);
53
+ throw new Error(\`Shader compile error: \${error}\`);
54
+ }
55
+ return s;
56
+ }
57
+
58
+ function createProgram(gl, vsSrc, fsSrc) {
59
+ const vs = createShader(gl, gl.VERTEX_SHADER, vsSrc);
60
+ const fs = createShader(gl, gl.FRAGMENT_SHADER, fsSrc);
61
+ const p = gl.createProgram();
62
+ gl.attachShader(p, vs);
63
+ gl.attachShader(p, fs);
64
+ gl.linkProgram(p);
65
+ if (!gl.getProgramParameter(p, gl.LINK_STATUS)) {
66
+ const error = gl.getProgramInfoLog(p);
67
+ gl.deleteProgram(p);
68
+ throw new Error(\`Program link error: \${error}\`);
69
+ }
70
+ return p;
71
+ }
72
+
73
+ function getUniform(gl, program, name) {
74
+ const loc = gl.getUniformLocation(program, name);
75
+ if (!loc) throw new Error(\`Uniform \${name} not found\`);
76
+ return loc;
77
+ }
78
+
79
+ function setupQuadBuffer(gl, program) {
80
+ const vbo = gl.createBuffer();
81
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
82
+ gl.bufferData(gl.ARRAY_BUFFER, FULLSCREEN_QUAD, gl.STATIC_DRAW);
83
+ const a_pos = gl.getAttribLocation(program, 'a_pos');
84
+ gl.enableVertexAttribArray(a_pos);
85
+ gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0);
86
+ }
87
+
88
+ function setUniform(gl, uniform, key, value) {
89
+ const type = UNIFORM_TYPES[key];
90
+ if (!type) return;
91
+
92
+ switch (type) {
93
+ case 'vec2':
94
+ gl.uniform2f(uniform, value[0], value[1]);
95
+ break;
96
+ case 'vec3f':
97
+ gl.uniform3fv(uniform, value);
98
+ break;
99
+ case 'vec2f':
100
+ gl.uniform2fv(uniform, value);
101
+ break;
102
+ case 'i32':
103
+ gl.uniform1i(uniform, value);
104
+ break;
105
+ case 'f32':
106
+ gl.uniform1f(uniform, value);
107
+ break;
108
+ }
109
+ }
110
+
111
+ function initWorker(offscreenCanvas, fragShader) {
112
+ try {
113
+ gl = offscreenCanvas.getContext('webgl2', { antialias: true });
114
+ if (!gl) {
115
+ throw new Error('WebGL2 not supported');
116
+ }
117
+
118
+ program = createProgram(gl, VERTEX_SHADER, fragShader);
119
+ gl.useProgram(program);
120
+
121
+ setupQuadBuffer(gl, program);
122
+
123
+ for (const name of SHADER_UNIFORMS) {
124
+ uniforms[name] = getUniform(gl, program, name);
125
+ }
126
+
127
+ self.postMessage({ type: 'ready' });
128
+ } catch (error) {
129
+ self.postMessage({ type: 'error', error: error.message });
130
+ }
131
+ }
132
+
133
+ function performRender(time) {
134
+ if (!gl || !program) {
135
+ return;
136
+ }
137
+
138
+ gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
139
+ gl.clearColor(0, 0, 0, 0);
140
+ gl.clear(gl.COLOR_BUFFER_BIT);
141
+
142
+ gl.useProgram(program);
143
+ gl.uniform1f(uniforms.u_time, time);
144
+ gl.uniform2f(uniforms.u_resolution, gl.canvas.width, gl.canvas.height);
145
+
146
+ for (const [key, value] of Object.entries(currentUniforms)) {
147
+ const uniform = uniforms[key];
148
+ if (uniform && key !== 'u_resolution') setUniform(gl, uniform, key, value);
149
+ }
150
+
151
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
152
+ }
153
+
154
+ self.onmessage = (event) => {
155
+ const { type } = event.data;
156
+
157
+ switch (type) {
158
+ case 'init': {
159
+ const { offscreenCanvas, fragShader } = event.data;
160
+ if (offscreenCanvas && fragShader) {
161
+ initWorker(offscreenCanvas, fragShader);
162
+ }
163
+ break;
164
+ }
165
+ case 'render': {
166
+ const { time } = event.data;
167
+ if (time !== undefined) {
168
+ performRender(time);
169
+ }
170
+ break;
171
+ }
172
+ case 'updateUniforms': {
173
+ const { uniforms: newUniforms } = event.data;
174
+ if (newUniforms) {
175
+ currentUniforms = { ...currentUniforms, ...newUniforms };
176
+ }
177
+ break;
178
+ }
179
+ case 'resize': {
180
+ const { width, height } = event.data;
181
+ if (gl && width && height) {
182
+ gl.canvas.width = width;
183
+ gl.canvas.height = height;
184
+ }
185
+ break;
186
+ }
187
+ case 'destroy': {
188
+ break;
189
+ }
190
+ }
191
+ };
192
+ `;
193
+ const blob = new Blob([workerCode], { type: 'application/javascript' });
194
+ const workerUrl = URL.createObjectURL(blob);
195
+ return new Worker(workerUrl);
196
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chroma-noise",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",
@@ -38,6 +38,7 @@
38
38
  "@sveltejs/kit": "^2.43.2",
39
39
  "@sveltejs/package": "^2.5.4",
40
40
  "@sveltejs/vite-plugin-svelte": "^6.2.0",
41
+ "patch-package": "^8.0.1",
41
42
  "prettier": "^3.6.2",
42
43
  "prettier-plugin-svelte": "^3.4.0",
43
44
  "publint": "^0.3.13",