@swf2es/render 0.1.18 → 0.1.20
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/dist/webgl/atlas.d.ts +14 -1
- package/dist/webgl/atlas.d.ts.map +1 -1
- package/dist/webgl/atlas.js +119 -28
- package/dist/webgl/atlas.js.map +1 -1
- package/dist/webgl/batches.d.ts +68 -18
- package/dist/webgl/batches.d.ts.map +1 -1
- package/dist/webgl/batches.js +252 -63
- package/dist/webgl/batches.js.map +1 -1
- package/dist/webgl/draws.d.ts +26 -8
- package/dist/webgl/draws.d.ts.map +1 -1
- package/dist/webgl/draws.js +92 -36
- package/dist/webgl/draws.js.map +1 -1
- package/dist/webgl/programs.d.ts +10 -3
- package/dist/webgl/programs.d.ts.map +1 -1
- package/dist/webgl/programs.js +13 -5
- package/dist/webgl/programs.js.map +1 -1
- package/package.json +2 -2
- package/src/webgl/atlas.ts +149 -27
- package/src/webgl/batches.ts +316 -68
- package/src/webgl/draws.ts +104 -40
- package/src/webgl/programs.ts +13 -5
package/src/webgl/atlas.ts
CHANGED
|
@@ -24,6 +24,48 @@ const GLYPHS_LEAST = 1024;
|
|
|
24
24
|
const LEAST = 1 << 16;
|
|
25
25
|
/** Holes past which, and past the live vertices, the atlas is packed again. */
|
|
26
26
|
const SLACK = 1 << 16;
|
|
27
|
+
/**
|
|
28
|
+
* The vertices, and the indices, staged before an upload: geometries placed
|
|
29
|
+
* one after another go to the GPU in one call for each buffer, not two a
|
|
30
|
+
* geometry, which shapes drawn anew each frame paid for some thousand times
|
|
31
|
+
* a frame. A geometry larger than the staging is uploaded from its own copy.
|
|
32
|
+
*/
|
|
33
|
+
const STAGED_VERTICES = 1 << 14;
|
|
34
|
+
const STAGED_INDICES = 1 << 16;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* `data`'s `count` vertices interleaved into `floats` from float `at`, `words` the same bytes:
|
|
38
|
+
* a position, a texel or zeros, then the colour's bytes or a mesh's depth.
|
|
39
|
+
*/
|
|
40
|
+
function interleave(
|
|
41
|
+
data: GeometryData,
|
|
42
|
+
count: number,
|
|
43
|
+
floats: Float32Array,
|
|
44
|
+
words: Uint32Array,
|
|
45
|
+
at: number,
|
|
46
|
+
): void {
|
|
47
|
+
const positions = data.positions;
|
|
48
|
+
const texels = data.texels;
|
|
49
|
+
const depths = data.depths;
|
|
50
|
+
const colors = data.colors;
|
|
51
|
+
for (let i = 0; i < count; i++, at += 5) {
|
|
52
|
+
floats[at] = positions[i * 2];
|
|
53
|
+
floats[at + 1] = positions[i * 2 + 1];
|
|
54
|
+
if (texels) {
|
|
55
|
+
floats[at + 2] = texels[i * 2];
|
|
56
|
+
floats[at + 3] = texels[i * 2 + 1];
|
|
57
|
+
} else {
|
|
58
|
+
floats[at + 2] = 0;
|
|
59
|
+
floats[at + 3] = 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (depths) {
|
|
63
|
+
floats[at + 4] = depths[i];
|
|
64
|
+
} else {
|
|
65
|
+
words[at + 4] = colors[i];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
27
69
|
|
|
28
70
|
/** Where a geometry lies in the atlas, or the glyph atlas with its text's mode and table. */
|
|
29
71
|
export interface Place {
|
|
@@ -58,6 +100,15 @@ export class GeometryAtlas {
|
|
|
58
100
|
private indexTop = 0;
|
|
59
101
|
private live = 0;
|
|
60
102
|
private holes = 0;
|
|
103
|
+
/** Vertices staged for the atlas from vertex `stagedVertexAt`, as floats and as words. */
|
|
104
|
+
private readonly stagedFloats = new Float32Array(STAGED_VERTICES * (VERTEX_BYTES / 4));
|
|
105
|
+
private readonly stagedWords = new Uint32Array(this.stagedFloats.buffer);
|
|
106
|
+
private stagedVertexAt = 0;
|
|
107
|
+
private stagedVertices = 0;
|
|
108
|
+
/** Indices staged for the atlas from index `stagedIndexAt`. */
|
|
109
|
+
private readonly stagedIndices = new Uint32Array(STAGED_INDICES);
|
|
110
|
+
private stagedIndexAt = 0;
|
|
111
|
+
private stagedIndexCount = 0;
|
|
61
112
|
places: (Place | null)[] = [];
|
|
62
113
|
glyphArray!: WebGLVertexArrayObject;
|
|
63
114
|
private glyphBuffer!: WebGLBuffer;
|
|
@@ -123,6 +174,8 @@ export class GeometryAtlas {
|
|
|
123
174
|
});
|
|
124
175
|
this.vertexCapacity = 0;
|
|
125
176
|
this.indexCapacity = 0;
|
|
177
|
+
this.stagedVertices = 0;
|
|
178
|
+
this.stagedIndexCount = 0;
|
|
126
179
|
this.places = [];
|
|
127
180
|
}
|
|
128
181
|
|
|
@@ -147,6 +200,13 @@ export class GeometryAtlas {
|
|
|
147
200
|
}
|
|
148
201
|
|
|
149
202
|
geometries.removed.length = 0;
|
|
203
|
+
// Nothing left in it: filled again from its start, in the buffers it has.
|
|
204
|
+
if (this.live === 0) {
|
|
205
|
+
this.vertexTop = 0;
|
|
206
|
+
this.indexTop = 0;
|
|
207
|
+
this.holes = 0;
|
|
208
|
+
}
|
|
209
|
+
|
|
150
210
|
// Changed in place: copied again where they lie, else as added.
|
|
151
211
|
for (const id of geometries.updated) {
|
|
152
212
|
const place = this.places[id];
|
|
@@ -211,6 +271,7 @@ export class GeometryAtlas {
|
|
|
211
271
|
}
|
|
212
272
|
|
|
213
273
|
geometries.added.length = 0;
|
|
274
|
+
this.flush();
|
|
214
275
|
}
|
|
215
276
|
|
|
216
277
|
/** Every live shape's geometry copied into new buffers, with room for twice what is live. */
|
|
@@ -233,6 +294,9 @@ export class GeometryAtlas {
|
|
|
233
294
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
234
295
|
gl.bufferData(gl.ARRAY_BUFFER, this.vertexCapacity * VERTEX_BYTES, gl.STATIC_DRAW);
|
|
235
296
|
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indexCapacity * 4, gl.STATIC_DRAW);
|
|
297
|
+
// What was staged for the buffers replaced is copied again below.
|
|
298
|
+
this.stagedVertices = 0;
|
|
299
|
+
this.stagedIndexCount = 0;
|
|
236
300
|
this.vertexTop = 0;
|
|
237
301
|
this.indexTop = 0;
|
|
238
302
|
this.live = 0;
|
|
@@ -243,6 +307,8 @@ export class GeometryAtlas {
|
|
|
243
307
|
this.copyIn(id, data);
|
|
244
308
|
}
|
|
245
309
|
}
|
|
310
|
+
|
|
311
|
+
this.flush();
|
|
246
312
|
}
|
|
247
313
|
|
|
248
314
|
/** Every live text's quads copied into new glyph buffers: none till a text needs them. */
|
|
@@ -285,54 +351,110 @@ export class GeometryAtlas {
|
|
|
285
351
|
return;
|
|
286
352
|
}
|
|
287
353
|
|
|
288
|
-
const gl = this.gl;
|
|
289
354
|
const count = data.positions.length / 2;
|
|
290
355
|
const base = this.vertexTop;
|
|
291
356
|
this.copyVertices(data, base);
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
357
|
+
const source = data.indices;
|
|
358
|
+
const length = source.length;
|
|
359
|
+
if (length > STAGED_INDICES) {
|
|
360
|
+
const indices = new Uint32Array(length);
|
|
361
|
+
for (let i = 0; i < length; i++) {
|
|
362
|
+
indices[i] = source[i] + base;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
this.flushIndices();
|
|
366
|
+
this.state.bindVertexArray(this.vertexArray);
|
|
367
|
+
this.gl.bufferSubData(this.gl.ELEMENT_ARRAY_BUFFER, this.indexTop * 4, indices);
|
|
368
|
+
} else {
|
|
369
|
+
if (
|
|
370
|
+
this.stagedIndexCount + length > STAGED_INDICES ||
|
|
371
|
+
this.stagedIndexAt + this.stagedIndexCount !== this.indexTop
|
|
372
|
+
) {
|
|
373
|
+
this.flushIndices();
|
|
374
|
+
this.stagedIndexAt = this.indexTop;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const staged = this.stagedIndices;
|
|
378
|
+
const at = this.stagedIndexCount;
|
|
379
|
+
for (let i = 0; i < length; i++) {
|
|
380
|
+
staged[at + i] = source[i] + base;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
this.stagedIndexCount = at + length;
|
|
295
384
|
}
|
|
296
385
|
|
|
297
|
-
this.state.bindVertexArray(this.vertexArray);
|
|
298
|
-
gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, this.indexTop * 4, indices);
|
|
299
386
|
this.places[id] = {
|
|
300
387
|
vertexStart: base,
|
|
301
388
|
vertices: count,
|
|
302
389
|
indexStart: this.indexTop,
|
|
303
|
-
indices:
|
|
390
|
+
indices: length,
|
|
304
391
|
glyphs: null,
|
|
305
392
|
flat: data.flat === true,
|
|
306
393
|
batch: this.batch(data),
|
|
307
394
|
};
|
|
308
395
|
this.vertexTop += count;
|
|
309
|
-
this.indexTop +=
|
|
396
|
+
this.indexTop += length;
|
|
310
397
|
this.live += count;
|
|
311
398
|
}
|
|
312
399
|
|
|
313
|
-
/** `data`'s vertices interleaved
|
|
400
|
+
/** `data`'s vertices interleaved for the atlas from vertex `base`: staged, or uploaded if too many. */
|
|
314
401
|
private copyVertices(data: GeometryData, base: number): void {
|
|
315
|
-
const gl = this.gl;
|
|
316
402
|
const count = data.positions.length / 2;
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
floats[i * 5 + 1] = data.positions[i * 2 + 1];
|
|
325
|
-
floats[i * 5 + 2] = texels ? texels[i * 2] : 0;
|
|
326
|
-
floats[i * 5 + 3] = texels ? texels[i * 2 + 1] : 0;
|
|
327
|
-
if (depths) {
|
|
328
|
-
floats[i * 5 + 4] = depths[i];
|
|
329
|
-
} else {
|
|
330
|
-
words[i * 5 + 4] = data.colors[i];
|
|
331
|
-
}
|
|
403
|
+
if (count > STAGED_VERTICES) {
|
|
404
|
+
const floats = new Float32Array(count * (VERTEX_BYTES / 4));
|
|
405
|
+
interleave(data, count, floats, new Uint32Array(floats.buffer), 0);
|
|
406
|
+
this.flushVertices();
|
|
407
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
408
|
+
this.gl.bufferSubData(this.gl.ARRAY_BUFFER, base * VERTEX_BYTES, floats);
|
|
409
|
+
return;
|
|
332
410
|
}
|
|
333
411
|
|
|
334
|
-
|
|
335
|
-
|
|
412
|
+
if (
|
|
413
|
+
this.stagedVertices + count > STAGED_VERTICES ||
|
|
414
|
+
this.stagedVertexAt + this.stagedVertices !== base
|
|
415
|
+
) {
|
|
416
|
+
this.flushVertices();
|
|
417
|
+
this.stagedVertexAt = base;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
interleave(data, count, this.stagedFloats, this.stagedWords, this.stagedVertices * 5);
|
|
421
|
+
this.stagedVertices += count;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/** What is staged, uploaded: before anything draws from the atlas. */
|
|
425
|
+
private flush(): void {
|
|
426
|
+
this.flushVertices();
|
|
427
|
+
this.flushIndices();
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
private flushVertices(): void {
|
|
431
|
+
if (this.stagedVertices > 0) {
|
|
432
|
+
const gl = this.gl;
|
|
433
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
434
|
+
gl.bufferSubData(
|
|
435
|
+
gl.ARRAY_BUFFER,
|
|
436
|
+
this.stagedVertexAt * VERTEX_BYTES,
|
|
437
|
+
this.stagedFloats,
|
|
438
|
+
0,
|
|
439
|
+
this.stagedVertices * 5,
|
|
440
|
+
);
|
|
441
|
+
this.stagedVertices = 0;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
private flushIndices(): void {
|
|
446
|
+
if (this.stagedIndexCount > 0) {
|
|
447
|
+
const gl = this.gl;
|
|
448
|
+
this.state.bindVertexArray(this.vertexArray);
|
|
449
|
+
gl.bufferSubData(
|
|
450
|
+
gl.ELEMENT_ARRAY_BUFFER,
|
|
451
|
+
this.stagedIndexAt * 4,
|
|
452
|
+
this.stagedIndices,
|
|
453
|
+
0,
|
|
454
|
+
this.stagedIndexCount,
|
|
455
|
+
);
|
|
456
|
+
this.stagedIndexCount = 0;
|
|
457
|
+
}
|
|
336
458
|
}
|
|
337
459
|
|
|
338
460
|
private batch(data: GeometryData): Place["batch"] {
|