@fjandin/react-shader 0.0.12 → 0.0.15

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,3 +1,3 @@
1
1
  import type { ReactShaderProps } from "./types";
2
- export declare function ReactShader({ className, fragment, vertex, uniforms, fullscreen, timeScale, onFrame, onClick, onMouseMove, onMouseDown, onMouseUp, }: ReactShaderProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function ReactShader({ className, fragment, vertex, uniforms, fullscreen, timeScale, onFrame, onClick, onMouseMove, onMouseDown, onMouseUp, onMouseWheel, }: ReactShaderProps): import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=ReactShader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReactShader.d.ts","sourceRoot":"","sources":["../src/ReactShader.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAgC/C,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,QAAQ,EACR,MAAuB,EACvB,QAAQ,EACR,UAAkB,EAClB,SAAa,EACb,OAAO,EACP,OAAO,EACP,WAAW,EACX,WAAW,EACX,SAAS,GACV,EAAE,gBAAgB,2CAyDlB"}
1
+ {"version":3,"file":"ReactShader.d.ts","sourceRoot":"","sources":["../src/ReactShader.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAgC/C,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,QAAQ,EACR,MAAuB,EACvB,QAAQ,EACR,UAAkB,EAClB,SAAa,EACb,OAAO,EACP,OAAO,EACP,WAAW,EACX,WAAW,EACX,SAAS,EACT,YAAY,GACb,EAAE,gBAAgB,2CA0DlB"}
@@ -1 +1 @@
1
- {"version":3,"file":"frontend.d.ts","sourceRoot":"","sources":["../../src/example/frontend.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,aAAa,CAAA;AAwBpB,wBAAgB,GAAG,4CAwFlB"}
1
+ {"version":3,"file":"frontend.d.ts","sourceRoot":"","sources":["../../src/example/frontend.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,aAAa,CAAA;AAiHpB,wBAAgB,GAAG,4CAwGlB"}
@@ -0,0 +1,2 @@
1
+ export declare const textureFragment: string;
2
+ //# sourceMappingURL=texture-demo.glsl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"texture-demo.glsl.d.ts","sourceRoot":"","sources":["../../../src/example/glsl/texture-demo.glsl.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,QAsC3B,CAAA"}
@@ -9,6 +9,7 @@ interface UseWebGLOptions {
9
9
  onMouseDown?: (info: FrameInfo) => void;
10
10
  onMouseUp?: (info: FrameInfo) => void;
11
11
  onMouseMove?: (info: FrameInfo) => void;
12
+ onMouseWheel?: (info: FrameInfo, wheelDelta: number) => void;
12
13
  timeScale?: number;
13
14
  }
14
15
  export declare function useWebGL(options: UseWebGLOptions): {
@@ -1 +1 @@
1
- {"version":3,"file":"useWebGL.d.ts","sourceRoot":"","sources":["../../src/hooks/useWebGL.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAIvD,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACvC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACrC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAqED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe;;;EAyRhD"}
1
+ {"version":3,"file":"useWebGL.d.ts","sourceRoot":"","sources":["../../src/hooks/useWebGL.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAKvD,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACvC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACrC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAwED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe;;;EA0ShD"}
package/dist/index.cjs CHANGED
@@ -88,6 +88,147 @@ function createShaderProgram(gl, vertexSource, fragmentSource) {
88
88
  }
89
89
  }
90
90
 
91
+ // src/utils/textures.ts
92
+ function isTextureSource(value) {
93
+ if (typeof window === "undefined")
94
+ return false;
95
+ return value instanceof HTMLImageElement || value instanceof HTMLCanvasElement || value instanceof HTMLVideoElement || typeof ImageBitmap !== "undefined" && value instanceof ImageBitmap || value instanceof ImageData || typeof OffscreenCanvas !== "undefined" && value instanceof OffscreenCanvas;
96
+ }
97
+ function isTextureOptions(value) {
98
+ return typeof value === "object" && value !== null && "source" in value && isTextureSource(value.source);
99
+ }
100
+ function isTexture(value) {
101
+ return isTextureSource(value) || isTextureOptions(value);
102
+ }
103
+ function getWrapMode(gl, wrap) {
104
+ switch (wrap) {
105
+ case "repeat":
106
+ return gl.REPEAT;
107
+ case "mirror":
108
+ return gl.MIRRORED_REPEAT;
109
+ default:
110
+ return gl.CLAMP_TO_EDGE;
111
+ }
112
+ }
113
+ function getMinFilter(gl, filter) {
114
+ switch (filter) {
115
+ case "nearest":
116
+ return gl.NEAREST;
117
+ case "mipmap":
118
+ return gl.LINEAR_MIPMAP_LINEAR;
119
+ default:
120
+ return gl.LINEAR;
121
+ }
122
+ }
123
+ function getMagFilter(gl, filter) {
124
+ switch (filter) {
125
+ case "nearest":
126
+ return gl.NEAREST;
127
+ default:
128
+ return gl.LINEAR;
129
+ }
130
+ }
131
+ function isPowerOfTwo(value) {
132
+ return (value & value - 1) === 0 && value !== 0;
133
+ }
134
+ function getSourceDimensions(source) {
135
+ if (source instanceof HTMLImageElement) {
136
+ return { width: source.naturalWidth, height: source.naturalHeight };
137
+ }
138
+ if (source instanceof HTMLVideoElement) {
139
+ return { width: source.videoWidth, height: source.videoHeight };
140
+ }
141
+ if (source instanceof ImageData) {
142
+ return { width: source.width, height: source.height };
143
+ }
144
+ return { width: source.width, height: source.height };
145
+ }
146
+ function createTextureManager(gl) {
147
+ const maxUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
148
+ return {
149
+ cache: new Map,
150
+ nextUnit: 0,
151
+ maxUnits
152
+ };
153
+ }
154
+ function createTexture(gl, source, options = {}) {
155
+ const texture = gl.createTexture();
156
+ if (!texture) {
157
+ throw new Error("Failed to create WebGL texture");
158
+ }
159
+ const { wrapS = "clamp", wrapT = "clamp", minFilter = "linear", magFilter = "linear", flipY = true } = options;
160
+ gl.bindTexture(gl.TEXTURE_2D, texture);
161
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
162
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
163
+ const { width, height } = getSourceDimensions(source);
164
+ const pot = isPowerOfTwo(width) && isPowerOfTwo(height);
165
+ const isWebGL2 = "texStorage2D" in gl;
166
+ const actualMinFilter = minFilter === "mipmap" && (pot || isWebGL2) ? minFilter : minFilter === "mipmap" ? "linear" : minFilter;
167
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, getWrapMode(gl, wrapS));
168
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, getWrapMode(gl, wrapT));
169
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, getMinFilter(gl, actualMinFilter));
170
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, getMagFilter(gl, magFilter));
171
+ if (actualMinFilter === "mipmap") {
172
+ gl.generateMipmap(gl.TEXTURE_2D);
173
+ }
174
+ gl.bindTexture(gl.TEXTURE_2D, null);
175
+ return texture;
176
+ }
177
+ function updateTexture(gl, texture, source, flipY = true) {
178
+ gl.bindTexture(gl.TEXTURE_2D, texture);
179
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
180
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
181
+ gl.bindTexture(gl.TEXTURE_2D, null);
182
+ }
183
+ function needsVideoUpdate(source) {
184
+ if (!(source instanceof HTMLVideoElement))
185
+ return false;
186
+ return !source.paused && !source.ended && source.readyState >= 2;
187
+ }
188
+ function bindTextureUniform(gl, program, name, value, manager, locationCache) {
189
+ const source = isTextureOptions(value) ? value.source : value;
190
+ const options = isTextureOptions(value) ? value : {};
191
+ let entry = manager.cache.get(name);
192
+ if (entry && entry.source !== source) {
193
+ gl.deleteTexture(entry.texture);
194
+ entry = undefined;
195
+ }
196
+ if (!entry) {
197
+ if (manager.nextUnit >= manager.maxUnits) {
198
+ console.warn(`Maximum texture units (${manager.maxUnits}) exceeded for uniform "${name}"`);
199
+ return;
200
+ }
201
+ const texture = createTexture(gl, source, options);
202
+ entry = {
203
+ texture,
204
+ unit: manager.nextUnit++,
205
+ source
206
+ };
207
+ manager.cache.set(name, entry);
208
+ }
209
+ if (needsVideoUpdate(source)) {
210
+ const flipY = isTextureOptions(value) ? value.flipY ?? true : true;
211
+ updateTexture(gl, entry.texture, source, flipY);
212
+ }
213
+ gl.activeTexture(gl.TEXTURE0 + entry.unit);
214
+ gl.bindTexture(gl.TEXTURE_2D, entry.texture);
215
+ let location = locationCache.get(name);
216
+ if (location === undefined) {
217
+ location = gl.getUniformLocation(program, name);
218
+ locationCache.set(name, location);
219
+ }
220
+ if (location !== null) {
221
+ gl.uniform1i(location, entry.unit);
222
+ }
223
+ }
224
+ function cleanupTextures(gl, manager) {
225
+ for (const entry of manager.cache.values()) {
226
+ gl.deleteTexture(entry.texture);
227
+ }
228
+ manager.cache.clear();
229
+ manager.nextUnit = 0;
230
+ }
231
+
91
232
  // src/utils/uniforms.ts
92
233
  var MAX_ARRAY_LENGTH = 100;
93
234
  function isVec2(value) {
@@ -139,8 +280,14 @@ function setUniform(gl, location, value) {
139
280
  function getUniformLocation(gl, program, name) {
140
281
  return gl.getUniformLocation(program, name);
141
282
  }
142
- function setUniforms(gl, program, uniforms, locationCache) {
283
+ function setUniforms(gl, program, uniforms, locationCache, textureManager) {
143
284
  for (const [name, value] of Object.entries(uniforms)) {
285
+ if (isTexture(value)) {
286
+ if (textureManager) {
287
+ bindTextureUniform(gl, program, name, value, textureManager, locationCache);
288
+ }
289
+ continue;
290
+ }
144
291
  let location = locationCache.get(name);
145
292
  if (location === undefined) {
146
293
  location = getUniformLocation(gl, program, name);
@@ -164,6 +311,9 @@ function createUniformLocationCache() {
164
311
  return new Map;
165
312
  }
166
313
  function getUniformType(value) {
314
+ if (isTexture(value)) {
315
+ return "sampler2D";
316
+ }
167
317
  if (typeof value === "number") {
168
318
  return "float";
169
319
  }
@@ -247,10 +397,12 @@ function initializeWebGL(canvas, vertexSource, fragmentSource, customUniforms) {
247
397
  program,
248
398
  positionBuffer,
249
399
  positionAttributeLocation,
250
- uniformLocationCache: createUniformLocationCache()
400
+ uniformLocationCache: createUniformLocationCache(),
401
+ textureManager: createTextureManager(gl)
251
402
  };
252
403
  }
253
404
  function cleanupWebGL(gl, state) {
405
+ cleanupTextures(gl, state.textureManager);
254
406
  gl.deleteBuffer(state.positionBuffer);
255
407
  gl.deleteProgram(state.program);
256
408
  }
@@ -272,6 +424,7 @@ function useWebGL(options) {
272
424
  const onMouseDownRef = import_react.useRef(options.onMouseDown);
273
425
  const onMouseUpRef = import_react.useRef(options.onMouseUp);
274
426
  const onMouseMoveRef = import_react.useRef(options.onMouseMove);
427
+ const onMouseWheelRef = import_react.useRef(options.onMouseWheel);
275
428
  const timeScaleRef = import_react.useRef(options.timeScale ?? 1);
276
429
  const vertexRef = import_react.useRef(options.vertex);
277
430
  const fragmentRef = import_react.useRef(options.fragment);
@@ -290,6 +443,7 @@ function useWebGL(options) {
290
443
  onMouseDownRef.current = options.onMouseDown;
291
444
  onMouseUpRef.current = options.onMouseUp;
292
445
  onMouseMoveRef.current = options.onMouseMove;
446
+ onMouseWheelRef.current = options.onMouseWheel;
293
447
  timeScaleRef.current = options.timeScale ?? 1;
294
448
  vertexRef.current = options.vertex;
295
449
  fragmentRef.current = options.fragment;
@@ -303,7 +457,7 @@ function useWebGL(options) {
303
457
  const deltaTime = lastFrameTimeRef.current === 0 ? 0 : (time - lastFrameTimeRef.current) / 1000;
304
458
  lastFrameTimeRef.current = time;
305
459
  elapsedTimeRef.current += deltaTime * timeScaleRef.current;
306
- const { gl, program, positionAttributeLocation, uniformLocationCache } = state;
460
+ const { gl, program, positionAttributeLocation, uniformLocationCache, textureManager } = state;
307
461
  const elapsedTime = elapsedTimeRef.current;
308
462
  const dpr = dprRef.current;
309
463
  const displayWidth = canvas.clientWidth;
@@ -331,7 +485,7 @@ function useWebGL(options) {
331
485
  defaultUniforms.iMouseNormalized = mouseNormalizedRef.current;
332
486
  defaultUniforms.iMouseLeftDown = mouseLeftDownRef.current ? 1 : 0;
333
487
  defaultUniforms.iResolution = [canvas.width, canvas.height];
334
- setUniforms(gl, program, { ...defaultUniforms, ...uniformsRef.current }, uniformLocationCache);
488
+ setUniforms(gl, program, { ...defaultUniforms, ...uniformsRef.current }, uniformLocationCache, textureManager);
335
489
  gl.drawArrays(gl.TRIANGLES, 0, 6);
336
490
  if (onFrameRef.current) {
337
491
  onFrameRef.current({
@@ -464,10 +618,21 @@ function useWebGL(options) {
464
618
  mouseLeftDown: mouseLeftDownRef.current
465
619
  });
466
620
  };
621
+ const handleMouseWheel = (event) => {
622
+ onMouseWheelRef.current?.({
623
+ deltaTime: 0,
624
+ time: elapsedTimeRef.current,
625
+ resolution: [canvas.width, canvas.height],
626
+ mouse: mouseRef.current,
627
+ mouseNormalized: mouseNormalizedRef.current,
628
+ mouseLeftDown: mouseLeftDownRef.current
629
+ }, event.deltaY);
630
+ };
467
631
  window.addEventListener("mousemove", handleMouseMove);
468
632
  window.addEventListener("mousedown", handleMouseDown);
469
633
  window.addEventListener("mouseup", handleMouseUp);
470
634
  canvas.addEventListener("click", handleClick);
635
+ window.addEventListener("wheel", handleMouseWheel);
471
636
  return () => {
472
637
  resizeObserver.disconnect();
473
638
  window.removeEventListener("scroll", updateRect);
@@ -475,6 +640,7 @@ function useWebGL(options) {
475
640
  window.removeEventListener("mousedown", handleMouseDown);
476
641
  window.removeEventListener("mouseup", handleMouseUp);
477
642
  canvas.removeEventListener("click", handleClick);
643
+ window.removeEventListener("wheel", handleMouseWheel);
478
644
  };
479
645
  }, []);
480
646
  return { canvasRef, mouseRef };
@@ -518,7 +684,8 @@ function ReactShader({
518
684
  onClick,
519
685
  onMouseMove,
520
686
  onMouseDown,
521
- onMouseUp
687
+ onMouseUp,
688
+ onMouseWheel
522
689
  }) {
523
690
  const [error, setError] = import_react2.useState(null);
524
691
  const handleError = import_react2.useCallback((err) => {
@@ -538,6 +705,7 @@ function ReactShader({
538
705
  onMouseMove,
539
706
  onMouseDown,
540
707
  onMouseUp,
708
+ onMouseWheel,
541
709
  timeScale
542
710
  });
543
711
  const containerStyle = import_react2.useMemo(() => fullscreen ? FULLSCREEN_CONTAINER_STYLE : DEFAULT_CONTAINER_STYLE, [fullscreen]);
package/dist/index.d.ts CHANGED
@@ -4,5 +4,5 @@ export { generateDistortionRippleFunction } from "./shaders/distortion-ripple";
4
4
  export { generateSceneCirclesFunction } from "./shaders/scene-circles";
5
5
  export { generateSimplexNoiseFunction } from "./shaders/simplex-noise";
6
6
  export { generateUtilsFunction } from "./shaders/utils";
7
- export type { DefaultUniforms, FloatArray, FrameInfo, ReactShaderProps, UniformValue, Vec2, Vec2Array, Vec3, Vec3Array, Vec4, Vec4Array, } from "./types";
7
+ export type { DefaultUniforms, FloatArray, FrameInfo, ReactShaderProps, TextureMagFilter, TextureMinFilter, TextureOptions, TextureSource, TextureWrap, UniformValue, Vec2, Vec2Array, Vec3, Vec3Array, Vec4, Vec4Array, } from "./types";
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6BAA6B,CAAA;AAC9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACvD,YAAY,EACV,eAAe,EACf,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,SAAS,GACV,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6BAA6B,CAAA;AAC9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACvD,YAAY,EACV,eAAe,EACf,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,SAAS,GACV,MAAM,SAAS,CAAA"}
package/dist/index.js CHANGED
@@ -48,6 +48,147 @@ function createShaderProgram(gl, vertexSource, fragmentSource) {
48
48
  }
49
49
  }
50
50
 
51
+ // src/utils/textures.ts
52
+ function isTextureSource(value) {
53
+ if (typeof window === "undefined")
54
+ return false;
55
+ return value instanceof HTMLImageElement || value instanceof HTMLCanvasElement || value instanceof HTMLVideoElement || typeof ImageBitmap !== "undefined" && value instanceof ImageBitmap || value instanceof ImageData || typeof OffscreenCanvas !== "undefined" && value instanceof OffscreenCanvas;
56
+ }
57
+ function isTextureOptions(value) {
58
+ return typeof value === "object" && value !== null && "source" in value && isTextureSource(value.source);
59
+ }
60
+ function isTexture(value) {
61
+ return isTextureSource(value) || isTextureOptions(value);
62
+ }
63
+ function getWrapMode(gl, wrap) {
64
+ switch (wrap) {
65
+ case "repeat":
66
+ return gl.REPEAT;
67
+ case "mirror":
68
+ return gl.MIRRORED_REPEAT;
69
+ default:
70
+ return gl.CLAMP_TO_EDGE;
71
+ }
72
+ }
73
+ function getMinFilter(gl, filter) {
74
+ switch (filter) {
75
+ case "nearest":
76
+ return gl.NEAREST;
77
+ case "mipmap":
78
+ return gl.LINEAR_MIPMAP_LINEAR;
79
+ default:
80
+ return gl.LINEAR;
81
+ }
82
+ }
83
+ function getMagFilter(gl, filter) {
84
+ switch (filter) {
85
+ case "nearest":
86
+ return gl.NEAREST;
87
+ default:
88
+ return gl.LINEAR;
89
+ }
90
+ }
91
+ function isPowerOfTwo(value) {
92
+ return (value & value - 1) === 0 && value !== 0;
93
+ }
94
+ function getSourceDimensions(source) {
95
+ if (source instanceof HTMLImageElement) {
96
+ return { width: source.naturalWidth, height: source.naturalHeight };
97
+ }
98
+ if (source instanceof HTMLVideoElement) {
99
+ return { width: source.videoWidth, height: source.videoHeight };
100
+ }
101
+ if (source instanceof ImageData) {
102
+ return { width: source.width, height: source.height };
103
+ }
104
+ return { width: source.width, height: source.height };
105
+ }
106
+ function createTextureManager(gl) {
107
+ const maxUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
108
+ return {
109
+ cache: new Map,
110
+ nextUnit: 0,
111
+ maxUnits
112
+ };
113
+ }
114
+ function createTexture(gl, source, options = {}) {
115
+ const texture = gl.createTexture();
116
+ if (!texture) {
117
+ throw new Error("Failed to create WebGL texture");
118
+ }
119
+ const { wrapS = "clamp", wrapT = "clamp", minFilter = "linear", magFilter = "linear", flipY = true } = options;
120
+ gl.bindTexture(gl.TEXTURE_2D, texture);
121
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
122
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
123
+ const { width, height } = getSourceDimensions(source);
124
+ const pot = isPowerOfTwo(width) && isPowerOfTwo(height);
125
+ const isWebGL2 = "texStorage2D" in gl;
126
+ const actualMinFilter = minFilter === "mipmap" && (pot || isWebGL2) ? minFilter : minFilter === "mipmap" ? "linear" : minFilter;
127
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, getWrapMode(gl, wrapS));
128
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, getWrapMode(gl, wrapT));
129
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, getMinFilter(gl, actualMinFilter));
130
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, getMagFilter(gl, magFilter));
131
+ if (actualMinFilter === "mipmap") {
132
+ gl.generateMipmap(gl.TEXTURE_2D);
133
+ }
134
+ gl.bindTexture(gl.TEXTURE_2D, null);
135
+ return texture;
136
+ }
137
+ function updateTexture(gl, texture, source, flipY = true) {
138
+ gl.bindTexture(gl.TEXTURE_2D, texture);
139
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
140
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
141
+ gl.bindTexture(gl.TEXTURE_2D, null);
142
+ }
143
+ function needsVideoUpdate(source) {
144
+ if (!(source instanceof HTMLVideoElement))
145
+ return false;
146
+ return !source.paused && !source.ended && source.readyState >= 2;
147
+ }
148
+ function bindTextureUniform(gl, program, name, value, manager, locationCache) {
149
+ const source = isTextureOptions(value) ? value.source : value;
150
+ const options = isTextureOptions(value) ? value : {};
151
+ let entry = manager.cache.get(name);
152
+ if (entry && entry.source !== source) {
153
+ gl.deleteTexture(entry.texture);
154
+ entry = undefined;
155
+ }
156
+ if (!entry) {
157
+ if (manager.nextUnit >= manager.maxUnits) {
158
+ console.warn(`Maximum texture units (${manager.maxUnits}) exceeded for uniform "${name}"`);
159
+ return;
160
+ }
161
+ const texture = createTexture(gl, source, options);
162
+ entry = {
163
+ texture,
164
+ unit: manager.nextUnit++,
165
+ source
166
+ };
167
+ manager.cache.set(name, entry);
168
+ }
169
+ if (needsVideoUpdate(source)) {
170
+ const flipY = isTextureOptions(value) ? value.flipY ?? true : true;
171
+ updateTexture(gl, entry.texture, source, flipY);
172
+ }
173
+ gl.activeTexture(gl.TEXTURE0 + entry.unit);
174
+ gl.bindTexture(gl.TEXTURE_2D, entry.texture);
175
+ let location = locationCache.get(name);
176
+ if (location === undefined) {
177
+ location = gl.getUniformLocation(program, name);
178
+ locationCache.set(name, location);
179
+ }
180
+ if (location !== null) {
181
+ gl.uniform1i(location, entry.unit);
182
+ }
183
+ }
184
+ function cleanupTextures(gl, manager) {
185
+ for (const entry of manager.cache.values()) {
186
+ gl.deleteTexture(entry.texture);
187
+ }
188
+ manager.cache.clear();
189
+ manager.nextUnit = 0;
190
+ }
191
+
51
192
  // src/utils/uniforms.ts
52
193
  var MAX_ARRAY_LENGTH = 100;
53
194
  function isVec2(value) {
@@ -99,8 +240,14 @@ function setUniform(gl, location, value) {
99
240
  function getUniformLocation(gl, program, name) {
100
241
  return gl.getUniformLocation(program, name);
101
242
  }
102
- function setUniforms(gl, program, uniforms, locationCache) {
243
+ function setUniforms(gl, program, uniforms, locationCache, textureManager) {
103
244
  for (const [name, value] of Object.entries(uniforms)) {
245
+ if (isTexture(value)) {
246
+ if (textureManager) {
247
+ bindTextureUniform(gl, program, name, value, textureManager, locationCache);
248
+ }
249
+ continue;
250
+ }
104
251
  let location = locationCache.get(name);
105
252
  if (location === undefined) {
106
253
  location = getUniformLocation(gl, program, name);
@@ -124,6 +271,9 @@ function createUniformLocationCache() {
124
271
  return new Map;
125
272
  }
126
273
  function getUniformType(value) {
274
+ if (isTexture(value)) {
275
+ return "sampler2D";
276
+ }
127
277
  if (typeof value === "number") {
128
278
  return "float";
129
279
  }
@@ -207,10 +357,12 @@ function initializeWebGL(canvas, vertexSource, fragmentSource, customUniforms) {
207
357
  program,
208
358
  positionBuffer,
209
359
  positionAttributeLocation,
210
- uniformLocationCache: createUniformLocationCache()
360
+ uniformLocationCache: createUniformLocationCache(),
361
+ textureManager: createTextureManager(gl)
211
362
  };
212
363
  }
213
364
  function cleanupWebGL(gl, state) {
365
+ cleanupTextures(gl, state.textureManager);
214
366
  gl.deleteBuffer(state.positionBuffer);
215
367
  gl.deleteProgram(state.program);
216
368
  }
@@ -232,6 +384,7 @@ function useWebGL(options) {
232
384
  const onMouseDownRef = useRef(options.onMouseDown);
233
385
  const onMouseUpRef = useRef(options.onMouseUp);
234
386
  const onMouseMoveRef = useRef(options.onMouseMove);
387
+ const onMouseWheelRef = useRef(options.onMouseWheel);
235
388
  const timeScaleRef = useRef(options.timeScale ?? 1);
236
389
  const vertexRef = useRef(options.vertex);
237
390
  const fragmentRef = useRef(options.fragment);
@@ -250,6 +403,7 @@ function useWebGL(options) {
250
403
  onMouseDownRef.current = options.onMouseDown;
251
404
  onMouseUpRef.current = options.onMouseUp;
252
405
  onMouseMoveRef.current = options.onMouseMove;
406
+ onMouseWheelRef.current = options.onMouseWheel;
253
407
  timeScaleRef.current = options.timeScale ?? 1;
254
408
  vertexRef.current = options.vertex;
255
409
  fragmentRef.current = options.fragment;
@@ -263,7 +417,7 @@ function useWebGL(options) {
263
417
  const deltaTime = lastFrameTimeRef.current === 0 ? 0 : (time - lastFrameTimeRef.current) / 1000;
264
418
  lastFrameTimeRef.current = time;
265
419
  elapsedTimeRef.current += deltaTime * timeScaleRef.current;
266
- const { gl, program, positionAttributeLocation, uniformLocationCache } = state;
420
+ const { gl, program, positionAttributeLocation, uniformLocationCache, textureManager } = state;
267
421
  const elapsedTime = elapsedTimeRef.current;
268
422
  const dpr = dprRef.current;
269
423
  const displayWidth = canvas.clientWidth;
@@ -291,7 +445,7 @@ function useWebGL(options) {
291
445
  defaultUniforms.iMouseNormalized = mouseNormalizedRef.current;
292
446
  defaultUniforms.iMouseLeftDown = mouseLeftDownRef.current ? 1 : 0;
293
447
  defaultUniforms.iResolution = [canvas.width, canvas.height];
294
- setUniforms(gl, program, { ...defaultUniforms, ...uniformsRef.current }, uniformLocationCache);
448
+ setUniforms(gl, program, { ...defaultUniforms, ...uniformsRef.current }, uniformLocationCache, textureManager);
295
449
  gl.drawArrays(gl.TRIANGLES, 0, 6);
296
450
  if (onFrameRef.current) {
297
451
  onFrameRef.current({
@@ -424,10 +578,21 @@ function useWebGL(options) {
424
578
  mouseLeftDown: mouseLeftDownRef.current
425
579
  });
426
580
  };
581
+ const handleMouseWheel = (event) => {
582
+ onMouseWheelRef.current?.({
583
+ deltaTime: 0,
584
+ time: elapsedTimeRef.current,
585
+ resolution: [canvas.width, canvas.height],
586
+ mouse: mouseRef.current,
587
+ mouseNormalized: mouseNormalizedRef.current,
588
+ mouseLeftDown: mouseLeftDownRef.current
589
+ }, event.deltaY);
590
+ };
427
591
  window.addEventListener("mousemove", handleMouseMove);
428
592
  window.addEventListener("mousedown", handleMouseDown);
429
593
  window.addEventListener("mouseup", handleMouseUp);
430
594
  canvas.addEventListener("click", handleClick);
595
+ window.addEventListener("wheel", handleMouseWheel);
431
596
  return () => {
432
597
  resizeObserver.disconnect();
433
598
  window.removeEventListener("scroll", updateRect);
@@ -435,6 +600,7 @@ function useWebGL(options) {
435
600
  window.removeEventListener("mousedown", handleMouseDown);
436
601
  window.removeEventListener("mouseup", handleMouseUp);
437
602
  canvas.removeEventListener("click", handleClick);
603
+ window.removeEventListener("wheel", handleMouseWheel);
438
604
  };
439
605
  }, []);
440
606
  return { canvasRef, mouseRef };
@@ -478,7 +644,8 @@ function ReactShader({
478
644
  onClick,
479
645
  onMouseMove,
480
646
  onMouseDown,
481
- onMouseUp
647
+ onMouseUp,
648
+ onMouseWheel
482
649
  }) {
483
650
  const [error, setError] = useState(null);
484
651
  const handleError = useCallback2((err) => {
@@ -498,6 +665,7 @@ function ReactShader({
498
665
  onMouseMove,
499
666
  onMouseDown,
500
667
  onMouseUp,
668
+ onMouseWheel,
501
669
  timeScale
502
670
  });
503
671
  const containerStyle = useMemo(() => fullscreen ? FULLSCREEN_CONTAINER_STYLE : DEFAULT_CONTAINER_STYLE, [fullscreen]);
package/dist/types.d.ts CHANGED
@@ -5,7 +5,19 @@ export type FloatArray = number[];
5
5
  export type Vec2Array = Vec2[];
6
6
  export type Vec3Array = Vec3[];
7
7
  export type Vec4Array = Vec4[];
8
- export type UniformValue = number | Vec2 | Vec3 | Vec4 | FloatArray | Vec2Array | Vec3Array | Vec4Array;
8
+ export type TextureSource = HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap | ImageData | OffscreenCanvas;
9
+ export type TextureWrap = "repeat" | "clamp" | "mirror";
10
+ export type TextureMinFilter = "nearest" | "linear" | "mipmap";
11
+ export type TextureMagFilter = "nearest" | "linear";
12
+ export interface TextureOptions {
13
+ source: TextureSource;
14
+ wrapS?: TextureWrap;
15
+ wrapT?: TextureWrap;
16
+ minFilter?: TextureMinFilter;
17
+ magFilter?: TextureMagFilter;
18
+ flipY?: boolean;
19
+ }
20
+ export type UniformValue = number | Vec2 | Vec3 | Vec4 | FloatArray | Vec2Array | Vec3Array | Vec4Array | TextureSource | TextureOptions;
9
21
  export interface FrameInfo {
10
22
  deltaTime: number;
11
23
  time: number;
@@ -26,6 +38,7 @@ export interface ReactShaderProps {
26
38
  onMouseMove?: (info: FrameInfo) => void;
27
39
  onMouseDown?: (info: FrameInfo) => void;
28
40
  onMouseUp?: (info: FrameInfo) => void;
41
+ onMouseWheel?: (info: FrameInfo, wheelDelta: number) => void;
29
42
  }
30
43
  export interface DefaultUniforms {
31
44
  iTime: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AACnC,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAC3C,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAEnD,MAAM,MAAM,UAAU,GAAG,MAAM,EAAE,CAAA;AACjC,MAAM,MAAM,SAAS,GAAG,IAAI,EAAE,CAAA;AAC9B,MAAM,MAAM,SAAS,GAAG,IAAI,EAAE,CAAA;AAC9B,MAAM,MAAM,SAAS,GAAG,IAAI,EAAE,CAAA;AAE9B,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAA;AAEvG,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvB,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,aAAa,EAAE,OAAO,CAAA;CACvB;AACD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACvC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;CACtC;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,IAAI,CAAA;IACZ,gBAAgB,EAAE,IAAI,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,IAAI,CAAA;CAClB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AACnC,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAC3C,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAEnD,MAAM,MAAM,UAAU,GAAG,MAAM,EAAE,CAAA;AACjC,MAAM,MAAM,SAAS,GAAG,IAAI,EAAE,CAAA;AAC9B,MAAM,MAAM,SAAS,GAAG,IAAI,EAAE,CAAA;AAC9B,MAAM,MAAM,SAAS,GAAG,IAAI,EAAE,CAAA;AAE9B,MAAM,MAAM,aAAa,GACrB,gBAAgB,GAChB,iBAAiB,GACjB,gBAAgB,GAChB,WAAW,GACX,SAAS,GACT,eAAe,CAAA;AAEnB,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAA;AACvD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAC9D,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEnD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,aAAa,CAAA;IACrB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,SAAS,CAAC,EAAE,gBAAgB,CAAA;IAC5B,SAAS,CAAC,EAAE,gBAAgB,CAAA;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,UAAU,GACV,SAAS,GACT,SAAS,GACT,SAAS,GACT,aAAa,GACb,cAAc,CAAA;AAElB,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvB,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,aAAa,EAAE,OAAO,CAAA;CACvB;AACD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACvC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACrC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;CAC7D;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,IAAI,CAAA;IACZ,gBAAgB,EAAE,IAAI,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,IAAI,CAAA;CAClB"}
@@ -0,0 +1,23 @@
1
+ import type { TextureOptions, TextureSource } from "../types";
2
+ type WebGLContext = WebGLRenderingContext | WebGL2RenderingContext;
3
+ interface TextureEntry {
4
+ texture: WebGLTexture;
5
+ unit: number;
6
+ source: TextureSource;
7
+ }
8
+ export interface TextureManager {
9
+ cache: Map<string, TextureEntry>;
10
+ nextUnit: number;
11
+ maxUnits: number;
12
+ }
13
+ export declare function isTextureSource(value: unknown): value is TextureSource;
14
+ export declare function isTextureOptions(value: unknown): value is TextureOptions;
15
+ export declare function isTexture(value: unknown): value is TextureSource | TextureOptions;
16
+ export declare function createTextureManager(gl: WebGLContext): TextureManager;
17
+ export declare function createTexture(gl: WebGLContext, source: TextureSource, options?: Partial<TextureOptions>): WebGLTexture;
18
+ export declare function updateTexture(gl: WebGLContext, texture: WebGLTexture, source: TextureSource, flipY?: boolean): void;
19
+ export declare function needsVideoUpdate(source: TextureSource): boolean;
20
+ export declare function bindTextureUniform(gl: WebGLContext, program: WebGLProgram, name: string, value: TextureSource | TextureOptions, manager: TextureManager, locationCache: Map<string, WebGLUniformLocation | null>): void;
21
+ export declare function cleanupTextures(gl: WebGLContext, manager: TextureManager): void;
22
+ export {};
23
+ //# sourceMappingURL=textures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textures.d.ts","sourceRoot":"","sources":["../../src/utils/textures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsC,cAAc,EAAE,aAAa,EAAe,MAAM,UAAU,CAAA;AAE9G,KAAK,YAAY,GAAG,qBAAqB,GAAG,sBAAsB,CAAA;AAElE,UAAU,YAAY;IACpB,OAAO,EAAE,YAAY,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,aAAa,CAAA;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IAChC,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAUtE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAOxE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,GAAG,cAAc,CAEjF;AAmDD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,YAAY,GAAG,cAAc,CAOrE;AAED,wBAAgB,aAAa,CAC3B,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE,OAAO,CAAC,cAAc,CAAM,GACpC,YAAY,CAqCd;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,UAAO,GAAG,IAAI,CAKhH;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAG/D;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,YAAY,EAChB,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,aAAa,GAAG,cAAc,EACrC,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAC,GACtD,IAAI,CA+CN;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAM/E"}
@@ -1,9 +1,10 @@
1
1
  import type { UniformValue } from "../types";
2
+ import { type TextureManager } from "./textures";
2
3
  type WebGLContext = WebGLRenderingContext | WebGL2RenderingContext;
3
4
  export declare const MAX_ARRAY_LENGTH = 100;
4
5
  export declare function setUniform(gl: WebGLContext, location: WebGLUniformLocation | null, value: UniformValue): void;
5
6
  export declare function getUniformLocation(gl: WebGLContext, program: WebGLProgram, name: string): WebGLUniformLocation | null;
6
- export declare function setUniforms(gl: WebGLContext, program: WebGLProgram, uniforms: Record<string, UniformValue>, locationCache: Map<string, WebGLUniformLocation | null>): void;
7
+ export declare function setUniforms(gl: WebGLContext, program: WebGLProgram, uniforms: Record<string, UniformValue>, locationCache: Map<string, WebGLUniformLocation | null>, textureManager?: TextureManager): void;
7
8
  export declare function createUniformLocationCache(): Map<string, WebGLUniformLocation | null>;
8
9
  export declare function generateUniformDeclarations(uniforms: Record<string, UniformValue>): string;
9
10
  export declare function injectUniformDeclarations(shaderSource: string, customUniforms: Record<string, UniformValue> | undefined, defaultUniforms: Record<string, UniformValue>): string;
@@ -1 +1 @@
1
- {"version":3,"file":"uniforms.d.ts","sourceRoot":"","sources":["../../src/utils/uniforms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,YAAY,EAAqD,MAAM,UAAU,CAAA;AAE3G,KAAK,YAAY,GAAG,qBAAqB,GAAG,sBAAsB,CAAA;AAElE,eAAO,MAAM,gBAAgB,MAAM,CAAA;AAkCnC,wBAAgB,UAAU,CAAC,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,oBAAoB,GAAG,IAAI,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAsB7G;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAErH;AAED,wBAAgB,WAAW,CACzB,EAAE,EAAE,YAAY,EAChB,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EACtC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAC,GACtD,IAAI,CAsBN;AAED,wBAAgB,0BAA0B,IAAI,GAAG,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAC,CAErF;AA8BD,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,MAAM,CAa1F;AAID,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,SAAS,EACxD,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAC5C,MAAM,CAQR"}
1
+ {"version":3,"file":"uniforms.d.ts","sourceRoot":"","sources":["../../src/utils/uniforms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,YAAY,EAAqD,MAAM,UAAU,CAAA;AAC3G,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,YAAY,CAAA;AAE/E,KAAK,YAAY,GAAG,qBAAqB,GAAG,sBAAsB,CAAA;AAElE,eAAO,MAAM,gBAAgB,MAAM,CAAA;AAkCnC,wBAAgB,UAAU,CAAC,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,oBAAoB,GAAG,IAAI,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAsB7G;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAErH;AAED,wBAAgB,WAAW,CACzB,EAAE,EAAE,YAAY,EAChB,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EACtC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAC,EACvD,cAAc,CAAC,EAAE,cAAc,GAC9B,IAAI,CA8BN;AAED,wBAAgB,0BAA0B,IAAI,GAAG,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAC,CAErF;AAiCD,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,MAAM,CAa1F;AAID,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,SAAS,EACxD,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAC5C,MAAM,CAQR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fjandin/react-shader",
3
- "version": "0.0.12",
3
+ "version": "0.0.15",
4
4
  "description": "React component for rendering WebGL shaders",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",