@volter/editor-threejs 0.5.192 → 0.5.193

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@volter/editor-threejs",
3
3
  "author": "Volter AI, Inc.",
4
- "version": "0.5.192",
4
+ "version": "0.5.193",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -135,12 +135,12 @@
135
135
  "serving": "./dist-node/serving.mjs"
136
136
  },
137
137
  "dependencies": {
138
- "@volter/editor-project": "0.5.192",
138
+ "@volter/editor-project": "0.5.193",
139
139
  "@sparkjsdev/spark": "^2.1.0",
140
140
  "three.quarks": "^0.16.0",
141
141
  "zod": "^4.3.6",
142
142
  "typescript": "5.9.3",
143
- "@volter/editor-sdk": "0.5.192",
143
+ "@volter/editor-sdk": "0.5.193",
144
144
  "postprocessing": "6.38.3",
145
145
  "quarks.core": "0.16.0",
146
146
  "@fortawesome/free-solid-svg-icons": "^7.2.0"
@@ -1534,7 +1534,6 @@ export class Object3DDocumentSession {
1534
1534
  const target = new THREE.WebGLRenderTarget(transform ? outputWidth : renderWidth, transform ? outputHeight : renderHeight);
1535
1535
  let resolved: THREE.WebGLRenderTarget | null = null;
1536
1536
  const previousTarget = this.renderer.getRenderTarget();
1537
- const previousPixelRatio = this.renderer.getPixelRatio();
1538
1537
  const perspective = this.viewport.camera;
1539
1538
  const previousAspect = perspective.aspect;
1540
1539
  try {
@@ -1545,7 +1544,6 @@ export class Object3DDocumentSession {
1545
1544
  perspective.aspect = outputWidth / outputHeight;
1546
1545
  perspective.updateProjectionMatrix();
1547
1546
  }
1548
- this.renderer.setPixelRatio(1);
1549
1547
  this.renderer.setRenderTarget(sceneTarget);
1550
1548
  this.renderCapture(
1551
1549
  (camera) => this.renderSolidForCapture(camera, sceneTarget, renderWidth, renderHeight),
@@ -1586,21 +1584,11 @@ export class Object3DDocumentSession {
1586
1584
  perspective.aspect = previousAspect;
1587
1585
  perspective.updateProjectionMatrix();
1588
1586
  this.renderer.setRenderTarget(previousTarget);
1589
- this.renderer.setPixelRatio(previousPixelRatio);
1590
- // THE COMPOSER IS SIZED AGAIN AT THE DISPLAY'S RATIO. The capture's own draw restores the
1591
- // composer's size while the ratio is still 1 (`renderSolidForCapture`), and the composer
1592
- // sizes its buffers from the renderer's drawing buffer: every capture (a selection's
1593
- // preview takes one) left the view and its outline mask at CSS resolution until the next
1594
- // resize. Measured on the stage: a crisp outline stating 4 device px drew 10 right after a
1595
- // selection and 4 after a repaint that resized.
1596
- this.composer?.setSize(this.renderWidth, this.renderHeight, false);
1597
1587
  target.dispose();
1598
1588
  resolved?.dispose();
1599
1589
  sceneTarget.dispose();
1600
- // AND THE VIEW IS DRAWN AGAIN. Sizing the composer clears what the view showed, and a stage
1601
- // that draws on demand had nothing asking it to: on the browser-substrate page every photograph
1602
- // (Save Screenshot, an agent's get_viewport_screenshot) left the viewport a flat grey until the
1603
- // pointer next moved over it (measured 2026-09-28: stddev 0 across the view, restored on hover).
1590
+ // Refresh any draw-time state after the offscreen photograph. Neither
1591
+ // renderer pixel ratio nor canvas dimensions change during capture.
1604
1592
  invalidateStages();
1605
1593
  }
1606
1594
  }
@@ -1780,21 +1768,30 @@ export class Object3DDocumentSession {
1780
1768
  const composer = this.composer;
1781
1769
  const outlined = (this.selectionOutline?.selection.size ?? 0) > 0;
1782
1770
  if (!composer || !outlined || !this.sceneRenderPass || !this.selectionOutlinePass) {
1783
- this.renderer.render(this.scene, camera);
1771
+ this.renderLinearScene(camera, target);
1784
1772
  return;
1785
1773
  }
1786
- const previousWidth = this.renderWidth;
1787
- const previousHeight = this.renderHeight;
1774
+ const previousSize = this.renderer.getDrawingBufferSize(new THREE.Vector2());
1788
1775
  try {
1789
- composer.setSize(width, height, false);
1776
+ this.resizeComposerBuffers(width, height);
1790
1777
  this.renderLinearScene(camera, target);
1791
1778
  } finally {
1792
- composer.setSize(previousWidth, previousHeight, false);
1779
+ this.resizeComposerBuffers(previousSize.x, previousSize.y);
1793
1780
  this.syncComposerOutput();
1794
1781
  this.renderer.setRenderTarget(target);
1795
1782
  }
1796
1783
  }
1797
1784
 
1785
+ /** Offscreen sizing must not call EffectComposer.setSize: it also resizes
1786
+ * the renderer's visible canvas, clearing the frame a human is watching. */
1787
+ private resizeComposerBuffers(width: number, height: number): void {
1788
+ const composer = this.composer;
1789
+ if (!composer) return;
1790
+ composer.inputBuffer.setSize(width, height);
1791
+ composer.outputBuffer.setSize(width, height);
1792
+ for (const pass of composer.passes) pass.setSize(width, height);
1793
+ }
1794
+
1798
1795
  /** Live HDR draw at the renderer's CURRENT size. Resizing the composer with
1799
1796
  * device pixels here would resize the canvas and multiply HiDPI twice on
1800
1797
  * every frame. Only an offscreen photograph changes its sizing. */
@@ -1802,10 +1799,20 @@ export class Object3DDocumentSession {
1802
1799
  const composer = this.composer;
1803
1800
  const outlined = (this.selectionOutline?.selection.size ?? 0) > 0;
1804
1801
  if (!composer || !outlined || !this.sceneRenderPass || !this.selectionOutlinePass) {
1802
+ // EffectComposer disables renderer.autoClear when it is created. This
1803
+ // direct path owns a whole scene frame too, including an unselected HDR
1804
+ // viewport and plain photographs, so it must clear its previous depth.
1805
+ this.renderer.setRenderTarget(target);
1806
+ this.renderer.clear(true, true, false);
1805
1807
  this.renderer.render(this.scene, camera);
1806
1808
  return;
1807
1809
  }
1808
1810
  try {
1811
+ // These passes are driven directly rather than by composer.render().
1812
+ // Update both passes to the drawing camera, including native camera views
1813
+ // and offscreen captures; the composer's previous free camera can differ.
1814
+ composer.setMainScene(this.scene);
1815
+ composer.setMainCamera(camera);
1809
1816
  this.sceneRenderPass.renderToScreen = false;
1810
1817
  this.selectionOutlinePass.renderToScreen = false;
1811
1818
  this.sceneRenderPass.render(this.renderer, composer.inputBuffer, composer.outputBuffer, 0);