q5 2.14.4 → 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.
- package/README.md +1 -1
- package/package.json +1 -1
- package/q5.js +4 -11
- package/q5.min.js +1 -1
- package/q5js_brand.webp +0 -0
- package/q5js_icon.png +0 -0
- package/src/q5-2d-canvas.js +0 -202
- package/src/q5-2d-drawing.js +0 -399
- package/src/q5-2d-image.js +0 -330
- package/src/q5-2d-soft-filters.js +0 -145
- package/src/q5-2d-text.js +0 -279
- package/src/q5-ai.js +0 -65
- package/src/q5-canvas.js +0 -367
- package/src/q5-color.js +0 -322
- package/src/q5-core.js +0 -319
- package/src/q5-display.js +0 -101
- package/src/q5-dom.js +0 -2
- package/src/q5-input.js +0 -215
- package/src/q5-math.js +0 -424
- package/src/q5-noisier.js +0 -264
- package/src/q5-record.js +0 -366
- package/src/q5-sensors.js +0 -98
- package/src/q5-sound.js +0 -64
- package/src/q5-util.js +0 -50
- package/src/q5-vector.js +0 -305
- package/src/q5-webgpu-canvas.js +0 -565
- package/src/q5-webgpu-drawing.js +0 -638
- package/src/q5-webgpu-image.js +0 -268
- package/src/q5-webgpu-text.js +0 -594
- package/src/readme.md +0 -248
package/src/q5-webgpu-canvas.js
DELETED
|
@@ -1,565 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* q5-webgpu
|
|
3
|
-
*
|
|
4
|
-
* EXPERIMENTAL, for developer testing only!
|
|
5
|
-
*/
|
|
6
|
-
Q5.renderers.webgpu = {};
|
|
7
|
-
|
|
8
|
-
Q5.renderers.webgpu.canvas = ($, q) => {
|
|
9
|
-
let c = $.canvas;
|
|
10
|
-
|
|
11
|
-
c.width = $.width = 500;
|
|
12
|
-
c.height = $.height = 500;
|
|
13
|
-
|
|
14
|
-
// q2d graphics context
|
|
15
|
-
$._g = $.createGraphics(1, 1);
|
|
16
|
-
|
|
17
|
-
if ($.colorMode) $.colorMode('rgb', 1);
|
|
18
|
-
|
|
19
|
-
let pass,
|
|
20
|
-
mainView,
|
|
21
|
-
colorIndex = 1,
|
|
22
|
-
colorStackIndex = 8;
|
|
23
|
-
|
|
24
|
-
$._pipelineConfigs = [];
|
|
25
|
-
$._pipelines = [];
|
|
26
|
-
|
|
27
|
-
// local variables used for slightly better performance
|
|
28
|
-
// stores pipeline shifts and vertex counts/image indices
|
|
29
|
-
let drawStack = ($.drawStack = []);
|
|
30
|
-
|
|
31
|
-
// colors used for each draw call
|
|
32
|
-
let colorStack = ($.colorStack = new Float32Array(1e6));
|
|
33
|
-
|
|
34
|
-
// prettier-ignore
|
|
35
|
-
colorStack.set([
|
|
36
|
-
0, 0, 0, 1, // black
|
|
37
|
-
1, 1, 1, 1 // white
|
|
38
|
-
]);
|
|
39
|
-
|
|
40
|
-
let mainLayout = Q5.device.createBindGroupLayout({
|
|
41
|
-
label: 'mainLayout',
|
|
42
|
-
entries: [
|
|
43
|
-
{
|
|
44
|
-
binding: 0,
|
|
45
|
-
visibility: GPUShaderStage.VERTEX,
|
|
46
|
-
buffer: { type: 'uniform' }
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
binding: 1,
|
|
50
|
-
visibility: GPUShaderStage.VERTEX,
|
|
51
|
-
buffer: { type: 'read-only-storage' }
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
binding: 2,
|
|
55
|
-
visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
|
|
56
|
-
buffer: { type: 'read-only-storage' }
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
$.bindGroupLayouts = [mainLayout];
|
|
62
|
-
|
|
63
|
-
let uniformBuffer = Q5.device.createBuffer({
|
|
64
|
-
size: 8, // Size of two floats
|
|
65
|
-
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
let createMainView = () => {
|
|
69
|
-
mainView = Q5.device
|
|
70
|
-
.createTexture({
|
|
71
|
-
size: [$.canvas.width, $.canvas.height],
|
|
72
|
-
sampleCount: 4,
|
|
73
|
-
format: 'bgra8unorm',
|
|
74
|
-
usage: GPUTextureUsage.RENDER_ATTACHMENT
|
|
75
|
-
})
|
|
76
|
-
.createView();
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
$._createCanvas = (w, h, opt) => {
|
|
80
|
-
q.ctx = q.drawingContext = c.getContext('webgpu');
|
|
81
|
-
|
|
82
|
-
opt.format ??= navigator.gpu.getPreferredCanvasFormat();
|
|
83
|
-
opt.device ??= Q5.device;
|
|
84
|
-
if (opt.alpha) opt.alphaMode = 'premultiplied';
|
|
85
|
-
|
|
86
|
-
$.ctx.configure(opt);
|
|
87
|
-
|
|
88
|
-
Q5.device.queue.writeBuffer(uniformBuffer, 0, new Float32Array([$.canvas.hw, $.canvas.hh]));
|
|
89
|
-
|
|
90
|
-
createMainView();
|
|
91
|
-
return c;
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
$._resizeCanvas = (w, h) => {
|
|
95
|
-
$._setCanvasSize(w, h);
|
|
96
|
-
createMainView();
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
$.pixelDensity = (v) => {
|
|
100
|
-
if (!v || v == $._pixelDensity) return $._pixelDensity;
|
|
101
|
-
$._pixelDensity = v;
|
|
102
|
-
$._setCanvasSize(c.w, c.h);
|
|
103
|
-
createMainView();
|
|
104
|
-
return v;
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
// current color index, used to associate a vertex with a color
|
|
108
|
-
let addColor = (r, g, b, a = 1) => {
|
|
109
|
-
if (typeof r == 'string') r = $.color(r);
|
|
110
|
-
else if (b == undefined) {
|
|
111
|
-
// grayscale mode `fill(1, 0.5)`
|
|
112
|
-
a = g ?? 1;
|
|
113
|
-
g = b = r;
|
|
114
|
-
}
|
|
115
|
-
if (r._q5Color) {
|
|
116
|
-
a = r.a;
|
|
117
|
-
b = r.b;
|
|
118
|
-
g = r.g;
|
|
119
|
-
r = r.r;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
let cs = colorStack,
|
|
123
|
-
i = colorStackIndex;
|
|
124
|
-
cs[i++] = r;
|
|
125
|
-
cs[i++] = g;
|
|
126
|
-
cs[i++] = b;
|
|
127
|
-
cs[i++] = a;
|
|
128
|
-
colorStackIndex = i;
|
|
129
|
-
|
|
130
|
-
colorIndex++;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
$._stroke = 0;
|
|
134
|
-
$._fill = $._tint = $._globalAlpha = 1;
|
|
135
|
-
$._doFill = $._doStroke = true;
|
|
136
|
-
|
|
137
|
-
$.fill = (r, g, b, a) => {
|
|
138
|
-
addColor(r, g, b, a);
|
|
139
|
-
$._doFill = $._fillSet = true;
|
|
140
|
-
$._fill = colorIndex;
|
|
141
|
-
};
|
|
142
|
-
$.stroke = (r, g, b, a) => {
|
|
143
|
-
addColor(r, g, b, a);
|
|
144
|
-
$._doStroke = $._strokeSet = true;
|
|
145
|
-
$._stroke = colorIndex;
|
|
146
|
-
};
|
|
147
|
-
$.tint = (r, g, b, a) => {
|
|
148
|
-
addColor(r, g, b, a);
|
|
149
|
-
$._tint = colorIndex;
|
|
150
|
-
};
|
|
151
|
-
$.opacity = (a) => ($._globalAlpha = a);
|
|
152
|
-
|
|
153
|
-
$.noFill = () => ($._doFill = false);
|
|
154
|
-
$.noStroke = () => ($._doStroke = false);
|
|
155
|
-
$.noTint = () => ($._tint = 1);
|
|
156
|
-
|
|
157
|
-
$._strokeWeight = 1;
|
|
158
|
-
$._hsw = 0.5;
|
|
159
|
-
$._scaledSW = 1;
|
|
160
|
-
$.strokeWeight = (v) => {
|
|
161
|
-
v = Math.abs(v);
|
|
162
|
-
$._strokeWeight = v;
|
|
163
|
-
$._scaledSW = v * $._scale;
|
|
164
|
-
$._hsw = v / 2;
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const MAX_TRANSFORMS = 1e7, // or whatever maximum you need
|
|
168
|
-
MATRIX_SIZE = 16, // 4x4 matrix
|
|
169
|
-
transforms = new Float32Array(MAX_TRANSFORMS * MATRIX_SIZE);
|
|
170
|
-
|
|
171
|
-
let matrix,
|
|
172
|
-
matrices = [],
|
|
173
|
-
matricesIndexStack = [];
|
|
174
|
-
|
|
175
|
-
// tracks if the matrix has been modified
|
|
176
|
-
$._matrixDirty = false;
|
|
177
|
-
|
|
178
|
-
// initialize with a 4x4 identity matrix
|
|
179
|
-
// prettier-ignore
|
|
180
|
-
matrices.push([
|
|
181
|
-
1, 0, 0, 0,
|
|
182
|
-
0, 1, 0, 0,
|
|
183
|
-
0, 0, 1, 0,
|
|
184
|
-
0, 0, 0, 1
|
|
185
|
-
]);
|
|
186
|
-
|
|
187
|
-
transforms.set(matrices[0]);
|
|
188
|
-
|
|
189
|
-
$.resetMatrix = () => {
|
|
190
|
-
matrix = matrices[0].slice();
|
|
191
|
-
$._matrixIndex = 0;
|
|
192
|
-
};
|
|
193
|
-
$.resetMatrix();
|
|
194
|
-
|
|
195
|
-
$.translate = (x, y, z) => {
|
|
196
|
-
if (!x && !y && !z) return;
|
|
197
|
-
// update the translation values
|
|
198
|
-
matrix[12] += x;
|
|
199
|
-
matrix[13] -= y;
|
|
200
|
-
matrix[14] += z || 0;
|
|
201
|
-
$._matrixDirty = true;
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
$.rotate = (a) => {
|
|
205
|
-
if (!a) return;
|
|
206
|
-
if ($._angleMode) a *= $._DEGTORAD;
|
|
207
|
-
|
|
208
|
-
let cosR = Math.cos(a),
|
|
209
|
-
sinR = Math.sin(a),
|
|
210
|
-
m = matrix,
|
|
211
|
-
m0 = m[0],
|
|
212
|
-
m1 = m[1],
|
|
213
|
-
m4 = m[4],
|
|
214
|
-
m5 = m[5];
|
|
215
|
-
|
|
216
|
-
// if identity matrix, just set the rotation values
|
|
217
|
-
if (m0 == 1 && !m1 && !m4 && m5 == 1) {
|
|
218
|
-
m[0] = cosR;
|
|
219
|
-
m[1] = -sinR;
|
|
220
|
-
m[4] = sinR;
|
|
221
|
-
m[5] = cosR;
|
|
222
|
-
} else {
|
|
223
|
-
// combine the current rotation with the new rotation
|
|
224
|
-
m[0] = m0 * cosR + m1 * sinR;
|
|
225
|
-
m[1] = m1 * cosR - m0 * sinR;
|
|
226
|
-
m[4] = m4 * cosR + m5 * sinR;
|
|
227
|
-
m[5] = m5 * cosR - m4 * sinR;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
$._matrixDirty = true;
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
$._scale = 1;
|
|
234
|
-
|
|
235
|
-
$.scale = (x = 1, y, z = 1) => {
|
|
236
|
-
y ??= x;
|
|
237
|
-
|
|
238
|
-
$._scale = Math.max(Math.abs(x), Math.abs(y));
|
|
239
|
-
$._scaledSW = $._strokeWeight * $._scale;
|
|
240
|
-
|
|
241
|
-
let m = matrix;
|
|
242
|
-
|
|
243
|
-
m[0] *= x;
|
|
244
|
-
m[1] *= x;
|
|
245
|
-
m[2] *= x;
|
|
246
|
-
m[3] *= x;
|
|
247
|
-
m[4] *= y;
|
|
248
|
-
m[5] *= y;
|
|
249
|
-
m[6] *= y;
|
|
250
|
-
m[7] *= y;
|
|
251
|
-
m[8] *= z;
|
|
252
|
-
m[9] *= z;
|
|
253
|
-
m[10] *= z;
|
|
254
|
-
m[11] *= z;
|
|
255
|
-
|
|
256
|
-
$._matrixDirty = true;
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
$.shearX = (ang) => {
|
|
260
|
-
if (!ang) return;
|
|
261
|
-
if ($._angleMode) ang *= $._DEGTORAD;
|
|
262
|
-
|
|
263
|
-
let tanAng = Math.tan(ang),
|
|
264
|
-
m = matrix,
|
|
265
|
-
m0 = m[0],
|
|
266
|
-
m1 = m[1],
|
|
267
|
-
m4 = m[4],
|
|
268
|
-
m5 = m[5];
|
|
269
|
-
|
|
270
|
-
m[0] = m0 + m4 * tanAng;
|
|
271
|
-
m[1] = m1 + m5 * tanAng;
|
|
272
|
-
|
|
273
|
-
$._matrixDirty = true;
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
$.shearY = (ang) => {
|
|
277
|
-
if (!ang) return;
|
|
278
|
-
if ($._angleMode) ang *= $._DEGTORAD;
|
|
279
|
-
|
|
280
|
-
let tanAng = Math.tan(ang),
|
|
281
|
-
m = matrix,
|
|
282
|
-
m0 = m[0],
|
|
283
|
-
m1 = m[1],
|
|
284
|
-
m4 = m[4],
|
|
285
|
-
m5 = m[5];
|
|
286
|
-
|
|
287
|
-
m[4] = m4 + m0 * tanAng;
|
|
288
|
-
m[5] = m5 + m1 * tanAng;
|
|
289
|
-
|
|
290
|
-
$._matrixDirty = true;
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
$.applyMatrix = (...args) => {
|
|
294
|
-
let m;
|
|
295
|
-
if (args.length == 1) m = args[0];
|
|
296
|
-
else m = args;
|
|
297
|
-
|
|
298
|
-
if (m.length == 9) {
|
|
299
|
-
// convert 3x3 matrix to 4x4 matrix
|
|
300
|
-
m = [m[0], m[1], 0, m[2], m[3], m[4], 0, m[5], 0, 0, 1, 0, m[6], m[7], 0, m[8]];
|
|
301
|
-
} else if (m.length != 16) {
|
|
302
|
-
throw new Error('Matrix must be a 3x3 or 4x4 array.');
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// overwrite the current transformation matrix
|
|
306
|
-
matrix = m.slice();
|
|
307
|
-
$._matrixDirty = true;
|
|
308
|
-
};
|
|
309
|
-
|
|
310
|
-
// function to save the current matrix state if dirty
|
|
311
|
-
$._saveMatrix = () => {
|
|
312
|
-
transforms.set(matrix, matrices.length * MATRIX_SIZE);
|
|
313
|
-
$._matrixIndex = matrices.length;
|
|
314
|
-
matrices.push(matrix.slice());
|
|
315
|
-
$._matrixDirty = false;
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
// push the current matrix index onto the stack
|
|
319
|
-
$.pushMatrix = () => {
|
|
320
|
-
if ($._matrixDirty) $._saveMatrix();
|
|
321
|
-
matricesIndexStack.push($._matrixIndex);
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
$.popMatrix = () => {
|
|
325
|
-
if (!matricesIndexStack.length) {
|
|
326
|
-
return console.warn('Matrix index stack is empty!');
|
|
327
|
-
}
|
|
328
|
-
// pop the last matrix index and set it as the current matrix index
|
|
329
|
-
let idx = matricesIndexStack.pop();
|
|
330
|
-
matrix = matrices[idx].slice();
|
|
331
|
-
$._matrixIndex = idx;
|
|
332
|
-
$._matrixDirty = false;
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
$.push = () => {
|
|
336
|
-
$.pushMatrix();
|
|
337
|
-
$.pushStyles();
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
$.pop = () => {
|
|
341
|
-
$.popMatrix();
|
|
342
|
-
$.popStyles();
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
$._calcBox = (x, y, w, h, mode) => {
|
|
346
|
-
let hw = w / 2;
|
|
347
|
-
let hh = h / 2;
|
|
348
|
-
|
|
349
|
-
// left, right, top, bottom
|
|
350
|
-
let l, r, t, b;
|
|
351
|
-
if (!mode || mode == 'corner') {
|
|
352
|
-
l = x;
|
|
353
|
-
r = x + w;
|
|
354
|
-
t = -y;
|
|
355
|
-
b = -(y + h);
|
|
356
|
-
} else if (mode == 'center') {
|
|
357
|
-
l = x - hw;
|
|
358
|
-
r = x + hw;
|
|
359
|
-
t = -(y - hh);
|
|
360
|
-
b = -(y + hh);
|
|
361
|
-
} else {
|
|
362
|
-
// CORNERS
|
|
363
|
-
l = x;
|
|
364
|
-
r = w;
|
|
365
|
-
t = -y;
|
|
366
|
-
b = -h;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
return [l, r, t, b];
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
// prettier-ignore
|
|
373
|
-
let blendFactors = [
|
|
374
|
-
'zero', // 0
|
|
375
|
-
'one', // 1
|
|
376
|
-
'src-alpha', // 2
|
|
377
|
-
'one-minus-src-alpha', // 3
|
|
378
|
-
'dst', // 4
|
|
379
|
-
'dst-alpha', // 5
|
|
380
|
-
'one-minus-dst-alpha', // 6
|
|
381
|
-
'one-minus-src' // 7
|
|
382
|
-
];
|
|
383
|
-
let blendOps = [
|
|
384
|
-
'add', // 0
|
|
385
|
-
'subtract', // 1
|
|
386
|
-
'reverse-subtract', // 2
|
|
387
|
-
'min', // 3
|
|
388
|
-
'max' // 4
|
|
389
|
-
];
|
|
390
|
-
|
|
391
|
-
// other blend modes are not supported yet
|
|
392
|
-
const blendModes = {
|
|
393
|
-
normal: [2, 3, 0, 2, 3, 0],
|
|
394
|
-
// destination_over: [6, 1, 0, 6, 1, 0],
|
|
395
|
-
additive: [1, 1, 0, 1, 1, 0]
|
|
396
|
-
// source_in: [5, 0, 0, 5, 0, 0],
|
|
397
|
-
// destination_in: [0, 2, 0, 0, 2, 0],
|
|
398
|
-
// source_out: [6, 0, 0, 6, 0, 0],
|
|
399
|
-
// destination_out: [0, 3, 0, 0, 3, 0],
|
|
400
|
-
// source_atop: [5, 3, 0, 5, 3, 0],
|
|
401
|
-
// destination_atop: [6, 2, 0, 6, 2, 0]
|
|
402
|
-
};
|
|
403
|
-
|
|
404
|
-
$.blendConfigs = {};
|
|
405
|
-
|
|
406
|
-
for (const [name, mode] of Object.entries(blendModes)) {
|
|
407
|
-
$.blendConfigs[name] = {
|
|
408
|
-
color: {
|
|
409
|
-
srcFactor: blendFactors[mode[0]],
|
|
410
|
-
dstFactor: blendFactors[mode[1]],
|
|
411
|
-
operation: blendOps[mode[2]]
|
|
412
|
-
},
|
|
413
|
-
alpha: {
|
|
414
|
-
srcFactor: blendFactors[mode[3]],
|
|
415
|
-
dstFactor: blendFactors[mode[4]],
|
|
416
|
-
operation: blendOps[mode[5]]
|
|
417
|
-
}
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
$._blendMode = 'normal';
|
|
422
|
-
|
|
423
|
-
$.blendMode = (mode) => {
|
|
424
|
-
if (mode == $._blendMode) return;
|
|
425
|
-
if (mode == 'source-over') mode = 'normal';
|
|
426
|
-
if (mode == 'lighter') mode = 'additive';
|
|
427
|
-
mode = mode.toLowerCase().replace(/[ -]/g, '_');
|
|
428
|
-
$._blendMode = mode;
|
|
429
|
-
|
|
430
|
-
for (let i = 0; i < $._pipelines.length; i++) {
|
|
431
|
-
$._pipelineConfigs[i].fragment.targets[0].blend = $.blendConfigs[mode];
|
|
432
|
-
$._pipelines[i] = Q5.device.createRenderPipeline($._pipelineConfigs[i]);
|
|
433
|
-
}
|
|
434
|
-
};
|
|
435
|
-
|
|
436
|
-
$.clear = () => {};
|
|
437
|
-
|
|
438
|
-
$._beginRender = () => {
|
|
439
|
-
$.encoder = Q5.device.createCommandEncoder();
|
|
440
|
-
|
|
441
|
-
pass = q.pass = $.encoder.beginRenderPass({
|
|
442
|
-
label: 'q5-webgpu',
|
|
443
|
-
colorAttachments: [
|
|
444
|
-
{
|
|
445
|
-
view: mainView,
|
|
446
|
-
resolveTarget: $.ctx.getCurrentTexture().createView(),
|
|
447
|
-
loadOp: 'clear',
|
|
448
|
-
storeOp: 'store',
|
|
449
|
-
clearValue: [0, 0, 0, 0]
|
|
450
|
-
}
|
|
451
|
-
]
|
|
452
|
-
});
|
|
453
|
-
};
|
|
454
|
-
|
|
455
|
-
$._render = () => {
|
|
456
|
-
let transformBuffer = Q5.device.createBuffer({
|
|
457
|
-
size: matrices.length * MATRIX_SIZE * 4, // 4 bytes per float
|
|
458
|
-
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
459
|
-
mappedAtCreation: true
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
new Float32Array(transformBuffer.getMappedRange()).set(transforms.slice(0, matrices.length * MATRIX_SIZE));
|
|
463
|
-
transformBuffer.unmap();
|
|
464
|
-
|
|
465
|
-
let colorsBuffer = Q5.device.createBuffer({
|
|
466
|
-
size: colorStackIndex * 4,
|
|
467
|
-
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
468
|
-
mappedAtCreation: true
|
|
469
|
-
});
|
|
470
|
-
|
|
471
|
-
new Float32Array(colorsBuffer.getMappedRange()).set(colorStack.slice(0, colorStackIndex));
|
|
472
|
-
colorsBuffer.unmap();
|
|
473
|
-
|
|
474
|
-
let mainBindGroup = Q5.device.createBindGroup({
|
|
475
|
-
layout: mainLayout,
|
|
476
|
-
entries: [
|
|
477
|
-
{ binding: 0, resource: { buffer: uniformBuffer } },
|
|
478
|
-
{ binding: 1, resource: { buffer: transformBuffer } },
|
|
479
|
-
{ binding: 2, resource: { buffer: colorsBuffer } }
|
|
480
|
-
]
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
pass.setBindGroup(0, mainBindGroup);
|
|
484
|
-
|
|
485
|
-
for (let m of $._hooks.preRender) m();
|
|
486
|
-
|
|
487
|
-
let drawVertOffset = 0,
|
|
488
|
-
imageVertOffset = 0,
|
|
489
|
-
textCharOffset = 0,
|
|
490
|
-
curPipelineIndex = -1;
|
|
491
|
-
|
|
492
|
-
for (let i = 0; i < drawStack.length; i += 2) {
|
|
493
|
-
let v = drawStack[i + 1];
|
|
494
|
-
|
|
495
|
-
if (curPipelineIndex != drawStack[i]) {
|
|
496
|
-
curPipelineIndex = drawStack[i];
|
|
497
|
-
pass.setPipeline($._pipelines[curPipelineIndex]);
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
if (curPipelineIndex == 0) {
|
|
501
|
-
// draw shapes
|
|
502
|
-
// v is the number of vertices
|
|
503
|
-
pass.draw(v, 1, drawVertOffset);
|
|
504
|
-
drawVertOffset += v;
|
|
505
|
-
} else if (curPipelineIndex == 1) {
|
|
506
|
-
// draw images
|
|
507
|
-
// v is the texture index
|
|
508
|
-
pass.setBindGroup(1, $._textureBindGroups[v]);
|
|
509
|
-
pass.draw(4, 1, imageVertOffset);
|
|
510
|
-
imageVertOffset += 4;
|
|
511
|
-
} else if (curPipelineIndex == 2) {
|
|
512
|
-
// draw text
|
|
513
|
-
let o = drawStack[i + 2];
|
|
514
|
-
pass.setBindGroup(1, $._fonts[o].bindGroup);
|
|
515
|
-
pass.setBindGroup(2, $._textBindGroup);
|
|
516
|
-
|
|
517
|
-
// v is the number of characters in the text
|
|
518
|
-
pass.draw(4, v, 0, textCharOffset);
|
|
519
|
-
textCharOffset += v;
|
|
520
|
-
i++;
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
};
|
|
524
|
-
|
|
525
|
-
$._finishRender = () => {
|
|
526
|
-
pass.end();
|
|
527
|
-
let commandBuffer = $.encoder.finish();
|
|
528
|
-
Q5.device.queue.submit([commandBuffer]);
|
|
529
|
-
|
|
530
|
-
q.pass = $.encoder = null;
|
|
531
|
-
|
|
532
|
-
// clear the stacks for the next frame
|
|
533
|
-
$.drawStack = drawStack = [];
|
|
534
|
-
colorIndex = 1;
|
|
535
|
-
colorStackIndex = 8;
|
|
536
|
-
matrices = [matrices[0]];
|
|
537
|
-
matricesIndexStack = [];
|
|
538
|
-
|
|
539
|
-
for (let m of $._hooks.postRender) m();
|
|
540
|
-
};
|
|
541
|
-
};
|
|
542
|
-
|
|
543
|
-
Q5.initWebGPU = async () => {
|
|
544
|
-
if (!navigator.gpu) {
|
|
545
|
-
console.warn('q5 WebGPU not supported on this browser! Use Google Chrome or Edge.');
|
|
546
|
-
return false;
|
|
547
|
-
}
|
|
548
|
-
if (!Q5.device) {
|
|
549
|
-
let adapter = await navigator.gpu.requestAdapter();
|
|
550
|
-
if (!adapter) {
|
|
551
|
-
console.warn('q5 WebGPU could not start! No appropriate GPUAdapter found, vulkan may need to be enabled.');
|
|
552
|
-
return false;
|
|
553
|
-
}
|
|
554
|
-
Q5.device = await adapter.requestDevice();
|
|
555
|
-
}
|
|
556
|
-
return true;
|
|
557
|
-
};
|
|
558
|
-
|
|
559
|
-
Q5.webgpu = async function (scope, parent) {
|
|
560
|
-
if (!scope || scope == 'global') Q5._hasGlobal = true;
|
|
561
|
-
if (!(await Q5.initWebGPU())) {
|
|
562
|
-
return new Q5(scope, parent, 'webgpu-fallback');
|
|
563
|
-
}
|
|
564
|
-
return new Q5(scope, parent, 'webgpu');
|
|
565
|
-
};
|