@swf2es/render 0.0.0-stage → 0.1.0
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/LICENSE +202 -0
- package/README.md +17 -2
- package/dist/commands.d.ts +67 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +93 -0
- package/dist/commands.js.map +1 -0
- package/dist/filter-plan.d.ts +110 -0
- package/dist/filter-plan.d.ts.map +1 -0
- package/dist/filter-plan.js +480 -0
- package/dist/filter-plan.js.map +1 -0
- package/dist/filter-shaders.d.ts +63 -0
- package/dist/filter-shaders.d.ts.map +1 -0
- package/dist/filter-shaders.js +350 -0
- package/dist/filter-shaders.js.map +1 -0
- package/dist/filters.d.ts +107 -0
- package/dist/filters.d.ts.map +1 -0
- package/dist/filters.js +187 -0
- package/dist/filters.js.map +1 -0
- package/dist/geometry.d.ts +83 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +93 -0
- package/dist/geometry.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/keeps.d.ts +17 -0
- package/dist/keeps.d.ts.map +1 -0
- package/dist/keeps.js +17 -0
- package/dist/keeps.js.map +1 -0
- package/dist/kernel-shaders.d.ts +74 -0
- package/dist/kernel-shaders.d.ts.map +1 -0
- package/dist/kernel-shaders.js +323 -0
- package/dist/kernel-shaders.js.map +1 -0
- package/dist/measure.d.ts +56 -0
- package/dist/measure.d.ts.map +1 -0
- package/dist/measure.js +287 -0
- package/dist/measure.js.map +1 -0
- package/dist/plan.d.ts +14 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +247 -0
- package/dist/plan.js.map +1 -0
- package/dist/registry.d.ts +49 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +87 -0
- package/dist/registry.js.map +1 -0
- package/dist/rows.d.ts +39 -0
- package/dist/rows.d.ts.map +1 -0
- package/dist/rows.js +60 -0
- package/dist/rows.js.map +1 -0
- package/dist/scene.d.ts +179 -0
- package/dist/scene.d.ts.map +1 -0
- package/dist/scene.js +265 -0
- package/dist/scene.js.map +1 -0
- package/dist/shelves.d.ts +23 -0
- package/dist/shelves.d.ts.map +1 -0
- package/dist/shelves.js +63 -0
- package/dist/shelves.js.map +1 -0
- package/dist/textures.d.ts +72 -0
- package/dist/textures.d.ts.map +1 -0
- package/dist/textures.js +160 -0
- package/dist/textures.js.map +1 -0
- package/dist/webgl/atlas.d.ts +63 -0
- package/dist/webgl/atlas.d.ts.map +1 -0
- package/dist/webgl/atlas.js +328 -0
- package/dist/webgl/atlas.js.map +1 -0
- package/dist/webgl/backend.d.ts +141 -0
- package/dist/webgl/backend.d.ts.map +1 -0
- package/dist/webgl/backend.js +659 -0
- package/dist/webgl/backend.js.map +1 -0
- package/dist/webgl/composite.d.ts +101 -0
- package/dist/webgl/composite.d.ts.map +1 -0
- package/dist/webgl/composite.js +293 -0
- package/dist/webgl/composite.js.map +1 -0
- package/dist/webgl/draws.d.ts +213 -0
- package/dist/webgl/draws.d.ts.map +1 -0
- package/dist/webgl/draws.js +714 -0
- package/dist/webgl/draws.js.map +1 -0
- package/dist/webgl/filters.d.ts +107 -0
- package/dist/webgl/filters.d.ts.map +1 -0
- package/dist/webgl/filters.js +351 -0
- package/dist/webgl/filters.js.map +1 -0
- package/dist/webgl/gpu-textures.d.ts +44 -0
- package/dist/webgl/gpu-textures.d.ts.map +1 -0
- package/dist/webgl/gpu-textures.js +178 -0
- package/dist/webgl/gpu-textures.js.map +1 -0
- package/dist/webgl/holds.d.ts +97 -0
- package/dist/webgl/holds.d.ts.map +1 -0
- package/dist/webgl/holds.js +453 -0
- package/dist/webgl/holds.js.map +1 -0
- package/dist/webgl/index.d.ts +2 -0
- package/dist/webgl/index.d.ts.map +1 -0
- package/dist/webgl/index.js +4 -0
- package/dist/webgl/index.js.map +1 -0
- package/dist/webgl/kernels.d.ts +64 -0
- package/dist/webgl/kernels.d.ts.map +1 -0
- package/dist/webgl/kernels.js +160 -0
- package/dist/webgl/kernels.js.map +1 -0
- package/dist/webgl/pool.d.ts +71 -0
- package/dist/webgl/pool.d.ts.map +1 -0
- package/dist/webgl/pool.js +192 -0
- package/dist/webgl/pool.js.map +1 -0
- package/dist/webgl/programs.d.ts +130 -0
- package/dist/webgl/programs.d.ts.map +1 -0
- package/dist/webgl/programs.js +582 -0
- package/dist/webgl/programs.js.map +1 -0
- package/dist/webgl/stage.d.ts +67 -0
- package/dist/webgl/stage.d.ts.map +1 -0
- package/dist/webgl/stage.js +173 -0
- package/dist/webgl/stage.js.map +1 -0
- package/dist/webgl/targets.d.ts +172 -0
- package/dist/webgl/targets.d.ts.map +1 -0
- package/dist/webgl/targets.js +323 -0
- package/dist/webgl/targets.js.map +1 -0
- package/package.json +35 -3
- package/src/commands.ts +98 -0
- package/src/filter-plan.ts +755 -0
- package/src/filter-shaders.ts +360 -0
- package/src/filters.ts +220 -0
- package/src/geometry.ts +143 -0
- package/src/index.ts +87 -0
- package/src/keeps.ts +21 -0
- package/src/kernel-shaders.ts +375 -0
- package/src/measure.ts +400 -0
- package/src/plan.ts +331 -0
- package/src/registry.ts +105 -0
- package/src/rows.ts +93 -0
- package/src/scene.ts +297 -0
- package/src/shelves.ts +70 -0
- package/src/textures.ts +198 -0
- package/src/webgl/atlas.ts +370 -0
- package/src/webgl/backend.ts +973 -0
- package/src/webgl/composite.ts +372 -0
- package/src/webgl/draws.ts +902 -0
- package/src/webgl/filters.ts +502 -0
- package/src/webgl/gpu-textures.ts +253 -0
- package/src/webgl/holds.ts +624 -0
- package/src/webgl/index.ts +3 -0
- package/src/webgl/kernels.ts +205 -0
- package/src/webgl/pool.ts +245 -0
- package/src/webgl/programs.ts +620 -0
- package/src/webgl/stage.ts +214 -0
- package/src/webgl/targets.ts +464 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import type { GlState } from "@swf2es/context3d/device";
|
|
2
|
+
import { type Geometries, type GeometryData, GLYPH_FLOATS } from "../geometry.js";
|
|
3
|
+
import {
|
|
4
|
+
COLOR_AT,
|
|
5
|
+
DEPTH_AT,
|
|
6
|
+
GLYPH_AT,
|
|
7
|
+
ORIGIN_AT,
|
|
8
|
+
POSITION_AT,
|
|
9
|
+
RUN_AT,
|
|
10
|
+
TEXEL_AT,
|
|
11
|
+
TINT_AT,
|
|
12
|
+
} from "./programs.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Bytes a vertex in the atlas: its position's two floats, its texel's two, then its colour's four
|
|
16
|
+
* bytes, or a mesh's depth's float.
|
|
17
|
+
*/
|
|
18
|
+
const VERTEX_BYTES = 20;
|
|
19
|
+
/** Bytes a vertex of advanced text's glyph quads, in an atlas of their own. */
|
|
20
|
+
const GLYPH_BYTES = GLYPH_FLOATS * 4;
|
|
21
|
+
/** The fewest glyph vertices the glyph atlas holds once a text needs it. */
|
|
22
|
+
const GLYPHS_LEAST = 1024;
|
|
23
|
+
/** The fewest vertices the atlas holds room for, and its indices thrice that. */
|
|
24
|
+
const LEAST = 1 << 16;
|
|
25
|
+
/** Holes past which, and past the live vertices, the atlas is packed again. */
|
|
26
|
+
const SLACK = 1 << 16;
|
|
27
|
+
|
|
28
|
+
/** Where a geometry lies in the atlas, or the glyph atlas with its text's mode and table. */
|
|
29
|
+
export interface Place {
|
|
30
|
+
vertexStart: number;
|
|
31
|
+
vertices: number;
|
|
32
|
+
indexStart: number;
|
|
33
|
+
indices: number;
|
|
34
|
+
glyphs: { mode: Float32Array; table: Float32Array } | null;
|
|
35
|
+
/** Its geometry's flat (GeometryData.flat). */
|
|
36
|
+
flat: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The geometry atlas: every geometry copied once into a vertex and an index
|
|
41
|
+
* buffer, and advanced text's glyph quads into an atlas of their own, where
|
|
42
|
+
* the draws find them by their places. A geometry let go of leaves a hole,
|
|
43
|
+
* and each atlas is packed again from the geometries' own arrays once the
|
|
44
|
+
* holes outweigh what is live.
|
|
45
|
+
*/
|
|
46
|
+
export class GeometryAtlas {
|
|
47
|
+
private readonly gl: WebGL2RenderingContext;
|
|
48
|
+
private readonly state: GlState;
|
|
49
|
+
vertexArray!: WebGLVertexArrayObject;
|
|
50
|
+
private vertexBuffer!: WebGLBuffer;
|
|
51
|
+
private indexBuffer!: WebGLBuffer;
|
|
52
|
+
private vertexCapacity = 0;
|
|
53
|
+
private indexCapacity = 0;
|
|
54
|
+
private vertexTop = 0;
|
|
55
|
+
private indexTop = 0;
|
|
56
|
+
private live = 0;
|
|
57
|
+
private holes = 0;
|
|
58
|
+
places: (Place | null)[] = [];
|
|
59
|
+
glyphArray!: WebGLVertexArrayObject;
|
|
60
|
+
private glyphBuffer!: WebGLBuffer;
|
|
61
|
+
private glyphIndexBuffer!: WebGLBuffer;
|
|
62
|
+
/** The glyph atlas' room and top, of vertices and of indices, and its vertices live and let go of. */
|
|
63
|
+
private readonly glyphs = {
|
|
64
|
+
capacity: 0,
|
|
65
|
+
top: 0,
|
|
66
|
+
indexCapacity: 0,
|
|
67
|
+
indexTop: 0,
|
|
68
|
+
live: 0,
|
|
69
|
+
holes: 0,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
constructor(gl: WebGL2RenderingContext, state: GlState) {
|
|
73
|
+
this.gl = gl;
|
|
74
|
+
this.state = state;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** The buffers and vertex arrays made, both atlases empty, as the context comes or comes back. */
|
|
78
|
+
setUp(): void {
|
|
79
|
+
const gl = this.gl;
|
|
80
|
+
this.vertexArray = gl.createVertexArray() as WebGLVertexArrayObject;
|
|
81
|
+
this.vertexBuffer = gl.createBuffer() as WebGLBuffer;
|
|
82
|
+
this.indexBuffer = gl.createBuffer() as WebGLBuffer;
|
|
83
|
+
this.state.bindVertexArray(this.vertexArray);
|
|
84
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
85
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
|
86
|
+
gl.enableVertexAttribArray(POSITION_AT);
|
|
87
|
+
gl.vertexAttribPointer(POSITION_AT, 2, gl.FLOAT, false, VERTEX_BYTES, 0);
|
|
88
|
+
gl.enableVertexAttribArray(TEXEL_AT);
|
|
89
|
+
gl.vertexAttribPointer(TEXEL_AT, 2, gl.FLOAT, false, VERTEX_BYTES, 8);
|
|
90
|
+
gl.enableVertexAttribArray(COLOR_AT);
|
|
91
|
+
gl.vertexAttribPointer(COLOR_AT, 4, gl.UNSIGNED_BYTE, true, VERTEX_BYTES, 16);
|
|
92
|
+
// The same bytes as a mesh's depth, which the mesh program reads in place of the colour.
|
|
93
|
+
gl.enableVertexAttribArray(DEPTH_AT);
|
|
94
|
+
gl.vertexAttribPointer(DEPTH_AT, 1, gl.FLOAT, false, VERTEX_BYTES, 16);
|
|
95
|
+
this.glyphArray = gl.createVertexArray() as WebGLVertexArrayObject;
|
|
96
|
+
this.glyphBuffer = gl.createBuffer() as WebGLBuffer;
|
|
97
|
+
this.glyphIndexBuffer = gl.createBuffer() as WebGLBuffer;
|
|
98
|
+
this.state.bindVertexArray(this.glyphArray);
|
|
99
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.glyphBuffer);
|
|
100
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.glyphIndexBuffer);
|
|
101
|
+
gl.enableVertexAttribArray(POSITION_AT);
|
|
102
|
+
gl.vertexAttribPointer(POSITION_AT, 2, gl.FLOAT, false, GLYPH_BYTES, 0);
|
|
103
|
+
for (const [at, offset] of [
|
|
104
|
+
[ORIGIN_AT, 8],
|
|
105
|
+
[GLYPH_AT, 24],
|
|
106
|
+
[RUN_AT, 40],
|
|
107
|
+
[TINT_AT, 56],
|
|
108
|
+
]) {
|
|
109
|
+
gl.enableVertexAttribArray(at);
|
|
110
|
+
gl.vertexAttribPointer(at, 4, gl.FLOAT, false, GLYPH_BYTES, offset);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
Object.assign(this.glyphs, {
|
|
114
|
+
capacity: 0,
|
|
115
|
+
top: 0,
|
|
116
|
+
indexCapacity: 0,
|
|
117
|
+
indexTop: 0,
|
|
118
|
+
live: 0,
|
|
119
|
+
holes: 0,
|
|
120
|
+
});
|
|
121
|
+
this.vertexCapacity = 0;
|
|
122
|
+
this.indexCapacity = 0;
|
|
123
|
+
this.places = [];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The geometries removed since the last frame let go of, and those added
|
|
128
|
+
* copied in: at the top while they fit, else into an atlas packed again,
|
|
129
|
+
* grown to twice what is live.
|
|
130
|
+
*/
|
|
131
|
+
place(geometries: Geometries): void {
|
|
132
|
+
for (const id of geometries.removed) {
|
|
133
|
+
const place = this.places[id];
|
|
134
|
+
if (place?.glyphs) {
|
|
135
|
+
this.places[id] = null;
|
|
136
|
+
this.glyphs.live -= place.vertices;
|
|
137
|
+
this.glyphs.holes += place.vertices;
|
|
138
|
+
} else if (place) {
|
|
139
|
+
this.places[id] = null;
|
|
140
|
+
this.live -= place.vertices;
|
|
141
|
+
this.holes += place.vertices;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
geometries.removed.length = 0;
|
|
146
|
+
// Changed in place: copied again where they lie, else as added.
|
|
147
|
+
for (const id of geometries.updated) {
|
|
148
|
+
const place = this.places[id];
|
|
149
|
+
const data = geometries.get(id);
|
|
150
|
+
if (place && data && !data.glyphs && place.vertices === data.positions.length / 2) {
|
|
151
|
+
this.copyVertices(data, place.vertexStart);
|
|
152
|
+
} else if (place && data) {
|
|
153
|
+
this.places[id] = null;
|
|
154
|
+
if (place.glyphs) {
|
|
155
|
+
this.glyphs.live -= place.vertices;
|
|
156
|
+
this.glyphs.holes += place.vertices;
|
|
157
|
+
} else {
|
|
158
|
+
this.live -= place.vertices;
|
|
159
|
+
this.holes += place.vertices;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
geometries.added.push(id);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
geometries.updated.length = 0;
|
|
167
|
+
let vertices = 0;
|
|
168
|
+
let indices = 0;
|
|
169
|
+
let glyphVertices = 0;
|
|
170
|
+
let glyphIndices = 0;
|
|
171
|
+
for (const id of geometries.added) {
|
|
172
|
+
const data = geometries.get(id);
|
|
173
|
+
if (data?.glyphs) {
|
|
174
|
+
glyphVertices += data.glyphs.vertices.length / GLYPH_FLOATS;
|
|
175
|
+
glyphIndices += data.indices.length;
|
|
176
|
+
} else if (data) {
|
|
177
|
+
vertices += data.positions.length / 2;
|
|
178
|
+
indices += data.indices.length;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Each atlas packed again on its own, so that texts' quads made again often never repack
|
|
183
|
+
// the shapes', nor shapes the texts'.
|
|
184
|
+
const g = this.glyphs;
|
|
185
|
+
const shapes =
|
|
186
|
+
this.vertexTop + vertices > this.vertexCapacity ||
|
|
187
|
+
this.indexTop + indices > this.indexCapacity ||
|
|
188
|
+
(this.holes > SLACK && this.holes > this.live);
|
|
189
|
+
const texts =
|
|
190
|
+
g.top + glyphVertices > g.capacity ||
|
|
191
|
+
g.indexTop + glyphIndices > g.indexCapacity ||
|
|
192
|
+
(g.holes > GLYPHS_LEAST && g.holes > g.live);
|
|
193
|
+
if (shapes) {
|
|
194
|
+
this.repack(geometries);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (texts) {
|
|
198
|
+
this.repackGlyphs(geometries);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
for (const id of geometries.added) {
|
|
202
|
+
const data = geometries.get(id);
|
|
203
|
+
if (data && !(data.glyphs ? texts : shapes)) {
|
|
204
|
+
this.copyIn(id, data);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
geometries.added.length = 0;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** Every live shape's geometry copied into new buffers, with room for twice what is live. */
|
|
212
|
+
repack(geometries: Geometries): void {
|
|
213
|
+
const gl = this.gl;
|
|
214
|
+
const ids = geometries.live();
|
|
215
|
+
let vertices = 0;
|
|
216
|
+
let indices = 0;
|
|
217
|
+
for (const id of ids) {
|
|
218
|
+
const data = geometries.get(id) as GeometryData;
|
|
219
|
+
if (!data.glyphs) {
|
|
220
|
+
vertices += data.positions.length / 2;
|
|
221
|
+
indices += data.indices.length;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
this.vertexCapacity = Math.max(LEAST, vertices * 2);
|
|
226
|
+
this.indexCapacity = Math.max(LEAST * 3, indices * 2);
|
|
227
|
+
this.state.bindVertexArray(this.vertexArray);
|
|
228
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
229
|
+
gl.bufferData(gl.ARRAY_BUFFER, this.vertexCapacity * VERTEX_BYTES, gl.STATIC_DRAW);
|
|
230
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indexCapacity * 4, gl.STATIC_DRAW);
|
|
231
|
+
this.vertexTop = 0;
|
|
232
|
+
this.indexTop = 0;
|
|
233
|
+
this.live = 0;
|
|
234
|
+
this.holes = 0;
|
|
235
|
+
for (const id of ids) {
|
|
236
|
+
const data = geometries.get(id) as GeometryData;
|
|
237
|
+
if (!data.glyphs) {
|
|
238
|
+
this.copyIn(id, data);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** Every live text's quads copied into new glyph buffers: none till a text needs them. */
|
|
244
|
+
repackGlyphs(geometries: Geometries): void {
|
|
245
|
+
const gl = this.gl;
|
|
246
|
+
const g = this.glyphs;
|
|
247
|
+
const ids = geometries.live();
|
|
248
|
+
let vertices = 0;
|
|
249
|
+
let indices = 0;
|
|
250
|
+
for (const id of ids) {
|
|
251
|
+
const data = geometries.get(id) as GeometryData;
|
|
252
|
+
if (data.glyphs) {
|
|
253
|
+
vertices += data.glyphs.vertices.length / GLYPH_FLOATS;
|
|
254
|
+
indices += data.indices.length;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
g.capacity = vertices > 0 ? Math.max(GLYPHS_LEAST, vertices * 2) : 0;
|
|
259
|
+
g.indexCapacity = vertices > 0 ? Math.max(GLYPHS_LEAST * 2, indices * 2) : 0;
|
|
260
|
+
this.state.bindVertexArray(this.glyphArray);
|
|
261
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.glyphBuffer);
|
|
262
|
+
gl.bufferData(gl.ARRAY_BUFFER, g.capacity * GLYPH_BYTES, gl.STATIC_DRAW);
|
|
263
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, g.indexCapacity * 4, gl.STATIC_DRAW);
|
|
264
|
+
g.top = 0;
|
|
265
|
+
g.indexTop = 0;
|
|
266
|
+
g.live = 0;
|
|
267
|
+
g.holes = 0;
|
|
268
|
+
for (const id of ids) {
|
|
269
|
+
const data = geometries.get(id) as GeometryData;
|
|
270
|
+
if (data.glyphs) {
|
|
271
|
+
this.copyGlyphs(id, data);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/** `data` copied in at the top of the atlas, its indices made absolute. */
|
|
277
|
+
private copyIn(id: number, data: GeometryData): void {
|
|
278
|
+
if (data.glyphs) {
|
|
279
|
+
this.copyGlyphs(id, data);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const gl = this.gl;
|
|
284
|
+
const count = data.positions.length / 2;
|
|
285
|
+
const base = this.vertexTop;
|
|
286
|
+
this.copyVertices(data, base);
|
|
287
|
+
const indices = new Uint32Array(data.indices.length);
|
|
288
|
+
for (let i = 0; i < indices.length; i++) {
|
|
289
|
+
indices[i] = data.indices[i] + base;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
this.state.bindVertexArray(this.vertexArray);
|
|
293
|
+
gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, this.indexTop * 4, indices);
|
|
294
|
+
this.places[id] = {
|
|
295
|
+
vertexStart: base,
|
|
296
|
+
vertices: count,
|
|
297
|
+
indexStart: this.indexTop,
|
|
298
|
+
indices: indices.length,
|
|
299
|
+
glyphs: null,
|
|
300
|
+
flat: data.flat === true,
|
|
301
|
+
};
|
|
302
|
+
this.vertexTop += count;
|
|
303
|
+
this.indexTop += indices.length;
|
|
304
|
+
this.live += count;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/** `data`'s vertices interleaved into the atlas from vertex `base`. */
|
|
308
|
+
private copyVertices(data: GeometryData, base: number): void {
|
|
309
|
+
const gl = this.gl;
|
|
310
|
+
const count = data.positions.length / 2;
|
|
311
|
+
const bytes = new ArrayBuffer(count * VERTEX_BYTES);
|
|
312
|
+
const floats = new Float32Array(bytes);
|
|
313
|
+
const words = new Uint32Array(bytes);
|
|
314
|
+
const texels = data.texels;
|
|
315
|
+
const depths = data.depths;
|
|
316
|
+
for (let i = 0; i < count; i++) {
|
|
317
|
+
floats[i * 5] = data.positions[i * 2];
|
|
318
|
+
floats[i * 5 + 1] = data.positions[i * 2 + 1];
|
|
319
|
+
floats[i * 5 + 2] = texels ? texels[i * 2] : 0;
|
|
320
|
+
floats[i * 5 + 3] = texels ? texels[i * 2 + 1] : 0;
|
|
321
|
+
if (depths) {
|
|
322
|
+
floats[i * 5 + 4] = depths[i];
|
|
323
|
+
} else {
|
|
324
|
+
words[i * 5 + 4] = data.colors[i];
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
329
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, base * VERTEX_BYTES, floats);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/** Glyph quads copied in at the top of the glyph atlas, their indices made absolute in it. */
|
|
333
|
+
private copyGlyphs(id: number, data: GeometryData): void {
|
|
334
|
+
const gl = this.gl;
|
|
335
|
+
const g = this.glyphs;
|
|
336
|
+
const glyphs = data.glyphs as NonNullable<GeometryData["glyphs"]>;
|
|
337
|
+
const count = glyphs.vertices.length / GLYPH_FLOATS;
|
|
338
|
+
const indices = new Uint32Array(data.indices.length);
|
|
339
|
+
for (let i = 0; i < indices.length; i++) {
|
|
340
|
+
indices[i] = data.indices[i] + g.top;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
this.state.bindVertexArray(this.glyphArray);
|
|
344
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.glyphBuffer);
|
|
345
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, g.top * GLYPH_BYTES, glyphs.vertices);
|
|
346
|
+
gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, g.indexTop * 4, indices);
|
|
347
|
+
this.places[id] = {
|
|
348
|
+
vertexStart: g.top,
|
|
349
|
+
vertices: count,
|
|
350
|
+
indexStart: g.indexTop,
|
|
351
|
+
indices: indices.length,
|
|
352
|
+
glyphs: { mode: glyphs.mode, table: glyphs.table },
|
|
353
|
+
flat: false,
|
|
354
|
+
};
|
|
355
|
+
g.top += count;
|
|
356
|
+
g.indexTop += indices.length;
|
|
357
|
+
g.live += count;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/** The buffers and vertex arrays made on the context, deleted. */
|
|
361
|
+
destroy(): void {
|
|
362
|
+
const gl = this.gl;
|
|
363
|
+
gl.deleteVertexArray(this.vertexArray);
|
|
364
|
+
gl.deleteBuffer(this.vertexBuffer);
|
|
365
|
+
gl.deleteBuffer(this.indexBuffer);
|
|
366
|
+
gl.deleteVertexArray(this.glyphArray);
|
|
367
|
+
gl.deleteBuffer(this.glyphBuffer);
|
|
368
|
+
gl.deleteBuffer(this.glyphIndexBuffer);
|
|
369
|
+
}
|
|
370
|
+
}
|