q5 2.13.2 → 2.13.9
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 +3 -27
- package/defaultFont-msdf.json +1 -0
- package/defaultFont.png +0 -0
- package/package.json +1 -1
- package/q5.d.ts +32 -5
- package/q5.js +74 -74
- package/q5.min.js +1 -1
- package/src/q5-2d-drawing.js +7 -7
- package/src/q5-2d-text.js +1 -1
- package/src/q5-core.js +8 -7
- package/src/q5-input.js +2 -2
- package/src/q5-math.js +2 -1
- package/src/q5-webgpu-canvas.js +13 -20
- package/src/q5-webgpu-drawing.js +9 -6
- package/src/q5-webgpu-image.js +4 -7
- package/src/q5-webgpu-text.js +28 -23
package/src/q5-math.js
CHANGED
|
@@ -46,8 +46,9 @@ Q5.modules.math = ($, q) => {
|
|
|
46
46
|
|
|
47
47
|
$.dist = function () {
|
|
48
48
|
let a = arguments;
|
|
49
|
+
if (a.length == 2) return Math.hypot(a[0].x - a[1].x, a[0].y - a[1].y);
|
|
49
50
|
if (a.length == 4) return Math.hypot(a[0] - a[2], a[1] - a[3]);
|
|
50
|
-
|
|
51
|
+
return Math.hypot(a[0] - a[3], a[1] - a[4], a[2] - a[5]);
|
|
51
52
|
};
|
|
52
53
|
|
|
53
54
|
$.lerp = (a, b, t) => a * (1 - t) + b * t;
|
package/src/q5-webgpu-canvas.js
CHANGED
|
@@ -159,12 +159,12 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
159
159
|
|
|
160
160
|
const MAX_TRANSFORMS = 1e7, // or whatever maximum you need
|
|
161
161
|
MATRIX_SIZE = 16, // 4x4 matrix
|
|
162
|
-
transforms = new Float32Array(MAX_TRANSFORMS * MATRIX_SIZE)
|
|
162
|
+
transforms = new Float32Array(MAX_TRANSFORMS * MATRIX_SIZE);
|
|
163
|
+
|
|
164
|
+
let matrix,
|
|
163
165
|
matrices = [],
|
|
164
166
|
matricesIndexStack = [];
|
|
165
167
|
|
|
166
|
-
let matrix;
|
|
167
|
-
|
|
168
168
|
// tracks if the matrix has been modified
|
|
169
169
|
$._matrixDirty = false;
|
|
170
170
|
|
|
@@ -459,7 +459,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
459
459
|
new Float32Array(colorsBuffer.getMappedRange()).set(colorStack.slice(0, colorStackIndex));
|
|
460
460
|
colorsBuffer.unmap();
|
|
461
461
|
|
|
462
|
-
mainBindGroup = Q5.device.createBindGroup({
|
|
462
|
+
let mainBindGroup = Q5.device.createBindGroup({
|
|
463
463
|
layout: mainLayout,
|
|
464
464
|
entries: [
|
|
465
465
|
{ binding: 0, resource: { buffer: uniformBuffer } },
|
|
@@ -475,8 +475,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
475
475
|
let drawVertOffset = 0,
|
|
476
476
|
imageVertOffset = 0,
|
|
477
477
|
textCharOffset = 0,
|
|
478
|
-
curPipelineIndex = -1
|
|
479
|
-
curTextureIndex = -1;
|
|
478
|
+
curPipelineIndex = -1;
|
|
480
479
|
|
|
481
480
|
for (let i = 0; i < drawStack.length; i += 2) {
|
|
482
481
|
let v = drawStack[i + 1];
|
|
@@ -492,15 +491,11 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
492
491
|
pass.draw(v, 1, drawVertOffset);
|
|
493
492
|
drawVertOffset += v;
|
|
494
493
|
} else if (curPipelineIndex == 1) {
|
|
495
|
-
// let instanceCount = drawStack[i + 2];
|
|
496
494
|
// draw images
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
pass.setBindGroup(1, $._textureBindGroups[v]);
|
|
500
|
-
}
|
|
495
|
+
// v is the texture index
|
|
496
|
+
pass.setBindGroup(1, $._textureBindGroups[v]);
|
|
501
497
|
pass.draw(4, 1, imageVertOffset);
|
|
502
498
|
imageVertOffset += 4;
|
|
503
|
-
// i++;
|
|
504
499
|
} else if (curPipelineIndex == 2) {
|
|
505
500
|
// draw text
|
|
506
501
|
let o = drawStack[i + 2];
|
|
@@ -513,8 +508,6 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
513
508
|
i++;
|
|
514
509
|
}
|
|
515
510
|
}
|
|
516
|
-
|
|
517
|
-
for (let m of $._hooks.postRender) m();
|
|
518
511
|
};
|
|
519
512
|
|
|
520
513
|
$._finishRender = () => {
|
|
@@ -525,19 +518,19 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
525
518
|
q.pass = $.encoder = null;
|
|
526
519
|
|
|
527
520
|
// clear the stacks for the next frame
|
|
528
|
-
$.drawStack
|
|
521
|
+
$.drawStack = drawStack = [];
|
|
529
522
|
colorIndex = 1;
|
|
530
523
|
colorStackIndex = 8;
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
524
|
+
matrices = [matrices[0]];
|
|
525
|
+
matricesIndexStack = [];
|
|
526
|
+
|
|
527
|
+
for (let m of $._hooks.postRender) m();
|
|
535
528
|
};
|
|
536
529
|
};
|
|
537
530
|
|
|
538
531
|
Q5.initWebGPU = async () => {
|
|
539
532
|
if (!navigator.gpu) {
|
|
540
|
-
console.warn('q5 WebGPU not supported on this browser!');
|
|
533
|
+
console.warn('q5 WebGPU not supported on this browser! Use Google Chrome or Edge.');
|
|
541
534
|
return false;
|
|
542
535
|
}
|
|
543
536
|
if (!Q5.device) {
|
package/src/q5-webgpu-drawing.js
CHANGED
|
@@ -46,7 +46,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
let vertexBufferLayout = {
|
|
49
|
-
arrayStride: 16, //
|
|
49
|
+
arrayStride: 16, // 4 floats * 4 bytes
|
|
50
50
|
attributes: [
|
|
51
51
|
{ format: 'float32x2', offset: 0, shaderLocation: 0 }, // position
|
|
52
52
|
{ format: 'float32', offset: 8, shaderLocation: 1 }, // colorIndex
|
|
@@ -306,8 +306,10 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
306
306
|
}
|
|
307
307
|
};
|
|
308
308
|
|
|
309
|
-
$.
|
|
310
|
-
|
|
309
|
+
$._strokeJoin = 'round';
|
|
310
|
+
|
|
311
|
+
$.strokeJoin = (x) => {
|
|
312
|
+
$._strokeJoin = x;
|
|
311
313
|
};
|
|
312
314
|
|
|
313
315
|
$.line = (x1, y1, x2, y2) => {
|
|
@@ -328,7 +330,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
328
330
|
|
|
329
331
|
addRect(x1 + px, -y1 - py, x1 - px, -y1 + py, x2 - px, -y2 + py, x2 + px, -y2 - py, ci, ti);
|
|
330
332
|
|
|
331
|
-
if (sw > 2) {
|
|
333
|
+
if (sw > 2 && $._strokeJoin != 'none') {
|
|
332
334
|
let n = getArcSegments(sw);
|
|
333
335
|
addEllipse(x1, y1, hsw, hsw, n, ci, ti);
|
|
334
336
|
addEllipse(x2, y2, hsw, hsw, n, ci, ti);
|
|
@@ -470,7 +472,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
470
472
|
};
|
|
471
473
|
|
|
472
474
|
$.background = (r, g, b, a) => {
|
|
473
|
-
$.
|
|
475
|
+
$.pushMatrix();
|
|
474
476
|
$.resetMatrix();
|
|
475
477
|
$._doStroke = false;
|
|
476
478
|
if (r.src) {
|
|
@@ -485,7 +487,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
485
487
|
$.rect(-c.hw, -c.hh, c.w, c.h);
|
|
486
488
|
$._rectMode = og;
|
|
487
489
|
}
|
|
488
|
-
$.
|
|
490
|
+
$.popMatrix();
|
|
489
491
|
if (!$._fillSet) $._fill = 1;
|
|
490
492
|
};
|
|
491
493
|
|
|
@@ -505,6 +507,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
505
507
|
});
|
|
506
508
|
|
|
507
509
|
$._hooks.postRender.push(() => {
|
|
510
|
+
drawStack = $.drawStack;
|
|
508
511
|
vertIndex = 0;
|
|
509
512
|
});
|
|
510
513
|
};
|
package/src/q5-webgpu-image.js
CHANGED
|
@@ -118,14 +118,11 @@ fn fragmentMain(f: FragmentParams) -> @location(0) vec4f {
|
|
|
118
118
|
minFilter: filter
|
|
119
119
|
});
|
|
120
120
|
};
|
|
121
|
-
makeSampler('linear');
|
|
122
121
|
|
|
123
|
-
$.smooth = () =>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
$.
|
|
127
|
-
makeSampler('nearest');
|
|
128
|
-
};
|
|
122
|
+
$.smooth = () => makeSampler('linear');
|
|
123
|
+
$.noSmooth = () => makeSampler('nearest');
|
|
124
|
+
|
|
125
|
+
$.smooth();
|
|
129
126
|
|
|
130
127
|
let MAX_TEXTURES = 12000;
|
|
131
128
|
|
package/src/q5-webgpu-text.js
CHANGED
|
@@ -319,8 +319,8 @@ fn fragmentMain(f : FragmentParams) -> @location(0) vec4f {
|
|
|
319
319
|
if (vert) $._textBaseline = vert;
|
|
320
320
|
};
|
|
321
321
|
|
|
322
|
-
|
|
323
|
-
|
|
322
|
+
let charStack = [],
|
|
323
|
+
textStack = [];
|
|
324
324
|
|
|
325
325
|
let measureText = (font, text, charCallback) => {
|
|
326
326
|
let maxWidth = 0,
|
|
@@ -373,11 +373,16 @@ fn fragmentMain(f : FragmentParams) -> @location(0) vec4f {
|
|
|
373
373
|
|
|
374
374
|
$.text = (str, x, y, w, h) => {
|
|
375
375
|
if (!$._font) {
|
|
376
|
-
// check if
|
|
377
|
-
|
|
378
|
-
if (navigator.onLine && !initLoadDefaultFont) {
|
|
376
|
+
// check if loading the default font hasn't been attempted
|
|
377
|
+
if (!initLoadDefaultFont) {
|
|
379
378
|
initLoadDefaultFont = true;
|
|
380
|
-
|
|
379
|
+
|
|
380
|
+
if (navigator.onLine) {
|
|
381
|
+
$.loadFont('https://q5js.org/defaultFont-msdf.json');
|
|
382
|
+
} else if (Q5._esm && import.meta?.url) {
|
|
383
|
+
let path = new URL('defaultFont-msdf.json', import.meta.url);
|
|
384
|
+
$.loadFont(path.href);
|
|
385
|
+
}
|
|
381
386
|
}
|
|
382
387
|
return;
|
|
383
388
|
}
|
|
@@ -417,7 +422,7 @@ fn fragmentMain(f : FragmentParams) -> @location(0) vec4f {
|
|
|
417
422
|
|
|
418
423
|
let ta = $._textAlign,
|
|
419
424
|
tb = $._textBaseline,
|
|
420
|
-
textIndex =
|
|
425
|
+
textIndex = textStack.length,
|
|
421
426
|
o = 0, // offset
|
|
422
427
|
measurements;
|
|
423
428
|
|
|
@@ -457,20 +462,20 @@ fn fragmentMain(f : FragmentParams) -> @location(0) vec4f {
|
|
|
457
462
|
o += 4;
|
|
458
463
|
});
|
|
459
464
|
}
|
|
460
|
-
|
|
465
|
+
charStack.push(charsData);
|
|
461
466
|
|
|
462
|
-
let
|
|
467
|
+
let txt = [];
|
|
463
468
|
|
|
464
469
|
if ($._matrixDirty) $._saveMatrix();
|
|
465
470
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
471
|
+
txt[0] = x;
|
|
472
|
+
txt[1] = -y;
|
|
473
|
+
txt[2] = $._textSize / 44;
|
|
474
|
+
txt[3] = $._matrixIndex;
|
|
475
|
+
txt[4] = $._fillSet ? $._fill : 0;
|
|
476
|
+
txt[5] = $._stroke;
|
|
472
477
|
|
|
473
|
-
|
|
478
|
+
textStack.push(txt);
|
|
474
479
|
$.drawStack.push(2, measurements.printedCharCount, $._font.index);
|
|
475
480
|
};
|
|
476
481
|
|
|
@@ -531,11 +536,11 @@ fn fragmentMain(f : FragmentParams) -> @location(0) vec4f {
|
|
|
531
536
|
};
|
|
532
537
|
|
|
533
538
|
$._hooks.preRender.push(() => {
|
|
534
|
-
if (
|
|
539
|
+
if (!charStack.length) return;
|
|
535
540
|
|
|
536
541
|
// calculate total buffer size for text data
|
|
537
542
|
let totalTextSize = 0;
|
|
538
|
-
for (let charsData of
|
|
543
|
+
for (let charsData of charStack) {
|
|
539
544
|
totalTextSize += charsData.length * 4;
|
|
540
545
|
}
|
|
541
546
|
|
|
@@ -547,11 +552,11 @@ fn fragmentMain(f : FragmentParams) -> @location(0) vec4f {
|
|
|
547
552
|
});
|
|
548
553
|
|
|
549
554
|
// copy all the text data into the buffer
|
|
550
|
-
new Float32Array(charBuffer.getMappedRange()).set(
|
|
555
|
+
new Float32Array(charBuffer.getMappedRange()).set(charStack.flat());
|
|
551
556
|
charBuffer.unmap();
|
|
552
557
|
|
|
553
558
|
// calculate total buffer size for metadata
|
|
554
|
-
let totalMetadataSize =
|
|
559
|
+
let totalMetadataSize = textStack.length * 6 * 4;
|
|
555
560
|
|
|
556
561
|
// create a single buffer for all metadata
|
|
557
562
|
let textBuffer = Q5.device.createBuffer({
|
|
@@ -562,7 +567,7 @@ fn fragmentMain(f : FragmentParams) -> @location(0) vec4f {
|
|
|
562
567
|
});
|
|
563
568
|
|
|
564
569
|
// copy all metadata into the buffer
|
|
565
|
-
new Float32Array(textBuffer.getMappedRange()).set(
|
|
570
|
+
new Float32Array(textBuffer.getMappedRange()).set(textStack.flat());
|
|
566
571
|
textBuffer.unmap();
|
|
567
572
|
|
|
568
573
|
// create a single bind group for the text buffer and metadata buffer
|
|
@@ -577,7 +582,7 @@ fn fragmentMain(f : FragmentParams) -> @location(0) vec4f {
|
|
|
577
582
|
});
|
|
578
583
|
|
|
579
584
|
$._hooks.postRender.push(() => {
|
|
580
|
-
|
|
581
|
-
|
|
585
|
+
charStack = [];
|
|
586
|
+
textStack = [];
|
|
582
587
|
});
|
|
583
588
|
};
|