@expofp/renderer 2.2.1 → 2.3.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.d.ts CHANGED
@@ -691,6 +691,16 @@ export declare interface ViewportAPI {
691
691
  * @param dynamicTransformMatrix dynamic transform matrix (changes every frame)
692
692
  */
693
693
  setDynamicTransform: (dynamicTransformMatrix: number[]) => void;
694
+ /**
695
+ * Set the maximum zoom factor. Default is 35.
696
+ * @param maxZoom Maximum zoom factor
697
+ */
698
+ setMaxZoom: (maxZoom: number) => void;
699
+ /**
700
+ * Set the minimum zoom factor. Default is 0.1.
701
+ * @param minZoom Minimum zoom factor
702
+ */
703
+ setMinZoom: (minZoom: number) => void;
694
704
  }
695
705
 
696
706
  /** Options for the {@link ControlsAPI.zoomTo} method. */
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, AlwaysDepth, DoubleSide, MeshBasicMaterial, Texture, Group, PlaneGeometry, SRGBColorSpace, Vector2, Quaternion, BufferGeometry, Mesh, LessEqualDepth, LinearSRGBColorSpace, Plane, Raycaster, Sphere, Box3, Spherical, PerspectiveCamera, Camera, Scene, MathUtils, Clock, WebGLRenderer } from "three";
5
+ import { DataTexture, FloatType, UnsignedIntType, IntType, RGBAFormat, RGBAIntegerFormat, RGFormat, RGIntegerFormat, RedFormat, RedIntegerFormat, BatchedMesh as BatchedMesh$1, BufferAttribute, StreamDrawUsage, Color, Matrix4, Vector3, Frustum, Sphere, Box3, Vector4, AlwaysDepth, DoubleSide, MeshBasicMaterial, Texture, Group, PlaneGeometry, SRGBColorSpace, Vector2, Quaternion, BufferGeometry, Mesh, LessEqualDepth, LinearSRGBColorSpace, Plane, Raycaster, Spherical, PerspectiveCamera, Camera, Scene, MathUtils, Clock, WebGLRenderer } from "three";
6
6
  import { traverseAncestorsGenerator } from "three/examples/jsm/utils/SceneUtils.js";
7
7
  import createLog from "debug";
8
8
  import { BatchedText as BatchedText$1, Text as Text$1 } from "troika-three-text";
@@ -551,9 +551,12 @@ class BatchedText extends BatchedText$1 {
551
551
  // eslint-disable-next-line jsdoc/require-jsdoc
552
552
  constructor() {
553
553
  super();
554
- __publicField(this, "mapInstanceIdToText", /* @__PURE__ */ new Map());
555
554
  __publicField(this, "textArray", []);
556
555
  __publicField(this, "textureNeedsUpdate", false);
556
+ __publicField(this, "boundsNeedsUpdate", false);
557
+ this.addEventListener("synccomplete", () => {
558
+ this.boundsNeedsUpdate = true;
559
+ });
557
560
  }
558
561
  /** Number of texts in the batch */
559
562
  get size() {
@@ -569,7 +572,13 @@ class BatchedText extends BatchedText$1 {
569
572
  * @returns Text object
570
573
  */
571
574
  getText(instanceId) {
572
- return this.mapInstanceIdToText.get(instanceId);
575
+ return this.textArray[instanceId];
576
+ }
577
+ /**
578
+ * Mark this BatchedText as needing bounds update. This should be called when changing text transforms.
579
+ */
580
+ invalidateBounds() {
581
+ this.boundsNeedsUpdate = true;
573
582
  }
574
583
  /**
575
584
  * Set the visibility of the {@link Text} object by instance id.
@@ -583,17 +592,39 @@ class BatchedText extends BatchedText$1 {
583
592
  }
584
593
  addText(text, instanceId) {
585
594
  super.addText(text);
586
- if (instanceId !== void 0) {
587
- this.mapInstanceIdToText.set(instanceId, text);
588
- }
589
- this.textArray.push(text);
595
+ if (instanceId !== void 0) this.textArray[instanceId] = text;
596
+ this.boundsNeedsUpdate = true;
597
+ }
598
+ removeText(text) {
599
+ super.removeText(text);
600
+ this.textArray.splice(this.textArray.indexOf(text), 1);
601
+ this.boundsNeedsUpdate = true;
590
602
  }
591
603
  dispose() {
592
604
  super.dispose();
605
+ this.textArray.length = 0;
593
606
  this.dispatchEvent({ type: "dispose" });
594
607
  }
595
- // TODO: Check performance
596
- _prepareForRender(material) {
608
+ updateBounds() {
609
+ if (this.boundsNeedsUpdate) {
610
+ const bbox = this.geometry.boundingBox.makeEmpty();
611
+ for (const text of this.textArray) {
612
+ if (!text.visible) continue;
613
+ if (text.matrixAutoUpdate) text.updateMatrix();
614
+ _box$1.copy(text.geometry.boundingBox).applyMatrix4(text.matrix);
615
+ bbox.union(_box$1);
616
+ }
617
+ bbox.getBoundingSphere(this.geometry.boundingSphere);
618
+ this.boundsNeedsUpdate = false;
619
+ }
620
+ }
621
+ onBeforeRender(renderer, scene, camera, geometry, material) {
622
+ this.sync();
623
+ if ("isTroikaTextMaterial" in material && material.isTroikaTextMaterial) {
624
+ this.prepareForRender(material, scene, camera);
625
+ }
626
+ }
627
+ prepareForRender(material, scene, camera) {
597
628
  var _a2;
598
629
  const isOutline = material.isTextOutlineMaterial;
599
630
  material.uniforms.uTroikaIsOutline.value = isOutline;
@@ -612,12 +643,15 @@ class BatchedText extends BatchedText$1 {
612
643
  }
613
644
  const texData = texture.image.data;
614
645
  this.textureNeedsUpdate = false;
646
+ _matrix$1.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse).multiply(scene.matrixWorld);
647
+ _frustum$1.setFromProjectionMatrix(_matrix$1, camera.coordinateSystem);
615
648
  for (const text of this.textArray) {
616
649
  const index = ((_a2 = this._members.get(text)) == null ? void 0 : _a2.index) ?? -1;
617
650
  const textRenderInfo = text.textRenderInfo;
618
651
  if (index < 0 || !textRenderInfo) continue;
619
652
  const startIndex = index * floatsPerMember;
620
- if (!text.visible) {
653
+ const isHidden = !text.visible || !_frustum$1.intersectsSphere(_sphere$1.copy(text.geometry.boundingSphere).applyMatrix4(text.matrix));
654
+ if (isHidden) {
621
655
  for (let i = 0; i < 16; i++) {
622
656
  this.setTexData(startIndex + i, 0, texData);
623
657
  }
@@ -732,7 +766,6 @@ class Text extends Text$1 {
732
766
  blockBounds[3] + pad
733
767
  );
734
768
  }
735
- this.geometry.applyClipRect(uniforms.uTroikaClipRect.value);
736
769
  }
737
770
  uniforms.uTroikaSDFDebug.value = !!this.debugSDF;
738
771
  material.polygonOffset = !!this.depthOffset;
@@ -764,6 +797,10 @@ class Text extends Text$1 {
764
797
  }
765
798
  }
766
799
  }
800
+ const _matrix$1 = new Matrix4();
801
+ const _frustum$1 = new Frustum();
802
+ const _sphere$1 = new Sphere();
803
+ const _box$1 = new Box3();
767
804
  function setDimming(root, dim) {
768
805
  root.userData["uDim"] = dim === void 0 ? void 0 : +dim;
769
806
  }
@@ -2001,19 +2038,30 @@ class TextSystem extends RenderableSystem {
2001
2038
  group.add(newBatchedText);
2002
2039
  }
2003
2040
  updateDefImpl(textDef, mesh, instanceIds) {
2004
- for (const [i, line] of textDef.lines.entries()) {
2041
+ const lines = [];
2042
+ for (let i = 0; i < textDef.lines.length; i++) {
2043
+ const line = textDef.lines[i];
2005
2044
  const text = mesh.getText(instanceIds[i]);
2006
- if (text) {
2007
- text.text = line.text;
2008
- text.color = this.textColor.set(line.color).getHex(LinearSRGBColorSpace);
2009
- text.font = line.fontUrl;
2010
- if (line.stroke) {
2011
- text.outlineColor = line.stroke.color;
2012
- text.outlineWidth = line.stroke.width / line.fontSize;
2013
- }
2045
+ if (line.fontSize === 0) {
2046
+ text.visible = false;
2047
+ continue;
2048
+ }
2049
+ text.visible = true;
2050
+ text.text = line.text;
2051
+ text.color = this.textColor.set(line.color).getHex(LinearSRGBColorSpace);
2052
+ text.font = line.fontUrl;
2053
+ if (line.stroke) {
2054
+ text.outlineColor = line.stroke.color;
2055
+ text.outlineWidth = line.fontSize == 0 ? 0 : line.stroke.width / line.fontSize;
2014
2056
  }
2057
+ const fontSize = line.fontSize;
2058
+ const height = line.text.split("\n").length * text.lineHeight * fontSize;
2059
+ lines.push({ text, fontSize, height });
2060
+ }
2061
+ if (lines.length > 0) {
2062
+ if (textDef.alignment.vertical === "bottom") lines.reverse();
2063
+ this.updateScale(textDef, mesh, lines);
2015
2064
  }
2016
- this.updateScale(textDef);
2017
2065
  }
2018
2066
  buildBatchedText(layer) {
2019
2067
  const textDefs = layer.children;
@@ -2028,6 +2076,7 @@ class TextSystem extends RenderableSystem {
2028
2076
  text.fontSize = 1;
2029
2077
  text.lineHeight = 1.1;
2030
2078
  text.whiteSpace = "nowrap";
2079
+ text.clipRect = [0, 0, 0, 0];
2031
2080
  batchedText.addText(text, instanceId);
2032
2081
  instanceIds.push(instanceId);
2033
2082
  instanceId++;
@@ -2047,9 +2096,8 @@ class TextSystem extends RenderableSystem {
2047
2096
  return batchedText;
2048
2097
  }
2049
2098
  // TODO: Simplify
2050
- updateScale(textDef) {
2099
+ updateScale(textDef, mesh, lines) {
2051
2100
  const dpr = this.renderer.context.getPixelRatio();
2052
- const lines = this.getTextLines(textDef);
2053
2101
  this.calculateStartInBoundsPosition(
2054
2102
  textDef,
2055
2103
  lines,
@@ -2057,41 +2105,18 @@ class TextSystem extends RenderableSystem {
2057
2105
  this.alignmentOffset,
2058
2106
  this.localPosition
2059
2107
  );
2060
- for (const { text, fontSize, height, alignment } of lines) {
2061
- if (!fontSize || !height) {
2062
- text.visible = false;
2063
- continue;
2064
- }
2065
- text.visible = true;
2066
- setAnchorsAndAlignment(text, alignment);
2108
+ for (const { text, fontSize, height } of lines) {
2109
+ setAnchorsAndAlignment(text, textDef.alignment);
2067
2110
  this.worldPosition.copy(this.localPosition).rotateAround({ x: 0, y: 0 }, textDef.bounds.rotation).add(textDef.bounds.center);
2068
2111
  this.textScale.copy(this.initialTextScale).multiplyScalar(fontSize * dpr);
2069
2112
  text.scale.set(this.textScale.x, this.textScale.y, 1);
2070
2113
  text.position.set(this.worldPosition.x, this.worldPosition.y, 0);
2071
2114
  text.rotation.set(0, 0, textDef.bounds.rotation);
2072
- text.clipRect = this.calculateClipRect(
2073
- textDef,
2074
- this.localPosition,
2075
- this.textScale,
2076
- this.localToMin,
2077
- this.localToMax
2078
- );
2115
+ this.calculateClipRect(text, textDef, this.localPosition, this.textScale, this.localToMin, this.localToMax);
2079
2116
  this.localPosition.y += height * dpr;
2117
+ mesh.invalidateBounds();
2080
2118
  }
2081
2119
  }
2082
- getTextLines(textDef) {
2083
- const { object: mesh, instanceIds } = this.getObjectInstanceByDef(textDef);
2084
- const alignment = textDef.alignment;
2085
- const lines = instanceIds.map((instanceId, i) => {
2086
- const text = mesh.getText(instanceId);
2087
- const line = textDef.lines[i];
2088
- const fontSize = line.fontSize;
2089
- const height = fontSize ? text.text.split("\n").length * text.lineHeight * fontSize : 0;
2090
- return { text, fontSize, height, alignment };
2091
- });
2092
- if (alignment.vertical === "bottom") lines.reverse();
2093
- return lines;
2094
- }
2095
2120
  calculateStartInBoundsPosition(textDef, lines, alignmentDirection, alignmentOffset, inBoundsPosition) {
2096
2121
  const padding = textDef.padding;
2097
2122
  const alignment = textDef.alignment;
@@ -2106,10 +2131,13 @@ class TextSystem extends RenderableSystem {
2106
2131
  }
2107
2132
  inBoundsPosition.multiply(alignmentDirection);
2108
2133
  }
2109
- calculateClipRect(textDef, inBoundsPosition, textScale, toMin, toMax) {
2134
+ calculateClipRect(text, textDef, inBoundsPosition, textScale, toMin, toMax) {
2110
2135
  toMin.subVectors(textDef.bounds.min, textDef.bounds.center).multiply(this.initialTextScale).sub(inBoundsPosition).divide(textScale);
2111
2136
  toMax.subVectors(textDef.bounds.max, textDef.bounds.center).multiply(this.initialTextScale).sub(inBoundsPosition).divide(textScale);
2112
- return [toMin.x, toMin.y, toMax.x, toMax.y];
2137
+ text.clipRect[0] = toMin.x;
2138
+ text.clipRect[1] = toMin.y;
2139
+ text.clipRect[2] = toMax.x;
2140
+ text.clipRect[3] = toMax.y;
2113
2141
  }
2114
2142
  }
2115
2143
  function getAlignmentDirection(alignment) {
@@ -2147,7 +2175,8 @@ class LayerSystem {
2147
2175
  __publicField(this, "mapLayerDefToParent", /* @__PURE__ */ new Map());
2148
2176
  __publicField(this, "layerDefRenderOrder", []);
2149
2177
  __publicField(this, "pendingDefs", /* @__PURE__ */ new Set());
2150
- __publicField(this, "useUpdateBuffering", false);
2178
+ __publicField(this, "culledDefs", /* @__PURE__ */ new Set());
2179
+ __publicField(this, "useUpdateBuffering", true);
2151
2180
  this.renderer = renderer;
2152
2181
  this.materialSystem = new MaterialSystem();
2153
2182
  this.meshSystem = new MeshSystem(this.materialSystem, this.renderer);
@@ -2181,30 +2210,57 @@ class LayerSystem {
2181
2210
  */
2182
2211
  updateDefs(defs) {
2183
2212
  for (const def of defs) {
2184
- if (this.useUpdateBuffering) this.pendingDefs.add(def);
2185
- else this.updateDef(def);
2213
+ if (this.useUpdateBuffering) {
2214
+ this.pendingDefs.add(def);
2215
+ this.culledDefs.delete(def);
2216
+ } else this.updateDef(def);
2186
2217
  }
2187
2218
  }
2188
2219
  /**
2189
2220
  * Drain the queued updates within a time budget.
2190
2221
  * Returns true if any def was updated during this call.
2222
+ * @param scene {@link Scene} instance to get the world matrix from
2223
+ * @param camera {@link Camera} instance to do frustum culling against
2191
2224
  * @param timeBudgetMs frame time budget to perform updates in milliseconds
2192
2225
  * @returns true if any def was updated during this call
2193
2226
  */
2194
- processPendingUpdates(timeBudgetMs = 5) {
2227
+ processPendingUpdates(scene, camera, timeBudgetMs = -1) {
2195
2228
  if (!this.useUpdateBuffering) return false;
2196
- if (this.pendingDefs.size === 0) return false;
2229
+ if (this.pendingDefs.size === 0 && this.culledDefs.size === 0) return false;
2197
2230
  const startTime = performance.now();
2198
- let processed = 0;
2199
- while (this.pendingDefs.size && performance.now() - startTime < timeBudgetMs) {
2200
- const def = this.pendingDefs.values().next().value;
2231
+ _matrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse).multiply(scene.matrixWorld);
2232
+ _frustum.setFromProjectionMatrix(_matrix, camera.coordinateSystem);
2233
+ let processedCount = 0;
2234
+ const overBudget = () => timeBudgetMs > 0 && performance.now() - startTime >= timeBudgetMs;
2235
+ for (const def of this.pendingDefs) {
2236
+ if (overBudget()) break;
2237
+ let culled = false;
2201
2238
  this.pendingDefs.delete(def);
2239
+ if (isTextDef(def) || isImageDef(def)) {
2240
+ const bounds = def.bounds;
2241
+ _box.min.set(bounds.min.x, bounds.min.y, 0);
2242
+ _box.max.set(bounds.max.x, bounds.max.y, 0);
2243
+ culled = !_frustum.intersectsBox(_box);
2244
+ }
2245
+ if (culled) this.culledDefs.add(def);
2246
+ else {
2247
+ this.updateDef(def);
2248
+ processedCount++;
2249
+ }
2250
+ }
2251
+ for (const def of this.culledDefs) {
2252
+ if (overBudget()) break;
2253
+ this.culledDefs.delete(def);
2202
2254
  this.updateDef(def);
2203
- processed++;
2255
+ processedCount++;
2204
2256
  }
2205
2257
  const took = (performance.now() - startTime).toFixed(2);
2206
- if (processed) logger$5.debug(`processed ${processed} defs in ${took}ms, ${this.pendingDefs.size} remaining`);
2207
- return processed > 0;
2258
+ if (processedCount > 0) {
2259
+ const culled = this.culledDefs.size;
2260
+ const remaining = this.pendingDefs.size;
2261
+ logger$5.debug(`processed ${processedCount} defs (${culled} culled, ${remaining} remaining) in ${took}ms`);
2262
+ }
2263
+ return processedCount > 0;
2208
2264
  }
2209
2265
  /**
2210
2266
  * Build the scene graph from the given scene definition.
@@ -2337,6 +2393,9 @@ class LayerSystem {
2337
2393
  return fullName;
2338
2394
  }
2339
2395
  }
2396
+ const _matrix = new Matrix4();
2397
+ const _frustum = new Frustum();
2398
+ const _box = new Box3();
2340
2399
  /*!
2341
2400
  * camera-controls
2342
2401
  * https://github.com/yomotsu/camera-controls
@@ -4947,6 +5006,17 @@ class CameraSystem {
4947
5006
  if (zoomFactor <= 0) return this.zoomIdentityDistance;
4948
5007
  return this.zoomIdentityDistance / zoomFactor;
4949
5008
  }
5009
+ /**
5010
+ * Set the zoom factor bounds.
5011
+ * @param minZoom Minimum zoom factor. Default is 0.1.
5012
+ * @param maxZoom Maximum zoom factor. Default is 35.
5013
+ */
5014
+ setZoomBounds(minZoom, maxZoom) {
5015
+ if (!this.zoomBounds) return;
5016
+ if (minZoom) this.zoomBounds[0] = minZoom;
5017
+ if (maxZoom) this.zoomBounds[1] = maxZoom;
5018
+ this.updateCamera();
5019
+ }
4950
5020
  /**
4951
5021
  * Initializes the camera with the given zoom bounds.
4952
5022
  * @param zoomBounds [minZoom, maxZoom]
@@ -5292,7 +5362,7 @@ class ViewportSystem {
5292
5362
  */
5293
5363
  initViewport(sceneDef) {
5294
5364
  if (!this.renderer.isExternalMode) this.sceneSystem.initScene(sceneDef.viewbox);
5295
- this.cameraSystem.initCamera([0.1, sceneDef.viewbox.size.x > 1e5 ? 100 : 35]);
5365
+ this.cameraSystem.initCamera([0.1, sceneDef.viewbox.size.x > 1e4 ? 100 : 35]);
5296
5366
  }
5297
5367
  /** Updates the viewport when the renderer size changes. */
5298
5368
  updateViewport() {
@@ -5397,12 +5467,28 @@ class ViewportSystem {
5397
5467
  zoomFactorToDistance(zoomFactor) {
5398
5468
  return this.cameraSystem.zoomFactorToDistance(zoomFactor);
5399
5469
  }
5470
+ /**
5471
+ * Set the maximum zoom factor. Default is 35.
5472
+ * @param maxZoom Maximum zoom factor
5473
+ */
5474
+ setMaxZoom(maxZoom) {
5475
+ this.cameraSystem.setZoomBounds(void 0, maxZoom);
5476
+ }
5477
+ /**
5478
+ * Set the minimum zoom factor. Default is 0.1.
5479
+ * @param minZoom Minimum zoom factor
5480
+ */
5481
+ setMinZoom(minZoom) {
5482
+ this.cameraSystem.setZoomBounds(minZoom, void 0);
5483
+ }
5400
5484
  }
5401
5485
  function asViewportAPI(viewportSystem) {
5402
5486
  return {
5403
5487
  canvasToSvg: viewportSystem.canvasToSvg.bind(viewportSystem),
5404
5488
  setStaticTransform: viewportSystem.setStaticTransform.bind(viewportSystem),
5405
- setDynamicTransform: viewportSystem.setDynamicTransform.bind(viewportSystem)
5489
+ setDynamicTransform: viewportSystem.setDynamicTransform.bind(viewportSystem),
5490
+ setMaxZoom: viewportSystem.setMaxZoom.bind(viewportSystem),
5491
+ setMinZoom: viewportSystem.setMinZoom.bind(viewportSystem)
5406
5492
  };
5407
5493
  }
5408
5494
  function eventToCanvas(event) {
@@ -6418,10 +6504,13 @@ class Renderer {
6418
6504
  const api = asViewportAPI(this.viewportSystem);
6419
6505
  const guard = (name) => this.assertInitialized(`viewport.${name}`) && this.assertNotDisposed(`viewport.${name}`);
6420
6506
  const guardExternal = (name) => guard(name) && this.assertExternalMode(`viewport.${name}`);
6507
+ const guardNotExternal = (name) => guard(name) && this.assertNotExternalMode(`viewport.${name}`);
6421
6508
  this.viewportAPI = {
6422
6509
  canvasToSvg: guardFn(guard, api.canvasToSvg, { x: 0, y: 0 }),
6423
6510
  setStaticTransform: guardFn(guardExternal, api.setStaticTransform),
6424
- setDynamicTransform: guardFn(guardExternal, api.setDynamicTransform)
6511
+ setDynamicTransform: guardFn(guardExternal, api.setDynamicTransform),
6512
+ setMaxZoom: guardFn(guardNotExternal, api.setMaxZoom),
6513
+ setMinZoom: guardFn(guardNotExternal, api.setMinZoom)
6425
6514
  };
6426
6515
  return this.viewportAPI;
6427
6516
  }
@@ -6521,12 +6610,13 @@ class Renderer {
6521
6610
  (_b = (_a2 = this.ui) == null ? void 0 : _a2.stats) == null ? void 0 : _b.begin();
6522
6611
  if (this.isExternalMode) this.renderer.resetState();
6523
6612
  else this.resizeCanvasToDisplaySize();
6524
- this.viewportSystem.updatePtScale();
6525
- const hasDefsUpdated = this.layerSystem.processPendingUpdates();
6613
+ const { scene, camera } = this.viewportSystem;
6526
6614
  const hasControlsUpdated = this.interactionsSystem.updateControls(this.clock.getDelta());
6615
+ this.viewportSystem.updatePtScale();
6616
+ const hasDefsUpdated = this.layerSystem.processPendingUpdates(scene, camera, 3);
6527
6617
  const needsRedraw = this.needsRedraw || hasControlsUpdated || hasDefsUpdated || this.isExternalMode || this.ui;
6528
6618
  if (needsRedraw) {
6529
- this.renderer.render(this.viewportSystem.scene, this.viewportSystem.camera);
6619
+ this.renderer.render(scene, camera);
6530
6620
  this.needsRedraw = false;
6531
6621
  }
6532
6622
  (_d = (_c = this.ui) == null ? void 0 : _c.stats) == null ? void 0 : _d.end();
@@ -6562,7 +6652,8 @@ class Renderer {
6562
6652
  // https://webgl2fundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
6563
6653
  resizeCanvasToDisplaySize() {
6564
6654
  const dpr = window.devicePixelRatio;
6565
- const { width, height } = this.canvas.getBoundingClientRect();
6655
+ const width = this.canvas.clientWidth;
6656
+ const height = this.canvas.clientHeight;
6566
6657
  const displayWidth = Math.floor(width * dpr);
6567
6658
  const displayHeight = Math.floor(height * dpr);
6568
6659
  if (this.canvas.width !== displayWidth || this.canvas.height !== displayHeight || this.renderer.getPixelRatio() !== dpr) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expofp/renderer",
3
- "version": "2.2.1",
3
+ "version": "2.3.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"