rayzee 7.12.0 → 7.13.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rayzee",
3
- "version": "7.12.0",
3
+ "version": "7.13.0",
4
4
  "type": "module",
5
5
  "description": "Real-time WebGPU path tracing engine built on Three.js",
6
6
  "main": "dist/rayzee.umd.js",
@@ -146,6 +146,9 @@ export class PathTracerApp extends EventDispatcher {
146
146
  this._loadingInProgress = false;
147
147
  this._needsDisplayRefresh = false;
148
148
  this._paused = false;
149
+ // Emissive-triangle NEE auto-follows the scene (on when it has emissive geometry)
150
+ // until the user toggles it explicitly; reset on each fresh model load.
151
+ this._emissiveSamplingUserSet = false;
149
152
 
150
153
  // Render completion tracking
151
154
  this.completion = new CompletionTracker();
@@ -759,6 +762,9 @@ export class PathTracerApp extends EventDispatcher {
759
762
  try {
760
763
 
761
764
  await loadFn();
765
+ // A fresh model re-establishes the emissive-sampling auto-default (incremental
766
+ // rebuilds — add/remove object, texture reprocess — preserve the user's choice).
767
+ this._emissiveSamplingUserSet = false;
762
768
  // Replace-load clears any dynamically-appended models — but only AFTER
763
769
  // loadFn() succeeds, so a failed load leaves the current scene intact.
764
770
  // (The old primary was already released by releaseTargetModel() in loadFn.)
@@ -871,6 +877,16 @@ export class PathTracerApp extends EventDispatcher {
871
877
  this.settings.set( 'groundProjectionLevel', sceneMinY, { reset: false } );
872
878
  this.settings.set( 'groundCatcherHeight', sceneMinY, { reset: false } );
873
879
 
880
+ // Auto-follow the scene: enable emissive-triangle NEE when the scene has emissive
881
+ // geometry, disable it when it doesn't — unless the user set the toggle explicitly.
882
+ // Runs before applyAll()/SceneRebuild so the uniform and UI both pick up the new value.
883
+ if ( ! this._emissiveSamplingUserSet ) {
884
+
885
+ const hasEmissive = ( this._sdf?.emissiveTriangleCount ?? 0 ) > 0;
886
+ this.settings.set( 'enableEmissiveTriangleSampling', hasEmissive, { reset: false } );
887
+
888
+ }
889
+
874
890
  // Apply all settings to stages in one shot
875
891
  timer.start( 'Apply settings' );
876
892
  this.settings.applyAll();
@@ -1512,6 +1528,28 @@ export class PathTracerApp extends EventDispatcher {
1512
1528
 
1513
1529
  }
1514
1530
 
1531
+ /**
1532
+ * Explicitly enable/disable emissive-triangle next-event estimation. Marks the
1533
+ * setting as user-controlled so scene rebuilds stop auto-following the scene's
1534
+ * emissive content; the next fresh model load re-arms the auto-default.
1535
+ * @param {boolean} enabled
1536
+ */
1537
+ setEmissiveTriangleSampling( enabled ) {
1538
+
1539
+ this._emissiveSamplingUserSet = true;
1540
+ this.settings.set( 'enableEmissiveTriangleSampling', enabled );
1541
+
1542
+ }
1543
+
1544
+ /**
1545
+ * @returns {boolean} True if the current scene contains emissive geometry.
1546
+ */
1547
+ hasEmissiveGeometry() {
1548
+
1549
+ return ( this._sdf?.emissiveTriangleCount ?? 0 ) > 0;
1550
+
1551
+ }
1552
+
1515
1553
  /**
1516
1554
  * Update per-mesh visibility without rebuilding the scene.
1517
1555
  * Walks the parent chain to resolve world-space visibility.
@@ -228,6 +228,12 @@ export const generateSampledDirection = Fn( ( [
228
228
 
229
229
  export const regularizePathContribution = /*@__PURE__*/ wgslFn( `
230
230
  fn regularizePathContribution( contribution: vec3f, pathLength: f32, fireflyThreshold: f32, frame: i32 ) -> vec3f {
231
+ // Indirect-only clamp: pathLength 0 is a direct/primary contribution (bounce-0 hit, direct NEE,
232
+ // or a directly-viewed backdrop/sun) — that is signal, not a firefly, and clamping it darkens
233
+ // legitimately bright pixels. Fireflies arise on indirect bounces, so only suppress pathLength>=1.
234
+ if ( pathLength < 0.5 ) {
235
+ return contribution;
236
+ }
231
237
  let threshold = calculateFireflyThreshold( fireflyThreshold, i32( pathLength ), frame );
232
238
  return applySoftSuppressionRGB( contribution, threshold, 0.5f );
233
239
  }