@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.js
CHANGED
|
@@ -220,30 +220,15 @@ function isVec3(value) {
|
|
|
220
220
|
function isVec4(value) {
|
|
221
221
|
return Array.isArray(value) && value.length === 4 && typeof value[0] === "number";
|
|
222
222
|
}
|
|
223
|
-
function isVec4Array(value) {
|
|
224
|
-
return Array.isArray(value) && value.length > 0 && Array.isArray(value[0]) && value[0].length === 4;
|
|
225
|
-
}
|
|
226
223
|
function inferWgslType(value) {
|
|
227
|
-
if (typeof value === "number")
|
|
228
|
-
return
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
arrayLength: 100
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
if (isVec4(value)) {
|
|
239
|
-
return { wgslType: "vec4f", baseType: "vec4f", isArray: false, arrayLength: 0 };
|
|
240
|
-
}
|
|
241
|
-
if (isVec3(value)) {
|
|
242
|
-
return { wgslType: "vec3f", baseType: "vec3f", isArray: false, arrayLength: 0 };
|
|
243
|
-
}
|
|
244
|
-
if (isVec2(value)) {
|
|
245
|
-
return { wgslType: "vec2f", baseType: "vec2f", isArray: false, arrayLength: 0 };
|
|
246
|
-
}
|
|
224
|
+
if (typeof value === "number")
|
|
225
|
+
return "f32";
|
|
226
|
+
if (isVec4(value))
|
|
227
|
+
return "vec4f";
|
|
228
|
+
if (isVec3(value))
|
|
229
|
+
return "vec3f";
|
|
230
|
+
if (isVec2(value))
|
|
231
|
+
return "vec2f";
|
|
247
232
|
throw new Error(`Unsupported uniform value type: ${typeof value}`);
|
|
248
233
|
}
|
|
249
234
|
function getTypeAlignment(type) {
|
|
@@ -269,7 +254,6 @@ function getTypeSize(type) {
|
|
|
269
254
|
return 16;
|
|
270
255
|
}
|
|
271
256
|
}
|
|
272
|
-
var UNIFORM_ARRAY_STRIDE = 16;
|
|
273
257
|
var DEFAULT_UNIFORMS = [
|
|
274
258
|
{ name: "iTime", baseType: "f32" },
|
|
275
259
|
{ name: "iMouseLeftDown", baseType: "f32" },
|
|
@@ -284,49 +268,20 @@ function calculateUniformLayout(customUniforms) {
|
|
|
284
268
|
const alignment = getTypeAlignment(baseType);
|
|
285
269
|
const size = getTypeSize(baseType);
|
|
286
270
|
offset = Math.ceil(offset / alignment) * alignment;
|
|
287
|
-
fields.push({ name, type: baseType, offset, size
|
|
271
|
+
fields.push({ name, type: baseType, offset, size });
|
|
288
272
|
offset += size;
|
|
289
273
|
};
|
|
290
|
-
const addArrayField = (name, baseType, arrayLength) => {
|
|
291
|
-
offset = Math.ceil(offset / 16) * 16;
|
|
292
|
-
const totalSize = arrayLength * UNIFORM_ARRAY_STRIDE;
|
|
293
|
-
fields.push({
|
|
294
|
-
name,
|
|
295
|
-
type: `array<${baseType}, ${arrayLength}>`,
|
|
296
|
-
offset,
|
|
297
|
-
size: totalSize,
|
|
298
|
-
isArray: true,
|
|
299
|
-
arrayLength,
|
|
300
|
-
elementStride: UNIFORM_ARRAY_STRIDE
|
|
301
|
-
});
|
|
302
|
-
offset += totalSize;
|
|
303
|
-
};
|
|
304
274
|
for (const u of DEFAULT_UNIFORMS) {
|
|
305
275
|
addField(u.name, u.baseType);
|
|
306
276
|
}
|
|
307
277
|
if (customUniforms) {
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
scalarEntries.push({ name, inferred });
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
for (const { name } of arrayEntries) {
|
|
319
|
-
scalarEntries.push({
|
|
320
|
-
name: `${name}_count`,
|
|
321
|
-
inferred: { wgslType: "f32", baseType: "f32", isArray: false, arrayLength: 0 }
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
scalarEntries.sort((a, b) => getTypeAlignment(b.inferred.baseType) - getTypeAlignment(a.inferred.baseType));
|
|
325
|
-
for (const { name, inferred } of scalarEntries) {
|
|
326
|
-
addField(name, inferred.baseType);
|
|
327
|
-
}
|
|
328
|
-
for (const { name, inferred } of arrayEntries) {
|
|
329
|
-
addArrayField(name, inferred.baseType, inferred.arrayLength);
|
|
278
|
+
const entries = Object.entries(customUniforms).map(([name, value]) => ({
|
|
279
|
+
name,
|
|
280
|
+
baseType: inferWgslType(value)
|
|
281
|
+
}));
|
|
282
|
+
entries.sort((a, b) => getTypeAlignment(b.baseType) - getTypeAlignment(a.baseType));
|
|
283
|
+
for (const { name, baseType } of entries) {
|
|
284
|
+
addField(name, baseType);
|
|
330
285
|
}
|
|
331
286
|
}
|
|
332
287
|
const bufferSize = Math.ceil(offset / 16) * 16;
|
|
@@ -341,21 +296,9 @@ ${members}
|
|
|
341
296
|
}
|
|
342
297
|
function packUniformValue(field, value, floatData) {
|
|
343
298
|
const floatOffset = field.offset / 4;
|
|
344
|
-
if (
|
|
345
|
-
const stride = field.elementStride / 4;
|
|
346
|
-
const maxLen = field.arrayLength;
|
|
347
|
-
if (isVec4Array(value)) {
|
|
348
|
-
for (let i = 0;i < value.length && i < maxLen; i++) {
|
|
349
|
-
const elemOffset = floatOffset + i * stride;
|
|
350
|
-
floatData[elemOffset] = value[i][0];
|
|
351
|
-
floatData[elemOffset + 1] = value[i][1];
|
|
352
|
-
floatData[elemOffset + 2] = value[i][2];
|
|
353
|
-
floatData[elemOffset + 3] = value[i][3];
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
} else if (typeof value === "number") {
|
|
299
|
+
if (typeof value === "number") {
|
|
357
300
|
floatData[floatOffset] = value;
|
|
358
|
-
} else if (Array.isArray(value)
|
|
301
|
+
} else if (Array.isArray(value)) {
|
|
359
302
|
for (let i = 0;i < value.length; i++) {
|
|
360
303
|
floatData[floatOffset + i] = value[i];
|
|
361
304
|
}
|
|
@@ -383,11 +326,60 @@ fn main(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
|
|
|
383
326
|
return output;
|
|
384
327
|
}
|
|
385
328
|
`;
|
|
386
|
-
function
|
|
329
|
+
function getStorageBufferNames(defs) {
|
|
330
|
+
if (!defs)
|
|
331
|
+
return [];
|
|
332
|
+
return Object.keys(defs).sort();
|
|
333
|
+
}
|
|
334
|
+
function createStorageBuffer(device, name, binding, data) {
|
|
335
|
+
const length = Math.max(data.length, 1);
|
|
336
|
+
const byteSize = length * 16;
|
|
337
|
+
const buffer = device.createBuffer({
|
|
338
|
+
label: `storage: ${name}`,
|
|
339
|
+
size: byteSize,
|
|
340
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
341
|
+
});
|
|
342
|
+
const packingArray = new Float32Array(length * 4);
|
|
343
|
+
for (let i = 0;i < data.length; i++) {
|
|
344
|
+
const off = i * 4;
|
|
345
|
+
packingArray[off] = data[i][0];
|
|
346
|
+
packingArray[off + 1] = data[i][1];
|
|
347
|
+
packingArray[off + 2] = data[i][2];
|
|
348
|
+
packingArray[off + 3] = data[i][3];
|
|
349
|
+
}
|
|
350
|
+
device.queue.writeBuffer(buffer, 0, packingArray);
|
|
351
|
+
return { name, binding, buffer, currentLength: length, packingArray };
|
|
352
|
+
}
|
|
353
|
+
function packAndUploadStorageBuffer(device, entry, data) {
|
|
354
|
+
const arr = entry.packingArray;
|
|
355
|
+
arr.fill(0);
|
|
356
|
+
for (let i = 0;i < data.length; i++) {
|
|
357
|
+
const off = i * 4;
|
|
358
|
+
arr[off] = data[i][0];
|
|
359
|
+
arr[off + 1] = data[i][1];
|
|
360
|
+
arr[off + 2] = data[i][2];
|
|
361
|
+
arr[off + 3] = data[i][3];
|
|
362
|
+
}
|
|
363
|
+
device.queue.writeBuffer(entry.buffer, 0, arr);
|
|
364
|
+
}
|
|
365
|
+
function rebuildBindGroup(state) {
|
|
366
|
+
const entries = [{ binding: 0, resource: { buffer: state.uniformBuffer } }];
|
|
367
|
+
for (const sb of state.storageBuffers) {
|
|
368
|
+
entries.push({ binding: sb.binding, resource: { buffer: sb.buffer } });
|
|
369
|
+
}
|
|
370
|
+
return state.device.createBindGroup({
|
|
371
|
+
layout: state.bindGroupLayout,
|
|
372
|
+
entries
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
function createFragmentShader(userCode, layout, storageBufferNames) {
|
|
376
|
+
const storageDeclarations = storageBufferNames.map((name, i) => `@group(0) @binding(${i + 1}) var<storage, read> ${name}: array<vec4f>;`).join(`
|
|
377
|
+
`);
|
|
387
378
|
return `
|
|
388
379
|
${generateUniformStruct(layout)}
|
|
389
380
|
|
|
390
381
|
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
|
|
382
|
+
${storageDeclarations}
|
|
391
383
|
|
|
392
384
|
${userCode}
|
|
393
385
|
|
|
@@ -400,7 +392,7 @@ fn main(@location(0) uv: vec2f) -> @location(0) vec4f {
|
|
|
400
392
|
}
|
|
401
393
|
`;
|
|
402
394
|
}
|
|
403
|
-
async function initializeWebGPU(canvas, fragmentSource, customUniforms) {
|
|
395
|
+
async function initializeWebGPU(canvas, fragmentSource, customUniforms, storageBufferDefs) {
|
|
404
396
|
if (!navigator.gpu) {
|
|
405
397
|
throw new Error("WebGPU not supported in this browser");
|
|
406
398
|
}
|
|
@@ -423,36 +415,43 @@ async function initializeWebGPU(canvas, fragmentSource, customUniforms) {
|
|
|
423
415
|
alphaMode: "premultiplied"
|
|
424
416
|
});
|
|
425
417
|
const uniformLayout = calculateUniformLayout(customUniforms);
|
|
418
|
+
const storageBufferNames = getStorageBufferNames(storageBufferDefs);
|
|
426
419
|
const vertexModule = device.createShaderModule({
|
|
427
420
|
label: "vertex shader",
|
|
428
421
|
code: VERTEX_SHADER
|
|
429
422
|
});
|
|
430
423
|
const fragmentModule = device.createShaderModule({
|
|
431
424
|
label: "fragment shader",
|
|
432
|
-
code: createFragmentShader(fragmentSource, uniformLayout)
|
|
425
|
+
code: createFragmentShader(fragmentSource, uniformLayout, storageBufferNames)
|
|
433
426
|
});
|
|
434
427
|
const uniformBuffer = device.createBuffer({
|
|
435
428
|
label: "uniforms",
|
|
436
429
|
size: uniformLayout.bufferSize,
|
|
437
430
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
438
431
|
});
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
432
|
+
const storageBuffers = storageBufferNames.map((name, i) => createStorageBuffer(device, name, i + 1, storageBufferDefs?.[name] ?? []));
|
|
433
|
+
const layoutEntries = [
|
|
434
|
+
{
|
|
435
|
+
binding: 0,
|
|
436
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
437
|
+
buffer: { type: "uniform" }
|
|
438
|
+
}
|
|
439
|
+
];
|
|
440
|
+
for (const sb of storageBuffers) {
|
|
441
|
+
layoutEntries.push({
|
|
442
|
+
binding: sb.binding,
|
|
443
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
444
|
+
buffer: { type: "read-only-storage" }
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
const bindGroupLayout = device.createBindGroupLayout({ entries: layoutEntries });
|
|
448
|
+
const bindGroupEntries = [{ binding: 0, resource: { buffer: uniformBuffer } }];
|
|
449
|
+
for (const sb of storageBuffers) {
|
|
450
|
+
bindGroupEntries.push({ binding: sb.binding, resource: { buffer: sb.buffer } });
|
|
451
|
+
}
|
|
448
452
|
const uniformBindGroup = device.createBindGroup({
|
|
449
453
|
layout: bindGroupLayout,
|
|
450
|
-
entries:
|
|
451
|
-
{
|
|
452
|
-
binding: 0,
|
|
453
|
-
resource: { buffer: uniformBuffer }
|
|
454
|
-
}
|
|
455
|
-
]
|
|
454
|
+
entries: bindGroupEntries
|
|
456
455
|
});
|
|
457
456
|
const pipelineLayout = device.createPipelineLayout({
|
|
458
457
|
bindGroupLayouts: [bindGroupLayout]
|
|
@@ -476,10 +475,15 @@ async function initializeWebGPU(canvas, fragmentSource, customUniforms) {
|
|
|
476
475
|
pipeline,
|
|
477
476
|
uniformBuffer,
|
|
478
477
|
uniformBindGroup,
|
|
479
|
-
uniformLayout
|
|
478
|
+
uniformLayout,
|
|
479
|
+
bindGroupLayout,
|
|
480
|
+
storageBuffers
|
|
480
481
|
};
|
|
481
482
|
}
|
|
482
483
|
function cleanupWebGPU(state) {
|
|
484
|
+
for (const sb of state.storageBuffers) {
|
|
485
|
+
sb.buffer.destroy();
|
|
486
|
+
}
|
|
483
487
|
state.uniformBuffer.destroy();
|
|
484
488
|
state.device.destroy();
|
|
485
489
|
}
|
|
@@ -503,7 +507,10 @@ function useWebGPU(options) {
|
|
|
503
507
|
const timeScaleRef = useRef2(options.timeScale ?? 1);
|
|
504
508
|
const fragmentRef = useRef2(options.fragment);
|
|
505
509
|
const uniformsRef = useRef2(options.uniforms);
|
|
510
|
+
const storageBuffersRef = useRef2(options.storageBuffers);
|
|
506
511
|
const dprRef = useRef2(window.devicePixelRatio || 1);
|
|
512
|
+
const uniformDataRef = useRef2(null);
|
|
513
|
+
const allValuesRef = useRef2({});
|
|
507
514
|
const frameInfoRef = useRef2({
|
|
508
515
|
deltaTime: 0,
|
|
509
516
|
time: 0,
|
|
@@ -522,6 +529,7 @@ function useWebGPU(options) {
|
|
|
522
529
|
timeScaleRef.current = options.timeScale ?? 1;
|
|
523
530
|
fragmentRef.current = options.fragment;
|
|
524
531
|
uniformsRef.current = options.uniforms;
|
|
532
|
+
storageBuffersRef.current = options.storageBuffers;
|
|
525
533
|
const render = useCallback2((time) => {
|
|
526
534
|
const state = stateRef.current;
|
|
527
535
|
const canvas = canvasRef.current;
|
|
@@ -531,18 +539,18 @@ function useWebGPU(options) {
|
|
|
531
539
|
const deltaTime = lastFrameTimeRef.current === 0 ? 0 : (time - lastFrameTimeRef.current) / 1000;
|
|
532
540
|
lastFrameTimeRef.current = time;
|
|
533
541
|
elapsedTimeRef.current += deltaTime * timeScaleRef.current;
|
|
534
|
-
frameInfoRef.current
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
+
const info = frameInfoRef.current;
|
|
543
|
+
info.deltaTime = deltaTime;
|
|
544
|
+
info.time = elapsedTimeRef.current;
|
|
545
|
+
info.resolution[0] = canvas.width;
|
|
546
|
+
info.resolution[1] = canvas.height;
|
|
547
|
+
info.mouse = mouseRef.current;
|
|
548
|
+
info.mouseNormalized = mouseNormalizedRef.current;
|
|
549
|
+
info.mouseLeftDown = mouseLeftDownRef.current;
|
|
542
550
|
if (onFrameRef.current) {
|
|
543
551
|
onFrameRef.current(frameInfoRef.current);
|
|
544
552
|
}
|
|
545
|
-
const { device, context, pipeline, uniformBuffer,
|
|
553
|
+
const { device, context, pipeline, uniformBuffer, uniformLayout } = state;
|
|
546
554
|
const dpr = dprRef.current;
|
|
547
555
|
const displayWidth = canvas.clientWidth;
|
|
548
556
|
const displayHeight = canvas.clientHeight;
|
|
@@ -556,22 +564,19 @@ function useWebGPU(options) {
|
|
|
556
564
|
canvas.width = bufferWidth;
|
|
557
565
|
canvas.height = bufferHeight;
|
|
558
566
|
}
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
};
|
|
566
|
-
const allValues = { ...defaultValues, ...uniformsRef.current };
|
|
567
|
+
const allValues = allValuesRef.current;
|
|
568
|
+
allValues.iTime = elapsedTimeRef.current;
|
|
569
|
+
allValues.iMouseLeftDown = mouseLeftDownRef.current ? 1 : 0;
|
|
570
|
+
allValues.iResolution = [canvas.width, canvas.height];
|
|
571
|
+
allValues.iMouse = mouseRef.current;
|
|
572
|
+
allValues.iMouseNormalized = mouseNormalizedRef.current;
|
|
567
573
|
if (uniformsRef.current) {
|
|
568
574
|
for (const [name, value] of Object.entries(uniformsRef.current)) {
|
|
569
|
-
|
|
570
|
-
allValues[`${name}_count`] = value.length;
|
|
571
|
-
}
|
|
575
|
+
allValues[name] = value;
|
|
572
576
|
}
|
|
573
577
|
}
|
|
574
|
-
const uniformData =
|
|
578
|
+
const uniformData = uniformDataRef.current;
|
|
579
|
+
uniformData.fill(0);
|
|
575
580
|
for (const field of uniformLayout.fields) {
|
|
576
581
|
const value = allValues[field.name];
|
|
577
582
|
if (value === undefined) {
|
|
@@ -580,6 +585,29 @@ function useWebGPU(options) {
|
|
|
580
585
|
packUniformValue(field, value, uniformData);
|
|
581
586
|
}
|
|
582
587
|
device.queue.writeBuffer(uniformBuffer, 0, uniformData);
|
|
588
|
+
let needsBindGroupRebuild = false;
|
|
589
|
+
for (const entry of state.storageBuffers) {
|
|
590
|
+
const data = storageBuffersRef.current?.[entry.name];
|
|
591
|
+
if (!data)
|
|
592
|
+
continue;
|
|
593
|
+
const requiredLength = Math.max(data.length, 1);
|
|
594
|
+
if (requiredLength !== entry.currentLength) {
|
|
595
|
+
entry.buffer.destroy();
|
|
596
|
+
const byteSize = requiredLength * 16;
|
|
597
|
+
entry.buffer = device.createBuffer({
|
|
598
|
+
label: `storage: ${entry.name}`,
|
|
599
|
+
size: byteSize,
|
|
600
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
601
|
+
});
|
|
602
|
+
entry.packingArray = new Float32Array(requiredLength * 4);
|
|
603
|
+
entry.currentLength = requiredLength;
|
|
604
|
+
needsBindGroupRebuild = true;
|
|
605
|
+
}
|
|
606
|
+
packAndUploadStorageBuffer(device, entry, data);
|
|
607
|
+
}
|
|
608
|
+
if (needsBindGroupRebuild) {
|
|
609
|
+
state.uniformBindGroup = rebuildBindGroup(state);
|
|
610
|
+
}
|
|
583
611
|
const commandEncoder = device.createCommandEncoder();
|
|
584
612
|
const textureView = context.getCurrentTexture().createView();
|
|
585
613
|
const renderPass = commandEncoder.beginRenderPass({
|
|
@@ -593,7 +621,7 @@ function useWebGPU(options) {
|
|
|
593
621
|
]
|
|
594
622
|
});
|
|
595
623
|
renderPass.setPipeline(pipeline);
|
|
596
|
-
renderPass.setBindGroup(0, uniformBindGroup);
|
|
624
|
+
renderPass.setBindGroup(0, state.uniformBindGroup);
|
|
597
625
|
renderPass.draw(3);
|
|
598
626
|
renderPass.end();
|
|
599
627
|
device.queue.submit([commandEncoder.finish()]);
|
|
@@ -606,12 +634,13 @@ function useWebGPU(options) {
|
|
|
606
634
|
let mounted = true;
|
|
607
635
|
const initialize = async () => {
|
|
608
636
|
try {
|
|
609
|
-
const state = await initializeWebGPU(canvas, fragmentRef.current, uniformsRef.current);
|
|
637
|
+
const state = await initializeWebGPU(canvas, fragmentRef.current, uniformsRef.current, storageBuffersRef.current);
|
|
610
638
|
if (!mounted) {
|
|
611
639
|
cleanupWebGPU(state);
|
|
612
640
|
return;
|
|
613
641
|
}
|
|
614
642
|
stateRef.current = state;
|
|
643
|
+
uniformDataRef.current = new Float32Array(state.uniformLayout.bufferSize / 4);
|
|
615
644
|
elapsedTimeRef.current = 0;
|
|
616
645
|
lastFrameTimeRef.current = 0;
|
|
617
646
|
animationFrameRef.current = requestAnimationFrame(render);
|
|
@@ -728,6 +757,7 @@ function ReactGpuShader({
|
|
|
728
757
|
className,
|
|
729
758
|
fragment,
|
|
730
759
|
uniforms,
|
|
760
|
+
storageBuffers,
|
|
731
761
|
fullscreen = false,
|
|
732
762
|
timeScale,
|
|
733
763
|
onFrame,
|
|
@@ -748,6 +778,7 @@ function ReactGpuShader({
|
|
|
748
778
|
const { canvasRef } = useWebGPU({
|
|
749
779
|
fragment,
|
|
750
780
|
uniforms,
|
|
781
|
+
storageBuffers,
|
|
751
782
|
onError: handleError,
|
|
752
783
|
timeScale,
|
|
753
784
|
onFrame,
|
|
@@ -999,11 +1030,11 @@ function isVec2Array(value) {
|
|
|
999
1030
|
function isVec3Array(value) {
|
|
1000
1031
|
return Array.isArray(value) && value.length > 0 && Array.isArray(value[0]) && value[0].length === 3;
|
|
1001
1032
|
}
|
|
1002
|
-
function
|
|
1033
|
+
function isVec4Array(value) {
|
|
1003
1034
|
return Array.isArray(value) && value.length > 0 && Array.isArray(value[0]) && value[0].length === 4;
|
|
1004
1035
|
}
|
|
1005
1036
|
function isArrayUniform(value) {
|
|
1006
|
-
return isFloatArray(value) || isVec2Array(value) || isVec3Array(value) ||
|
|
1037
|
+
return isFloatArray(value) || isVec2Array(value) || isVec3Array(value) || isVec4Array(value);
|
|
1007
1038
|
}
|
|
1008
1039
|
function setUniform(gl, location, value) {
|
|
1009
1040
|
if (location === null) {
|
|
@@ -1011,7 +1042,7 @@ function setUniform(gl, location, value) {
|
|
|
1011
1042
|
}
|
|
1012
1043
|
if (typeof value === "number") {
|
|
1013
1044
|
gl.uniform1f(location, value);
|
|
1014
|
-
} else if (
|
|
1045
|
+
} else if (isVec4Array(value)) {
|
|
1015
1046
|
gl.uniform4fv(location, value.flat());
|
|
1016
1047
|
} else if (isVec3Array(value)) {
|
|
1017
1048
|
gl.uniform3fv(location, value.flat());
|
|
@@ -1067,7 +1098,7 @@ function getUniformType(value) {
|
|
|
1067
1098
|
if (typeof value === "number") {
|
|
1068
1099
|
return "float";
|
|
1069
1100
|
}
|
|
1070
|
-
if (
|
|
1101
|
+
if (isVec4Array(value)) {
|
|
1071
1102
|
return `vec4[${MAX_ARRAY_LENGTH}]`;
|
|
1072
1103
|
}
|
|
1073
1104
|
if (isVec3Array(value)) {
|
package/dist/types.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ 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 GpuUniformValue = number | Vec2 | Vec3 | Vec4;
|
|
9
|
+
export type GpuStorageBuffers = Record<string, Vec4Array>;
|
|
8
10
|
export type TextureSource = HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap | ImageData | OffscreenCanvas;
|
|
9
11
|
export type TextureWrap = "repeat" | "clamp" | "mirror";
|
|
10
12
|
export type TextureMinFilter = "nearest" | "linear" | "mipmap";
|
package/dist/types.d.ts.map
CHANGED
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|