q5 2.12.10 → 2.13.1

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.
@@ -11,6 +11,9 @@ Q5.renderers.webgpu.canvas = ($, q) => {
11
11
  c.width = $.width = 500;
12
12
  c.height = $.height = 500;
13
13
 
14
+ // q2d graphics context
15
+ $._g = $.createGraphics(1, 1);
16
+
14
17
  if ($.colorMode) $.colorMode('rgb', 1);
15
18
 
16
19
  let pass,
@@ -146,7 +149,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
146
149
  };
147
150
 
148
151
  $._stroke = 0;
149
- $._fill = 1;
152
+ $._fill = $._tint = 1;
150
153
  $._doFill = $._doStroke = true;
151
154
 
152
155
  $.fill = (r, g, b, a) => {
@@ -159,42 +162,51 @@ Q5.renderers.webgpu.canvas = ($, q) => {
159
162
  $._doStroke = $._strokeSet = true;
160
163
  $._stroke = colorIndex;
161
164
  };
165
+ $.tint = (r, g, b, a) => {
166
+ addColor(r, g, b, a);
167
+ $._tint = colorIndex;
168
+ };
162
169
 
163
170
  $.noFill = () => ($._doFill = false);
164
171
  $.noStroke = () => ($._doStroke = false);
172
+ $.noTint = () => ($._tint = 1);
165
173
 
166
174
  $._strokeWeight = 1;
167
175
  $.strokeWeight = (v) => ($._strokeWeight = Math.abs(v));
168
176
 
169
- $.resetMatrix = () => {
170
- // initialize the transformation matrix as 4x4 identity matrix
171
-
172
- // prettier-ignore
173
- $._matrix = [
174
- 1, 0, 0, 0,
175
- 0, 1, 0, 0,
176
- 0, 0, 1, 0,
177
- 0, 0, 0, 1
178
- ];
179
- $._transformIndex = 0;
180
- };
181
- $.resetMatrix();
177
+ const MAX_TRANSFORMS = 1e7, // or whatever maximum you need
178
+ MATRIX_SIZE = 16, // 4x4 matrix
179
+ transforms = new Float32Array(MAX_TRANSFORMS * MATRIX_SIZE),
180
+ matrices = [],
181
+ matricesIndexStack = [];
182
+ let matrix;
182
183
 
183
184
  // tracks if the matrix has been modified
184
185
  $._matrixDirty = false;
185
186
 
186
- // array to store transformation matrices for the render pass
187
- let transformStates = [$._matrix.slice()];
187
+ // initialize with a 4x4 identity matrix
188
+ // prettier-ignore
189
+ matrices.push([
190
+ 1, 0, 0, 0,
191
+ 0, 1, 0, 0,
192
+ 0, 0, 1, 0,
193
+ 0, 0, 0, 1
194
+ ]);
195
+
196
+ transforms.set(matrices[0]);
188
197
 
189
- // stack to keep track of transformation matrix indexes
190
- $._transformIndexStack = [];
198
+ $.resetMatrix = () => {
199
+ matrix = matrices[0].slice();
200
+ $._matrixIndex = 0;
201
+ };
202
+ $.resetMatrix();
191
203
 
192
204
  $.translate = (x, y, z) => {
193
205
  if (!x && !y && !z) return;
194
206
  // update the translation values
195
- $._matrix[12] += x;
196
- $._matrix[13] -= y;
197
- $._matrix[14] += z || 0;
207
+ matrix[12] += x;
208
+ matrix[13] -= y;
209
+ matrix[14] += z || 0;
198
210
  $._matrixDirty = true;
199
211
  };
200
212
 
@@ -205,7 +217,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
205
217
  let cosR = Math.cos(a);
206
218
  let sinR = Math.sin(a);
207
219
 
208
- let m = $._matrix;
220
+ let m = matrix;
209
221
 
210
222
  let m0 = m[0],
211
223
  m1 = m[1],
@@ -232,7 +244,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
232
244
  $.scale = (x = 1, y, z = 1) => {
233
245
  y ??= x;
234
246
 
235
- let m = $._matrix;
247
+ let m = matrix;
236
248
 
237
249
  m[0] *= x;
238
250
  m[1] *= x;
@@ -256,13 +268,13 @@ Q5.renderers.webgpu.canvas = ($, q) => {
256
268
 
257
269
  let tanAng = Math.tan(ang);
258
270
 
259
- let m0 = $._matrix[0],
260
- m1 = $._matrix[1],
261
- m4 = $._matrix[4],
262
- m5 = $._matrix[5];
271
+ let m0 = matrix[0],
272
+ m1 = matrix[1],
273
+ m4 = matrix[4],
274
+ m5 = matrix[5];
263
275
 
264
- $._matrix[0] = m0 + m4 * tanAng;
265
- $._matrix[1] = m1 + m5 * tanAng;
276
+ matrix[0] = m0 + m4 * tanAng;
277
+ matrix[1] = m1 + m5 * tanAng;
266
278
 
267
279
  $._matrixDirty = true;
268
280
  };
@@ -273,13 +285,13 @@ Q5.renderers.webgpu.canvas = ($, q) => {
273
285
 
274
286
  let tanAng = Math.tan(ang);
275
287
 
276
- let m0 = $._matrix[0],
277
- m1 = $._matrix[1],
278
- m4 = $._matrix[4],
279
- m5 = $._matrix[5];
288
+ let m0 = matrix[0],
289
+ m1 = matrix[1],
290
+ m4 = matrix[4],
291
+ m5 = matrix[5];
280
292
 
281
- $._matrix[4] = m4 + m0 * tanAng;
282
- $._matrix[5] = m5 + m1 * tanAng;
293
+ matrix[4] = m4 + m0 * tanAng;
294
+ matrix[5] = m5 + m1 * tanAng;
283
295
 
284
296
  $._matrixDirty = true;
285
297
  };
@@ -297,31 +309,32 @@ Q5.renderers.webgpu.canvas = ($, q) => {
297
309
  }
298
310
 
299
311
  // overwrite the current transformation matrix
300
- $._matrix = m.slice();
312
+ matrix = m.slice();
301
313
  $._matrixDirty = true;
302
314
  };
303
315
 
304
316
  // function to save the current matrix state if dirty
305
317
  $._saveMatrix = () => {
306
- transformStates.push($._matrix.slice());
307
- $._transformIndex = transformStates.length - 1;
318
+ transforms.set(matrix, matrices.length * MATRIX_SIZE);
319
+ $._matrixIndex = matrices.length;
320
+ matrices.push(matrix.slice());
308
321
  $._matrixDirty = false;
309
322
  };
310
323
 
311
324
  // push the current matrix index onto the stack
312
325
  $.pushMatrix = () => {
313
326
  if ($._matrixDirty) $._saveMatrix();
314
- $._transformIndexStack.push($._transformIndex);
327
+ matricesIndexStack.push($._matrixIndex);
315
328
  };
316
329
 
317
330
  $.popMatrix = () => {
318
- if (!$._transformIndexStack.length) {
331
+ if (!matricesIndexStack.length) {
319
332
  return console.warn('Matrix index stack is empty!');
320
333
  }
321
334
  // pop the last matrix index and set it as the current matrix index
322
- let idx = $._transformIndexStack.pop();
323
- $._matrix = transformStates[idx].slice();
324
- $._transformIndex = idx;
335
+ let idx = matricesIndexStack.pop();
336
+ matrix = matrices[idx].slice();
337
+ $._matrixIndex = idx;
325
338
  $._matrixDirty = false;
326
339
  };
327
340
 
@@ -446,14 +459,14 @@ Q5.renderers.webgpu.canvas = ($, q) => {
446
459
  };
447
460
 
448
461
  $._render = () => {
449
- if (transformStates.length > 1 || !$._transformBindGroup) {
462
+ if (matrices.length > 1 || !$._transformBindGroup) {
450
463
  let transformBuffer = Q5.device.createBuffer({
451
- size: transformStates.length * 64, // 64 is the size of 16 floats
464
+ size: matrices.length * MATRIX_SIZE * 4, // 4 bytes per float
452
465
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
453
466
  mappedAtCreation: true
454
467
  });
455
468
 
456
- new Float32Array(transformBuffer.getMappedRange()).set(transformStates.flat());
469
+ new Float32Array(transformBuffer.getMappedRange()).set(transforms.slice(0, matrices.length * MATRIX_SIZE));
457
470
  transformBuffer.unmap();
458
471
 
459
472
  $._transformBindGroup = Q5.device.createBindGroup({
@@ -481,7 +494,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
481
494
  entries: [{ binding: 0, resource: { buffer: colorsBuffer } }]
482
495
  });
483
496
 
484
- $.pass.setBindGroup(1, $._colorsBindGroup);
497
+ pass.setBindGroup(1, $._colorsBindGroup);
485
498
 
486
499
  for (let m of $._hooks.preRender) m();
487
500
 
@@ -505,6 +518,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
505
518
  pass.draw(v, 1, drawVertOffset);
506
519
  drawVertOffset += v;
507
520
  } else if (curPipelineIndex == 1) {
521
+ // let vertCount = drawStack[i + 2];
508
522
  // draw images
509
523
  if (curTextureIndex != v) {
510
524
  // v is the texture index
@@ -512,6 +526,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
512
526
  }
513
527
  pass.draw(4, 1, imageVertOffset);
514
528
  imageVertOffset += 4;
529
+ // i++;
515
530
  } else if (curPipelineIndex == 2) {
516
531
  // draw text
517
532
  let o = drawStack[i + 2];
@@ -540,8 +555,9 @@ Q5.renderers.webgpu.canvas = ($, q) => {
540
555
  colorIndex = 1;
541
556
  colorStackIndex = 8;
542
557
  rotation = 0;
543
- transformStates.length = 1;
544
- $._transformIndexStack.length = 0;
558
+ transforms.length = MATRIX_SIZE;
559
+ matrices.length = 1;
560
+ matricesIndexStack.length = 0;
545
561
  };
546
562
  };
547
563
 
@@ -552,7 +568,10 @@ Q5.initWebGPU = async () => {
552
568
  }
553
569
  if (!Q5.device) {
554
570
  let adapter = await navigator.gpu.requestAdapter();
555
- if (!adapter) throw new Error('No appropriate GPUAdapter found.');
571
+ if (!adapter) {
572
+ console.warn('q5 WebGPU could not start! No appropriate GPUAdapter found, vulkan may need to be enabled.');
573
+ return false;
574
+ }
556
575
  Q5.device = await adapter.requestDevice();
557
576
  }
558
577
  return true;
@@ -10,7 +10,7 @@ Q5.renderers.webgpu.drawing = ($, q) => {
10
10
  struct VertexInput {
11
11
  @location(0) pos: vec2f,
12
12
  @location(1) colorIndex: f32,
13
- @location(2) transformIndex: f32
13
+ @location(2) matrixIndex: f32
14
14
  }
15
15
  struct VertexOutput {
16
16
  @builtin(position) position: vec4f,
@@ -29,7 +29,7 @@ struct Uniforms {
29
29
  @vertex
30
30
  fn vertexMain(input: VertexInput) -> VertexOutput {
31
31
  var vert = vec4f(input.pos, 0.0, 1.0);
32
- vert = transforms[i32(input.transformIndex)] * vert;
32
+ vert = transforms[i32(input.matrixIndex)] * vert;
33
33
  vert.x /= uniforms.halfWidth;
34
34
  vert.y /= uniforms.halfHeight;
35
35
 
@@ -56,7 +56,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
56
56
  attributes: [
57
57
  { format: 'float32x2', offset: 0, shaderLocation: 0 }, // position
58
58
  { format: 'float32', offset: 8, shaderLocation: 1 }, // colorIndex
59
- { format: 'float32', offset: 12, shaderLocation: 2 } // transformIndex
59
+ { format: 'float32', offset: 12, shaderLocation: 2 } // matrixIndex
60
60
  ]
61
61
  };
62
62
 
@@ -210,7 +210,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
210
210
  let [l, r, t, b] = $._calcBox(x, y, w, h, $._rectMode);
211
211
  let ci, ti;
212
212
  if ($._matrixDirty) $._saveMatrix();
213
- ti = $._transformIndex;
213
+ ti = $._matrixIndex;
214
214
 
215
215
  if ($._doFill) {
216
216
  ci = $._fill;
@@ -284,7 +284,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
284
284
  let b = w == h ? a : Math.max(h, 1) / 2;
285
285
 
286
286
  if ($._matrixDirty) $._saveMatrix();
287
- let ti = $._transformIndex;
287
+ let ti = $._matrixIndex;
288
288
 
289
289
  if ($._doFill) {
290
290
  addEllipse(x, y, a, b, n, $._fill, ti);
@@ -300,7 +300,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
300
300
 
301
301
  $.point = (x, y) => {
302
302
  if ($._matrixDirty) $._saveMatrix();
303
- let ti = $._transformIndex,
303
+ let ti = $._matrixIndex,
304
304
  ci = $._stroke,
305
305
  sw = $._strokeWeight;
306
306
 
@@ -320,7 +320,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
320
320
 
321
321
  $.line = (x1, y1, x2, y2) => {
322
322
  if ($._matrixDirty) $._saveMatrix();
323
- let ti = $._transformIndex,
323
+ let ti = $._matrixIndex,
324
324
  ci = $._stroke,
325
325
  sw = $._strokeWeight,
326
326
  hsw = sw / 2;
@@ -355,7 +355,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
355
355
 
356
356
  $.vertex = (x, y) => {
357
357
  if ($._matrixDirty) $._saveMatrix();
358
- sv.push(x, -y, $._fill, $._transformIndex);
358
+ sv.push(x, -y, $._fill, $._matrixIndex);
359
359
  shapeVertCount++;
360
360
  };
361
361
 
@@ -400,7 +400,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
400
400
  (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 +
401
401
  (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3);
402
402
 
403
- sv.push(x, y, $._fill, $._transformIndex);
403
+ sv.push(x, y, $._fill, $._matrixIndex);
404
404
  shapeVertCount++;
405
405
  }
406
406
  }
@@ -1,13 +1,21 @@
1
1
  Q5.renderers.webgpu.image = ($, q) => {
2
2
  $._textureBindGroups = [];
3
- let vertexStack = [];
3
+ let vertexStack = new Float32Array(1e7),
4
+ vertIndex = 0;
4
5
 
5
- let vertexShader = Q5.device.createShaderModule({
6
- label: 'imageVertexShader',
6
+ let imageShader = Q5.device.createShaderModule({
7
+ label: 'imageShader',
7
8
  code: `
9
+ struct VertexInput {
10
+ @location(0) pos: vec2f,
11
+ @location(1) texCoord: vec2f,
12
+ @location(2) tintIndex: f32,
13
+ @location(3) matrixIndex: f32
14
+ }
8
15
  struct VertexOutput {
9
16
  @builtin(position) position: vec4f,
10
- @location(0) texCoord: vec2f
17
+ @location(0) texCoord: vec2f,
18
+ @location(1) tintIndex: f32
11
19
  }
12
20
  struct Uniforms {
13
21
  halfWidth: f32,
@@ -17,31 +25,33 @@ struct Uniforms {
17
25
  @group(0) @binding(0) var<uniform> uniforms: Uniforms;
18
26
  @group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;
19
27
 
28
+ @group(1) @binding(0) var<storage> colors : array<vec4f>;
29
+
30
+ @group(2) @binding(0) var samp: sampler;
31
+ @group(2) @binding(1) var texture: texture_2d<f32>;
32
+
20
33
  @vertex
21
- fn vertexMain(@location(0) pos: vec2f, @location(1) texCoord: vec2f, @location(2) transformIndex: f32) -> VertexOutput {
22
- var vert = vec4f(pos, 0.0, 1.0);
23
- vert = transforms[i32(transformIndex)] * vert;
34
+ fn vertexMain(input: VertexInput) -> VertexOutput {
35
+ var vert = vec4f(input.pos, 0.0, 1.0);
36
+ vert = transforms[i32(input.matrixIndex)] * vert;
24
37
  vert.x /= uniforms.halfWidth;
25
38
  vert.y /= uniforms.halfHeight;
26
39
 
27
40
  var output: VertexOutput;
28
41
  output.position = vert;
29
- output.texCoord = texCoord;
42
+ output.texCoord = input.texCoord;
43
+ output.tintIndex = input.tintIndex;
30
44
  return output;
31
45
  }
32
- `
33
- });
34
-
35
- let fragmentShader = Q5.device.createShaderModule({
36
- label: 'imageFragmentShader',
37
- code: `
38
- @group(2) @binding(0) var samp: sampler;
39
- @group(2) @binding(1) var texture: texture_2d<f32>;
40
46
 
41
47
  @fragment
42
- fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
43
- // Sample the texture using the interpolated texture coordinate
44
- return textureSample(texture, samp, texCoord);
48
+ fn fragmentMain(@location(0) texCoord: vec2f, @location(1) tintIndex: f32) -> @location(0) vec4f {
49
+ let texColor = textureSample(texture, samp, texCoord);
50
+ let tintColor = colors[i32(tintIndex)];
51
+
52
+ // Mix original and tinted colors using tint alpha as blend factor
53
+ let tinted = vec4f(texColor.rgb * tintColor.rgb, texColor.a);
54
+ return mix(texColor, tinted, tintColor.a);
45
55
  }
46
56
  `
47
57
  });
@@ -63,11 +73,12 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
63
73
  });
64
74
 
65
75
  const vertexBufferLayout = {
66
- arrayStride: 20,
76
+ arrayStride: 24,
67
77
  attributes: [
68
78
  { shaderLocation: 0, offset: 0, format: 'float32x2' },
69
79
  { shaderLocation: 1, offset: 8, format: 'float32x2' },
70
- { shaderLocation: 2, offset: 16, format: 'float32' } // transformIndex
80
+ { shaderLocation: 2, offset: 16, format: 'float32' }, // tintIndex
81
+ { shaderLocation: 3, offset: 20, format: 'float32' } // matrixIndex
71
82
  ]
72
83
  };
73
84
 
@@ -80,12 +91,12 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
80
91
  label: 'imagePipeline',
81
92
  layout: pipelineLayout,
82
93
  vertex: {
83
- module: vertexShader,
94
+ module: imageShader,
84
95
  entryPoint: 'vertexMain',
85
96
  buffers: [{ arrayStride: 0, attributes: [] }, vertexBufferLayout]
86
97
  },
87
98
  fragment: {
88
- module: fragmentShader,
99
+ module: imageShader,
89
100
  entryPoint: 'fragmentMain',
90
101
  targets: [{ format: 'bgra8unorm', blend: $.blendConfigs.normal }]
91
102
  },
@@ -161,58 +172,63 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
161
172
 
162
173
  $.loadImage = (src, cb) => {
163
174
  q._preloadCount++;
164
- const img = new Image();
165
- img.crossOrigin = 'Anonymous';
166
- img.onload = () => {
167
- // calculate the default width and height that the image
168
- // should be drawn at if the user doesn't specify a display size
169
- img.defaultWidth = img.width * $._defaultImageScale;
170
- img.defaultHeight = img.height * $._defaultImageScale;
171
- img.pixelDensity = 1;
172
-
175
+ let g = $._g.loadImage(src, (img) => {
176
+ g.defaultWidth = img.width * $._defaultImageScale;
177
+ g.defaultHeight = img.height * $._defaultImageScale;
173
178
  $._createTexture(img);
174
179
  q._preloadCount--;
175
180
  if (cb) cb(img);
176
- };
177
- img.src = src;
178
- return img;
181
+ });
182
+ return g;
179
183
  };
180
184
 
181
185
  $.imageMode = (x) => ($._imageMode = x);
182
186
 
183
- $.image = (img, dx, dy, dw, dh, sx = 0, sy = 0, sw, sh) => {
187
+ const addVert = (x, y, u, v, ci, ti) => {
188
+ let s = vertexStack,
189
+ i = vertIndex;
190
+ s[i++] = x;
191
+ s[i++] = y;
192
+ s[i++] = u;
193
+ s[i++] = v;
194
+ s[i++] = ci;
195
+ s[i++] = ti;
196
+ vertIndex = i;
197
+ };
198
+
199
+ $.image = (img, dx = 0, dy = 0, dw, dh, sx = 0, sy = 0, sw, sh) => {
200
+ let g = img;
184
201
  if (img.canvas) img = img.canvas;
185
202
  if (img.textureIndex == undefined) return;
186
203
 
187
204
  if ($._matrixDirty) $._saveMatrix();
188
- let ti = $._transformIndex;
189
205
 
190
- let w = img.width;
191
- let h = img.height;
206
+ let ti = $._matrixIndex,
207
+ w = img.width,
208
+ h = img.height;
192
209
 
193
- dw ??= img.defaultWidth;
194
- dh ??= img.defaultHeight;
210
+ dw ??= g.defaultWidth;
211
+ dh ??= g.defaultHeight;
195
212
  sw ??= w;
196
213
  sh ??= h;
197
214
 
198
- let pd = img.pixelDensity || 1;
215
+ let pd = g._pixelDensity || 1;
199
216
  dw *= pd;
200
217
  dh *= pd;
201
218
 
202
219
  let [l, r, t, b] = $._calcBox(dx, dy, dw, dh, $._imageMode);
203
220
 
204
- let u0 = sx / w;
205
- let v0 = sy / h;
206
- let u1 = (sx + sw) / w;
207
- let v1 = (sy + sh) / h;
208
-
209
- // prettier-ignore
210
- vertexStack.push(
211
- l, t, u0, v0, ti,
212
- r, t, u1, v0, ti,
213
- l, b, u0, v1, ti,
214
- r, b, u1, v1, ti
215
- );
221
+ let u0 = sx / w,
222
+ v0 = sy / h,
223
+ u1 = (sx + sw) / w,
224
+ v1 = (sy + sh) / h;
225
+
226
+ let ci = $._tint;
227
+
228
+ addVert(l, t, u0, v0, ci, ti);
229
+ addVert(r, t, u1, v0, ci, ti);
230
+ addVert(l, b, u0, v1, ci, ti);
231
+ addVert(r, b, u1, v1, ci, ti);
216
232
 
217
233
  $.drawStack.push(1, img.textureIndex);
218
234
  };
@@ -223,20 +239,20 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
223
239
  // Switch to image pipeline
224
240
  $.pass.setPipeline($._pipelines[1]);
225
241
 
226
- const vertexBuffer = Q5.device.createBuffer({
227
- size: vertexStack.length * 4,
242
+ let vertexBuffer = Q5.device.createBuffer({
243
+ size: vertIndex * 4,
228
244
  usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
229
245
  mappedAtCreation: true
230
246
  });
231
247
 
232
- new Float32Array(vertexBuffer.getMappedRange()).set(vertexStack);
248
+ new Float32Array(vertexBuffer.getMappedRange()).set(vertexStack.slice(0, vertIndex));
233
249
  vertexBuffer.unmap();
234
250
 
235
251
  $.pass.setVertexBuffer(1, vertexBuffer);
236
252
  });
237
253
 
238
254
  $._hooks.postRender.push(() => {
239
- vertexStack.length = 0;
255
+ vertIndex = 0;
240
256
  });
241
257
  };
242
258
 
@@ -23,7 +23,7 @@ struct Char {
23
23
  struct Text {
24
24
  pos: vec2f,
25
25
  scale: f32,
26
- transformIndex: f32,
26
+ matrixIndex: f32,
27
27
  fillIndex: f32,
28
28
  strokeIndex: f32
29
29
  }
@@ -55,7 +55,7 @@ fn vertexMain(input : VertexInput) -> VertexOutput {
55
55
  let charPos = ((pos[input.vertex] * fontChar.size + char.xy + fontChar.offset) * text.scale) + text.pos;
56
56
 
57
57
  var vert = vec4f(charPos, 0.0, 1.0);
58
- vert = transforms[i32(text.transformIndex)] * vert;
58
+ vert = transforms[i32(text.matrixIndex)] * vert;
59
59
  vert.x /= uniforms.halfWidth;
60
60
  vert.y /= uniforms.halfHeight;
61
61
 
@@ -279,13 +279,11 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
279
279
  if (cb) cb(fontName);
280
280
  };
281
281
 
282
- // q2d graphics context to use for text image creation
283
- let g = $.createGraphics(1, 1);
284
- g.colorMode($.RGB, 1);
282
+ $._g.colorMode($.RGB, 1);
285
283
 
286
284
  $.loadFont = (url, cb) => {
287
285
  let ext = url.slice(url.lastIndexOf('.') + 1);
288
- if (ext != 'json') return g.loadFont(url, cb);
286
+ if (ext != 'json') return $._g.loadFont(url, cb);
289
287
  let fontName = url.slice(url.lastIndexOf('/') + 1, url.lastIndexOf('-'));
290
288
  createFont(url, fontName, cb);
291
289
  return fontName;
@@ -470,7 +468,7 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
470
468
  text[0] = x;
471
469
  text[1] = -y;
472
470
  text[2] = $._textSize / 44;
473
- text[3] = $._transformIndex;
471
+ text[3] = $._matrixIndex;
474
472
  text[4] = $._fillSet ? $._fill : 0;
475
473
  text[5] = $._stroke;
476
474
 
@@ -484,18 +482,18 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
484
482
  };
485
483
 
486
484
  $.createTextImage = (str, w, h) => {
487
- g.textSize($._textSize);
485
+ $._g.textSize($._textSize);
488
486
 
489
487
  if ($._doFill) {
490
488
  let fi = $._fill * 4;
491
- g.fill(colorStack.slice(fi, fi + 4));
489
+ $._g.fill(colorStack.slice(fi, fi + 4));
492
490
  }
493
491
  if ($._doStroke) {
494
492
  let si = $._stroke * 4;
495
- g.stroke(colorStack.slice(si, si + 4));
493
+ $._g.stroke(colorStack.slice(si, si + 4));
496
494
  }
497
495
 
498
- let img = g.createTextImage(str, w, h);
496
+ let img = $._g.createTextImage(str, w, h);
499
497
 
500
498
  if (img.canvas.textureIndex == undefined) {
501
499
  $._createTexture(img);