q5 2.14.3 → 2.14.5

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,525 +0,0 @@
1
- Q5.renderers.webgpu.drawing = ($, q) => {
2
- let c = $.canvas,
3
- drawStack = $.drawStack,
4
- vertexStack = new Float32Array(1e7),
5
- vertIndex = 0;
6
-
7
- let drawingShader = Q5.device.createShaderModule({
8
- label: 'drawingShader',
9
- code: `
10
- struct Uniforms {
11
- halfWidth: f32,
12
- halfHeight: f32
13
- }
14
- struct VertexParams {
15
- @location(0) pos: vec2f,
16
- @location(1) colorIndex: f32,
17
- @location(2) matrixIndex: f32
18
- }
19
- struct FragmentParams {
20
- @builtin(position) position: vec4f,
21
- @location(0) color: vec4f
22
- }
23
-
24
- @group(0) @binding(0) var<uniform> uniforms: Uniforms;
25
- @group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;
26
- @group(0) @binding(2) var<storage> colors : array<vec4f>;
27
-
28
- @vertex
29
- fn vertexMain(v: VertexParams) -> FragmentParams {
30
- var vert = vec4f(v.pos, 0.0, 1.0);
31
- vert = transforms[i32(v.matrixIndex)] * vert;
32
- vert.x /= uniforms.halfWidth;
33
- vert.y /= uniforms.halfHeight;
34
-
35
- var f: FragmentParams;
36
- f.position = vert;
37
- f.color = colors[i32(v.colorIndex)];
38
- return f;
39
- }
40
-
41
- @fragment
42
- fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
43
- return color;
44
- }
45
- `
46
- });
47
-
48
- let vertexBufferLayout = {
49
- arrayStride: 16, // 4 floats * 4 bytes
50
- attributes: [
51
- { format: 'float32x2', offset: 0, shaderLocation: 0 }, // position
52
- { format: 'float32', offset: 8, shaderLocation: 1 }, // colorIndex
53
- { format: 'float32', offset: 12, shaderLocation: 2 } // matrixIndex
54
- ]
55
- };
56
-
57
- let pipelineLayout = Q5.device.createPipelineLayout({
58
- label: 'drawingPipelineLayout',
59
- bindGroupLayouts: $.bindGroupLayouts
60
- });
61
-
62
- $._pipelineConfigs[0] = {
63
- label: 'drawingPipeline',
64
- layout: pipelineLayout,
65
- vertex: {
66
- module: drawingShader,
67
- entryPoint: 'vertexMain',
68
- buffers: [vertexBufferLayout]
69
- },
70
- fragment: {
71
- module: drawingShader,
72
- entryPoint: 'fragmentMain',
73
- targets: [{ format: 'bgra8unorm', blend: $.blendConfigs.normal }]
74
- },
75
- primitive: { topology: 'triangle-strip', stripIndexFormat: 'uint32' },
76
- multisample: { count: 4 }
77
- };
78
-
79
- $._pipelines[0] = Q5.device.createRenderPipeline($._pipelineConfigs[0]);
80
-
81
- const addVert = (x, y, ci, ti) => {
82
- let v = vertexStack,
83
- i = vertIndex;
84
- v[i++] = x;
85
- v[i++] = y;
86
- v[i++] = ci;
87
- v[i++] = ti;
88
- vertIndex = i;
89
- };
90
-
91
- const addRect = (x1, y1, x2, y2, x3, y3, x4, y4, ci, ti) => {
92
- let v = vertexStack,
93
- i = vertIndex;
94
-
95
- v[i++] = x1;
96
- v[i++] = y1;
97
- v[i++] = ci;
98
- v[i++] = ti;
99
-
100
- v[i++] = x2;
101
- v[i++] = y2;
102
- v[i++] = ci;
103
- v[i++] = ti;
104
-
105
- v[i++] = x4;
106
- v[i++] = y4;
107
- v[i++] = ci;
108
- v[i++] = ti;
109
-
110
- v[i++] = x3;
111
- v[i++] = y3;
112
- v[i++] = ci;
113
- v[i++] = ti;
114
-
115
- vertIndex = i;
116
- drawStack.push(0, 4);
117
- };
118
-
119
- const addEllipse = (x, y, a, b, n, ci, ti) => {
120
- y = -y;
121
- let t = 0,
122
- angleIncrement = $.TAU / n;
123
-
124
- let v = vertexStack,
125
- i = vertIndex;
126
-
127
- for (let j = 0; j <= n; j++) {
128
- // add center vertex
129
- v[i++] = x;
130
- v[i++] = y;
131
- v[i++] = ci;
132
- v[i++] = ti;
133
-
134
- // calculate perimeter vertex
135
- let vx = x + a * Math.cos(t);
136
- let vy = y + b * Math.sin(t);
137
-
138
- // add perimeter vertex
139
- v[i++] = vx;
140
- v[i++] = vy;
141
- v[i++] = ci;
142
- v[i++] = ti;
143
-
144
- t += angleIncrement;
145
- }
146
-
147
- // close the triangle strip
148
- // add center vertex
149
- v[i++] = x;
150
- v[i++] = y;
151
- v[i++] = ci;
152
- v[i++] = ti;
153
-
154
- // add first perimeter vertex
155
- v[i++] = x + a;
156
- v[i++] = y;
157
- v[i++] = ci;
158
- v[i++] = ti;
159
-
160
- vertIndex = i;
161
- drawStack.push(0, (n + 1) * 2 + 2);
162
- };
163
-
164
- const addEllipseStroke = (x, y, outerA, outerB, innerA, innerB, n, ci, ti) => {
165
- y = -y;
166
- let angleIncrement = $.TAU / n;
167
- let t = 0;
168
-
169
- let v = vertexStack,
170
- i = vertIndex;
171
-
172
- for (let j = 0; j <= n; j++) {
173
- // Outer vertex
174
- let vxOuter = x + outerA * Math.cos(t);
175
- let vyOuter = y + outerB * Math.sin(t);
176
-
177
- // Inner vertex
178
- let vxInner = x + innerA * Math.cos(t);
179
- let vyInner = y + innerB * Math.sin(t);
180
-
181
- // Add vertices for triangle strip
182
- v[i++] = vxOuter;
183
- v[i++] = vyOuter;
184
- v[i++] = ci;
185
- v[i++] = ti;
186
-
187
- v[i++] = vxInner;
188
- v[i++] = vyInner;
189
- v[i++] = ci;
190
- v[i++] = ti;
191
-
192
- t += angleIncrement;
193
- }
194
-
195
- vertIndex = i;
196
- drawStack.push(0, (n + 1) * 2); // Use triangle strip
197
- };
198
-
199
- $.rectMode = (x) => ($._rectMode = x);
200
-
201
- $.rect = (x, y, w, h) => {
202
- let [l, r, t, b] = $._calcBox(x, y, w, h, $._rectMode);
203
- let ci, ti;
204
- if ($._matrixDirty) $._saveMatrix();
205
- ti = $._matrixIndex;
206
-
207
- if ($._doFill) {
208
- ci = $._fill;
209
- addRect(l, t, r, t, r, b, l, b, ci, ti);
210
- }
211
-
212
- if ($._doStroke) {
213
- ci = $._stroke;
214
- let sw = $._strokeWeight / 2;
215
-
216
- // Calculate stroke positions
217
- let lsw = l - sw,
218
- rsw = r + sw,
219
- tsw = t + sw,
220
- bsw = b - sw,
221
- lpsw = l + sw,
222
- rpsw = r - sw,
223
- tpsw = t - sw,
224
- bpsw = b + sw;
225
-
226
- addRect(lsw, tpsw, rsw, tpsw, rsw, tsw, lsw, tsw, ci, ti); // Top
227
- addRect(lsw, bsw, rsw, bsw, rsw, bpsw, lsw, bpsw, ci, ti); // Bottom
228
-
229
- // Adjust side strokes to avoid overlapping corners
230
- tsw = t - sw;
231
- bsw = b + sw;
232
-
233
- addRect(lsw, tsw, lpsw, tsw, lpsw, bsw, lsw, bsw, ci, ti); // Left
234
- addRect(rpsw, tsw, rsw, tsw, rsw, bsw, rpsw, bsw, ci, ti); // Right
235
- }
236
- };
237
-
238
- $.square = (x, y, s) => $.rect(x, y, s, s);
239
-
240
- // prettier-ignore
241
- const getArcSegments = (d) =>
242
- d < 4 ? 6 :
243
- d < 6 ? 8 :
244
- d < 10 ? 10 :
245
- d < 16 ? 12 :
246
- d < 20 ? 14 :
247
- d < 22 ? 16 :
248
- d < 24 ? 18 :
249
- d < 28 ? 20 :
250
- d < 34 ? 22 :
251
- d < 42 ? 24 :
252
- d < 48 ? 26 :
253
- d < 56 ? 28 :
254
- d < 64 ? 30 :
255
- d < 72 ? 32 :
256
- d < 84 ? 34 :
257
- d < 96 ? 36 :
258
- d < 98 ? 38 :
259
- d < 113 ? 40 :
260
- d < 149 ? 44 :
261
- d < 199 ? 48 :
262
- d < 261 ? 52 :
263
- d < 353 ? 56 :
264
- d < 461 ? 60 :
265
- d < 585 ? 64 :
266
- d < 1200 ? 70 :
267
- d < 1800 ? 80 :
268
- d < 2400 ? 90 :
269
- 100;
270
-
271
- $.ellipseMode = (x) => ($._ellipseMode = x);
272
-
273
- $.ellipse = (x, y, w, h) => {
274
- let n = getArcSegments(Math.max(Math.abs(w), Math.abs(h)) * $._scale);
275
- let a = w / 2;
276
- let b = w == h ? a : h / 2;
277
-
278
- if ($._matrixDirty) $._saveMatrix();
279
- let ti = $._matrixIndex;
280
-
281
- if ($._doFill) {
282
- addEllipse(x, y, a, b, n, $._fill, ti);
283
- }
284
- if ($._doStroke) {
285
- let sw = $._strokeWeight / 2;
286
- // Draw the stroke as a ring using triangle strips
287
- addEllipseStroke(x, y, a + sw, b + sw, a - sw, b - sw, n, $._stroke, ti);
288
- }
289
- };
290
-
291
- $.circle = (x, y, d) => $.ellipse(x, y, d, d);
292
-
293
- $.point = (x, y) => {
294
- if ($._matrixDirty) $._saveMatrix();
295
- let ti = $._matrixIndex,
296
- ci = $._stroke,
297
- sw = $._strokeWeight;
298
-
299
- if ($._scaledSW < 2) {
300
- let [l, r, t, b] = $._calcBox(x, y, sw, sw, 'corner');
301
- addRect(l, t, r, t, r, b, l, b, ci, ti);
302
- } else {
303
- let n = getArcSegments(sw);
304
- sw /= 2;
305
- addEllipse(x, y, sw, sw, n, ci, ti);
306
- }
307
- };
308
-
309
- $._strokeJoin = 'round';
310
-
311
- $.strokeJoin = (x) => {
312
- $._strokeJoin = x;
313
- };
314
-
315
- $.line = (x1, y1, x2, y2) => {
316
- if ($._matrixDirty) $._saveMatrix();
317
- let ti = $._matrixIndex,
318
- ci = $._stroke,
319
- sw = $._strokeWeight,
320
- hsw = sw / 2;
321
-
322
- // calculate the direction vector and length
323
- let dx = x2 - x1,
324
- dy = y2 - y1,
325
- length = Math.hypot(dx, dy);
326
-
327
- // calculate the perpendicular vector for line thickness
328
- let px = -(dy / length) * hsw,
329
- py = (dx / length) * hsw;
330
-
331
- addRect(x1 + px, -y1 - py, x1 - px, -y1 + py, x2 - px, -y2 + py, x2 + px, -y2 - py, ci, ti);
332
-
333
- if ($._scaledSW > 2 && $._strokeJoin != 'none') {
334
- let n = getArcSegments($._scaledSW);
335
- addEllipse(x1, y1, hsw, hsw, n, ci, ti);
336
- addEllipse(x2, y2, hsw, hsw, n, ci, ti);
337
- }
338
- };
339
-
340
- let shapeVertCount;
341
- let sv = []; // shape vertices
342
- let curveVertices = []; // curve vertices
343
-
344
- $.beginShape = () => {
345
- shapeVertCount = 0;
346
- sv = [];
347
- curveVertices = [];
348
- };
349
-
350
- $.vertex = (x, y) => {
351
- if ($._matrixDirty) $._saveMatrix();
352
- sv.push(x, -y, $._fill, $._matrixIndex);
353
- shapeVertCount++;
354
- };
355
-
356
- $.curveVertex = (x, y) => {
357
- if ($._matrixDirty) $._saveMatrix();
358
- curveVertices.push({ x: x, y: -y });
359
- };
360
-
361
- $.endShape = (close) => {
362
- if (curveVertices.length > 0) {
363
- // duplicate start and end points if necessary
364
- let points = [...curveVertices];
365
- if (points.length < 4) {
366
- // duplicate first and last points
367
- while (points.length < 4) {
368
- points.unshift(points[0]);
369
- points.push(points[points.length - 1]);
370
- }
371
- }
372
-
373
- for (let i = 0; i < points.length - 3; i++) {
374
- let p0 = points[i];
375
- let p1 = points[i + 1];
376
- let p2 = points[i + 2];
377
- let p3 = points[i + 3];
378
-
379
- for (let t = 0; t <= 1; t += 0.1) {
380
- let t2 = t * t;
381
- let t3 = t2 * t;
382
-
383
- let x =
384
- 0.5 *
385
- (2 * p1.x +
386
- (-p0.x + p2.x) * t +
387
- (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 +
388
- (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3);
389
-
390
- let y =
391
- 0.5 *
392
- (2 * p1.y +
393
- (-p0.y + p2.y) * t +
394
- (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 +
395
- (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3);
396
-
397
- sv.push(x, y, $._fill, $._matrixIndex);
398
- shapeVertCount++;
399
- }
400
- }
401
- }
402
-
403
- if (shapeVertCount < 3) {
404
- throw new Error('A shape must have at least 3 vertices.');
405
- }
406
-
407
- // close the shape if requested
408
- if (close) {
409
- let firstIndex = 0;
410
- let lastIndex = (shapeVertCount - 1) * 4;
411
-
412
- let firstX = sv[firstIndex];
413
- let firstY = sv[firstIndex + 1];
414
- let lastX = sv[lastIndex];
415
- let lastY = sv[lastIndex + 1];
416
-
417
- if (firstX !== lastX || firstY !== lastY) {
418
- sv.push(firstX, firstY, sv[firstIndex + 2], sv[firstIndex + 3]);
419
- shapeVertCount++;
420
- }
421
- }
422
-
423
- if ($._doFill) {
424
- if (shapeVertCount == 5) {
425
- // for quads, draw two triangles
426
- addVert(sv[0], sv[1], sv[2], sv[3]); // v0
427
- addVert(sv[4], sv[5], sv[6], sv[7]); // v1
428
- addVert(sv[12], sv[13], sv[14], sv[15]); // v3
429
- addVert(sv[8], sv[9], sv[10], sv[11]); // v2
430
- drawStack.push(0, 4);
431
- } else {
432
- // triangulate the shape
433
- for (let i = 1; i < shapeVertCount - 1; i++) {
434
- let v0 = 0;
435
- let v1 = i * 4;
436
- let v2 = (i + 1) * 4;
437
-
438
- addVert(sv[v0], sv[v0 + 1], sv[v0 + 2], sv[v0 + 3]);
439
- addVert(sv[v1], sv[v1 + 1], sv[v1 + 2], sv[v1 + 3]);
440
- addVert(sv[v2], sv[v2 + 1], sv[v2 + 2], sv[v2 + 3]);
441
- }
442
- drawStack.push(0, (shapeVertCount - 2) * 3);
443
- }
444
- }
445
-
446
- if ($._doStroke) {
447
- // draw lines between vertices
448
- for (let i = 0; i < shapeVertCount - 1; i++) {
449
- let v1 = i * 4;
450
- let v2 = (i + 1) * 4;
451
- $.line(sv[v1], -sv[v1 + 1], sv[v2], -sv[v2 + 1]);
452
- }
453
- if (close) {
454
- let v1 = (shapeVertCount - 1) * 4;
455
- let v2 = 0;
456
- $.line(sv[v1], -sv[v1 + 1], sv[v2], -sv[v2 + 1]);
457
- }
458
- }
459
-
460
- // reset for the next shape
461
- shapeVertCount = 0;
462
- sv = [];
463
- curveVertices = [];
464
- };
465
-
466
- $.triangle = (x1, y1, x2, y2, x3, y3) => {
467
- $.beginShape();
468
- $.vertex(x1, y1);
469
- $.vertex(x2, y2);
470
- $.vertex(x3, y3);
471
- $.endShape(true);
472
- };
473
-
474
- $.quad = (x1, y1, x2, y2, x3, y3, x4, y4) => {
475
- $.beginShape();
476
- $.vertex(x1, y1);
477
- $.vertex(x2, y2);
478
- $.vertex(x3, y3);
479
- $.vertex(x4, y4);
480
- $.endShape(true);
481
- };
482
-
483
- $.background = (r, g, b, a) => {
484
- let mi = $._matrixIndex;
485
- $._matrixIndex = 0;
486
- $._doStroke = false;
487
- if (r.src) {
488
- let img = r;
489
- let im = $._imageMode;
490
- $._imageMode = 'corner';
491
- $.image(img, -c.hw, -c.hh, c.w, c.h);
492
- $._imageMode = im;
493
- } else {
494
- let rm = $._rectMode;
495
- $._rectMode = 'corner';
496
- let fill = $._fill;
497
- $.fill(r, g, b, a);
498
- $.rect(-c.hw, -c.hh, c.w, c.h);
499
- $._rectMode = rm;
500
- $._fill = fill;
501
- }
502
- $._doStroke = true;
503
- $._matrixIndex = mi;
504
- };
505
-
506
- $._hooks.preRender.push(() => {
507
- $.pass.setPipeline($._pipelines[0]);
508
-
509
- let vertexBuffer = Q5.device.createBuffer({
510
- size: vertIndex * 4,
511
- usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
512
- mappedAtCreation: true
513
- });
514
-
515
- new Float32Array(vertexBuffer.getMappedRange()).set(vertexStack.slice(0, vertIndex));
516
- vertexBuffer.unmap();
517
-
518
- $.pass.setVertexBuffer(0, vertexBuffer);
519
- });
520
-
521
- $._hooks.postRender.push(() => {
522
- drawStack = $.drawStack;
523
- vertIndex = 0;
524
- });
525
- };