@fjandin/react-shader 0.0.19 → 0.0.21
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 +248 -22
- package/dist/ReactGpuShader.d.ts +3 -4
- package/dist/ReactGpuShader.d.ts.map +1 -1
- package/dist/hooks/useWebGPU.d.ts +2 -2
- package/dist/hooks/useWebGPU.d.ts.map +1 -1
- package/dist/index.cjs +152 -121
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +152 -121
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -266,30 +266,15 @@ function isVec3(value) {
|
|
|
266
266
|
function isVec4(value) {
|
|
267
267
|
return Array.isArray(value) && value.length === 4 && typeof value[0] === "number";
|
|
268
268
|
}
|
|
269
|
-
function isVec4Array(value) {
|
|
270
|
-
return Array.isArray(value) && value.length > 0 && Array.isArray(value[0]) && value[0].length === 4;
|
|
271
|
-
}
|
|
272
269
|
function inferWgslType(value) {
|
|
273
|
-
if (typeof value === "number")
|
|
274
|
-
return
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
arrayLength: 100
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
if (isVec4(value)) {
|
|
285
|
-
return { wgslType: "vec4f", baseType: "vec4f", isArray: false, arrayLength: 0 };
|
|
286
|
-
}
|
|
287
|
-
if (isVec3(value)) {
|
|
288
|
-
return { wgslType: "vec3f", baseType: "vec3f", isArray: false, arrayLength: 0 };
|
|
289
|
-
}
|
|
290
|
-
if (isVec2(value)) {
|
|
291
|
-
return { wgslType: "vec2f", baseType: "vec2f", isArray: false, arrayLength: 0 };
|
|
292
|
-
}
|
|
270
|
+
if (typeof value === "number")
|
|
271
|
+
return "f32";
|
|
272
|
+
if (isVec4(value))
|
|
273
|
+
return "vec4f";
|
|
274
|
+
if (isVec3(value))
|
|
275
|
+
return "vec3f";
|
|
276
|
+
if (isVec2(value))
|
|
277
|
+
return "vec2f";
|
|
293
278
|
throw new Error(`Unsupported uniform value type: ${typeof value}`);
|
|
294
279
|
}
|
|
295
280
|
function getTypeAlignment(type) {
|
|
@@ -315,7 +300,6 @@ function getTypeSize(type) {
|
|
|
315
300
|
return 16;
|
|
316
301
|
}
|
|
317
302
|
}
|
|
318
|
-
var UNIFORM_ARRAY_STRIDE = 16;
|
|
319
303
|
var DEFAULT_UNIFORMS = [
|
|
320
304
|
{ name: "iTime", baseType: "f32" },
|
|
321
305
|
{ name: "iMouseLeftDown", baseType: "f32" },
|
|
@@ -330,49 +314,20 @@ function calculateUniformLayout(customUniforms) {
|
|
|
330
314
|
const alignment = getTypeAlignment(baseType);
|
|
331
315
|
const size = getTypeSize(baseType);
|
|
332
316
|
offset = Math.ceil(offset / alignment) * alignment;
|
|
333
|
-
fields.push({ name, type: baseType, offset, size
|
|
317
|
+
fields.push({ name, type: baseType, offset, size });
|
|
334
318
|
offset += size;
|
|
335
319
|
};
|
|
336
|
-
const addArrayField = (name, baseType, arrayLength) => {
|
|
337
|
-
offset = Math.ceil(offset / 16) * 16;
|
|
338
|
-
const totalSize = arrayLength * UNIFORM_ARRAY_STRIDE;
|
|
339
|
-
fields.push({
|
|
340
|
-
name,
|
|
341
|
-
type: `array<${baseType}, ${arrayLength}>`,
|
|
342
|
-
offset,
|
|
343
|
-
size: totalSize,
|
|
344
|
-
isArray: true,
|
|
345
|
-
arrayLength,
|
|
346
|
-
elementStride: UNIFORM_ARRAY_STRIDE
|
|
347
|
-
});
|
|
348
|
-
offset += totalSize;
|
|
349
|
-
};
|
|
350
320
|
for (const u of DEFAULT_UNIFORMS) {
|
|
351
321
|
addField(u.name, u.baseType);
|
|
352
322
|
}
|
|
353
323
|
if (customUniforms) {
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
scalarEntries.push({ name, inferred });
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
for (const { name } of arrayEntries) {
|
|
365
|
-
scalarEntries.push({
|
|
366
|
-
name: `${name}_count`,
|
|
367
|
-
inferred: { wgslType: "f32", baseType: "f32", isArray: false, arrayLength: 0 }
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
scalarEntries.sort((a, b) => getTypeAlignment(b.inferred.baseType) - getTypeAlignment(a.inferred.baseType));
|
|
371
|
-
for (const { name, inferred } of scalarEntries) {
|
|
372
|
-
addField(name, inferred.baseType);
|
|
373
|
-
}
|
|
374
|
-
for (const { name, inferred } of arrayEntries) {
|
|
375
|
-
addArrayField(name, inferred.baseType, inferred.arrayLength);
|
|
324
|
+
const entries = Object.entries(customUniforms).map(([name, value]) => ({
|
|
325
|
+
name,
|
|
326
|
+
baseType: inferWgslType(value)
|
|
327
|
+
}));
|
|
328
|
+
entries.sort((a, b) => getTypeAlignment(b.baseType) - getTypeAlignment(a.baseType));
|
|
329
|
+
for (const { name, baseType } of entries) {
|
|
330
|
+
addField(name, baseType);
|
|
376
331
|
}
|
|
377
332
|
}
|
|
378
333
|
const bufferSize = Math.ceil(offset / 16) * 16;
|
|
@@ -387,21 +342,9 @@ ${members}
|
|
|
387
342
|
}
|
|
388
343
|
function packUniformValue(field, value, floatData) {
|
|
389
344
|
const floatOffset = field.offset / 4;
|
|
390
|
-
if (
|
|
391
|
-
const stride = field.elementStride / 4;
|
|
392
|
-
const maxLen = field.arrayLength;
|
|
393
|
-
if (isVec4Array(value)) {
|
|
394
|
-
for (let i = 0;i < value.length && i < maxLen; i++) {
|
|
395
|
-
const elemOffset = floatOffset + i * stride;
|
|
396
|
-
floatData[elemOffset] = value[i][0];
|
|
397
|
-
floatData[elemOffset + 1] = value[i][1];
|
|
398
|
-
floatData[elemOffset + 2] = value[i][2];
|
|
399
|
-
floatData[elemOffset + 3] = value[i][3];
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
} else if (typeof value === "number") {
|
|
345
|
+
if (typeof value === "number") {
|
|
403
346
|
floatData[floatOffset] = value;
|
|
404
|
-
} else if (Array.isArray(value)
|
|
347
|
+
} else if (Array.isArray(value)) {
|
|
405
348
|
for (let i = 0;i < value.length; i++) {
|
|
406
349
|
floatData[floatOffset + i] = value[i];
|
|
407
350
|
}
|
|
@@ -429,11 +372,60 @@ fn main(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
|
|
|
429
372
|
return output;
|
|
430
373
|
}
|
|
431
374
|
`;
|
|
432
|
-
function
|
|
375
|
+
function getStorageBufferNames(defs) {
|
|
376
|
+
if (!defs)
|
|
377
|
+
return [];
|
|
378
|
+
return Object.keys(defs).sort();
|
|
379
|
+
}
|
|
380
|
+
function createStorageBuffer(device, name, binding, data) {
|
|
381
|
+
const length = Math.max(data.length, 1);
|
|
382
|
+
const byteSize = length * 16;
|
|
383
|
+
const buffer = device.createBuffer({
|
|
384
|
+
label: `storage: ${name}`,
|
|
385
|
+
size: byteSize,
|
|
386
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
387
|
+
});
|
|
388
|
+
const packingArray = new Float32Array(length * 4);
|
|
389
|
+
for (let i = 0;i < data.length; i++) {
|
|
390
|
+
const off = i * 4;
|
|
391
|
+
packingArray[off] = data[i][0];
|
|
392
|
+
packingArray[off + 1] = data[i][1];
|
|
393
|
+
packingArray[off + 2] = data[i][2];
|
|
394
|
+
packingArray[off + 3] = data[i][3];
|
|
395
|
+
}
|
|
396
|
+
device.queue.writeBuffer(buffer, 0, packingArray);
|
|
397
|
+
return { name, binding, buffer, currentLength: length, packingArray };
|
|
398
|
+
}
|
|
399
|
+
function packAndUploadStorageBuffer(device, entry, data) {
|
|
400
|
+
const arr = entry.packingArray;
|
|
401
|
+
arr.fill(0);
|
|
402
|
+
for (let i = 0;i < data.length; i++) {
|
|
403
|
+
const off = i * 4;
|
|
404
|
+
arr[off] = data[i][0];
|
|
405
|
+
arr[off + 1] = data[i][1];
|
|
406
|
+
arr[off + 2] = data[i][2];
|
|
407
|
+
arr[off + 3] = data[i][3];
|
|
408
|
+
}
|
|
409
|
+
device.queue.writeBuffer(entry.buffer, 0, arr);
|
|
410
|
+
}
|
|
411
|
+
function rebuildBindGroup(state) {
|
|
412
|
+
const entries = [{ binding: 0, resource: { buffer: state.uniformBuffer } }];
|
|
413
|
+
for (const sb of state.storageBuffers) {
|
|
414
|
+
entries.push({ binding: sb.binding, resource: { buffer: sb.buffer } });
|
|
415
|
+
}
|
|
416
|
+
return state.device.createBindGroup({
|
|
417
|
+
layout: state.bindGroupLayout,
|
|
418
|
+
entries
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
function createFragmentShader(userCode, layout, storageBufferNames) {
|
|
422
|
+
const storageDeclarations = storageBufferNames.map((name, i) => `@group(0) @binding(${i + 1}) var<storage, read> ${name}: array<vec4f>;`).join(`
|
|
423
|
+
`);
|
|
433
424
|
return `
|
|
434
425
|
${generateUniformStruct(layout)}
|
|
435
426
|
|
|
436
427
|
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
|
|
428
|
+
${storageDeclarations}
|
|
437
429
|
|
|
438
430
|
${userCode}
|
|
439
431
|
|
|
@@ -446,7 +438,7 @@ fn main(@location(0) uv: vec2f) -> @location(0) vec4f {
|
|
|
446
438
|
}
|
|
447
439
|
`;
|
|
448
440
|
}
|
|
449
|
-
async function initializeWebGPU(canvas, fragmentSource, customUniforms) {
|
|
441
|
+
async function initializeWebGPU(canvas, fragmentSource, customUniforms, storageBufferDefs) {
|
|
450
442
|
if (!navigator.gpu) {
|
|
451
443
|
throw new Error("WebGPU not supported in this browser");
|
|
452
444
|
}
|
|
@@ -469,36 +461,43 @@ async function initializeWebGPU(canvas, fragmentSource, customUniforms) {
|
|
|
469
461
|
alphaMode: "premultiplied"
|
|
470
462
|
});
|
|
471
463
|
const uniformLayout = calculateUniformLayout(customUniforms);
|
|
464
|
+
const storageBufferNames = getStorageBufferNames(storageBufferDefs);
|
|
472
465
|
const vertexModule = device.createShaderModule({
|
|
473
466
|
label: "vertex shader",
|
|
474
467
|
code: VERTEX_SHADER
|
|
475
468
|
});
|
|
476
469
|
const fragmentModule = device.createShaderModule({
|
|
477
470
|
label: "fragment shader",
|
|
478
|
-
code: createFragmentShader(fragmentSource, uniformLayout)
|
|
471
|
+
code: createFragmentShader(fragmentSource, uniformLayout, storageBufferNames)
|
|
479
472
|
});
|
|
480
473
|
const uniformBuffer = device.createBuffer({
|
|
481
474
|
label: "uniforms",
|
|
482
475
|
size: uniformLayout.bufferSize,
|
|
483
476
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
484
477
|
});
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
478
|
+
const storageBuffers = storageBufferNames.map((name, i) => createStorageBuffer(device, name, i + 1, storageBufferDefs?.[name] ?? []));
|
|
479
|
+
const layoutEntries = [
|
|
480
|
+
{
|
|
481
|
+
binding: 0,
|
|
482
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
483
|
+
buffer: { type: "uniform" }
|
|
484
|
+
}
|
|
485
|
+
];
|
|
486
|
+
for (const sb of storageBuffers) {
|
|
487
|
+
layoutEntries.push({
|
|
488
|
+
binding: sb.binding,
|
|
489
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
490
|
+
buffer: { type: "read-only-storage" }
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
const bindGroupLayout = device.createBindGroupLayout({ entries: layoutEntries });
|
|
494
|
+
const bindGroupEntries = [{ binding: 0, resource: { buffer: uniformBuffer } }];
|
|
495
|
+
for (const sb of storageBuffers) {
|
|
496
|
+
bindGroupEntries.push({ binding: sb.binding, resource: { buffer: sb.buffer } });
|
|
497
|
+
}
|
|
494
498
|
const uniformBindGroup = device.createBindGroup({
|
|
495
499
|
layout: bindGroupLayout,
|
|
496
|
-
entries:
|
|
497
|
-
{
|
|
498
|
-
binding: 0,
|
|
499
|
-
resource: { buffer: uniformBuffer }
|
|
500
|
-
}
|
|
501
|
-
]
|
|
500
|
+
entries: bindGroupEntries
|
|
502
501
|
});
|
|
503
502
|
const pipelineLayout = device.createPipelineLayout({
|
|
504
503
|
bindGroupLayouts: [bindGroupLayout]
|
|
@@ -522,10 +521,15 @@ async function initializeWebGPU(canvas, fragmentSource, customUniforms) {
|
|
|
522
521
|
pipeline,
|
|
523
522
|
uniformBuffer,
|
|
524
523
|
uniformBindGroup,
|
|
525
|
-
uniformLayout
|
|
524
|
+
uniformLayout,
|
|
525
|
+
bindGroupLayout,
|
|
526
|
+
storageBuffers
|
|
526
527
|
};
|
|
527
528
|
}
|
|
528
529
|
function cleanupWebGPU(state) {
|
|
530
|
+
for (const sb of state.storageBuffers) {
|
|
531
|
+
sb.buffer.destroy();
|
|
532
|
+
}
|
|
529
533
|
state.uniformBuffer.destroy();
|
|
530
534
|
state.device.destroy();
|
|
531
535
|
}
|
|
@@ -549,7 +553,10 @@ function useWebGPU(options) {
|
|
|
549
553
|
const timeScaleRef = import_react2.useRef(options.timeScale ?? 1);
|
|
550
554
|
const fragmentRef = import_react2.useRef(options.fragment);
|
|
551
555
|
const uniformsRef = import_react2.useRef(options.uniforms);
|
|
556
|
+
const storageBuffersRef = import_react2.useRef(options.storageBuffers);
|
|
552
557
|
const dprRef = import_react2.useRef(window.devicePixelRatio || 1);
|
|
558
|
+
const uniformDataRef = import_react2.useRef(null);
|
|
559
|
+
const allValuesRef = import_react2.useRef({});
|
|
553
560
|
const frameInfoRef = import_react2.useRef({
|
|
554
561
|
deltaTime: 0,
|
|
555
562
|
time: 0,
|
|
@@ -568,6 +575,7 @@ function useWebGPU(options) {
|
|
|
568
575
|
timeScaleRef.current = options.timeScale ?? 1;
|
|
569
576
|
fragmentRef.current = options.fragment;
|
|
570
577
|
uniformsRef.current = options.uniforms;
|
|
578
|
+
storageBuffersRef.current = options.storageBuffers;
|
|
571
579
|
const render = import_react2.useCallback((time) => {
|
|
572
580
|
const state = stateRef.current;
|
|
573
581
|
const canvas = canvasRef.current;
|
|
@@ -577,18 +585,18 @@ function useWebGPU(options) {
|
|
|
577
585
|
const deltaTime = lastFrameTimeRef.current === 0 ? 0 : (time - lastFrameTimeRef.current) / 1000;
|
|
578
586
|
lastFrameTimeRef.current = time;
|
|
579
587
|
elapsedTimeRef.current += deltaTime * timeScaleRef.current;
|
|
580
|
-
frameInfoRef.current
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
+
const info = frameInfoRef.current;
|
|
589
|
+
info.deltaTime = deltaTime;
|
|
590
|
+
info.time = elapsedTimeRef.current;
|
|
591
|
+
info.resolution[0] = canvas.width;
|
|
592
|
+
info.resolution[1] = canvas.height;
|
|
593
|
+
info.mouse = mouseRef.current;
|
|
594
|
+
info.mouseNormalized = mouseNormalizedRef.current;
|
|
595
|
+
info.mouseLeftDown = mouseLeftDownRef.current;
|
|
588
596
|
if (onFrameRef.current) {
|
|
589
597
|
onFrameRef.current(frameInfoRef.current);
|
|
590
598
|
}
|
|
591
|
-
const { device, context, pipeline, uniformBuffer,
|
|
599
|
+
const { device, context, pipeline, uniformBuffer, uniformLayout } = state;
|
|
592
600
|
const dpr = dprRef.current;
|
|
593
601
|
const displayWidth = canvas.clientWidth;
|
|
594
602
|
const displayHeight = canvas.clientHeight;
|
|
@@ -602,22 +610,19 @@ function useWebGPU(options) {
|
|
|
602
610
|
canvas.width = bufferWidth;
|
|
603
611
|
canvas.height = bufferHeight;
|
|
604
612
|
}
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
};
|
|
612
|
-
const allValues = { ...defaultValues, ...uniformsRef.current };
|
|
613
|
+
const allValues = allValuesRef.current;
|
|
614
|
+
allValues.iTime = elapsedTimeRef.current;
|
|
615
|
+
allValues.iMouseLeftDown = mouseLeftDownRef.current ? 1 : 0;
|
|
616
|
+
allValues.iResolution = [canvas.width, canvas.height];
|
|
617
|
+
allValues.iMouse = mouseRef.current;
|
|
618
|
+
allValues.iMouseNormalized = mouseNormalizedRef.current;
|
|
613
619
|
if (uniformsRef.current) {
|
|
614
620
|
for (const [name, value] of Object.entries(uniformsRef.current)) {
|
|
615
|
-
|
|
616
|
-
allValues[`${name}_count`] = value.length;
|
|
617
|
-
}
|
|
621
|
+
allValues[name] = value;
|
|
618
622
|
}
|
|
619
623
|
}
|
|
620
|
-
const uniformData =
|
|
624
|
+
const uniformData = uniformDataRef.current;
|
|
625
|
+
uniformData.fill(0);
|
|
621
626
|
for (const field of uniformLayout.fields) {
|
|
622
627
|
const value = allValues[field.name];
|
|
623
628
|
if (value === undefined) {
|
|
@@ -626,6 +631,29 @@ function useWebGPU(options) {
|
|
|
626
631
|
packUniformValue(field, value, uniformData);
|
|
627
632
|
}
|
|
628
633
|
device.queue.writeBuffer(uniformBuffer, 0, uniformData);
|
|
634
|
+
let needsBindGroupRebuild = false;
|
|
635
|
+
for (const entry of state.storageBuffers) {
|
|
636
|
+
const data = storageBuffersRef.current?.[entry.name];
|
|
637
|
+
if (!data)
|
|
638
|
+
continue;
|
|
639
|
+
const requiredLength = Math.max(data.length, 1);
|
|
640
|
+
if (requiredLength !== entry.currentLength) {
|
|
641
|
+
entry.buffer.destroy();
|
|
642
|
+
const byteSize = requiredLength * 16;
|
|
643
|
+
entry.buffer = device.createBuffer({
|
|
644
|
+
label: `storage: ${entry.name}`,
|
|
645
|
+
size: byteSize,
|
|
646
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
647
|
+
});
|
|
648
|
+
entry.packingArray = new Float32Array(requiredLength * 4);
|
|
649
|
+
entry.currentLength = requiredLength;
|
|
650
|
+
needsBindGroupRebuild = true;
|
|
651
|
+
}
|
|
652
|
+
packAndUploadStorageBuffer(device, entry, data);
|
|
653
|
+
}
|
|
654
|
+
if (needsBindGroupRebuild) {
|
|
655
|
+
state.uniformBindGroup = rebuildBindGroup(state);
|
|
656
|
+
}
|
|
629
657
|
const commandEncoder = device.createCommandEncoder();
|
|
630
658
|
const textureView = context.getCurrentTexture().createView();
|
|
631
659
|
const renderPass = commandEncoder.beginRenderPass({
|
|
@@ -639,7 +667,7 @@ function useWebGPU(options) {
|
|
|
639
667
|
]
|
|
640
668
|
});
|
|
641
669
|
renderPass.setPipeline(pipeline);
|
|
642
|
-
renderPass.setBindGroup(0, uniformBindGroup);
|
|
670
|
+
renderPass.setBindGroup(0, state.uniformBindGroup);
|
|
643
671
|
renderPass.draw(3);
|
|
644
672
|
renderPass.end();
|
|
645
673
|
device.queue.submit([commandEncoder.finish()]);
|
|
@@ -652,12 +680,13 @@ function useWebGPU(options) {
|
|
|
652
680
|
let mounted = true;
|
|
653
681
|
const initialize = async () => {
|
|
654
682
|
try {
|
|
655
|
-
const state = await initializeWebGPU(canvas, fragmentRef.current, uniformsRef.current);
|
|
683
|
+
const state = await initializeWebGPU(canvas, fragmentRef.current, uniformsRef.current, storageBuffersRef.current);
|
|
656
684
|
if (!mounted) {
|
|
657
685
|
cleanupWebGPU(state);
|
|
658
686
|
return;
|
|
659
687
|
}
|
|
660
688
|
stateRef.current = state;
|
|
689
|
+
uniformDataRef.current = new Float32Array(state.uniformLayout.bufferSize / 4);
|
|
661
690
|
elapsedTimeRef.current = 0;
|
|
662
691
|
lastFrameTimeRef.current = 0;
|
|
663
692
|
animationFrameRef.current = requestAnimationFrame(render);
|
|
@@ -774,6 +803,7 @@ function ReactGpuShader({
|
|
|
774
803
|
className,
|
|
775
804
|
fragment,
|
|
776
805
|
uniforms,
|
|
806
|
+
storageBuffers,
|
|
777
807
|
fullscreen = false,
|
|
778
808
|
timeScale,
|
|
779
809
|
onFrame,
|
|
@@ -794,6 +824,7 @@ function ReactGpuShader({
|
|
|
794
824
|
const { canvasRef } = useWebGPU({
|
|
795
825
|
fragment,
|
|
796
826
|
uniforms,
|
|
827
|
+
storageBuffers,
|
|
797
828
|
onError: handleError,
|
|
798
829
|
timeScale,
|
|
799
830
|
onFrame,
|
|
@@ -1045,11 +1076,11 @@ function isVec2Array(value) {
|
|
|
1045
1076
|
function isVec3Array(value) {
|
|
1046
1077
|
return Array.isArray(value) && value.length > 0 && Array.isArray(value[0]) && value[0].length === 3;
|
|
1047
1078
|
}
|
|
1048
|
-
function
|
|
1079
|
+
function isVec4Array(value) {
|
|
1049
1080
|
return Array.isArray(value) && value.length > 0 && Array.isArray(value[0]) && value[0].length === 4;
|
|
1050
1081
|
}
|
|
1051
1082
|
function isArrayUniform(value) {
|
|
1052
|
-
return isFloatArray(value) || isVec2Array(value) || isVec3Array(value) ||
|
|
1083
|
+
return isFloatArray(value) || isVec2Array(value) || isVec3Array(value) || isVec4Array(value);
|
|
1053
1084
|
}
|
|
1054
1085
|
function setUniform(gl, location, value) {
|
|
1055
1086
|
if (location === null) {
|
|
@@ -1057,7 +1088,7 @@ function setUniform(gl, location, value) {
|
|
|
1057
1088
|
}
|
|
1058
1089
|
if (typeof value === "number") {
|
|
1059
1090
|
gl.uniform1f(location, value);
|
|
1060
|
-
} else if (
|
|
1091
|
+
} else if (isVec4Array(value)) {
|
|
1061
1092
|
gl.uniform4fv(location, value.flat());
|
|
1062
1093
|
} else if (isVec3Array(value)) {
|
|
1063
1094
|
gl.uniform3fv(location, value.flat());
|
|
@@ -1113,7 +1144,7 @@ function getUniformType(value) {
|
|
|
1113
1144
|
if (typeof value === "number") {
|
|
1114
1145
|
return "float";
|
|
1115
1146
|
}
|
|
1116
|
-
if (
|
|
1147
|
+
if (isVec4Array(value)) {
|
|
1117
1148
|
return `vec4[${MAX_ARRAY_LENGTH}]`;
|
|
1118
1149
|
}
|
|
1119
1150
|
if (isVec3Array(value)) {
|
package/dist/index.d.ts
CHANGED
|
@@ -11,5 +11,5 @@ export { generateSceneCirclesFunctionGpu } from "./shaders/scene-circles-gpu";
|
|
|
11
11
|
export { generateSimplexNoiseFunction } from "./shaders/simplex-noise";
|
|
12
12
|
export { generateSimplexNoiseFunctionGpu } from "./shaders/simplex-noise-gpu";
|
|
13
13
|
export { generateUtilsFunction } from "./shaders/utils";
|
|
14
|
-
export type { AudioConnectionState, AudioLevels, AudioSourceType, DefaultUniforms, FloatArray, FrameInfo, ReactShaderProps, TextureMagFilter, TextureMinFilter, TextureOptions, TextureSource, TextureWrap, UniformValue, UseAudioOptions, UseAudioReturn, Vec2, Vec2Array, Vec3, Vec3Array, Vec4, Vec4Array, } from "./types";
|
|
14
|
+
export type { AudioConnectionState, AudioLevels, AudioSourceType, DefaultUniforms, FloatArray, FrameInfo, GpuStorageBuffers, ReactShaderProps, TextureMagFilter, TextureMinFilter, TextureOptions, TextureSource, TextureWrap, UniformValue, UseAudioOptions, UseAudioReturn, Vec2, Vec2Array, Vec3, Vec3Array, Vec4, Vec4Array, } from "./types";
|
|
15
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,+BAA+B,EAAE,MAAM,6BAA6B,CAAA;AAC7E,OAAO,EAAE,gCAAgC,EAAE,MAAM,6BAA6B,CAAA;AAC9E,OAAO,EAAE,mCAAmC,EAAE,MAAM,iCAAiC,CAAA;AACrF,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,+BAA+B,EAAE,MAAM,6BAA6B,CAAA;AAC7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,+BAA+B,EAAE,MAAM,6BAA6B,CAAA;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACvD,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,eAAe,EACf,eAAe,EACf,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,eAAe,EACf,cAAc,EACd,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,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,+BAA+B,EAAE,MAAM,6BAA6B,CAAA;AAC7E,OAAO,EAAE,gCAAgC,EAAE,MAAM,6BAA6B,CAAA;AAC9E,OAAO,EAAE,mCAAmC,EAAE,MAAM,iCAAiC,CAAA;AACrF,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,+BAA+B,EAAE,MAAM,6BAA6B,CAAA;AAC7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,+BAA+B,EAAE,MAAM,6BAA6B,CAAA;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACvD,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,eAAe,EACf,eAAe,EACf,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,eAAe,EACf,cAAc,EACd,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,SAAS,GACV,MAAM,SAAS,CAAA"}
|