rayzee 9.4.1 → 9.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.
Files changed (145) hide show
  1. package/README.md +226 -25
  2. package/dist/ActiveColor-YvuQq44O.js +13 -0
  3. package/dist/ArchiveImporter-xuUJiklP.js +4301 -0
  4. package/dist/AssetConfig-DSEntE65.js +30 -0
  5. package/dist/BidirectionalIntegrator-C5PKjJoT.js +934 -0
  6. package/dist/ColorManagement-CheBCPaW.js +1488 -0
  7. package/dist/EngineDefaults-DH3bI5t-.js +844 -0
  8. package/dist/EngineEvents-Ci8dVWCP.js +73 -0
  9. package/dist/EngineIssues-CIZnXHsF.js +72 -0
  10. package/dist/FileFormats-sPGJeCRc.js +102 -0
  11. package/dist/Logger-BnHghprG.js +97 -0
  12. package/dist/{NeuralRetouch-vkdXXyK2.js → NeuralRetouch-CW11yLZ_.js} +8 -6
  13. package/dist/{NeuralSuperRes-FVqRJKQV.js → NeuralSuperRes-BekaecYg.js} +55 -120
  14. package/dist/PathTracer-Ccl9KOuF.js +29729 -0
  15. package/dist/PhysicalSky-Dv2PMFGW.js +1219 -0
  16. package/dist/RayzeeRenderer-BQxnzCTD.js +3542 -0
  17. package/dist/SolarLimb-ken-JbDK.js +721 -0
  18. package/dist/ToneMapGPU-BHi5JzIq.js +177 -0
  19. package/dist/ViewTransforms-D0rTLBsX.js +255 -0
  20. package/dist/WorkingMatrix-C6y233hT.js +27 -0
  21. package/dist/ZipReader-gDSWr0I5.js +98 -0
  22. package/dist/addons/archives.es.js +3 -0
  23. package/dist/addons/bidirectional.es.js +2 -0
  24. package/dist/addons/color.es.js +3 -0
  25. package/dist/addons/formats.es.js +2 -0
  26. package/dist/addons/physical-sky.es.js +2 -0
  27. package/dist/addons/storage.es.js +3 -0
  28. package/dist/archiveFormats-BZw7TiDp.js +75 -0
  29. package/dist/identity-DrQsGT2o.js +39 -0
  30. package/dist/openStorage-DwcBRUj7.js +820 -0
  31. package/dist/rayzee-core.es.js +12 -0
  32. package/dist/rayzee.es.js +2266 -44125
  33. package/dist/rayzee.umd.js +485 -473
  34. package/dist/sceneCachePolicy-BmwYOYDu.js +183 -0
  35. package/dist/shared-BGBcSxBQ.js +17 -0
  36. package/package.json +23 -2
  37. package/src/Color/ActiveColor.js +34 -0
  38. package/src/Color/BasicColor.js +147 -0
  39. package/src/Color/ColorManagement.js +7 -31
  40. package/src/EngineDefaults.js +23 -14
  41. package/src/EngineEvents.js +2 -0
  42. package/src/EngineIssues.js +1 -0
  43. package/src/PathTracerApp.js +617 -4016
  44. package/src/Pipeline/PipelineContext.js +0 -4
  45. package/src/Platform.js +36 -0
  46. package/src/Processor/ArchiveCache.js +1 -1
  47. package/src/Processor/ArchiveImporter.js +1259 -0
  48. package/src/Processor/AssetLoader.js +322 -1746
  49. package/src/Processor/AtmosphereModel.js +1 -2
  50. package/src/Processor/BVHBuilder.js +4 -95
  51. package/src/Processor/EnvironmentExactTable.js +187 -0
  52. package/src/Processor/EquirectHDRInfo.js +30 -223
  53. package/src/Processor/FileFormats.js +116 -0
  54. package/src/Processor/GLTFDecoders.js +85 -0
  55. package/src/Processor/GLTFDiffuseTransmission.js +63 -0
  56. package/src/Processor/GeometryExtractor.js +12 -1
  57. package/src/Processor/IESParser.js +47 -35
  58. package/src/Processor/KernelManager.js +35 -2
  59. package/src/Processor/MaterialPacking.js +8 -7
  60. package/src/Processor/PBRT/PBRTMaterials.js +129 -41
  61. package/src/Processor/PBRT/PBRTParser.js +30 -17
  62. package/src/Processor/PBRT/PBRTSceneBuilder.js +548 -37
  63. package/src/Processor/PBRT/PBRTTextureBake.js +154 -0
  64. package/src/Processor/PBRT/PFM.js +59 -0
  65. package/src/Processor/PackedRayBuffer.js +116 -9
  66. package/src/Processor/ParallelBVHBuilder.js +3 -6
  67. package/src/Processor/PhysicalSky.js +5 -4
  68. package/src/Processor/PlatformImageLoader.js +50 -6
  69. package/src/Processor/QueueManager.js +12 -3
  70. package/src/Processor/ReinsertionOptimizer.js +2 -2
  71. package/src/Processor/SceneProcessor.js +15 -55
  72. package/src/Processor/ShaderBuilder.js +6 -16
  73. package/src/Processor/SimpleSky.js +1 -62
  74. package/src/Processor/SolarLimb.js +3 -0
  75. package/src/Processor/TextureCreator.js +1 -1
  76. package/src/Processor/Workers/BVHSubtreeWorker.js +1 -34
  77. package/src/Processor/Workers/BVHWorker.js +5 -18
  78. package/src/Processor/Workers/CDFWorker.js +6 -183
  79. package/src/Processor/archiveFormats.js +7 -0
  80. package/src/Processor/utils.js +2 -1
  81. package/src/RayzeeRenderer.js +3902 -0
  82. package/src/RenderSettings.js +49 -41
  83. package/src/Stages/ASVGF.js +5 -7
  84. package/src/Stages/AutoExposure.js +3 -12
  85. package/src/Stages/Compositor.js +8 -23
  86. package/src/Stages/NRD.js +9 -2
  87. package/src/Stages/NormalDepth.js +9 -6
  88. package/src/Stages/PathTracer.js +254 -38
  89. package/src/Stages/PathTracerStage.js +11 -16
  90. package/src/Storage/BLASCache.js +1 -1
  91. package/src/Storage/CDFCache.js +18 -17
  92. package/src/Storage/DownloadCache.js +1 -1
  93. package/src/Storage/SceneGraphCodec.js +46 -3
  94. package/src/Storage/SpillStore.js +1 -1
  95. package/src/Storage/StorageManager.js +2 -4
  96. package/src/Storage/areas.js +4 -0
  97. package/src/TSL/BVHTraversal.js +62 -24
  98. package/src/TSL/Bidirectional.js +204 -0
  99. package/src/TSL/BidirectionalLamps.js +132 -0
  100. package/src/TSL/Clearcoat.js +15 -6
  101. package/src/TSL/Common.js +19 -14
  102. package/src/TSL/ConnectKernel.js +147 -0
  103. package/src/TSL/Debugger.js +1 -1
  104. package/src/TSL/Displacement.js +4 -3
  105. package/src/TSL/EmissiveSampling.js +64 -17
  106. package/src/TSL/Environment.js +77 -106
  107. package/src/TSL/EnvironmentCDF.js +85 -39
  108. package/src/TSL/ExtendKernel.js +8 -3
  109. package/src/TSL/FinalWriteKernel.js +4 -4
  110. package/src/TSL/GenerateKernel.js +18 -4
  111. package/src/TSL/HitFacet.js +35 -5
  112. package/src/TSL/LightBVHSampling.js +40 -9
  113. package/src/TSL/LightGenerateKernel.js +293 -0
  114. package/src/TSL/LightGuide.js +198 -0
  115. package/src/TSL/LightSplatKernel.js +165 -0
  116. package/src/TSL/LightsCore.js +13 -38
  117. package/src/TSL/LightsDirect.js +28 -29
  118. package/src/TSL/LightsIndirect.js +3 -1
  119. package/src/TSL/LightsSampling.js +90 -38
  120. package/src/TSL/MaterialEvaluation.js +113 -31
  121. package/src/TSL/MaterialProperties.js +44 -17
  122. package/src/TSL/MaterialTransmission.js +52 -47
  123. package/src/TSL/MergeKernel.js +218 -0
  124. package/src/TSL/PathTracerCore.js +65 -29
  125. package/src/TSL/Random.js +4 -0
  126. package/src/TSL/SceneResources.js +51 -0
  127. package/src/TSL/ShadeKernel.js +881 -103
  128. package/src/TSL/Struct.js +10 -0
  129. package/src/TSL/Sun.js +1 -1
  130. package/src/TSL/TextureSampling.js +65 -60
  131. package/src/addons/archives.js +14 -0
  132. package/src/addons/bidirectional.js +13 -0
  133. package/src/addons/color.js +32 -0
  134. package/src/addons/formats.js +16 -0
  135. package/src/addons/physicalSky.js +14 -0
  136. package/src/addons/storage.js +19 -0
  137. package/src/core.js +35 -0
  138. package/src/index.js +3 -1
  139. package/src/integrators/BidirectionalIntegrator.js +832 -0
  140. package/src/managers/EnvironmentManager.js +94 -91
  141. package/src/managers/MaterialDataManager.js +42 -0
  142. package/src/managers/UniformManager.js +0 -1
  143. package/dist/ToneMapGPU-DKQM1pMd.js +0 -552
  144. package/dist/rolldown-runtime-CAFD8bLK.js +0 -11
  145. package/src/Processor/TreeletOptimizer.js +0 -574
@@ -5,13 +5,13 @@ import { ISSUE_CODES } from './EngineIssues.js';
5
5
  import { toPortable, fromPortable } from './SceneState/portable.js';
6
6
 
7
7
  /**
8
- * Routing table: maps each setting key to its target stage/handler.
8
+ * The renderer core's settings: maps each key to its target.
9
9
  *
10
10
  * - `uniform` → forwarded to PathTracer.setUniform(uniform, value)
11
11
  * - `handler` → calls a named handler method for multi-stage settings
12
- * - `delegate` → routes to a named manager's updateParam(param, value)
13
12
  * - `reset` → whether to reset accumulation after the change (default true)
14
- * - `after` → optional method to call on PathTracer after the uniform is set
13
+ *
14
+ * Other layers add their own keys with {@link RenderSettings#define}.
15
15
  */
16
16
  const SETTING_ROUTES = {
17
17
 
@@ -68,7 +68,6 @@ const SETTING_ROUTES = {
68
68
  panoramaLonRange: { handler: 'handlePanoramaLonRange', reset: true },
69
69
  panoramaLatRange: { handler: 'handlePanoramaLatRange', reset: true },
70
70
  interactionModeEnabled: { handler: 'handleInteractionModeEnabled', reset: false },
71
- interactionRenderScale: { handler: 'handleInteractionRenderScale', reset: false },
72
71
  maxSamples: { handler: 'handleMaxSamples', reset: false },
73
72
  transparentBackground: { handler: 'handleTransparentBackground' },
74
73
  backgroundColor: { handler: 'handleBackgroundColor', reset: true },
@@ -77,6 +76,7 @@ const SETTING_ROUTES = {
77
76
  renderLimitMode: { handler: 'handleRenderLimitMode' },
78
77
  renderTimeLimit: { handler: 'handleRenderTimeLimit', reset: false },
79
78
  renderMode: { handler: 'handleRenderMode' },
79
+ integrator: { handler: 'handleIntegrator', reset: true },
80
80
  environmentRotation: { handler: 'handleEnvironmentRotation' },
81
81
 
82
82
  };
@@ -122,6 +122,12 @@ export class RenderSettings extends EventDispatcher {
122
122
 
123
123
  this._issues = issues;
124
124
 
125
+ /** Default values, kept for keys another layer defines later */
126
+ this._defaults = defaults;
127
+
128
+ /** @type {Map<string, Object>} - the core's routes and those other layers define */
129
+ this._routes = new Map( Object.entries( SETTING_ROUTES ) );
130
+
125
131
  /** @type {Map<string, *>} */
126
132
  this._values = new Map();
127
133
 
@@ -137,39 +143,55 @@ export class RenderSettings extends EventDispatcher {
137
143
  /** @type {Object<string, Function>} - Named handlers for multi-stage settings */
138
144
  this._handlers = {};
139
145
 
140
- /** @type {Object<string, Object>} - Named delegate managers */
141
- this._delegates = {};
142
-
143
146
  // Initialize values from ENGINE_DEFAULTS
144
147
  this._initDefaults( defaults );
145
148
 
146
149
  }
147
150
 
148
151
  /**
149
- * Wires internal references. Called by PathTracerApp after init().
152
+ * Wires the core's settings to their targets. Called by the renderer during init().
150
153
  *
151
154
  * @param {Object} params
152
- * @param {Object} params.stages - Pipeline stages { pathTracer, compositor, autoExposure, ... }
155
+ * @param {Object} params.stages - Pipeline stages { pathTracer, compositor }
153
156
  * @param {Function} params.resetCallback - Called to reset accumulation
154
157
  * @param {Function} [params.reconcileCompletion] - Called when completion limits change
155
- * @param {Object} [params.denoisingManager] - Needed to force ASVGF off under panorama
156
- * @param {Function} [params.onInteractionRenderScale] - Applies a new moving-camera render scale
158
+ * @param {Function} [params.applyExposure] - Shows a new `exposure`
157
159
  * @param {Function} [params.onCameraProjection] - The camera's side of a `cameraProjection` change
158
160
  */
159
161
  bind( params ) {
160
162
 
161
163
  this._pathTracer = params.stages.pathTracer;
162
164
  this._resetCallback = params.resetCallback;
163
- this._delegates = {};
164
165
  this._handlers = this._buildHandlers( params );
165
166
 
166
167
  }
167
168
 
169
+ /**
170
+ * Adds a setting of another layer — the viewer's, or an add-on's — with the same provenance, events, session
171
+ * saving and reset as the core's. Its default comes from the defaults this store was built with.
172
+ * @param {string} key
173
+ * @param {Object} route
174
+ * @param {function(*, *): void} route.apply - called with ( value, prev ) on every change, and by applyAll()
175
+ * @param {boolean} [route.reset=true] - reset accumulation after a change
176
+ */
177
+ define( key, { apply, reset = true } ) {
178
+
179
+ if ( this._routes.has( key ) ) throw new Error( `setting "${key}" is already defined` );
180
+ this._routes.set( key, { apply, reset } );
181
+ if ( ! this._values.has( key ) && key in this._defaults ) {
182
+
183
+ this._values.set( key, this._defaults[ key ] );
184
+ this._sources.set( key, SETTING_SOURCE.DEFAULT );
185
+
186
+ }
187
+
188
+ }
189
+
168
190
  /**
169
191
  * Builds handler functions for multi-stage settings that can't
170
192
  * be routed with a simple uniform forward.
171
193
  */
172
- _buildHandlers( { stages, renderer, resetCallback, reconcileCompletion, denoisingManager, onInteractionRenderScale, onCameraProjection } ) {
194
+ _buildHandlers( { stages, resetCallback, reconcileCompletion, applyExposure, onCameraProjection } ) {
173
195
 
174
196
  // UniformManager copies into the existing node, so one scratch vector serves every write.
175
197
  const panoScratch = new Vector2();
@@ -187,13 +209,6 @@ export class RenderSettings extends EventDispatcher {
187
209
  stages.pathTracer?.setUniform( 'cameraProjection', CAMERA_PROJECTION_IDS[ value ] ?? CAMERA_PROJECTION_IDS.perspective );
188
210
  onCameraProjection?.( value );
189
211
 
190
- if ( value !== 'equirectangular' ) return;
191
-
192
- // MotionVector unprojects through projectionMatrixInverse, which is meaningless once
193
- // every pixel is its own direction. Fall back to the spatial-only denoiser rather
194
- // than leaving no strategy.
195
- if ( denoisingManager?.requiresMotionVectors ) denoisingManager.setDenoiserStrategy( 'edgeaware' );
196
-
197
212
  },
198
213
 
199
214
  handleDofMode: ( value ) => stages.pathTracer?.setUniform( 'dofMode', value === 'look' ? 1 : 0 ),
@@ -220,13 +235,7 @@ export class RenderSettings extends EventDispatcher {
220
235
 
221
236
  handleExposure: ( value ) => {
222
237
 
223
- // Three.js applies toneMappingExposure inside the tone-mapping branch,
224
- // so this has no effect when renderer.toneMapping === NoToneMapping.
225
- if ( ! stages.autoExposure?.enabled && renderer ) {
226
-
227
- renderer.toneMappingExposure = value;
228
-
229
- }
238
+ applyExposure?.( value );
230
239
 
231
240
  },
232
241
 
@@ -274,21 +283,21 @@ export class RenderSettings extends EventDispatcher {
274
283
 
275
284
  },
276
285
 
277
- handleEnvironmentRotation: ( value ) => {
286
+ handleIntegrator: ( value ) => {
278
287
 
279
- stages.pathTracer?.environment.setEnvironmentRotation( value );
288
+ stages.pathTracer?.setIntegrator?.( value );
280
289
 
281
290
  },
282
291
 
283
- handleInteractionModeEnabled: ( value ) => {
292
+ handleEnvironmentRotation: ( value ) => {
284
293
 
285
- stages.pathTracer?.setInteractionModeEnabled( value );
294
+ stages.pathTracer?.environment.setEnvironmentRotation( value );
286
295
 
287
296
  },
288
297
 
289
- handleInteractionRenderScale: ( value ) => {
298
+ handleInteractionModeEnabled: ( value ) => {
290
299
 
291
- onInteractionRenderScale?.( value );
300
+ stages.pathTracer?.setInteractionModeEnabled( value );
292
301
 
293
302
  },
294
303
 
@@ -365,7 +374,7 @@ export class RenderSettings extends EventDispatcher {
365
374
  this._values.set( key, value );
366
375
  this._sources.set( key, source );
367
376
 
368
- const route = SETTING_ROUTES[ key ];
377
+ const route = this._routes.get( key );
369
378
  if ( ! route ) {
370
379
 
371
380
  this._reportUnknownKey( key );
@@ -410,7 +419,7 @@ export class RenderSettings extends EventDispatcher {
410
419
  out[ key ] = {
411
420
  value,
412
421
  source: this._sources.get( key ) ?? SETTING_SOURCE.DEFAULT,
413
- routed: SETTING_ROUTES[ key ] !== undefined,
422
+ routed: this._routes.has( key ),
414
423
  };
415
424
 
416
425
  }
@@ -431,7 +440,7 @@ export class RenderSettings extends EventDispatcher {
431
440
  const out = {};
432
441
  for ( const [ key, value ] of this._values ) {
433
442
 
434
- if ( this._sources.get( key ) !== SETTING_SOURCE.HOST || ! SETTING_ROUTES[ key ] ) continue;
443
+ if ( this._sources.get( key ) !== SETTING_SOURCE.HOST || ! this._routes.has( key ) ) continue;
435
444
  const portable = toPortable( value );
436
445
  if ( portable !== undefined ) out[ key ] = portable;
437
446
 
@@ -452,7 +461,7 @@ export class RenderSettings extends EventDispatcher {
452
461
  const unknown = [];
453
462
  for ( const [ key, value ] of Object.entries( values ?? {} ) ) {
454
463
 
455
- if ( SETTING_ROUTES[ key ] ) known[ key ] = fromPortable( value );
464
+ if ( this._routes.has( key ) ) known[ key ] = fromPortable( value );
456
465
  else unknown.push( key );
457
466
 
458
467
  }
@@ -470,7 +479,7 @@ export class RenderSettings extends EventDispatcher {
470
479
 
471
480
  for ( const [ key, value ] of this._values ) {
472
481
 
473
- const route = SETTING_ROUTES[ key ];
482
+ const route = this._routes.get( key );
474
483
  if ( ! route ) continue;
475
484
 
476
485
  // prev is undefined on initial apply — handlers should not rely on it
@@ -487,15 +496,14 @@ export class RenderSettings extends EventDispatcher {
487
496
  if ( route.uniform ) {
488
497
 
489
498
  this._pathTracer?.setUniform( route.uniform, value );
490
- if ( route.after ) this._pathTracer?.[ route.after ]?.();
491
499
 
492
500
  } else if ( route.handler ) {
493
501
 
494
502
  this._handlers[ route.handler ]?.( value, prev );
495
503
 
496
- } else if ( route.delegate ) {
504
+ } else {
497
505
 
498
- this._delegates[ route.delegate ]?.updateParam?.( route.param, value );
506
+ route.apply( value, prev );
499
507
 
500
508
  }
501
509
 
@@ -52,7 +52,7 @@ export class ASVGF extends RenderStage {
52
52
  this.resH = uniform( options.height || 1 );
53
53
 
54
54
  this.temporalEnabledU = uniform( 1.0 );
55
- // 1.0 for one frame after asvgf:reset → forces a fresh sample so stale pre-reset
55
+ // 1.0 for one frame after pipeline:historyReset → forces a fresh sample so stale pre-reset
56
56
  // (wrong-scene) history isn't blended in (mirrors Variance's _needsWarmReset).
57
57
  this.forceResetU = uniform( 0.0 );
58
58
 
@@ -398,7 +398,7 @@ export class ASVGF extends RenderStage {
398
398
  const demodResult = vec4( currentLighting, 1.0 ).toVar();
399
399
  const modulatedResult = vec4( currentColor, currentAlpha ).toVar();
400
400
 
401
- // forceResetU skips the blend for one frame after asvgf:reset → re-anchors
401
+ // forceResetU skips the blend for one frame after pipeline:historyReset → re-anchors
402
402
  // history to the current (post-reset) scene instead of the stale ping-pong.
403
403
  If( temporalEnabledU.greaterThan( 0.5 ).and( forceResetU.lessThan( 0.5 ) ), () => {
404
404
 
@@ -647,9 +647,7 @@ export class ASVGF extends RenderStage {
647
647
 
648
648
  setupEventListeners() {
649
649
 
650
- this.on( 'asvgf:reset', () => this.resetTemporalData() );
651
-
652
- this.on( 'asvgf:updateParameters', ( data ) => this.updateParameters( data ) );
650
+ this.on( 'pipeline:historyReset', () => this.resetTemporalData() );
653
651
 
654
652
  }
655
653
 
@@ -720,7 +718,7 @@ export class ASVGF extends RenderStage {
720
718
 
721
719
  }
722
720
 
723
- // One-shot fresh re-anchor after asvgf:reset, threaded through the SINGLE
721
+ // One-shot fresh re-anchor after pipeline:historyReset, threaded through the SINGLE
724
722
  // writeNode dispatch (a dual-node warmup would alias the read target — see setSize).
725
723
  this.forceResetU.value = this._needsWarmReset ? 1.0 : 0.0;
726
724
  this.renderer.compute( writeNode );
@@ -865,7 +863,7 @@ export class ASVGF extends RenderStage {
865
863
 
866
864
  reset() {
867
865
 
868
- // No-op: motion vectors handle camera moves; explicit asvgf:reset
866
+ // No-op: motion vectors handle camera moves; explicit pipeline:historyReset
869
867
  // clears history on scene/mode change.
870
868
 
871
869
  }
@@ -80,9 +80,8 @@ const adaptExposure = /*@__PURE__*/ wgslFn( `
80
80
  * Execution: ALWAYS
81
81
  *
82
82
  * Events listened:
83
- * pipeline:reset — reset temporal history
84
- * autoexposure:toggle — enable/disable
85
- * autoexposure:updateParameters — update key value, speeds, bounds, percentiles
83
+ * pipeline:reset — soft reset (keeps the exposure, discards an in-flight readback)
84
+ * pipeline:lightingChanged — a new model or environment: start the exposure history over
86
85
  *
87
86
  * Textures published: (none — publishes state, not textures)
88
87
  * Textures read: edgeFiltering:output > asvgf:output > pathtracer:color
@@ -471,15 +470,7 @@ export class AutoExposure extends RenderStage {
471
470
  setupEventListeners() {
472
471
 
473
472
  this.on( 'pipeline:reset', () => this.reset() );
474
- this.on( 'autoexposure:resetHistory', () => this.resetHistory() );
475
-
476
- this.on( 'autoexposure:toggle', ( enabled ) => {
477
-
478
- this.enabled = enabled;
479
-
480
- } );
481
-
482
- this.on( 'autoexposure:updateParameters', ( data ) => data && this.updateParameters( data ) );
473
+ this.on( 'pipeline:lightingChanged', () => this.resetHistory() );
483
474
 
484
475
  }
485
476
 
@@ -4,15 +4,6 @@ import { NoBlending, NoToneMapping } from 'three';
4
4
  import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
5
5
  import { REC709_LUMINANCE_COEFFICIENTS } from '../TSL/Common.js';
6
6
 
7
- // In priority order: the first one published wins.
8
- const LIGHT_SOURCES = [
9
- 'oidn:output',
10
- 'edgeFiltering:output',
11
- 'bilateralFiltering:output',
12
- 'asvgf:output',
13
- 'nrd:output',
14
- 'pathtracer:color',
15
- ];
16
7
 
17
8
  /**
18
9
  * Compositor — Terminal pipeline stage.
@@ -36,6 +27,10 @@ export class Compositor extends RenderStage {
36
27
 
37
28
  this.renderer = renderer;
38
29
 
30
+ // In priority order: the first one published wins. Whoever builds the pipeline names the
31
+ // processed pictures; the accumulation is the fallback that is always there.
32
+ this._lightSources = [ ...( options.displaySources ?? [] ), 'pathtracer:color' ];
33
+
39
34
  // 1.0 = neutral; >1 boosts to compensate for ACES/AgX desaturation.
40
35
  this.saturation = uniform( options.saturation ?? 1.0 );
41
36
 
@@ -71,18 +66,8 @@ export class Compositor extends RenderStage {
71
66
  }
72
67
 
73
68
  /**
74
- * Later stages in the chain take priority; `pathtracer:color` is the
75
- * baseline fallback that is always present.
76
- */
77
- _resolveSourceTexture( context ) {
78
-
79
- return context.getTexture( 'bloom:output' ) || this.resolveLightTexture( context );
80
-
81
- }
82
-
83
- /**
84
- * The newest scene-referred image the pipeline holds — denoised when a denoiser has run — without
85
- * bloom, which is a look added on top rather than light in the scene.
69
+ * The picture to show: the first published of the display sources, else `pathtracer:color` — the newest
70
+ * scene-referred image the pipeline holds, denoised when a denoiser has run.
86
71
  */
87
72
  resolveLightTexture( context ) {
88
73
 
@@ -93,7 +78,7 @@ export class Compositor extends RenderStage {
93
78
  /** {@link resolveLightTexture} plus the context key it came from. */
94
79
  resolveLightSource( context ) {
95
80
 
96
- for ( const key of LIGHT_SOURCES ) {
81
+ for ( const key of this._lightSources ) {
97
82
 
98
83
  const texture = context.getTexture( key );
99
84
  if ( texture ) return { key, texture };
@@ -215,7 +200,7 @@ export class Compositor extends RenderStage {
215
200
 
216
201
  }
217
202
 
218
- const sourceTexture = this._resolveSourceTexture( context );
203
+ const sourceTexture = this.resolveLightTexture( context );
219
204
  if ( ! sourceTexture ) return;
220
205
 
221
206
  this._sourceTexNode.value = sourceTexture;
package/src/Stages/NRD.js CHANGED
@@ -133,7 +133,7 @@ function hash01( n ) {
133
133
  * Reads: pathtracer:color, pathtracer:albedo (.w = normHitDist), pathtracer:normalDepth,
134
134
  * pathtracer:shadingNormal (.w = roughness), motionVector:screenSpace
135
135
  * Publishes: nrd:output
136
- * Events: denoiser:reset
136
+ * Events: pipeline:historyReset
137
137
  */
138
138
  export class NRD extends RenderStage {
139
139
 
@@ -148,6 +148,11 @@ export class NRD extends RenderStage {
148
148
  this.pathTracer = options.pathTracer || null;
149
149
  this.settings = { ...NRD_DEFAULTS, ...( options.settings || {} ) };
150
150
 
151
+ // The path tracer's hit distance, normalised by view depth as ReBLUR reads it (pathtracer:albedo.w).
152
+ this._releaseHitDistance = this.pathTracer?.requestOutput?.( 'hitDistance', {
153
+ encode: ( distance, viewZ ) => distance.div( max( viewZ.mul( NRD_HIT_DIST_B ).add( NRD_HIT_DIST_A ), float( 1e-4 ) ) ).clamp( 0.0, 1.0 ),
154
+ } ) ?? null;
155
+
151
156
  const w = options.width || 1;
152
157
  const h = options.height || 1;
153
158
 
@@ -1185,7 +1190,7 @@ export class NRD extends RenderStage {
1185
1190
 
1186
1191
  setupEventListeners() {
1187
1192
 
1188
- this.on( 'denoiser:reset', () => this.resetHistory() );
1193
+ this.on( 'pipeline:historyReset', () => this.resetHistory() );
1189
1194
 
1190
1195
  }
1191
1196
 
@@ -1383,6 +1388,8 @@ export class NRD extends RenderStage {
1383
1388
 
1384
1389
  dispose() {
1385
1390
 
1391
+ this._releaseHitDistance?.();
1392
+ this._releaseHitDistance = null;
1386
1393
  this._disposeKernels();
1387
1394
  this._disposeStorage();
1388
1395
  this.outputTarget?.dispose();
@@ -8,7 +8,8 @@ import { Ray, HitInfo, RayTracingMaterial, UVCache } from '../TSL/Struct.js';
8
8
  import { traverseBVH } from '../TSL/BVHTraversal.js';
9
9
  import { cameraRayOf, cameraRayUniforms } from '../TSL/CameraRay.js';
10
10
  import { getMaterial } from '../TSL/Common.js';
11
- import { computeUVCache, processNormal, processBump, processMetalnessRoughness, triangleUVTangent, buildBucketTextureNodes, refreshBucketTextureNodes, setMaterialBucketTextures } from '../TSL/TextureSampling.js';
11
+ import { computeUVCache, processNormal, processBump, processMetalnessRoughness, triangleUVTangent, buildBucketTextureNodes, refreshBucketTextureNodes } from '../TSL/TextureSampling.js';
12
+ import { withSceneResources } from '../TSL/SceneResources.js';
12
13
 
13
14
  /**
14
15
  * NormalDepth — primary-ray G-buffer for SVGF gates.
@@ -207,11 +208,13 @@ export class NormalDepth extends RenderStage {
207
208
  const triStorage = this._triStorageNode;
208
209
  const bvhStorage = this._bvhStorageNode;
209
210
  const matStorage = this._matStorageNode;
210
- // Independent linear-pool bucket nodes for this pipeline (normal + bump). The sRGB pool
211
- // is never sampled here, so it gets placeholders. Publish to the sampling module before
212
- // the graph is built so processNormal/processBump bake in THESE (per-pipeline) nodes.
211
+ // Independent linear-pool bucket nodes for this pipeline (normal + bump), in its kernel's build
212
+ // context (SceneResources.js). The sRGB pool is never sampled here, so it gets placeholders.
213
213
  this._linearBuckets = buildBucketTextureNodes( this.pathTracer?.materialData?.linearBuckets );
214
- setMaterialBucketTextures( buildBucketTextureNodes( null ), this._linearBuckets );
214
+ const resources = {
215
+ srgbBuckets: buildBucketTextureNodes( null ), linearBuckets: this._linearBuckets,
216
+ shadowAlbedoMaps: null, goboMaps: null, iesProfiles: null, alphaShadows: null,
217
+ };
215
218
  const camWorld = this.cameraWorldMatrix;
216
219
  const camProjInv = this.cameraProjectionMatrixInverse;
217
220
  const resW = this.resolutionWidth;
@@ -308,7 +311,7 @@ export class NormalDepth extends RenderStage {
308
311
 
309
312
  } );
310
313
 
311
- this._computeNode = computeFn( camWorld, camProjInv ).compute(
314
+ this._computeNode = withSceneResources( computeFn( camWorld, camProjInv ), resources ).compute(
312
315
  [ this._dispatchX, this._dispatchY, 1 ],
313
316
  [ WG_SIZE, WG_SIZE, 1 ]
314
317
  );