@fjandin/react-shader 0.0.20 → 0.0.30

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @fjandin/react-shader
2
2
 
3
- A React component library for rendering WebGL and WebGPU shaders. Provides `<ReactShader>` for GLSL (Shadertoy-style) and `<ReactGpuShader>` for WGSL (WebGPU) with automatic uniform handling, texture support, storage buffers, and audio reactivity.
3
+ A React component library for rendering WebGPU shaders. Provides `<ReactGpuShader>` for WGSL with automatic uniform handling, storage buffers, and audio reactivity.
4
4
 
5
5
  ## Installation
6
6
 
@@ -12,42 +12,7 @@ yarn add @fjandin/react-shader
12
12
  bun add @fjandin/react-shader
13
13
  ```
14
14
 
15
- ## Components
16
-
17
- ### `<ReactShader>` (WebGL)
18
-
19
- Renders GLSL fragment shaders. Uses WebGL2 with WebGL1 fallback.
20
-
21
- ```tsx
22
- import { ReactShader } from "@fjandin/react-shader"
23
-
24
- const fragment = `#version 300 es
25
- precision highp float;
26
-
27
- uniform float iTime;
28
- uniform vec2 iResolution;
29
-
30
- out vec4 fragColor;
31
-
32
- void main() {
33
- vec2 uv = gl_FragCoord.xy / iResolution;
34
- vec3 color = 0.5 + 0.5 * cos(iTime + uv.xyx + vec3(0, 2, 4));
35
- fragColor = vec4(color, 1.0);
36
- }
37
- `
38
-
39
- function App() {
40
- return (
41
- <div style={{ width: "800px", height: "600px" }}>
42
- <ReactShader fragment={fragment} />
43
- </div>
44
- )
45
- }
46
- ```
47
-
48
- ### `<ReactGpuShader>` (WebGPU)
49
-
50
- Renders WGSL fragment shaders using WebGPU. Supports storage buffers for large array data.
15
+ ## Quick Start
51
16
 
52
17
  ```tsx
53
18
  import { ReactGpuShader } from "@fjandin/react-shader"
@@ -68,29 +33,10 @@ function App() {
68
33
  }
69
34
  ```
70
35
 
71
- WebGPU shaders define a `mainImage(uv: vec2f) -> vec4f` function. Built-in uniforms are accessed via `uniforms.iTime`, `uniforms.iResolution`, etc. The component automatically generates the uniform struct and wrapping `@fragment` entry point.
36
+ Shaders define a `mainImage(uv: vec2f) -> vec4f` function. Built-in uniforms are accessed via `uniforms.iTime`, `uniforms.iResolution`, etc. The component automatically generates the uniform struct and wrapping `@fragment` entry point.
72
37
 
73
38
  ## Props
74
39
 
75
- ### ReactShader
76
-
77
- | Prop | Type | Required | Default | Description |
78
- |------|------|----------|---------|-------------|
79
- | `fragment` | `string` | Yes | - | GLSL fragment shader source code |
80
- | `vertex` | `string` | No | Default quad shader | GLSL vertex shader source code |
81
- | `uniforms` | `Record<string, UniformValue>` | No | `{}` | Custom uniform values |
82
- | `className` | `string` | No | - | CSS class name for the canvas |
83
- | `fullscreen` | `boolean` | No | `false` | Render as fixed fullscreen overlay |
84
- | `timeScale` | `number` | No | `1` | Scale factor for elapsed time |
85
- | `onFrame` | `(info: FrameInfo) => void` | No | - | Callback invoked on each frame |
86
- | `onClick` | `(info: FrameInfo) => void` | No | - | Callback invoked on canvas click |
87
- | `onMouseMove` | `(info: FrameInfo) => void` | No | - | Callback invoked on mouse move |
88
- | `onMouseDown` | `(info: FrameInfo) => void` | No | - | Callback invoked on mouse button press |
89
- | `onMouseUp` | `(info: FrameInfo) => void` | No | - | Callback invoked on mouse button release |
90
- | `onMouseWheel` | `(info: FrameInfo, wheelDelta: number) => void` | No | - | Callback invoked on mouse wheel scroll |
91
-
92
- ### ReactGpuShader
93
-
94
40
  | Prop | Type | Required | Default | Description |
95
41
  |------|------|----------|---------|-------------|
96
42
  | `fragment` | `string` | Yes | - | WGSL fragment shader source code |
@@ -110,50 +56,16 @@ WebGPU shaders define a `mainImage(uv: vec2f) -> vec4f` function. Built-in unifo
110
56
 
111
57
  These uniforms are automatically provided to your shader every frame:
112
58
 
113
- | Uniform | GLSL Type | WGSL Type | Description |
114
- |---------|-----------|-----------|-------------|
115
- | `iTime` | `float` | `f32` | Elapsed time in seconds (scaled by `timeScale`) |
116
- | `iMouse` | `vec2` | `vec2f` | Mouse position in pixels (Y=0 at bottom) |
117
- | `iMouseNormalized` | `vec2` | `vec2f` | Mouse position normalized with aspect correction (shorter axis -0.5 to 0.5, center is 0,0) |
118
- | `iMouseLeftDown` | `float` | `f32` | `1.0` when left mouse button is pressed, `0.0` otherwise |
119
- | `iResolution` | `vec2` | `vec2f` | Canvas resolution in pixels (includes high-DPI scaling) |
59
+ | Uniform | WGSL Type | Description |
60
+ |---------|-----------|-------------|
61
+ | `iTime` | `f32` | Elapsed time in seconds (scaled by `timeScale`) |
62
+ | `iMouse` | `vec2f` | Mouse position in pixels (Y=0 at bottom) |
63
+ | `iMouseNormalized` | `vec2f` | Mouse position normalized with aspect correction (shorter axis -0.5 to 0.5, center is 0,0) |
64
+ | `iMouseLeftDown` | `f32` | `1.0` when left mouse button is pressed, `0.0` otherwise |
65
+ | `iResolution` | `vec2f` | Canvas resolution in pixels (includes high-DPI scaling) |
120
66
 
121
67
  ## Custom Uniforms
122
68
 
123
- ### WebGL (ReactShader)
124
-
125
- Pass custom uniform values via the `uniforms` prop. Supports scalars, vectors, arrays, and textures:
126
-
127
- ```tsx
128
- <ReactShader
129
- fragment={fragment}
130
- uniforms={{
131
- scale: 2.0, // float
132
- offset: [0.5, 0.5], // vec2
133
- color: [1.0, 0.5, 0.2], // vec3
134
- transform: [1, 0, 0, 1], // vec4
135
- weights: [0.1, 0.2, 0.3, 0.25, 0.15], // float array
136
- points: [[0, 0], [1, 0], [0.5, 1]], // vec2 array
137
- colors: [[1, 0, 0], [0, 1, 0]], // vec3 array
138
- ripples: [[0, 0, 0.5, 0.1]], // vec4 array
139
- }}
140
- />
141
- ```
142
-
143
- Supported types:
144
- - `number` → `float`
145
- - `[number, number]` → `vec2`
146
- - `[number, number, number]` → `vec3`
147
- - `[number, number, number, number]` → `vec4`
148
- - `number[]` (length > 4) → `float[N]`
149
- - `[number, number][]` → `vec2[N]`
150
- - `[number, number, number][]` → `vec3[N]`
151
- - `[number, number, number, number][]` → `vec4[N]`
152
- - `HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap | ImageData | OffscreenCanvas` → `sampler2D` (texture)
153
- - `TextureOptions` object → `sampler2D` with wrap/filter configuration
154
-
155
- ### WebGPU (ReactGpuShader)
156
-
157
69
  Custom uniforms support scalar and vector types:
158
70
 
159
71
  ```tsx
@@ -170,25 +82,9 @@ Custom uniforms support scalar and vector types:
170
82
 
171
83
  Custom uniforms are accessed via `uniforms.scale`, `uniforms.color`, etc. in your WGSL code.
172
84
 
173
- ## Array Count Uniforms (WebGL)
85
+ ## Storage Buffers
174
86
 
175
- For array uniforms, an additional `_count` uniform is automatically created and set:
176
-
177
- ```tsx
178
- uniforms={{ points: [[0, 0], [1, 0], [0.5, 1]] }}
179
- ```
180
-
181
- This generates both `uniform vec2 points[3]` and `uniform int points_count` (set to `3`), allowing you to loop over arrays in your shader:
182
-
183
- ```glsl
184
- for (int i = 0; i < points_count; i++) {
185
- // Use points[i]...
186
- }
187
- ```
188
-
189
- ## Storage Buffers (WebGPU)
190
-
191
- For large dynamic array data, `ReactGpuShader` supports storage buffers. These are more efficient than uniforms for large datasets and support dynamic resizing:
87
+ For large dynamic array data, storage buffers are more efficient than uniforms and support dynamic resizing:
192
88
 
193
89
  ```tsx
194
90
  const [particles, setParticles] = useState<Vec4Array>([
@@ -216,61 +112,12 @@ fn mainImage(uv: vec2f) -> vec4f {
216
112
 
217
113
  Storage buffers use over-allocation (1.5x growth) to minimize GPU buffer rebuilds when array sizes change frequently.
218
114
 
219
- ## Texture Uniforms (WebGL)
220
-
221
- Pass images, canvases, or video elements as texture uniforms:
222
-
223
- ```tsx
224
- <ReactShader
225
- fragment={fragment}
226
- uniforms={{
227
- myTexture: imageElement,
228
- // or with options:
229
- myTexture: {
230
- source: imageElement,
231
- wrapS: "repeat", // "repeat" | "clamp" | "mirror"
232
- wrapT: "repeat",
233
- minFilter: "linear", // "nearest" | "linear" | "mipmap"
234
- magFilter: "linear", // "nearest" | "linear"
235
- flipY: true,
236
- },
237
- }}
238
- />
239
- ```
240
-
241
- ## Automatic Uniform Injection (WebGL)
242
-
243
- Instead of manually declaring uniforms in your shader, you can use the `// @UNIFORM_VALUES` marker to automatically inject all uniform declarations:
244
-
245
- ```tsx
246
- const fragment = `#version 300 es
247
- precision highp float;
248
-
249
- // @UNIFORM_VALUES
250
-
251
- out vec4 fragColor;
252
-
253
- void main() {
254
- vec2 uv = gl_FragCoord.xy / iResolution;
255
- vec3 col = baseColor * (sin(iTime) * 0.5 + 0.5);
256
- fragColor = vec4(col, 1.0);
257
- }
258
- `
259
-
260
- <ReactShader
261
- fragment={fragment}
262
- uniforms={{ baseColor: [1.0, 0.5, 0.2] }}
263
- />
264
- ```
265
-
266
- The marker gets replaced with declarations for both built-in uniforms (`iTime`, `iMouse`, `iMouseNormalized`, `iMouseLeftDown`, `iResolution`) and your custom uniforms.
267
-
268
115
  ## Audio Reactivity
269
116
 
270
117
  The `useAudio` hook provides real-time audio analysis for audio-reactive shaders:
271
118
 
272
119
  ```tsx
273
- import { ReactShader, useAudio } from "@fjandin/react-shader"
120
+ import { ReactGpuShader, useAudio } from "@fjandin/react-shader"
274
121
 
275
122
  function AudioVisualizer() {
276
123
  const audio = useAudio({
@@ -283,7 +130,7 @@ function AudioVisualizer() {
283
130
  <button onClick={() => audio.isRunning ? audio.stop() : audio.start()}>
284
131
  {audio.isRunning ? "Stop" : "Start"}
285
132
  </button>
286
- <ReactShader
133
+ <ReactGpuShader
287
134
  fragment={fragment}
288
135
  uniforms={{
289
136
  audioLow: audio.levels.low,
@@ -320,17 +167,10 @@ function AudioVisualizer() {
320
167
 
321
168
  ## Shader Helper Functions
322
169
 
323
- Pre-built shader functions are available for both GLSL and WGSL:
170
+ Pre-built WGSL shader functions are available:
324
171
 
325
172
  ```tsx
326
173
  import {
327
- // GLSL (WebGL)
328
- generateSimplexNoiseFunction,
329
- generateColorPaletteFunction,
330
- generateDistortionRippleFunction,
331
- generateSceneCirclesFunction,
332
- generateUtilsFunction,
333
- // WGSL (WebGPU)
334
174
  generateSimplexNoiseFunctionGpu,
335
175
  generateColorPaletteFunctionGpu,
336
176
  generateDistortionRippleFunctionGpu,
@@ -341,14 +181,6 @@ import {
341
181
  Inject them into your shader source:
342
182
 
343
183
  ```tsx
344
- // GLSL
345
- const fragment = `#version 300 es
346
- precision highp float;
347
- ${generateSimplexNoiseFunction()}
348
- // Use SimplexNoise3D(vec3 v) in your shader...
349
- `
350
-
351
- // WGSL
352
184
  const fragment = /*wgsl*/ `
353
185
  ${generateSimplexNoiseFunctionGpu()}
354
186
  fn mainImage(uv: vec2f) -> vec4f {
@@ -367,7 +199,7 @@ function App() {
367
199
  const [customTime, setCustomTime] = useState(0)
368
200
 
369
201
  return (
370
- <ReactShader
202
+ <ReactGpuShader
371
203
  fragment={fragment}
372
204
  uniforms={{ customTime }}
373
205
  onFrame={(info) => {
@@ -395,21 +227,14 @@ import type {
395
227
  Vec2,
396
228
  Vec3,
397
229
  Vec4,
398
- FloatArray,
399
230
  Vec2Array,
400
231
  Vec3Array,
401
232
  Vec4Array,
402
- UniformValue,
233
+ GpuUniformValue,
403
234
  GpuStorageBuffers,
404
235
  DefaultUniforms,
405
236
  FrameInfo,
406
- ReactShaderProps,
407
237
  ReactGpuShaderProps,
408
- TextureSource,
409
- TextureOptions,
410
- TextureWrap,
411
- TextureMinFilter,
412
- TextureMagFilter,
413
238
  AudioLevels,
414
239
  AudioConnectionState,
415
240
  AudioSourceType,
@@ -418,39 +243,22 @@ import type {
418
243
  } from "@fjandin/react-shader"
419
244
  ```
420
245
 
421
- A utility function for generating uniform declarations is also exported:
422
-
423
- ```tsx
424
- import { generateUniformDeclarations } from "@fjandin/react-shader"
425
-
426
- const declarations = generateUniformDeclarations({
427
- scale: 1.0,
428
- points: [[0, 0], [1, 1]],
429
- })
430
- // Returns:
431
- // uniform float scale;
432
- // uniform vec2 points[2];
433
- // uniform int points_count;
434
- ```
435
-
436
246
  ## Features
437
247
 
438
- - WebGL2 with WebGL1 fallback (`ReactShader`)
439
- - WebGPU support with WGSL shaders (`ReactGpuShader`)
440
- - Storage buffers for large dynamic arrays (WebGPU)
441
- - Texture uniforms with configurable wrap/filter modes (WebGL)
248
+ - WebGPU rendering with WGSL shaders
249
+ - Storage buffers for large dynamic arrays
442
250
  - Audio reactivity via `useAudio` hook
443
251
  - Pre-built shader functions (simplex noise, color palettes, distortion ripples, circles)
444
252
  - High-DPI display support with automatic DPR change detection
445
253
  - Automatic canvas resizing
446
254
  - Shader compilation error display
447
- - Context loss/restoration handling
448
- - Mouse tracking with WebGL/WebGPU coordinate convention
255
+ - Mouse tracking with WebGPU coordinate convention
449
256
  - Optimized render loop with minimal per-frame allocations
450
257
 
451
258
  ## Requirements
452
259
 
453
260
  - React >= 17.0.0
261
+ - A browser with WebGPU support
454
262
 
455
263
  ## License
456
264
 
@@ -1 +1 @@
1
- {"version":3,"file":"frontend.d.ts","sourceRoot":"","sources":["../../src/example/frontend.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,aAAa,CAAA;AA0BpB,wBAAgB,GAAG,4CAyClB"}
1
+ {"version":3,"file":"frontend.d.ts","sourceRoot":"","sources":["../../src/example/frontend.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,aAAa,CAAA;AAyBpB,wBAAgB,GAAG,4CAiClB"}
@@ -1 +1 @@
1
- {"version":3,"file":"useWebGPU.d.ts","sourceRoot":"","sources":["../../src/hooks/useWebGPU.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAoB,SAAS,EAAE,MAAM,UAAU,CAAA;AAEvF,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,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;AAgYD,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB;;;EA8SlD"}
1
+ {"version":3,"file":"useWebGPU.d.ts","sourceRoot":"","sources":["../../src/hooks/useWebGPU.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAoB,SAAS,EAAE,MAAM,UAAU,CAAA;AAEvF,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,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;AAkXD,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB;;;EAiTlD"}