@expofp/renderer 1.4.2 → 1.5.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/dist/index.js CHANGED
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  var _a;
5
- import { DataTexture, FloatType, UnsignedIntType, IntType, RGBAFormat, RGBAIntegerFormat, RGFormat, RGIntegerFormat, RedFormat, RedIntegerFormat, BatchedMesh as BatchedMesh$1, BufferAttribute, StreamDrawUsage, Color, Matrix4, Vector3, Vector4, DoubleSide, MeshBasicMaterial, Texture, Quaternion, Group, PlaneGeometry, SRGBColorSpace, Vector2, BufferGeometry, LinearSRGBColorSpace, Mesh, Plane, Raycaster, Sphere, Box3, Spherical, PerspectiveCamera, Scene, Camera, MathUtils, Clock, WebGLRenderer } from "three";
5
+ import { Color, Matrix4, Vector3, DataTexture, RGBAFormat, FloatType, RedFormat, UnsignedIntType, IntType, RGBAIntegerFormat, RGFormat, RGIntegerFormat, RedIntegerFormat, BatchedMesh as BatchedMesh$1, BufferAttribute, StreamDrawUsage, Vector4, AlwaysDepth, DoubleSide, MeshBasicMaterial, Texture, Group, PlaneGeometry, SRGBColorSpace, Vector2, Mesh, LessEqualDepth, Quaternion, BufferGeometry, LinearSRGBColorSpace, Plane, Raycaster, Sphere, Box3, Spherical, PerspectiveCamera, Scene, Camera, MathUtils, Clock, WebGLRenderer } from "three";
6
6
  import { traverseAncestorsGenerator } from "three/examples/jsm/utils/SceneUtils.js";
7
7
  import { BatchedText as BatchedText$1, Text as Text$1 } from "troika-three-text";
8
8
  import { LineMaterial, LineSegmentsGeometry } from "three/examples/jsm/Addons.js";
@@ -10,351 +10,703 @@ import { MaxRectsPacker, Rectangle } from "maxrects-packer";
10
10
  import { converter, parse } from "culori";
11
11
  import { RAD2DEG, DEG2RAD as DEG2RAD$1 } from "three/src/math/MathUtils.js";
12
12
  import { EventManager, Rotate, Pan } from "mjolnir.js";
13
- function isObject(item) {
14
- return !!item && typeof item === "object" && !Array.isArray(item);
15
- }
16
- function deepMerge(target, ...sources) {
17
- if (!sources.length) return target;
18
- const source = sources.shift();
19
- if (source === void 0) {
20
- return target;
21
- }
22
- if (isObject(target) && isObject(source)) {
23
- for (const key in source) {
24
- if (isObject(source[key])) {
25
- if (!target[key]) {
26
- Object.assign(target, { [key]: {} });
27
- }
28
- deepMerge(target[key], source[key]);
29
- } else {
30
- Object.assign(target, { [key]: source[key] });
31
- }
32
- }
13
+ const floatsPerMember = 32;
14
+ const tempColor = new Color();
15
+ const defaultStrokeColor = 8421504;
16
+ const tempMat4 = new Matrix4();
17
+ const tempVec3a = new Vector3();
18
+ const tempVec3b = new Vector3();
19
+ const origin = new Vector3();
20
+ const defaultOrient = "+x+y";
21
+ class BatchedText extends BatchedText$1 {
22
+ // eslint-disable-next-line jsdoc/require-jsdoc
23
+ constructor() {
24
+ super();
25
+ __publicField(this, "mapInstanceIdToText", /* @__PURE__ */ new Map());
26
+ __publicField(this, "textArray", []);
27
+ __publicField(this, "textureNeedsUpdate", false);
33
28
  }
34
- return deepMerge(target, ...sources);
35
- }
36
- function getSquareTextureSize(capacity, pixelsPerInstance) {
37
- return Math.max(pixelsPerInstance, Math.ceil(Math.sqrt(capacity / pixelsPerInstance)) * pixelsPerInstance);
38
- }
39
- function getSquareTextureInfo(arrayType, channels, pixelsPerInstance, capacity) {
40
- if (channels === 3) {
41
- console.warn('"channels" cannot be 3. Set to 4. More info: https://github.com/mrdoob/three.js/pull/23228');
42
- channels = 4;
29
+ /** Number of texts in the batch */
30
+ get size() {
31
+ return this._members.size;
43
32
  }
44
- const size = getSquareTextureSize(capacity, pixelsPerInstance);
45
- const array = new arrayType(size * size * channels);
46
- const isFloat = arrayType.name.includes("Float");
47
- const isUnsignedInt = arrayType.name.includes("Uint");
48
- const type = isFloat ? FloatType : isUnsignedInt ? UnsignedIntType : IntType;
49
- let format;
50
- switch (channels) {
51
- case 1:
52
- format = isFloat ? RedFormat : RedIntegerFormat;
53
- break;
54
- case 2:
55
- format = isFloat ? RGFormat : RGIntegerFormat;
56
- break;
57
- case 4:
58
- format = isFloat ? RGBAFormat : RGBAIntegerFormat;
59
- break;
33
+ /** Base material before patching */
34
+ get baseMaterial() {
35
+ return this._baseMaterial;
60
36
  }
61
- return { array, size, type, format };
62
- }
63
- class SquareDataTexture extends DataTexture {
64
37
  /**
65
- * @param arrayType The constructor for the TypedArray.
66
- * @param channels The number of channels in the texture.
67
- * @param pixelsPerInstance The number of pixels required for each instance.
68
- * @param capacity The total number of instances.
69
- * @param uniformMap Optional map for handling uniform values.
70
- * @param fetchInFragmentShader Optional flag that determines if uniform values should be fetched in the fragment shader instead of the vertex shader.
38
+ * Get the {@link Text} object by instance id
39
+ * @param instanceId Instance id
40
+ * @returns Text object
71
41
  */
72
- constructor(arrayType, channels, pixelsPerInstance, capacity, uniformMap, fetchInFragmentShader) {
73
- if (channels === 3) channels = 4;
74
- const { array, format, size, type } = getSquareTextureInfo(arrayType, channels, pixelsPerInstance, capacity);
75
- super(array, size, size, format, type);
76
- __publicField(this, "data");
77
- __publicField(this, "channels");
78
- __publicField(this, "pixelsPerInstance");
79
- __publicField(this, "stride");
80
- __publicField(this, "uniformMap");
81
- __publicField(this, "fetchUniformsInFragmentShader");
82
- __publicField(this, "uniformPrefix", "batch_");
83
- this.data = array;
84
- this.channels = channels;
85
- this.pixelsPerInstance = pixelsPerInstance;
86
- this.stride = pixelsPerInstance * channels;
87
- this.uniformMap = uniformMap;
88
- this.fetchUniformsInFragmentShader = fetchInFragmentShader;
89
- this.needsUpdate = true;
42
+ getText(instanceId) {
43
+ return this.mapInstanceIdToText.get(instanceId);
90
44
  }
91
45
  /**
92
- * Sets a uniform value at the specified instance ID in the texture.
93
- * @param id The instance ID to set the uniform for.
94
- * @param name The name of the uniform.
95
- * @param value The value to set for the uniform.
46
+ * Set the visibility of the {@link Text} object by instance id.
47
+ * This is for interface compatibility with {@link BatchedMesh}.
48
+ * @param instanceId Instance id
49
+ * @param visible Visibility flag
96
50
  */
97
- setUniformAt(id, name, value) {
98
- const schema = this.uniformMap.get(name);
99
- if (!schema) {
100
- console.warn(`SquareDataTexture.setUniformAt: uniform ${name} not found`);
101
- return;
102
- }
103
- const { offset, size } = schema;
104
- const stride = this.stride;
105
- if (size === 1) {
106
- this.data[id * stride + offset] = value;
107
- } else {
108
- value.toArray(this.data, id * stride + offset);
109
- }
51
+ setVisibleAt(instanceId, visible) {
52
+ const text = this.getText(instanceId);
53
+ text.visible = visible;
110
54
  }
111
- /**
112
- * Retrieves a uniform value at the specified instance ID from the texture.
113
- * @param id The instance ID to retrieve the uniform from.
114
- * @param name The name of the uniform.
115
- * @param target Optional target object to store the uniform value.
116
- * @returns The uniform value for the specified instance.
117
- */
118
- getUniformAt(id, name, target) {
119
- const schema = this.uniformMap.get(name);
120
- if (!schema) {
121
- console.warn(`SquareDataTexture.getUniformAt: uniform ${name} not found`);
122
- return 0;
123
- }
124
- const { offset, size } = schema;
125
- const stride = this.stride;
126
- if (size === 1) {
127
- return this.data[id * stride + offset];
55
+ addText(text, instanceId) {
56
+ super.addText(text);
57
+ if (instanceId !== void 0) {
58
+ this.mapInstanceIdToText.set(instanceId, text);
128
59
  }
129
- return target.fromArray(this.data, id * stride + offset);
130
- }
131
- /** Mark the texture as needing an update. */
132
- update() {
133
- this.needsUpdate = true;
134
- }
135
- /**
136
- * Generates the GLSL code for accessing the uniform data stored in the texture.
137
- * @param textureName The name of the texture in the GLSL shader.
138
- * @param indexName The name of the index in the GLSL shader.
139
- * @param indexType The type of the index in the GLSL shader.
140
- * @returns An object containing the GLSL code for the vertex and fragment shaders.
141
- */
142
- getUniformsGLSL(textureName, indexName, indexType) {
143
- const vertex = this.getUniformsVertexGLSL(textureName, indexName, indexType);
144
- const fragment = this.getUniformsFragmentGLSL(textureName, indexName, indexType);
145
- return { vertex, fragment };
60
+ this.textArray.push(text);
146
61
  }
147
- getUniformsVertexGLSL(textureName, indexName, indexType) {
148
- if (this.fetchUniformsInFragmentShader) {
149
- return (
150
- /*glsl*/
151
- `
152
- flat varying ${indexType} ${this.uniformPrefix}${indexName};
153
- void main() {
154
- ${this.uniformPrefix}${indexName} = ${indexName};
155
- `
156
- );
157
- }
158
- const texelsFetch = this.texelsFetchGLSL(textureName, indexName);
159
- const getFromTexels = this.getFromTexelsGLSL();
160
- const { assignVarying, declareVarying } = this.getVarying();
161
- return (
162
- /*glsl*/
163
- `
164
- uniform highp sampler2D ${textureName};
165
- ${declareVarying}
166
- void main() {
167
- #ifdef USE_BATCHING
168
- ${indexType} ${indexName} = ${indexType}(getIndirectIndex(gl_DrawID));
169
- #endif
170
- ${texelsFetch}
171
- ${getFromTexels}
172
- ${assignVarying}`
173
- );
62
+ dispose() {
63
+ super.dispose();
64
+ this.dispatchEvent({ type: "dispose" });
174
65
  }
175
- getUniformsFragmentGLSL(textureName, indexName, indexType) {
176
- if (!this.fetchUniformsInFragmentShader) {
177
- const { declareVarying, getVarying } = this.getVarying();
178
- return (
179
- /*glsl*/
180
- `
181
- ${declareVarying}
182
- void main() {
183
- ${getVarying}`
66
+ // TODO: Check performance
67
+ _prepareForRender(material) {
68
+ var _a2;
69
+ const isOutline = material.isTextOutlineMaterial;
70
+ material.uniforms.uTroikaIsOutline.value = isOutline;
71
+ let texture = this._dataTextures[isOutline ? "outline" : "main"];
72
+ const dataLength = Math.pow(2, Math.ceil(Math.log2(this._members.size * floatsPerMember)));
73
+ if (!texture || dataLength !== texture.image.data.length) {
74
+ if (texture) texture.dispose();
75
+ const width = Math.min(dataLength / 4, 1024);
76
+ texture = this._dataTextures[isOutline ? "outline" : "main"] = new DataTexture(
77
+ new Float32Array(dataLength),
78
+ width,
79
+ dataLength / 4 / width,
80
+ RGBAFormat,
81
+ FloatType
184
82
  );
185
83
  }
186
- const texelsFetch = this.texelsFetchGLSL(textureName, `${this.uniformPrefix}${indexName}`);
187
- const getFromTexels = this.getFromTexelsGLSL();
188
- return (
189
- /*glsl*/
190
- `
191
- uniform highp sampler2D ${textureName};
192
- flat varying ${indexType} ${this.uniformPrefix}${indexName};
193
- void main() {
194
- ${texelsFetch}
195
- ${getFromTexels}`
196
- );
197
- }
198
- texelsFetchGLSL(textureName, indexName) {
199
- const pixelsPerInstance = this.pixelsPerInstance;
200
- let texelsFetch = (
201
- /*glsl*/
202
- `
203
- int size = textureSize(${textureName}, 0).x;
204
- int j = int(${indexName}) * ${pixelsPerInstance};
205
- int x = j % size;
206
- int y = j / size;
207
- `
208
- );
209
- for (let i = 0; i < pixelsPerInstance; i++) {
210
- texelsFetch += /*glsl*/
211
- `vec4 ${this.uniformPrefix}texel${i} = texelFetch(${textureName}, ivec2(x + ${i}, y), 0);
212
- `;
213
- }
214
- return texelsFetch;
215
- }
216
- getFromTexelsGLSL() {
217
- const uniforms = this.uniformMap;
218
- let getFromTexels = "";
219
- for (const [name, { type, offset, size }] of uniforms) {
220
- const tId = Math.floor(offset / this.channels);
221
- if (type === "mat3") {
222
- getFromTexels += /*glsl*/
223
- `mat3 ${name} = mat3(${this.uniformPrefix}texel${tId}.rgb, vec3(${this.uniformPrefix}texel${tId}.a, ${this.uniformPrefix}texel${tId + 1}.rg), vec3(${this.uniformPrefix}texel${tId + 1}.ba, ${this.uniformPrefix}texel${tId + 2}.r));
224
- `;
225
- } else if (type === "mat4") {
226
- getFromTexels += /*glsl*/
227
- `mat4 ${name} = mat4(${this.uniformPrefix}texel${tId}, ${this.uniformPrefix}texel${tId + 1}, ${this.uniformPrefix}texel${tId + 2}, ${this.uniformPrefix}texel${tId + 3});
228
- `;
84
+ const texData = texture.image.data;
85
+ this.textureNeedsUpdate = false;
86
+ for (const text of this.textArray) {
87
+ const index = ((_a2 = this._members.get(text)) == null ? void 0 : _a2.index) ?? -1;
88
+ const textRenderInfo = text.textRenderInfo;
89
+ if (index < 0 || !textRenderInfo) continue;
90
+ const startIndex = index * floatsPerMember;
91
+ if (!text.visible) {
92
+ for (let i = 0; i < 16; i++) {
93
+ this.setTexData(startIndex + i, 0, texData);
94
+ }
95
+ continue;
96
+ }
97
+ const matrix = text.matrix.elements;
98
+ for (let i = 0; i < 16; i++) {
99
+ this.setTexData(startIndex + i, matrix[i], texData);
100
+ }
101
+ text._prepareForRender(material);
102
+ const {
103
+ uTroikaTotalBounds,
104
+ uTroikaClipRect,
105
+ uTroikaPositionOffset,
106
+ uTroikaEdgeOffset,
107
+ uTroikaBlurRadius,
108
+ uTroikaStrokeWidth,
109
+ uTroikaStrokeColor,
110
+ uTroikaStrokeOpacity,
111
+ uTroikaFillOpacity,
112
+ uTroikaCurveRadius
113
+ } = material.uniforms;
114
+ for (let i = 0; i < 4; i++) {
115
+ this.setTexData(startIndex + 16 + i, uTroikaTotalBounds.value.getComponent(i), texData);
116
+ }
117
+ for (let i = 0; i < 4; i++) {
118
+ this.setTexData(startIndex + 20 + i, uTroikaClipRect.value.getComponent(i), texData);
119
+ }
120
+ let color = isOutline ? text.outlineColor || 0 : text.color;
121
+ color ?? (color = this.color);
122
+ color ?? (color = this.material.color);
123
+ color ?? (color = 16777215);
124
+ this.setTexData(startIndex + 24, tempColor.set(color).getHex(), texData);
125
+ this.setTexData(startIndex + 25, uTroikaFillOpacity.value, texData);
126
+ this.setTexData(startIndex + 26, uTroikaCurveRadius.value, texData);
127
+ if (isOutline) {
128
+ this.setTexData(startIndex + 28, uTroikaPositionOffset.value.x, texData);
129
+ this.setTexData(startIndex + 29, uTroikaPositionOffset.value.y, texData);
130
+ this.setTexData(startIndex + 30, uTroikaEdgeOffset.value, texData);
131
+ this.setTexData(startIndex + 31, uTroikaBlurRadius.value, texData);
229
132
  } else {
230
- const components = this.getUniformComponents(offset, size);
231
- getFromTexels += /*glsl*/
232
- `${type} ${name} = ${this.uniformPrefix}texel${tId}.${components};
233
- `;
133
+ this.setTexData(startIndex + 28, uTroikaStrokeWidth.value, texData);
134
+ this.setTexData(startIndex + 29, tempColor.set(uTroikaStrokeColor.value).getHex(), texData);
135
+ this.setTexData(startIndex + 30, uTroikaStrokeOpacity.value, texData);
234
136
  }
235
137
  }
236
- return getFromTexels;
237
- }
238
- getVarying() {
239
- const uniforms = this.uniformMap;
240
- let declareVarying = "";
241
- let assignVarying = "";
242
- let getVarying = "";
243
- for (const [name, { type }] of uniforms) {
244
- declareVarying += /*glsl*/
245
- `flat varying ${type} ${this.uniformPrefix}${name};
246
- `;
247
- assignVarying += /*glsl*/
248
- `${this.uniformPrefix}${name} = ${name};
249
- `;
250
- getVarying += /*glsl*/
251
- `${type} ${name} = ${this.uniformPrefix}${name};
252
- `;
253
- }
254
- return { declareVarying, assignVarying, getVarying };
138
+ texture.needsUpdate = this.textureNeedsUpdate;
139
+ material.setMatrixTexture(texture);
255
140
  }
256
- getUniformComponents(offset, size) {
257
- const startIndex = offset % this.channels;
258
- let components = "";
259
- for (let i = 0; i < size; i++) {
260
- components += componentsArray[startIndex + i];
141
+ setTexData(index, value, texData) {
142
+ if (value !== texData[index]) {
143
+ texData[index] = value;
144
+ this.textureNeedsUpdate = true;
261
145
  }
262
- return components;
263
146
  }
264
147
  }
265
- const componentsArray = ["r", "g", "b", "a"];
266
- const batchIdName = "batchId";
267
- class BatchedMesh extends BatchedMesh$1 {
268
- /**
269
- * @param instanceCount the max number of individual geometries planned to be added.
270
- * @param vertexCount the max number of vertices to be used by all geometries.
271
- * @param indexCount the max number of indices to be used by all geometries.
272
- * @param material an instance of {@link Material}. Default is a new {@link MeshBasicMaterial}.
273
- */
274
- constructor(instanceCount, vertexCount, indexCount, material) {
275
- super(instanceCount, vertexCount, indexCount, material);
276
- __publicField(this, "uniformsTexture");
277
- __publicField(this, "isMaterialPatched", false);
278
- __publicField(this, "uniformSchema", {});
279
- __publicField(this, "boundsNeedsUpdate", false);
280
- // Multi_draw with index causes excessive memory consumption on renderer process
281
- // TODO: Create issue in three.js repo
282
- __publicField(this, "useMultiDraw", false);
283
- __publicField(this, "useIndex", false);
284
- __publicField(this, "batchCount", 0);
285
- __publicField(this, "indexBuffer");
286
- __publicField(this, "geometryById", /* @__PURE__ */ new Map());
287
- __publicField(this, "mapGeometryToInstanceId", /* @__PURE__ */ new Map());
288
- material.forceSinglePass = true;
289
- addDim(this);
290
- this.addEventListener("added", () => {
291
- if (!this.useIndex && this.geometry.index !== null) {
292
- this.geometry = this.geometry.toNonIndexed();
293
- this.resizeToFitGeometry(this.geometry);
148
+ class Text extends Text$1 {
149
+ _prepareForRender(material) {
150
+ const isOutline = material.isTextOutlineMaterial;
151
+ const uniforms = material.uniforms;
152
+ const textInfo = this.textRenderInfo;
153
+ if (textInfo) {
154
+ const { sdfTexture, blockBounds } = textInfo;
155
+ const { width, height } = sdfTexture.image;
156
+ uniforms.uTroikaSDFTexture.value = sdfTexture;
157
+ uniforms.uTroikaSDFTextureSize.value.set(width, height);
158
+ uniforms.uTroikaSDFGlyphSize.value = textInfo.sdfGlyphSize;
159
+ uniforms.uTroikaSDFExponent.value = textInfo.sdfExponent;
160
+ uniforms.uTroikaTotalBounds.value.fromArray(blockBounds);
161
+ uniforms.uTroikaUseGlyphColors.value = !isOutline && !!textInfo.glyphColors;
162
+ let distanceOffset = 0;
163
+ let blurRadius = 0;
164
+ let strokeWidth = 0;
165
+ let fillOpacity;
166
+ let strokeOpacity = 1;
167
+ let strokeColor;
168
+ let offsetX = 0;
169
+ let offsetY = 0;
170
+ if (isOutline) {
171
+ const { outlineWidth, outlineOffsetX, outlineOffsetY, outlineBlur, outlineOpacity } = this;
172
+ distanceOffset = this._parsePercent(outlineWidth) || 0;
173
+ blurRadius = Math.max(0, this._parsePercent(outlineBlur) || 0);
174
+ fillOpacity = outlineOpacity;
175
+ offsetX = this._parsePercent(outlineOffsetX) || 0;
176
+ offsetY = this._parsePercent(outlineOffsetY) || 0;
177
+ } else {
178
+ strokeWidth = Math.max(0, this._parsePercent(this.strokeWidth) || 0);
179
+ if (strokeWidth) {
180
+ strokeColor = this.strokeColor;
181
+ uniforms.uTroikaStrokeColor.value.set(strokeColor ?? defaultStrokeColor);
182
+ strokeOpacity = this.strokeOpacity;
183
+ strokeOpacity ?? (strokeOpacity = 1);
184
+ }
185
+ fillOpacity = this.fillOpacity;
294
186
  }
295
- });
296
- }
297
- /**
298
- * Appends uniform definitions to the current schema, and creates a new {@link SquareDataTexture} if needed.
299
- * @param schema description of per-instance uniforms by shader stage (vertex/fragment)
300
- */
301
- addPerInstanceUniforms(schema) {
302
- this.uniformSchema = deepMerge(this.uniformSchema, schema);
303
- const parsedSchema = this.parseUniformSchema(this.uniformSchema);
304
- if (this.uniformsTexture) this.uniformsTexture.dispose();
305
- this.uniformsTexture = new SquareDataTexture(
306
- Float32Array,
307
- parsedSchema.channels,
308
- parsedSchema.texelsPerInstance,
309
- this.maxInstanceCount,
310
- parsedSchema.uniformMap,
311
- parsedSchema.fetchInFragmentShader
312
- );
313
- }
314
- addGeometry(geometry, reservedVertexRange, reservedIndexRange) {
315
- if (this.useMultiDraw) return super.addGeometry(geometry, reservedVertexRange, reservedIndexRange);
316
- this.addBatchIdBuffer(geometry, this.instanceCount);
317
- const geometryId = super.addGeometry(geometry, reservedVertexRange, reservedIndexRange);
318
- this.geometryById.set(geometryId, geometry);
319
- return geometryId;
320
- }
321
- addInstance(geometryId) {
322
- if (this.useMultiDraw) return super.addInstance(geometryId);
323
- if (this.mapGeometryToInstanceId.has(geometryId)) {
324
- const geometry = this.geometryById.get(geometryId);
325
- this.resizeToFitGeometry(geometry);
326
- geometryId = this.addGeometry(geometry);
187
+ uniforms.uTroikaEdgeOffset.value = distanceOffset;
188
+ uniforms.uTroikaPositionOffset.value.set(offsetX, offsetY);
189
+ uniforms.uTroikaBlurRadius.value = blurRadius;
190
+ uniforms.uTroikaStrokeWidth.value = strokeWidth;
191
+ uniforms.uTroikaStrokeOpacity.value = strokeOpacity;
192
+ uniforms.uTroikaFillOpacity.value = fillOpacity ?? 1;
193
+ uniforms.uTroikaCurveRadius.value = this.curveRadius || 0;
194
+ const clipRect = this.clipRect;
195
+ if (clipRect && Array.isArray(clipRect) && clipRect.length === 4) {
196
+ uniforms.uTroikaClipRect.value.fromArray(clipRect);
197
+ } else {
198
+ const pad = (this.fontSize || 0.1) * 100;
199
+ uniforms.uTroikaClipRect.value.set(
200
+ blockBounds[0] - pad,
201
+ blockBounds[1] - pad,
202
+ blockBounds[2] + pad,
203
+ blockBounds[3] + pad
204
+ );
205
+ }
206
+ this.geometry.applyClipRect(uniforms.uTroikaClipRect.value);
327
207
  }
328
- const instanceId = super.addInstance(geometryId);
329
- this.mapGeometryToInstanceId.set(geometryId, instanceId);
330
- return instanceId;
331
- }
332
- onBeforeRender(renderer, scene, camera, geometry, material, group) {
333
- var _a2;
334
- if (!this.isMaterialPatched) this.patchMaterial(material);
335
- (_a2 = this.uniformsTexture) == null ? void 0 : _a2.update();
336
- if (this.useMultiDraw) return super.onBeforeRender(renderer, scene, camera, geometry, material, group);
337
- if (!this.indexBuffer) {
338
- const vertexCount = geometry.getAttribute("position").count;
339
- this.indexBuffer = new BufferAttribute(new Uint32Array(vertexCount), 1).setUsage(StreamDrawUsage);
208
+ uniforms.uTroikaSDFDebug.value = !!this.debugSDF;
209
+ material.polygonOffset = !!this.depthOffset;
210
+ material.polygonOffsetFactor = material.polygonOffsetUnits = this.depthOffset || 0;
211
+ const color = isOutline ? this.outlineColor || 0 : this.color;
212
+ if (color == null) {
213
+ delete material.color;
214
+ } else {
215
+ const colorObj = material.hasOwnProperty("color") ? material.color : material.color = new Color();
216
+ if (color !== colorObj._input || typeof color === "object") {
217
+ colorObj.set(colorObj._input = color);
218
+ }
219
+ }
220
+ let orient = this.orientation || defaultOrient;
221
+ if (orient !== material._orientation) {
222
+ const rotMat = uniforms.uTroikaOrient.value;
223
+ orient = orient.replace(/[^-+xyz]/g, "");
224
+ const match = orient !== defaultOrient && /^([-+])([xyz])([-+])([xyz])$/.exec(orient);
225
+ if (match) {
226
+ const [, hSign, hAxis, vSign, vAxis] = match;
227
+ tempVec3a.set(0, 0, 0)[hAxis] = hSign === "-" ? 1 : -1;
228
+ tempVec3b.set(0, 0, 0)[vAxis] = vSign === "-" ? -1 : 1;
229
+ tempMat4.lookAt(origin, tempVec3a.cross(tempVec3b), tempVec3b);
230
+ rotMat.setFromMatrix4(tempMat4);
231
+ } else {
232
+ rotMat.identity();
233
+ }
234
+ material._orientation = orient;
340
235
  }
341
- super.onBeforeRender(renderer, scene, camera, geometry, material, group);
342
- this.batchCount = this.updateIndexBuffer(geometry);
343
- this._multiDrawCount = 0;
344
236
  }
345
- onAfterRender(renderer, scene, camera, geometry) {
346
- var _a2;
347
- if (this.useMultiDraw) return;
348
- const batchCount = this.batchCount;
349
- const gl = renderer.getContext();
350
- if (geometry.index == null) return console.warn("No index buffer", (_a2 = this.parent) == null ? void 0 : _a2.name);
351
- const type = this.getIndexType(gl, geometry.index);
352
- gl.drawElements(gl.TRIANGLES, batchCount, type, 0);
353
- renderer.info.update(batchCount, gl.TRIANGLES, 1);
354
- geometry.setIndex(null);
237
+ }
238
+ function setDimming(root, dim) {
239
+ root.userData["uDim"] = dim === void 0 ? void 0 : +dim;
240
+ }
241
+ function toggleInstanceDim(object, instanceId, dim) {
242
+ const value = dim === void 0 ? 0 : (+dim - 0.5) * 2;
243
+ if (object instanceof BatchedMesh) {
244
+ object.setUniformAt(instanceId, "skipDimInstance", value);
245
+ return;
355
246
  }
356
- /**
357
- * Retrieves the value of a uniform at the specified instance ID.
247
+ const skipDimTexture = object.userData["skipDimTexture"];
248
+ if (skipDimTexture) {
249
+ const skipDimData = skipDimTexture.image.data;
250
+ skipDimData[instanceId] = value;
251
+ skipDimTexture.needsUpdate = true;
252
+ }
253
+ }
254
+ function addDimToMaterial(material) {
255
+ if (material.userData.hasDimShader) return;
256
+ const onBeforeCompile = material.onBeforeCompile.bind(material);
257
+ const onBeforeRender = material.onBeforeRender.bind(material);
258
+ material.onBeforeCompile = (shader, renderer) => {
259
+ onBeforeCompile(shader, renderer);
260
+ shader.uniforms["uDim"] = { value: material.userData.uDim ?? 0 };
261
+ shader.uniforms["skipDimTexture"] = { value: material.userData.skipDimTexture ?? null };
262
+ shader.vertexShader = shader.vertexShader.replace("void main() {", `${dimColorVertexDefs}
263
+ void main() {`).replace(
264
+ "#include <fog_vertex>",
265
+ /*glsl*/
266
+ `
267
+ #include <fog_vertex>
268
+ setDimAmount();
269
+ `
270
+ ).concat(dimColorVertexImpl);
271
+ shader.fragmentShader = /*glsl*/
272
+ `
273
+ ${dimColorFrag}
274
+ ${shader.fragmentShader}
275
+ `.replace(
276
+ "#include <colorspace_fragment>",
277
+ /*glsl*/
278
+ `
279
+ gl_FragColor = dimColor(gl_FragColor);
280
+ #include <colorspace_fragment>
281
+ `
282
+ );
283
+ material.userData.shader = shader;
284
+ };
285
+ material.onBeforeRender = (renderer, scene, camera, geometry, object, group) => {
286
+ onBeforeRender(renderer, scene, camera, geometry, object, group);
287
+ const skipDimTexture = object.userData["skipDimTexture"];
288
+ let uDim = object.userData["uDim"];
289
+ if (uDim === void 0) {
290
+ for (const ancestor of traverseAncestorsGenerator(object)) {
291
+ if (ancestor.userData["uDim"] !== void 0) {
292
+ uDim = ancestor.userData["uDim"];
293
+ break;
294
+ }
295
+ }
296
+ }
297
+ const shader = material.userData.shader;
298
+ if (!shader) {
299
+ material.userData.uDim = uDim;
300
+ material.userData.skipDimTexture = object.userData["skipDimTexture"];
301
+ return;
302
+ }
303
+ shader.uniforms["uDim"].value = uDim ?? 0;
304
+ shader.uniforms["skipDimTexture"].value = skipDimTexture ?? null;
305
+ };
306
+ material.userData.hasDimShader = true;
307
+ }
308
+ function addDim(mesh) {
309
+ if (mesh instanceof BatchedMesh) mesh.addPerInstanceUniforms({ vertex: { skipDimInstance: "float" } });
310
+ if (mesh instanceof BatchedText) addSkipDimTexture(mesh);
311
+ }
312
+ function addSkipDimTexture(text) {
313
+ const count = text.size;
314
+ const size = Math.ceil(Math.sqrt(count));
315
+ const array = new Float32Array(size * size);
316
+ array.fill(0);
317
+ const texture = new DataTexture(array, size, size, RedFormat, FloatType);
318
+ texture.needsUpdate = true;
319
+ text.userData["skipDimTexture"] = texture;
320
+ text.addEventListener("dispose", () => texture.dispose());
321
+ return texture;
322
+ }
323
+ const dimColorVertexDefs = (
324
+ /*glsl*/
325
+ `
326
+ uniform float uDim;
327
+ out float dimAmount;
328
+ #ifdef TROIKA_DERIVED_MATERIAL_1
329
+ uniform sampler2D skipDimTexture;
330
+ #endif
331
+ void setDimAmount();
332
+ `
333
+ );
334
+ const dimColorVertexImpl = (
335
+ /*glsl*/
336
+ `
337
+ void setDimAmount() {
338
+ float instanceDim = 0.;
339
+ #ifdef USE_BATCH_UNIFORMS
340
+ instanceDim = batch_skipDimInstance;
341
+ #endif
342
+ #ifdef TROIKA_DERIVED_MATERIAL_1
343
+ float indirectIndex = aTroikaTextBatchMemberIndex;
344
+ int size = textureSize(skipDimTexture, 0).x;
345
+ int i = int(indirectIndex);
346
+ int x = i % size;
347
+ int y = i / size;
348
+ instanceDim = texelFetch(skipDimTexture, ivec2(x, y), 0).r;
349
+ #endif
350
+ dimAmount = instanceDim == 0. ? uDim : instanceDim / 2. + 0.5;
351
+ }
352
+ `
353
+ );
354
+ const dimColorFrag = (
355
+ /*glsl*/
356
+ `
357
+ in float dimAmount;
358
+
359
+ const vec3 grayWeights = vec3(0.299, 0.587, 0.114);
360
+ const float darkenFactor = pow(2., 2.2); // Gamma corrected
361
+
362
+ vec4 dimColor(vec4 col) {
363
+ vec3 color = col.rgb / col.a;
364
+ vec3 gray = vec3(dot(grayWeights, color));
365
+ vec3 m = mix(color, gray / darkenFactor, dimAmount);
366
+ return vec4(m * col.a, col.a);
367
+ }`
368
+ );
369
+ function isObject(item) {
370
+ return !!item && typeof item === "object" && !Array.isArray(item);
371
+ }
372
+ function deepMerge(target, ...sources) {
373
+ if (!sources.length) return target;
374
+ const source = sources.shift();
375
+ if (source === void 0) {
376
+ return target;
377
+ }
378
+ if (isObject(target) && isObject(source)) {
379
+ for (const key in source) {
380
+ if (isObject(source[key])) {
381
+ if (!target[key]) {
382
+ Object.assign(target, { [key]: {} });
383
+ }
384
+ deepMerge(target[key], source[key]);
385
+ } else {
386
+ Object.assign(target, { [key]: source[key] });
387
+ }
388
+ }
389
+ }
390
+ return deepMerge(target, ...sources);
391
+ }
392
+ function getSquareTextureSize(capacity, pixelsPerInstance) {
393
+ return Math.max(pixelsPerInstance, Math.ceil(Math.sqrt(capacity / pixelsPerInstance)) * pixelsPerInstance);
394
+ }
395
+ function getSquareTextureInfo(arrayType, channels, pixelsPerInstance, capacity) {
396
+ if (channels === 3) {
397
+ console.warn('"channels" cannot be 3. Set to 4. More info: https://github.com/mrdoob/three.js/pull/23228');
398
+ channels = 4;
399
+ }
400
+ const size = getSquareTextureSize(capacity, pixelsPerInstance);
401
+ const array = new arrayType(size * size * channels);
402
+ const isFloat = arrayType.name.includes("Float");
403
+ const isUnsignedInt = arrayType.name.includes("Uint");
404
+ const type = isFloat ? FloatType : isUnsignedInt ? UnsignedIntType : IntType;
405
+ let format;
406
+ switch (channels) {
407
+ case 1:
408
+ format = isFloat ? RedFormat : RedIntegerFormat;
409
+ break;
410
+ case 2:
411
+ format = isFloat ? RGFormat : RGIntegerFormat;
412
+ break;
413
+ case 4:
414
+ format = isFloat ? RGBAFormat : RGBAIntegerFormat;
415
+ break;
416
+ }
417
+ return { array, size, type, format };
418
+ }
419
+ class SquareDataTexture extends DataTexture {
420
+ /**
421
+ * @param arrayType The constructor for the TypedArray.
422
+ * @param channels The number of channels in the texture.
423
+ * @param pixelsPerInstance The number of pixels required for each instance.
424
+ * @param capacity The total number of instances.
425
+ * @param uniformMap Optional map for handling uniform values.
426
+ * @param fetchInFragmentShader Optional flag that determines if uniform values should be fetched in the fragment shader instead of the vertex shader.
427
+ */
428
+ constructor(arrayType, channels, pixelsPerInstance, capacity, uniformMap, fetchInFragmentShader) {
429
+ if (channels === 3) channels = 4;
430
+ const { array, format, size, type } = getSquareTextureInfo(arrayType, channels, pixelsPerInstance, capacity);
431
+ super(array, size, size, format, type);
432
+ __publicField(this, "data");
433
+ __publicField(this, "channels");
434
+ __publicField(this, "pixelsPerInstance");
435
+ __publicField(this, "stride");
436
+ __publicField(this, "uniformMap");
437
+ __publicField(this, "fetchUniformsInFragmentShader");
438
+ __publicField(this, "uniformPrefix", "batch_");
439
+ this.data = array;
440
+ this.channels = channels;
441
+ this.pixelsPerInstance = pixelsPerInstance;
442
+ this.stride = pixelsPerInstance * channels;
443
+ this.uniformMap = uniformMap;
444
+ this.fetchUniformsInFragmentShader = fetchInFragmentShader;
445
+ this.needsUpdate = true;
446
+ }
447
+ /**
448
+ * Sets a uniform value at the specified instance ID in the texture.
449
+ * @param id The instance ID to set the uniform for.
450
+ * @param name The name of the uniform.
451
+ * @param value The value to set for the uniform.
452
+ */
453
+ setUniformAt(id, name, value) {
454
+ const schema = this.uniformMap.get(name);
455
+ if (!schema) {
456
+ console.warn(`SquareDataTexture.setUniformAt: uniform ${name} not found`);
457
+ return;
458
+ }
459
+ const { offset, size } = schema;
460
+ const stride = this.stride;
461
+ if (size === 1) {
462
+ this.data[id * stride + offset] = value;
463
+ } else {
464
+ value.toArray(this.data, id * stride + offset);
465
+ }
466
+ }
467
+ /**
468
+ * Retrieves a uniform value at the specified instance ID from the texture.
469
+ * @param id The instance ID to retrieve the uniform from.
470
+ * @param name The name of the uniform.
471
+ * @param target Optional target object to store the uniform value.
472
+ * @returns The uniform value for the specified instance.
473
+ */
474
+ getUniformAt(id, name, target) {
475
+ const schema = this.uniformMap.get(name);
476
+ if (!schema) {
477
+ console.warn(`SquareDataTexture.getUniformAt: uniform ${name} not found`);
478
+ return 0;
479
+ }
480
+ const { offset, size } = schema;
481
+ const stride = this.stride;
482
+ if (size === 1) {
483
+ return this.data[id * stride + offset];
484
+ }
485
+ return target.fromArray(this.data, id * stride + offset);
486
+ }
487
+ /** Mark the texture as needing an update. */
488
+ update() {
489
+ this.needsUpdate = true;
490
+ }
491
+ /**
492
+ * Generates the GLSL code for accessing the uniform data stored in the texture.
493
+ * @param textureName The name of the texture in the GLSL shader.
494
+ * @param indexName The name of the index in the GLSL shader.
495
+ * @param indexType The type of the index in the GLSL shader.
496
+ * @returns An object containing the GLSL code for the vertex and fragment shaders.
497
+ */
498
+ getUniformsGLSL(textureName, indexName, indexType) {
499
+ const vertex = this.getUniformsVertexGLSL(textureName, indexName, indexType);
500
+ const fragment = this.getUniformsFragmentGLSL(textureName, indexName, indexType);
501
+ return { vertex, fragment };
502
+ }
503
+ getUniformsVertexGLSL(textureName, indexName, indexType) {
504
+ if (this.fetchUniformsInFragmentShader) {
505
+ return (
506
+ /*glsl*/
507
+ `
508
+ varying ${indexType} ${this.uniformPrefix}${indexName};
509
+ void main() {
510
+ ${this.uniformPrefix}${indexName} = ${indexName};
511
+ `
512
+ );
513
+ }
514
+ const texelsFetch = this.texelsFetchGLSL(textureName, indexName);
515
+ const getFromTexels = this.getFromTexelsGLSL();
516
+ const { assignVarying, declareVarying } = this.getVarying();
517
+ return (
518
+ /*glsl*/
519
+ `
520
+ uniform highp sampler2D ${textureName};
521
+ ${declareVarying}
522
+ void main() {
523
+ #ifdef USE_BATCHING
524
+ ${indexType} ${indexName} = ${indexType}(getIndirectIndex(gl_DrawID));
525
+ #endif
526
+ ${texelsFetch}
527
+ ${getFromTexels}
528
+ ${assignVarying}`
529
+ );
530
+ }
531
+ getUniformsFragmentGLSL(textureName, indexName, indexType) {
532
+ if (!this.fetchUniformsInFragmentShader) {
533
+ const { declareVarying, getVarying } = this.getVarying();
534
+ return (
535
+ /*glsl*/
536
+ `
537
+ ${declareVarying}
538
+ void main() {
539
+ ${getVarying}`
540
+ );
541
+ }
542
+ const texelsFetch = this.texelsFetchGLSL(textureName, `${this.uniformPrefix}${indexName}`);
543
+ const getFromTexels = this.getFromTexelsGLSL();
544
+ return (
545
+ /*glsl*/
546
+ `
547
+ uniform highp sampler2D ${textureName};
548
+ varying ${indexType} ${this.uniformPrefix}${indexName};
549
+ void main() {
550
+ ${texelsFetch}
551
+ ${getFromTexels}`
552
+ );
553
+ }
554
+ texelsFetchGLSL(textureName, indexName) {
555
+ const pixelsPerInstance = this.pixelsPerInstance;
556
+ let texelsFetch = (
557
+ /*glsl*/
558
+ `
559
+ int size = textureSize(${textureName}, 0).x;
560
+ int j = int(${indexName}) * ${pixelsPerInstance};
561
+ int x = j % size;
562
+ int y = j / size;
563
+ `
564
+ );
565
+ for (let i = 0; i < pixelsPerInstance; i++) {
566
+ texelsFetch += /*glsl*/
567
+ `vec4 ${this.uniformPrefix}texel${i} = texelFetch(${textureName}, ivec2(x + ${i}, y), 0);
568
+ `;
569
+ }
570
+ return texelsFetch;
571
+ }
572
+ getFromTexelsGLSL() {
573
+ const uniforms = this.uniformMap;
574
+ let getFromTexels = "";
575
+ for (const [name, { type, offset, size }] of uniforms) {
576
+ const tId = Math.floor(offset / this.channels);
577
+ if (type === "mat3") {
578
+ getFromTexels += /*glsl*/
579
+ `mat3 ${name} = mat3(${this.uniformPrefix}texel${tId}.rgb, vec3(${this.uniformPrefix}texel${tId}.a, ${this.uniformPrefix}texel${tId + 1}.rg), vec3(${this.uniformPrefix}texel${tId + 1}.ba, ${this.uniformPrefix}texel${tId + 2}.r));
580
+ `;
581
+ } else if (type === "mat4") {
582
+ getFromTexels += /*glsl*/
583
+ `mat4 ${name} = mat4(${this.uniformPrefix}texel${tId}, ${this.uniformPrefix}texel${tId + 1}, ${this.uniformPrefix}texel${tId + 2}, ${this.uniformPrefix}texel${tId + 3});
584
+ `;
585
+ } else {
586
+ const components = this.getUniformComponents(offset, size);
587
+ getFromTexels += /*glsl*/
588
+ `${type} ${name} = ${this.uniformPrefix}texel${tId}.${components};
589
+ `;
590
+ }
591
+ }
592
+ return getFromTexels;
593
+ }
594
+ getVarying() {
595
+ const uniforms = this.uniformMap;
596
+ let declareVarying = "";
597
+ let assignVarying = "";
598
+ let getVarying = "";
599
+ for (const [name, { type }] of uniforms) {
600
+ declareVarying += /*glsl*/
601
+ `varying ${type} ${this.uniformPrefix}${name};
602
+ `;
603
+ assignVarying += /*glsl*/
604
+ `${this.uniformPrefix}${name} = ${name};
605
+ `;
606
+ getVarying += /*glsl*/
607
+ `${type} ${name} = ${this.uniformPrefix}${name};
608
+ `;
609
+ }
610
+ return { declareVarying, assignVarying, getVarying };
611
+ }
612
+ getUniformComponents(offset, size) {
613
+ const startIndex = offset % this.channels;
614
+ let components = "";
615
+ for (let i = 0; i < size; i++) {
616
+ components += componentsArray[startIndex + i];
617
+ }
618
+ return components;
619
+ }
620
+ }
621
+ const componentsArray = ["r", "g", "b", "a"];
622
+ const batchIdName = "batchId";
623
+ const _BatchedMesh = class _BatchedMesh extends BatchedMesh$1 {
624
+ /**
625
+ * @param instanceCount the max number of individual geometries planned to be added.
626
+ * @param vertexCount the max number of vertices to be used by all geometries.
627
+ * @param indexCount the max number of indices to be used by all geometries.
628
+ * @param material an instance of {@link Material}. Default is a new {@link MeshBasicMaterial}.
629
+ */
630
+ constructor(instanceCount, vertexCount, indexCount, material) {
631
+ super(instanceCount, vertexCount, indexCount, material);
632
+ __publicField(this, "uniformsTexture");
633
+ __publicField(this, "uniformSchema", {});
634
+ __publicField(this, "isMaterialPatched", false);
635
+ __publicField(this, "boundsNeedsUpdate", false);
636
+ __publicField(this, "batchCount", 0);
637
+ __publicField(this, "indexBuffer");
638
+ __publicField(this, "geometryById", /* @__PURE__ */ new Map());
639
+ __publicField(this, "mapGeometryToInstanceId", /* @__PURE__ */ new Map());
640
+ material.forceSinglePass = true;
641
+ addDim(this);
642
+ this.addEventListener("added", () => {
643
+ if (!_BatchedMesh.useMultiDraw && this.geometry.index !== null) {
644
+ this.geometry = this.geometry.toNonIndexed();
645
+ this.resizeToFitGeometry(this.geometry);
646
+ }
647
+ });
648
+ }
649
+ /**
650
+ * Appends uniform definitions to the current schema, and creates a new {@link SquareDataTexture} if needed.
651
+ * @param schema description of per-instance uniforms by shader stage (vertex/fragment)
652
+ */
653
+ addPerInstanceUniforms(schema) {
654
+ this.uniformSchema = deepMerge(this.uniformSchema, schema);
655
+ const parsedSchema = this.parseUniformSchema(this.uniformSchema);
656
+ if (this.uniformsTexture) this.uniformsTexture.dispose();
657
+ this.uniformsTexture = new SquareDataTexture(
658
+ Float32Array,
659
+ parsedSchema.channels,
660
+ parsedSchema.texelsPerInstance,
661
+ this.maxInstanceCount,
662
+ parsedSchema.uniformMap,
663
+ parsedSchema.fetchInFragmentShader
664
+ );
665
+ if (!this.isMaterialPatched) this.patchMaterial(this.material);
666
+ }
667
+ addGeometry(geometry, reservedVertexRange, reservedIndexRange) {
668
+ if (_BatchedMesh.useMultiDraw) return super.addGeometry(geometry, reservedVertexRange, reservedIndexRange);
669
+ this.addBatchIdBuffer(geometry, this.instanceCount);
670
+ const geometryId = super.addGeometry(geometry, reservedVertexRange, reservedIndexRange);
671
+ this.geometryById.set(geometryId, geometry);
672
+ return geometryId;
673
+ }
674
+ addInstance(geometryId) {
675
+ if (_BatchedMesh.useMultiDraw) return super.addInstance(geometryId);
676
+ if (this.mapGeometryToInstanceId.has(geometryId)) {
677
+ const geometry = this.geometryById.get(geometryId);
678
+ this.resizeToFitGeometry(geometry);
679
+ geometryId = this.addGeometry(geometry);
680
+ }
681
+ const instanceId = super.addInstance(geometryId);
682
+ this.mapGeometryToInstanceId.set(geometryId, instanceId);
683
+ return instanceId;
684
+ }
685
+ onBeforeRender(renderer, scene, camera, geometry, material, group) {
686
+ var _a2;
687
+ (_a2 = this.uniformsTexture) == null ? void 0 : _a2.update();
688
+ if (_BatchedMesh.useMultiDraw) return super.onBeforeRender(renderer, scene, camera, geometry, material, group);
689
+ if (!this.indexBuffer) {
690
+ const vertexCount = geometry.getAttribute("position").count;
691
+ this.indexBuffer = new BufferAttribute(new Uint32Array(vertexCount), 1).setUsage(StreamDrawUsage);
692
+ }
693
+ super.onBeforeRender(renderer, scene, camera, geometry, material, group);
694
+ this.batchCount = this.updateIndexBuffer(geometry);
695
+ this._multiDrawCount = 0;
696
+ }
697
+ onAfterRender(renderer, scene, camera, geometry) {
698
+ var _a2;
699
+ if (_BatchedMesh.useMultiDraw) return;
700
+ const batchCount = this.batchCount;
701
+ const gl = renderer.getContext();
702
+ if (geometry.index == null) return console.warn("No index buffer", (_a2 = this.parent) == null ? void 0 : _a2.name);
703
+ const type = this.getIndexType(gl, geometry.index);
704
+ gl.drawElements(gl.TRIANGLES, batchCount, type, 0);
705
+ renderer.info.update(batchCount, gl.TRIANGLES, 1);
706
+ geometry.setIndex(null);
707
+ }
708
+ /**
709
+ * Retrieves the value of a uniform at the specified instance ID.
358
710
  * @param id instance ID
359
711
  * @param name uniform name
360
712
  * @param target Optional target object to store the uniform value
@@ -388,530 +740,179 @@ class BatchedMesh extends BatchedMesh$1 {
388
740
  this.boundsNeedsUpdate = false;
389
741
  }
390
742
  }
391
- setMatrixAt(instanceId, matrix) {
392
- super.setMatrixAt(instanceId, matrix);
393
- this.boundsNeedsUpdate = true;
394
- return this;
395
- }
396
- dispose() {
397
- var _a2;
398
- this.geometry.setIndex(this.indexBuffer ?? null);
399
- super.dispose();
400
- this.uniformSchema = {};
401
- (_a2 = this.uniformsTexture) == null ? void 0 : _a2.dispose();
402
- this.uniformsTexture = void 0;
403
- this.indexBuffer = void 0;
404
- this.geometryById.forEach((geometry) => geometry.dispose());
405
- this.geometryById.clear();
406
- this.mapGeometryToInstanceId.clear();
407
- return this;
408
- }
409
- resizeToFitGeometry(geometry) {
410
- var _a2;
411
- const vertexCount = geometry.attributes["position"].count;
412
- const indexCount = ((_a2 = geometry.index) == null ? void 0 : _a2.count) ?? 0;
413
- this._maxVertexCount += vertexCount;
414
- this._maxIndexCount += indexCount;
415
- this.setGeometrySize(this._maxVertexCount, this._maxIndexCount);
416
- }
417
- updateIndexBuffer(geometry) {
418
- const { _multiDrawStarts, _multiDrawCounts, _multiDrawCount } = this;
419
- const indexBuffer = this.indexBuffer;
420
- const indexArray = indexBuffer.array;
421
- const batchIdBuffer = geometry.getAttribute(batchIdName);
422
- const batchIdArray = batchIdBuffer.array;
423
- const indirectArray = this._indirectTexture.image.data;
424
- let indexCount = 0;
425
- for (let i = 0; i < _multiDrawCount; i++) {
426
- const start = _multiDrawStarts[i];
427
- const count = _multiDrawCounts[i];
428
- const batchId = batchIdArray[start];
429
- indirectArray[batchId] = batchId;
430
- for (let j = start; j < start + count; j++) {
431
- indexArray[indexCount++] = j;
432
- }
433
- }
434
- indexBuffer.needsUpdate = true;
435
- geometry.setIndex(indexBuffer);
436
- return indexCount;
437
- }
438
- addBatchIdBuffer(geometry, geometryId) {
439
- const hasAttribute = geometry.hasAttribute(batchIdName);
440
- const vertexCount = geometry.getAttribute("position").count;
441
- const batchIdArray = hasAttribute ? geometry.getAttribute(batchIdName).array : new Int32Array(vertexCount);
442
- for (let i = 0; i < vertexCount; i++) {
443
- batchIdArray[i] = geometryId;
444
- }
445
- if (!hasAttribute) {
446
- const batchIdBuffer = new BufferAttribute(batchIdArray, 1).setUsage(StreamDrawUsage);
447
- geometry.setAttribute(batchIdName, batchIdBuffer);
448
- }
449
- }
450
- patchMaterial(material) {
451
- const onBeforeCompile = material.onBeforeCompile.bind(material);
452
- const customProgramCacheKey = material.customProgramCacheKey.bind(material);
453
- material.onBeforeCompile = (shader, renderer) => {
454
- var _a2;
455
- onBeforeCompile(shader, renderer);
456
- shader.defines ?? (shader.defines = {});
457
- shader.defines["USE_BATCH_UNIFORMS"] = "";
458
- shader.uniforms["uniformsTexture"] = { value: this.uniformsTexture };
459
- const { vertex, fragment } = ((_a2 = this.uniformsTexture) == null ? void 0 : _a2.getUniformsGLSL("uniformsTexture", "instanceId", "int")) ?? {
460
- vertex: "",
461
- fragment: ""
462
- };
463
- const patch = (
464
- /*glsl*/
465
- `
466
- #ifdef gl_DrawID
467
- #define _gl_DrawID ${batchIdName}
468
- #else
469
- #define gl_DrawID ${batchIdName}
470
- #endif
471
- in int ${batchIdName};
472
- `
473
- );
474
- const main = "void main() {";
475
- if (!this.useMultiDraw) shader.vertexShader = shader.vertexShader.replace(main, `${patch}${main}`);
476
- if (vertex) shader.vertexShader = shader.vertexShader.replace(main, vertex);
477
- if (fragment) shader.fragmentShader = shader.fragmentShader.replace(main, fragment);
478
- };
479
- material.customProgramCacheKey = () => {
480
- return `batch_${this.id}_${!!this.uniformsTexture}_${customProgramCacheKey()}`;
481
- };
482
- this.isMaterialPatched = true;
483
- }
484
- // Taken from https://github.com/agargaro/instanced-mesh/blob/master/src/core/feature/Uniforms.ts
485
- parseUniformSchema(schema) {
486
- let totalSize = 0;
487
- const uniformMap = /* @__PURE__ */ new Map();
488
- const uniforms = [];
489
- const vertexSchema = schema.vertex ?? {};
490
- const fragmentSchema = schema.fragment ?? {};
491
- let fetchInFragmentShader = true;
492
- for (const name in vertexSchema) {
493
- const type = vertexSchema[name];
494
- const size = this.getUniformSize(type);
495
- totalSize += size;
496
- uniforms.push({ name, type, size });
497
- fetchInFragmentShader = false;
498
- }
499
- for (const name in fragmentSchema) {
500
- if (!vertexSchema[name]) {
501
- const type = fragmentSchema[name];
502
- const size = this.getUniformSize(type);
503
- totalSize += size;
504
- uniforms.push({ name, type, size });
505
- }
506
- }
507
- uniforms.sort((a, b) => b.size - a.size);
508
- const tempOffset = [];
509
- for (const { name, size, type } of uniforms) {
510
- const offset = this.getUniformOffset(size, tempOffset);
511
- uniformMap.set(name, { offset, size, type });
512
- }
513
- const pixelsPerInstance = Math.ceil(totalSize / 4);
514
- const channels = Math.min(totalSize, 4);
515
- return { channels, texelsPerInstance: pixelsPerInstance, uniformMap, fetchInFragmentShader };
516
- }
517
- getUniformOffset(size, tempOffset) {
518
- if (size < 4) {
519
- for (let i = 0; i < tempOffset.length; i++) {
520
- if (tempOffset[i] + size <= 4) {
521
- const offset2 = i * 4 + tempOffset[i];
522
- tempOffset[i] += size;
523
- return offset2;
524
- }
525
- }
526
- }
527
- const offset = tempOffset.length * 4;
528
- for (; size > 0; size -= 4) {
529
- tempOffset.push(size);
530
- }
531
- return offset;
532
- }
533
- getUniformSize(type) {
534
- switch (type) {
535
- case "float":
536
- return 1;
537
- case "vec2":
538
- return 2;
539
- case "vec3":
540
- return 3;
541
- case "vec4":
542
- return 4;
543
- case "mat3":
544
- return 9;
545
- case "mat4":
546
- return 16;
547
- }
548
- }
549
- getIndexType(gl, index) {
550
- const array = index.array;
551
- if (array instanceof Uint16Array) return gl.UNSIGNED_SHORT;
552
- if (array instanceof Uint32Array) return gl.UNSIGNED_INT;
553
- return gl.UNSIGNED_BYTE;
554
- }
555
- }
556
- const floatsPerMember = 32;
557
- const tempColor = new Color();
558
- const defaultStrokeColor = 8421504;
559
- const tempMat4 = new Matrix4();
560
- const tempVec3a = new Vector3();
561
- const tempVec3b = new Vector3();
562
- const origin = new Vector3();
563
- const defaultOrient = "+x+y";
564
- class BatchedText extends BatchedText$1 {
565
- // eslint-disable-next-line jsdoc/require-jsdoc
566
- constructor() {
567
- super();
568
- __publicField(this, "mapInstanceIdToText", /* @__PURE__ */ new Map());
569
- __publicField(this, "textArray", []);
570
- __publicField(this, "textureNeedsUpdate", false);
571
- }
572
- /** Number of texts in the batch */
573
- get size() {
574
- return this._members.size;
575
- }
576
- /** Base material before patching */
577
- get baseMaterial() {
578
- return this._baseMaterial;
579
- }
580
- /**
581
- * Get the {@link Text} object by instance id
582
- * @param instanceId Instance id
583
- * @returns Text object
584
- */
585
- getText(instanceId) {
586
- return this.mapInstanceIdToText.get(instanceId);
587
- }
588
- /**
589
- * Set the visibility of the {@link Text} object by instance id.
590
- * This is for interface compatibility with {@link BatchedMesh}.
591
- * @param instanceId Instance id
592
- * @param visible Visibility flag
593
- */
594
- setVisibleAt(instanceId, visible) {
595
- const text = this.getText(instanceId);
596
- text.visible = visible;
597
- }
598
- addText(text, instanceId) {
599
- super.addText(text);
600
- if (instanceId !== void 0) {
601
- this.mapInstanceIdToText.set(instanceId, text);
602
- }
603
- this.textArray.push(text);
743
+ setMatrixAt(instanceId, matrix) {
744
+ super.setMatrixAt(instanceId, matrix);
745
+ this.boundsNeedsUpdate = true;
746
+ return this;
604
747
  }
605
748
  dispose() {
749
+ var _a2;
750
+ this.geometry.setIndex(this.indexBuffer ?? null);
606
751
  super.dispose();
607
- this.dispatchEvent({ type: "dispose" });
752
+ this.uniformSchema = {};
753
+ (_a2 = this.uniformsTexture) == null ? void 0 : _a2.dispose();
754
+ this.uniformsTexture = void 0;
755
+ this.indexBuffer = void 0;
756
+ this.geometryById.forEach((geometry) => geometry.dispose());
757
+ this.geometryById.clear();
758
+ this.mapGeometryToInstanceId.clear();
759
+ return this;
608
760
  }
609
- _prepareForRender(material) {
761
+ resizeToFitGeometry(geometry) {
610
762
  var _a2;
611
- const isOutline = material.isTextOutlineMaterial;
612
- material.uniforms.uTroikaIsOutline.value = isOutline;
613
- let texture = this._dataTextures[isOutline ? "outline" : "main"];
614
- const dataLength = Math.pow(2, Math.ceil(Math.log2(this._members.size * floatsPerMember)));
615
- if (!texture || dataLength !== texture.image.data.length) {
616
- if (texture) texture.dispose();
617
- const width = Math.min(dataLength / 4, 1024);
618
- texture = this._dataTextures[isOutline ? "outline" : "main"] = new DataTexture(
619
- new Float32Array(dataLength),
620
- width,
621
- dataLength / 4 / width,
622
- RGBAFormat,
623
- FloatType
624
- );
625
- }
626
- const texData = texture.image.data;
627
- this.textureNeedsUpdate = false;
628
- for (const text of this.textArray) {
629
- const index = ((_a2 = this._members.get(text)) == null ? void 0 : _a2.index) ?? -1;
630
- const textRenderInfo = text.textRenderInfo;
631
- if (index < 0 || !textRenderInfo) continue;
632
- const startIndex = index * floatsPerMember;
633
- if (!text.visible) {
634
- for (let i = 0; i < 16; i++) {
635
- this.setTexData(startIndex + i, 0, texData);
636
- }
637
- continue;
638
- }
639
- const matrix = text.matrix.elements;
640
- for (let i = 0; i < 16; i++) {
641
- this.setTexData(startIndex + i, matrix[i], texData);
642
- }
643
- text._prepareForRender(material);
644
- const {
645
- uTroikaTotalBounds,
646
- uTroikaClipRect,
647
- uTroikaPositionOffset,
648
- uTroikaEdgeOffset,
649
- uTroikaBlurRadius,
650
- uTroikaStrokeWidth,
651
- uTroikaStrokeColor,
652
- uTroikaStrokeOpacity,
653
- uTroikaFillOpacity,
654
- uTroikaCurveRadius
655
- } = material.uniforms;
656
- for (let i = 0; i < 4; i++) {
657
- this.setTexData(startIndex + 16 + i, uTroikaTotalBounds.value.getComponent(i), texData);
658
- }
659
- for (let i = 0; i < 4; i++) {
660
- this.setTexData(startIndex + 20 + i, uTroikaClipRect.value.getComponent(i), texData);
661
- }
662
- let color = isOutline ? text.outlineColor || 0 : text.color;
663
- color ?? (color = this.color);
664
- color ?? (color = this.material.color);
665
- color ?? (color = 16777215);
666
- this.setTexData(startIndex + 24, tempColor.set(color).getHex(), texData);
667
- this.setTexData(startIndex + 25, uTroikaFillOpacity.value, texData);
668
- this.setTexData(startIndex + 26, uTroikaCurveRadius.value, texData);
669
- if (isOutline) {
670
- this.setTexData(startIndex + 28, uTroikaPositionOffset.value.x, texData);
671
- this.setTexData(startIndex + 29, uTroikaPositionOffset.value.y, texData);
672
- this.setTexData(startIndex + 30, uTroikaEdgeOffset.value, texData);
673
- this.setTexData(startIndex + 31, uTroikaBlurRadius.value, texData);
674
- } else {
675
- this.setTexData(startIndex + 28, uTroikaStrokeWidth.value, texData);
676
- this.setTexData(startIndex + 29, tempColor.set(uTroikaStrokeColor.value).getHex(), texData);
677
- this.setTexData(startIndex + 30, uTroikaStrokeOpacity.value, texData);
678
- }
679
- }
680
- texture.needsUpdate = this.textureNeedsUpdate;
681
- material.setMatrixTexture(texture);
763
+ const vertexCount = geometry.attributes["position"].count;
764
+ const indexCount = ((_a2 = geometry.index) == null ? void 0 : _a2.count) ?? 0;
765
+ this._maxVertexCount += vertexCount;
766
+ this._maxIndexCount += indexCount;
767
+ this.setGeometrySize(this._maxVertexCount, this._maxIndexCount);
682
768
  }
683
- setTexData(index, value, texData) {
684
- if (value !== texData[index]) {
685
- texData[index] = value;
686
- this.textureNeedsUpdate = true;
769
+ updateIndexBuffer(geometry) {
770
+ const { _multiDrawStarts, _multiDrawCounts, _multiDrawCount } = this;
771
+ const indexBuffer = this.indexBuffer;
772
+ const indexArray = indexBuffer.array;
773
+ const batchIdBuffer = geometry.getAttribute(batchIdName);
774
+ const batchIdArray = batchIdBuffer.array;
775
+ const indirectArray = this._indirectTexture.image.data;
776
+ let indexCount = 0;
777
+ for (let i = 0; i < _multiDrawCount; i++) {
778
+ const start = _multiDrawStarts[i];
779
+ const count = _multiDrawCounts[i];
780
+ const batchId = batchIdArray[start];
781
+ indirectArray[batchId] = batchId;
782
+ for (let j = start; j < start + count; j++) {
783
+ indexArray[indexCount++] = j;
784
+ }
687
785
  }
786
+ indexBuffer.needsUpdate = true;
787
+ geometry.setIndex(indexBuffer);
788
+ return indexCount;
688
789
  }
689
- }
690
- class Text extends Text$1 {
691
- _prepareForRender(material) {
692
- const isOutline = material.isTextOutlineMaterial;
693
- const uniforms = material.uniforms;
694
- const textInfo = this.textRenderInfo;
695
- if (textInfo) {
696
- const { sdfTexture, blockBounds } = textInfo;
697
- const { width, height } = sdfTexture.image;
698
- uniforms.uTroikaSDFTexture.value = sdfTexture;
699
- uniforms.uTroikaSDFTextureSize.value.set(width, height);
700
- uniforms.uTroikaSDFGlyphSize.value = textInfo.sdfGlyphSize;
701
- uniforms.uTroikaSDFExponent.value = textInfo.sdfExponent;
702
- uniforms.uTroikaTotalBounds.value.fromArray(blockBounds);
703
- uniforms.uTroikaUseGlyphColors.value = !isOutline && !!textInfo.glyphColors;
704
- let distanceOffset = 0;
705
- let blurRadius = 0;
706
- let strokeWidth = 0;
707
- let fillOpacity;
708
- let strokeOpacity = 1;
709
- let strokeColor;
710
- let offsetX = 0;
711
- let offsetY = 0;
712
- if (isOutline) {
713
- const { outlineWidth, outlineOffsetX, outlineOffsetY, outlineBlur, outlineOpacity } = this;
714
- distanceOffset = this._parsePercent(outlineWidth) || 0;
715
- blurRadius = Math.max(0, this._parsePercent(outlineBlur) || 0);
716
- fillOpacity = outlineOpacity;
717
- offsetX = this._parsePercent(outlineOffsetX) || 0;
718
- offsetY = this._parsePercent(outlineOffsetY) || 0;
719
- } else {
720
- strokeWidth = Math.max(0, this._parsePercent(this.strokeWidth) || 0);
721
- if (strokeWidth) {
722
- strokeColor = this.strokeColor;
723
- uniforms.uTroikaStrokeColor.value.set(strokeColor ?? defaultStrokeColor);
724
- strokeOpacity = this.strokeOpacity;
725
- strokeOpacity ?? (strokeOpacity = 1);
726
- }
727
- fillOpacity = this.fillOpacity;
728
- }
729
- uniforms.uTroikaEdgeOffset.value = distanceOffset;
730
- uniforms.uTroikaPositionOffset.value.set(offsetX, offsetY);
731
- uniforms.uTroikaBlurRadius.value = blurRadius;
732
- uniforms.uTroikaStrokeWidth.value = strokeWidth;
733
- uniforms.uTroikaStrokeOpacity.value = strokeOpacity;
734
- uniforms.uTroikaFillOpacity.value = fillOpacity ?? 1;
735
- uniforms.uTroikaCurveRadius.value = this.curveRadius || 0;
736
- const clipRect = this.clipRect;
737
- if (clipRect && Array.isArray(clipRect) && clipRect.length === 4) {
738
- uniforms.uTroikaClipRect.value.fromArray(clipRect);
739
- } else {
740
- const pad = (this.fontSize || 0.1) * 100;
741
- uniforms.uTroikaClipRect.value.set(
742
- blockBounds[0] - pad,
743
- blockBounds[1] - pad,
744
- blockBounds[2] + pad,
745
- blockBounds[3] + pad
746
- );
747
- }
748
- this.geometry.applyClipRect(uniforms.uTroikaClipRect.value);
790
+ addBatchIdBuffer(geometry, geometryId) {
791
+ const hasAttribute = geometry.hasAttribute(batchIdName);
792
+ const vertexCount = geometry.getAttribute("position").count;
793
+ const batchIdArray = hasAttribute ? geometry.getAttribute(batchIdName).array : new Int32Array(vertexCount);
794
+ for (let i = 0; i < vertexCount; i++) {
795
+ batchIdArray[i] = geometryId;
749
796
  }
750
- uniforms.uTroikaSDFDebug.value = !!this.debugSDF;
751
- material.polygonOffset = !!this.depthOffset;
752
- material.polygonOffsetFactor = material.polygonOffsetUnits = this.depthOffset || 0;
753
- const color = isOutline ? this.outlineColor || 0 : this.color;
754
- if (color == null) {
755
- delete material.color;
756
- } else {
757
- const colorObj = material.hasOwnProperty("color") ? material.color : material.color = new Color();
758
- if (color !== colorObj._input || typeof color === "object") {
759
- colorObj.set(colorObj._input = color);
760
- }
797
+ if (!hasAttribute) {
798
+ const batchIdBuffer = new BufferAttribute(batchIdArray, 1).setUsage(StreamDrawUsage);
799
+ geometry.setAttribute(batchIdName, batchIdBuffer);
761
800
  }
762
- let orient = this.orientation || defaultOrient;
763
- if (orient !== material._orientation) {
764
- const rotMat = uniforms.uTroikaOrient.value;
765
- orient = orient.replace(/[^-+xyz]/g, "");
766
- const match = orient !== defaultOrient && /^([-+])([xyz])([-+])([xyz])$/.exec(orient);
767
- if (match) {
768
- const [, hSign, hAxis, vSign, vAxis] = match;
769
- tempVec3a.set(0, 0, 0)[hAxis] = hSign === "-" ? 1 : -1;
770
- tempVec3b.set(0, 0, 0)[vAxis] = vSign === "-" ? -1 : 1;
771
- tempMat4.lookAt(origin, tempVec3a.cross(tempVec3b), tempVec3b);
772
- rotMat.setFromMatrix4(tempMat4);
773
- } else {
774
- rotMat.identity();
801
+ }
802
+ patchMaterial(material) {
803
+ const onBeforeCompile = material.onBeforeCompile.bind(material);
804
+ const customProgramCacheKey = material.customProgramCacheKey.bind(material);
805
+ material.onBeforeCompile = (shader, renderer) => {
806
+ var _a2;
807
+ onBeforeCompile(shader, renderer);
808
+ shader.defines ?? (shader.defines = {});
809
+ shader.defines["USE_BATCH_UNIFORMS"] = "";
810
+ shader.uniforms["uniformsTexture"] = { value: this.uniformsTexture };
811
+ const { vertex, fragment } = ((_a2 = this.uniformsTexture) == null ? void 0 : _a2.getUniformsGLSL("uniformsTexture", "instanceId", "int")) ?? {
812
+ vertex: "",
813
+ fragment: ""
814
+ };
815
+ const patch = (
816
+ /*glsl*/
817
+ `
818
+ #ifdef gl_DrawID
819
+ #define _gl_DrawID ${batchIdName}
820
+ #else
821
+ #define gl_DrawID ${batchIdName}
822
+ #endif
823
+ in int ${batchIdName};
824
+ `
825
+ );
826
+ const main = "void main() {";
827
+ if (!_BatchedMesh.useMultiDraw) shader.vertexShader = shader.vertexShader.replace(main, `${patch}${main}`);
828
+ if (vertex) shader.vertexShader = shader.vertexShader.replace(main, vertex);
829
+ if (fragment) shader.fragmentShader = shader.fragmentShader.replace(main, fragment);
830
+ };
831
+ material.customProgramCacheKey = () => {
832
+ return `batch_${this.id}_${!!this.uniformsTexture}_${customProgramCacheKey()}`;
833
+ };
834
+ this.isMaterialPatched = true;
835
+ }
836
+ // Taken from https://github.com/agargaro/instanced-mesh/blob/master/src/core/feature/Uniforms.ts
837
+ parseUniformSchema(schema) {
838
+ let totalSize = 0;
839
+ const uniformMap = /* @__PURE__ */ new Map();
840
+ const uniforms = [];
841
+ const vertexSchema = schema.vertex ?? {};
842
+ const fragmentSchema = schema.fragment ?? {};
843
+ let fetchInFragmentShader = true;
844
+ for (const name in vertexSchema) {
845
+ const type = vertexSchema[name];
846
+ const size = this.getUniformSize(type);
847
+ totalSize += size;
848
+ uniforms.push({ name, type, size });
849
+ fetchInFragmentShader = false;
850
+ }
851
+ for (const name in fragmentSchema) {
852
+ if (!vertexSchema[name]) {
853
+ const type = fragmentSchema[name];
854
+ const size = this.getUniformSize(type);
855
+ totalSize += size;
856
+ uniforms.push({ name, type, size });
775
857
  }
776
- material._orientation = orient;
777
858
  }
859
+ uniforms.sort((a, b) => b.size - a.size);
860
+ const tempOffset = [];
861
+ for (const { name, size, type } of uniforms) {
862
+ const offset = this.getUniformOffset(size, tempOffset);
863
+ uniformMap.set(name, { offset, size, type });
864
+ }
865
+ const pixelsPerInstance = Math.ceil(totalSize / 4);
866
+ const channels = Math.min(totalSize, 4);
867
+ return { channels, texelsPerInstance: pixelsPerInstance, uniformMap, fetchInFragmentShader };
778
868
  }
779
- }
780
- function setDimming(root, dim) {
781
- root.userData["uDim"] = dim === void 0 ? void 0 : +dim;
782
- }
783
- function toggleInstanceDim(object, instanceId, dim) {
784
- const value = dim === void 0 ? 0 : (+dim - 0.5) * 2;
785
- if (object instanceof BatchedMesh) {
786
- object.setUniformAt(instanceId, "skipDimInstance", value);
787
- return;
788
- }
789
- const skipDimTexture = object.userData["skipDimTexture"];
790
- if (skipDimTexture) {
791
- const skipDimData = skipDimTexture.image.data;
792
- skipDimData[instanceId] = value;
793
- skipDimTexture.needsUpdate = true;
794
- }
795
- }
796
- function addDimToMaterial(material) {
797
- if (material.userData.hasDimShader) return;
798
- const onBeforeCompile = material.onBeforeCompile.bind(material);
799
- const onBeforeRender = material.onBeforeRender.bind(material);
800
- material.onBeforeCompile = (shader, renderer) => {
801
- onBeforeCompile(shader, renderer);
802
- shader.uniforms["uDim"] = { value: material.userData.uDim ?? 0 };
803
- shader.uniforms["skipDimTexture"] = { value: material.userData.skipDimTexture ?? null };
804
- shader.vertexShader = shader.vertexShader.replace("void main() {", `${dimColorVertexDefs}
805
- void main() {`).replace(
806
- "#include <fog_vertex>",
807
- /*glsl*/
808
- `
809
- #include <fog_vertex>
810
- setDimAmount();
811
- `
812
- ).concat(dimColorVertexImpl);
813
- shader.fragmentShader = /*glsl*/
814
- `
815
- ${dimColorFrag}
816
- ${shader.fragmentShader}
817
- `.replace(
818
- "#include <colorspace_fragment>",
819
- /*glsl*/
820
- `
821
- gl_FragColor = dimColor(gl_FragColor);
822
- #include <colorspace_fragment>
823
- `
824
- );
825
- material.userData.shader = shader;
826
- };
827
- material.onBeforeRender = (renderer, scene, camera, geometry, object, group) => {
828
- onBeforeRender(renderer, scene, camera, geometry, object, group);
829
- const skipDimTexture = object.userData["skipDimTexture"];
830
- let uDim = object.userData["uDim"];
831
- if (uDim === void 0) {
832
- for (const ancestor of traverseAncestorsGenerator(object)) {
833
- if (ancestor.userData["uDim"] !== void 0) {
834
- uDim = ancestor.userData["uDim"];
835
- break;
869
+ getUniformOffset(size, tempOffset) {
870
+ if (size < 4) {
871
+ for (let i = 0; i < tempOffset.length; i++) {
872
+ if (tempOffset[i] + size <= 4) {
873
+ const offset2 = i * 4 + tempOffset[i];
874
+ tempOffset[i] += size;
875
+ return offset2;
836
876
  }
837
877
  }
838
878
  }
839
- const shader = material.userData.shader;
840
- if (!shader) {
841
- material.userData.uDim = uDim;
842
- material.userData.skipDimTexture = object.userData["skipDimTexture"];
843
- return;
879
+ const offset = tempOffset.length * 4;
880
+ for (; size > 0; size -= 4) {
881
+ tempOffset.push(size);
844
882
  }
845
- shader.uniforms["uDim"].value = uDim ?? 0;
846
- shader.uniforms["skipDimTexture"].value = skipDimTexture ?? null;
847
- };
848
- material.userData.hasDimShader = true;
849
- }
850
- function addDim(mesh) {
851
- if (mesh instanceof BatchedMesh) mesh.addPerInstanceUniforms({ vertex: { skipDimInstance: "float" } });
852
- if (mesh instanceof BatchedText) addSkipDimTexture(mesh);
853
- }
854
- function addSkipDimTexture(text) {
855
- const count = text.size;
856
- const size = Math.ceil(Math.sqrt(count));
857
- const array = new Float32Array(size * size);
858
- array.fill(0);
859
- const texture = new DataTexture(array, size, size, RedFormat, FloatType);
860
- texture.needsUpdate = true;
861
- text.userData["skipDimTexture"] = texture;
862
- text.addEventListener("dispose", () => texture.dispose());
863
- return texture;
864
- }
865
- const dimColorVertexDefs = (
866
- /*glsl*/
867
- `
868
- uniform float uDim;
869
- out float dimAmount;
870
- #ifdef TROIKA_DERIVED_MATERIAL_1
871
- uniform sampler2D skipDimTexture;
872
- #endif
873
- void setDimAmount();
874
- `
875
- );
876
- const dimColorVertexImpl = (
877
- /*glsl*/
878
- `
879
- void setDimAmount() {
880
- float instanceDim = 0.;
881
- #ifdef USE_BATCHING
882
- instanceDim = batch_skipDimInstance;
883
- #endif
884
- #ifdef TROIKA_DERIVED_MATERIAL_1
885
- float indirectIndex = aTroikaTextBatchMemberIndex;
886
- int size = textureSize(skipDimTexture, 0).x;
887
- int i = int(indirectIndex);
888
- int x = i % size;
889
- int y = i / size;
890
- instanceDim = texelFetch(skipDimTexture, ivec2(x, y), 0).r;
891
- #endif
892
- dimAmount = instanceDim == 0. ? uDim : instanceDim / 2. + 0.5;
883
+ return offset;
893
884
  }
894
- `
895
- );
896
- const dimColorFrag = (
897
- /*glsl*/
898
- `
899
- in float dimAmount;
900
-
901
- const vec3 grayWeights = vec3(0.299, 0.587, 0.114);
902
- const float darkenFactor = pow(2., 2.2); // Gamma corrected
903
-
904
- vec4 dimColor(vec4 col) {
905
- vec3 color = col.rgb / col.a;
906
- vec3 gray = vec3(dot(grayWeights, color));
907
- vec3 m = mix(color, gray / darkenFactor, dimAmount);
908
- return vec4(m * col.a, col.a);
909
- }`
910
- );
885
+ getUniformSize(type) {
886
+ switch (type) {
887
+ case "float":
888
+ return 1;
889
+ case "vec2":
890
+ return 2;
891
+ case "vec3":
892
+ return 3;
893
+ case "vec4":
894
+ return 4;
895
+ case "mat3":
896
+ return 9;
897
+ case "mat4":
898
+ return 16;
899
+ }
900
+ }
901
+ getIndexType(gl, index) {
902
+ const array = index.array;
903
+ if (array instanceof Uint16Array) return gl.UNSIGNED_SHORT;
904
+ if (array instanceof Uint32Array) return gl.UNSIGNED_INT;
905
+ return gl.UNSIGNED_BYTE;
906
+ }
907
+ };
908
+ /** Whether to use WebGL_multi_draw extension or less performant fallback (Firefox only) */
909
+ __publicField(_BatchedMesh, "useMultiDraw", true);
910
+ let BatchedMesh = _BatchedMesh;
911
911
  const sharedParameters = {
912
912
  side: DoubleSide,
913
913
  transparent: true,
914
- depthTest: false
914
+ forceSinglePass: true,
915
+ depthFunc: AlwaysDepth
915
916
  };
916
917
  class MaterialSystem {
917
918
  constructor() {
@@ -950,7 +951,6 @@ class MaterialSystem {
950
951
  uniforms["resolution"].value.set(this.viewport.z, this.viewport.w);
951
952
  }
952
953
  };
953
- this.addPolygonOffset(material);
954
954
  addDimToMaterial(material);
955
955
  return material;
956
956
  }
@@ -969,7 +969,6 @@ class MaterialSystem {
969
969
  color: params.color,
970
970
  opacity: params.opacity
971
971
  });
972
- this.addPolygonOffset(material);
973
972
  addDimToMaterial(material);
974
973
  return material;
975
974
  }
@@ -993,7 +992,6 @@ class MaterialSystem {
993
992
  );
994
993
  };
995
994
  }
996
- this.addPolygonOffset(material);
997
995
  addDimToMaterial(material);
998
996
  return material;
999
997
  }
@@ -1014,14 +1012,10 @@ class MaterialSystem {
1014
1012
  `
1015
1013
  );
1016
1014
  };
1017
- this.addPolygonOffset(this.backgroundMaterial);
1018
1015
  addDimToMaterial(this.backgroundMaterial);
1019
1016
  }
1020
1017
  return this.backgroundMaterial;
1021
1018
  }
1022
- addPolygonOffset(material) {
1023
- return;
1024
- }
1025
1019
  }
1026
1020
  function isShapeDef(def) {
1027
1021
  return def.shape !== void 0;
@@ -1053,6 +1047,31 @@ function isLineLayer(layer) {
1053
1047
  function isLayerLayer(layer) {
1054
1048
  return layer.children[0] && isLayerDef(layer.children[0]);
1055
1049
  }
1050
+ function groupBy(list, keyGetter) {
1051
+ const map = /* @__PURE__ */ new Map();
1052
+ list.forEach((item) => {
1053
+ const key = keyGetter(item);
1054
+ const collection = map.get(key);
1055
+ if (!collection) {
1056
+ map.set(key, [item]);
1057
+ } else {
1058
+ collection.push(item);
1059
+ }
1060
+ });
1061
+ return map;
1062
+ }
1063
+ function partition(list, pred) {
1064
+ const truthy = [];
1065
+ const falsy = [];
1066
+ for (const item of list) {
1067
+ if (pred(item)) {
1068
+ truthy.push(item);
1069
+ } else {
1070
+ falsy.push(item);
1071
+ }
1072
+ }
1073
+ return [truthy, falsy];
1074
+ }
1056
1075
  const INTERACTIVE_LAYER = 1;
1057
1076
  function setInteractive(object, isInteractive) {
1058
1077
  if (isInteractive) object.layers.enable(INTERACTIVE_LAYER);
@@ -1126,6 +1145,15 @@ class RenderableSystem {
1126
1145
  const shapeDef = this.getDefsByObject(mesh)[batchId];
1127
1146
  return shapeDef;
1128
1147
  }
1148
+ /**
1149
+ * Dispose all objects and clear the mappings
1150
+ */
1151
+ dispose() {
1152
+ for (const object of this.getAllObjects()) {
1153
+ this.disposeObject(object);
1154
+ }
1155
+ this.clearMappings();
1156
+ }
1129
1157
  /**
1130
1158
  * Protected implementation method that subclasses can override.
1131
1159
  * This ensures logging always happens even when the method is overridden.
@@ -1298,10 +1326,10 @@ class ImageSystem extends RenderableSystem {
1298
1326
  /** Textures memory limit in megabytes */
1299
1327
  __publicField(this, "memoryLimitMb");
1300
1328
  __publicField(this, "packer");
1301
- __publicField(this, "position", new Vector3());
1302
- __publicField(this, "rotation", new Quaternion());
1303
- __publicField(this, "scale", new Vector3());
1304
- __publicField(this, "matrix", new Matrix4());
1329
+ __publicField(this, "globalTranslationMatrix", new Matrix4());
1330
+ __publicField(this, "originTranslationMatrix", new Matrix4());
1331
+ __publicField(this, "rotationMatrix", new Matrix4());
1332
+ __publicField(this, "scaleMatrix", new Matrix4());
1305
1333
  this.materialSystem = materialSystem;
1306
1334
  const atlasTextureSize = renderer.context.capabilities.maxTextureSize;
1307
1335
  console.log(`Max texture size: ${atlasTextureSize}`);
@@ -1401,17 +1429,13 @@ class ImageSystem extends RenderableSystem {
1401
1429
  }
1402
1430
  updateDefImpl(imageDef, mesh, instanceIds) {
1403
1431
  const bounds = imageDef.bounds;
1404
- this.position.set(bounds.center.x, bounds.center.y, 0);
1405
- if (imageDef.origin) {
1406
- const xFactor = 0.5 - imageDef.origin[0];
1407
- const yFactor = 0.5 - imageDef.origin[1];
1408
- this.position.x += bounds.size.width * xFactor;
1409
- this.position.y += bounds.size.height * yFactor;
1410
- }
1411
- this.scale.set(bounds.size.width, bounds.size.height, 1);
1412
- this.rotation.setFromAxisAngle(new Vector3(0, 0, 1), bounds.rotation);
1413
- this.matrix.compose(this.position, this.rotation, this.scale);
1414
- mesh.setMatrixAt(instanceIds[0], this.matrix);
1432
+ const origin2 = imageDef.origin ?? [0.5, 0.5];
1433
+ this.originTranslationMatrix.makeTranslation(0.5 - origin2[0], 0.5 - origin2[1], 0);
1434
+ this.globalTranslationMatrix.makeTranslation(bounds.center.x, bounds.center.y, 0);
1435
+ this.scaleMatrix.makeScale(bounds.size.width, bounds.size.height, 1);
1436
+ this.rotationMatrix.makeRotationZ(bounds.rotation);
1437
+ const matrix = this.originTranslationMatrix.premultiply(this.scaleMatrix).premultiply(this.rotationMatrix).premultiply(this.globalTranslationMatrix);
1438
+ mesh.setMatrixAt(instanceIds[0], matrix);
1415
1439
  }
1416
1440
  packImages(images) {
1417
1441
  this.packer.reset();
@@ -1545,7 +1569,15 @@ class LineSystem extends RenderableSystem {
1545
1569
  }
1546
1570
  }
1547
1571
  function createVector2(vector2) {
1548
- return vector2 instanceof Vector2 ? vector2 : Array.isArray(vector2) ? new Vector2(vector2[0], vector2[1]) : new Vector2(vector2.x, vector2.y);
1572
+ if (vector2 instanceof Vector2) return vector2;
1573
+ if (Array.isArray(vector2)) return new Vector2(vector2[0], vector2[1]);
1574
+ return new Vector2(vector2.x, vector2.y);
1575
+ }
1576
+ function createVector3(vector3) {
1577
+ if (vector3 instanceof Vector2) return new Vector3(vector3.x, vector3.y, 0);
1578
+ if (vector3 instanceof Vector3) return vector3;
1579
+ if (Array.isArray(vector3)) return new Vector3(vector3[0], vector3[1], vector3[2] ?? 0);
1580
+ return new Vector3(vector3.x, vector3.y, "z" in vector3 ? vector3.z : 0);
1549
1581
  }
1550
1582
  class Rect {
1551
1583
  /**
@@ -1613,7 +1645,7 @@ class Polygon {
1613
1645
  __publicField(this, "vertices");
1614
1646
  /** Array of polygon indices. Each index is a triplet of vertex indices forming a triangle. */
1615
1647
  __publicField(this, "indices");
1616
- this.vertices = vertices.map(createVector2);
1648
+ this.vertices = vertices.map(createVector3);
1617
1649
  this.indices = indices;
1618
1650
  }
1619
1651
  /**
@@ -1657,37 +1689,15 @@ class Polygon {
1657
1689
  * @returns this {@link Polygon} instance
1658
1690
  */
1659
1691
  rotate(rotation, center) {
1692
+ const tempVec2 = new Vector2();
1660
1693
  this.vertices.forEach((vertex) => {
1661
- vertex.rotateAround(center, rotation);
1694
+ tempVec2.set(vertex.x, vertex.y);
1695
+ tempVec2.rotateAround(center, rotation);
1696
+ vertex.set(tempVec2.x, tempVec2.y, vertex.z);
1662
1697
  });
1663
1698
  return this;
1664
1699
  }
1665
1700
  }
1666
- function groupBy(list, keyGetter) {
1667
- const map = /* @__PURE__ */ new Map();
1668
- list.forEach((item) => {
1669
- const key = keyGetter(item);
1670
- const collection = map.get(key);
1671
- if (!collection) {
1672
- map.set(key, [item]);
1673
- } else {
1674
- collection.push(item);
1675
- }
1676
- });
1677
- return map;
1678
- }
1679
- function partition(list, pred) {
1680
- const truthy = [];
1681
- const falsy = [];
1682
- for (const item of list) {
1683
- if (pred(item)) {
1684
- truthy.push(item);
1685
- } else {
1686
- falsy.push(item);
1687
- }
1688
- }
1689
- return [truthy, falsy];
1690
- }
1691
1701
  class MeshSystem extends RenderableSystem {
1692
1702
  /**
1693
1703
  * @param materialSystem {@link MaterialSystem}
@@ -1725,6 +1735,12 @@ class MeshSystem extends RenderableSystem {
1725
1735
  opaqueMesh.name = "opaque";
1726
1736
  group.add(opaqueMesh);
1727
1737
  }
1738
+ if (layer.mode === "3d") {
1739
+ group.children.filter((child) => child instanceof Mesh).forEach((mesh) => {
1740
+ const material = mesh.material;
1741
+ material.depthFunc = LessEqualDepth;
1742
+ });
1743
+ }
1728
1744
  return group;
1729
1745
  }
1730
1746
  updateDefImpl(shapeDef, mesh, instanceIds) {
@@ -1741,12 +1757,10 @@ class MeshSystem extends RenderableSystem {
1741
1757
  let rectGeometry = void 0;
1742
1758
  const shapeDefToGeometry = /* @__PURE__ */ new Map();
1743
1759
  for (const shapeDef of shapes) {
1744
- if (shapeDef.shape instanceof Rect) {
1745
- if (!rectGeometry) {
1746
- rectGeometry = new PlaneGeometry(1, 1);
1747
- rectGeometry.deleteAttribute("normal");
1748
- rectGeometry.deleteAttribute("uv");
1749
- }
1760
+ if (shapeDef.shape instanceof Rect && !rectGeometry) {
1761
+ rectGeometry = new PlaneGeometry(1, 1);
1762
+ rectGeometry.deleteAttribute("normal");
1763
+ rectGeometry.deleteAttribute("uv");
1750
1764
  vertexCount += rectGeometry.getAttribute("position").count;
1751
1765
  indexCount += ((_a2 = rectGeometry.index) == null ? void 0 : _a2.count) ?? 0;
1752
1766
  } else if (shapeDef.shape instanceof Polygon) {
@@ -1758,6 +1772,7 @@ class MeshSystem extends RenderableSystem {
1758
1772
  }
1759
1773
  const material = this.materialSystem.createColorMaterial({ opacity });
1760
1774
  const batchedMesh = new BatchedMesh(shapes.length, vertexCount, indexCount, material);
1775
+ const rectGeometryId = rectGeometry ? batchedMesh.addGeometry(rectGeometry) : void 0;
1761
1776
  batchedMesh.setCustomSort((list) => this.sortInstances(batchedMesh, list));
1762
1777
  const position = new Vector3();
1763
1778
  const rotation = new Quaternion();
@@ -1765,8 +1780,7 @@ class MeshSystem extends RenderableSystem {
1765
1780
  const matrix = new Matrix4();
1766
1781
  for (const shapeDef of shapes) {
1767
1782
  let instanceId = void 0;
1768
- if (shapeDef.shape instanceof Rect) {
1769
- const rectGeometryId = rectGeometry ? batchedMesh.addGeometry(rectGeometry) : void 0;
1783
+ if (shapeDef.shape instanceof Rect && rectGeometryId !== void 0) {
1770
1784
  instanceId = batchedMesh.addInstance(rectGeometryId);
1771
1785
  position.set(shapeDef.shape.center.x, shapeDef.shape.center.y, 0);
1772
1786
  rotation.setFromAxisAngle(new Vector3(0, 0, 1), shapeDef.shape.rotation ?? 0);
@@ -1990,6 +2004,7 @@ class LayerSystem {
1990
2004
  * @param renderer {@link Renderer}
1991
2005
  */
1992
2006
  constructor(renderer) {
2007
+ __publicField(this, "backgroundMesh");
1993
2008
  __publicField(this, "materialSystem");
1994
2009
  __publicField(this, "meshSystem");
1995
2010
  __publicField(this, "imageSystem");
@@ -2089,6 +2104,18 @@ class LayerSystem {
2089
2104
  }
2090
2105
  return rootGroup;
2091
2106
  }
2107
+ /**
2108
+ * Dispose all objects and clear the mappings
2109
+ */
2110
+ disposeScene() {
2111
+ var _a2, _b, _c;
2112
+ for (const system of this.systems) {
2113
+ system.dispose();
2114
+ }
2115
+ (_a2 = this.backgroundMesh) == null ? void 0 : _a2.geometry.dispose();
2116
+ (_c = (_b = this.backgroundMesh) == null ? void 0 : _b.material) == null ? void 0 : _c.dispose();
2117
+ this.backgroundMesh = void 0;
2118
+ }
2092
2119
  updateDef(def) {
2093
2120
  if (isShapeDef(def)) this.meshSystem.updateDef(def);
2094
2121
  else if (isImageDef(def)) this.imageSystem.updateDef(def);
@@ -2153,6 +2180,7 @@ class LayerSystem {
2153
2180
  backgroundMesh.frustumCulled = false;
2154
2181
  backgroundMesh.renderOrder = 0;
2155
2182
  backgroundMesh.name = "background";
2183
+ this.backgroundMesh = backgroundMesh;
2156
2184
  return backgroundMesh;
2157
2185
  }
2158
2186
  initRenderOrder(rootLayer) {
@@ -2170,6 +2198,8 @@ class LayerSystem {
2170
2198
  this.layerDefRenderOrder.push(layer);
2171
2199
  }
2172
2200
  }
2201
+ const [threeDLayers, twoDLayers] = partition(this.layerDefRenderOrder, (layer) => layer.mode === "3d");
2202
+ this.layerDefRenderOrder = [...twoDLayers, ...threeDLayers];
2173
2203
  }
2174
2204
  getFullLayerName(layerDef) {
2175
2205
  let fullName = layerDef.name;
@@ -4899,7 +4929,7 @@ class ViewportSystem {
4899
4929
  __publicField(this, "raycaster", new Raycaster());
4900
4930
  __publicField(this, "intersectionPoint", new Vector3());
4901
4931
  __publicField(this, "viewboxPlane", new Plane(new Vector3(0, 0, 1), 0));
4902
- __publicField(this, "pxToSvgScaleThreshold", 1e-3);
4932
+ __publicField(this, "pxToSvgScaleThreshold", 1e-4);
4903
4933
  __publicField(this, "prevPxToSvgScale");
4904
4934
  __publicField(this, "externalStaticTransformMatrix", new Matrix4());
4905
4935
  this.renderer = renderer;
@@ -5960,6 +5990,7 @@ class Renderer {
5960
5990
  constructor(opts) {
5961
5991
  /** Whether to log debug information */
5962
5992
  __publicField(this, "debugLog");
5993
+ //FIXME: Add https://www.npmjs.com/package/debug
5963
5994
  /** {@link HTMLCanvasElement} that this renderer is rendering to */
5964
5995
  __publicField(this, "canvas");
5965
5996
  __publicField(this, "ui");
@@ -5999,6 +6030,7 @@ class Renderer {
5999
6030
  this.canvas.addEventListener("webglcontextlost", (e) => this.onContextLost(e), false);
6000
6031
  this.canvas.addEventListener("webglcontextrestored", (e) => this.onContextRestored(e), false);
6001
6032
  void ((_b = (_a2 = this.ui) == null ? void 0 : _a2.stats) == null ? void 0 : _b.init(this.renderer.getContext()));
6033
+ BatchedMesh.useMultiDraw = this.renderer.extensions.has("WEBGL_multi_draw");
6002
6034
  }
6003
6035
  /**
6004
6036
  * {@link ControlsAPI} instance for controlling the viewport
@@ -6106,6 +6138,20 @@ class Renderer {
6106
6138
  (_f = (_e = this.ui) == null ? void 0 : _e.stats) == null ? void 0 : _f.update();
6107
6139
  this.updateMemoryInfo();
6108
6140
  }
6141
+ /**
6142
+ * Stop the rendering loop
6143
+ */
6144
+ stop() {
6145
+ this.renderer.setAnimationLoop(null);
6146
+ this.clock.stop();
6147
+ }
6148
+ /**
6149
+ * Dispose all WebGL resources
6150
+ */
6151
+ dispose() {
6152
+ this.layerSystem.disposeScene();
6153
+ this.viewportSystem.scene.clear();
6154
+ }
6109
6155
  // https://webgl2fundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
6110
6156
  resizeCanvasToDisplaySize() {
6111
6157
  const dpr = window.devicePixelRatio;
@@ -6124,16 +6170,19 @@ class Renderer {
6124
6170
  var _a2;
6125
6171
  if (this.memoryInfoExtension && ((_a2 = this.ui) == null ? void 0 : _a2.memoryInfoPanel)) {
6126
6172
  const memoryInfo = this.memoryInfoExtension.getMemoryInfo();
6173
+ memoryInfo.resources["drawCalls"] = this.renderer.info.render.calls;
6127
6174
  const memoryInfoContent = JSON.stringify(memoryInfo.memory, null, 2);
6128
6175
  const elapsedTime = this.clock.getElapsedTime() * 1e3;
6129
6176
  if (memoryInfoContent !== this.memoryInfo) {
6130
6177
  const logMarker = `memoryInfo [${elapsedTime.toFixed(2)}ms since start]`;
6131
6178
  if (this.debugLog) console.log(logMarker, memoryInfo);
6179
+ console.log("Buffers", this.memoryInfoExtension.getResourcesInfo(WebGLBuffer));
6132
6180
  this.memoryInfo = memoryInfoContent;
6133
6181
  }
6134
6182
  this.ui.memoryInfoPanel.textContent = JSON.stringify(memoryInfo, null, 2);
6135
6183
  }
6136
6184
  }
6185
+ // FIXME: Test with mapbox
6137
6186
  onContextLost(event) {
6138
6187
  event.preventDefault();
6139
6188
  console.log("webglcontextlost event", event);
@@ -6153,6 +6202,7 @@ export {
6153
6202
  Rect,
6154
6203
  Renderer,
6155
6204
  createVector2,
6205
+ createVector3,
6156
6206
  isImageDef,
6157
6207
  isImageLayer,
6158
6208
  isLayerDef,