rayzee 10.0.0 → 11.0.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 (173) hide show
  1. package/README.md +252 -44
  2. package/dist/ActiveColor-YvuQq44O.js +13 -0
  3. package/dist/ArchiveImporter-BRQvLggb.js +4300 -0
  4. package/dist/AssetConfig-DSEntE65.js +30 -0
  5. package/dist/BidirectionalIntegrator-9lZQxFVH.js +934 -0
  6. package/dist/BufferLayout-D_IBo2ci.js +150 -0
  7. package/dist/ColorManagement-oeEk7oSu.js +1488 -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-dDDGj9Av.js +97 -0
  12. package/dist/{NeuralRetouch-CYgkQY8Z.js → NeuralRetouch-BCXylThH.js} +8 -6
  13. package/dist/{NeuralSuperRes-PkgDLQcD.js → NeuralSuperRes-sZAeS142.js} +55 -120
  14. package/dist/PathTracer-CQPW06Mm.js +29971 -0
  15. package/dist/PhysicalSky-BvqCw_dy.js +1219 -0
  16. package/dist/RayzeeRenderer-COpwotpU.js +3551 -0
  17. package/dist/SolarLimb-CPaeZVwz.js +721 -0
  18. package/dist/ToneMapGPU-CjU3osDd.js +177 -0
  19. package/dist/ViewTransforms-CYN7bq2w.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 +2551 -44024
  33. package/dist/rayzee.umd.js +528 -487
  34. package/dist/sceneCachePolicy-BSSsKY98.js +443 -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/Color/ViewTransforms.js +5 -1
  41. package/src/EngineDefaults.js +62 -1029
  42. package/src/EngineEvents.js +2 -0
  43. package/src/EngineIssues.js +2 -0
  44. package/src/Headless.js +6 -5
  45. package/src/Passes/AIUpscaler.js +58 -141
  46. package/src/Passes/OIDNDenoiser.js +92 -65
  47. package/src/Passes/OIDNTemporalHistory.js +1 -1
  48. package/src/PathTracerApp.js +620 -4026
  49. package/src/Pipeline/PipelineContext.js +0 -4
  50. package/src/Platform.js +36 -0
  51. package/src/Processor/ArchiveCache.js +1 -1
  52. package/src/Processor/ArchiveImporter.js +1259 -0
  53. package/src/Processor/AssetLoader.js +327 -1763
  54. package/src/Processor/AtmosphereModel.js +1 -2
  55. package/src/Processor/BVHBuilder.js +14 -126
  56. package/src/Processor/BVHLeafFold.js +4 -6
  57. package/src/Processor/BVHRefitter.js +67 -46
  58. package/src/Processor/BufferLayout.js +291 -0
  59. package/src/Processor/EmissiveTriangleBuilder.js +1 -1
  60. package/src/Processor/EnvironmentExactTable.js +187 -0
  61. package/src/Processor/EquirectHDRInfo.js +30 -223
  62. package/src/Processor/FileFormats.js +116 -0
  63. package/src/Processor/GLTFDecoders.js +85 -0
  64. package/src/Processor/GLTFDiffuseTransmission.js +63 -0
  65. package/src/Processor/GeometryExtractor.js +15 -5
  66. package/src/Processor/HostMemory.js +7 -1
  67. package/src/Processor/IESParser.js +47 -35
  68. package/src/Processor/InstanceTable.js +1 -1
  69. package/src/Processor/KernelManager.js +35 -2
  70. package/src/Processor/MaterialPacking.js +10 -8
  71. package/src/Processor/PBRT/PBRTMaterials.js +129 -41
  72. package/src/Processor/PBRT/PBRTParser.js +30 -17
  73. package/src/Processor/PBRT/PBRTSceneBuilder.js +548 -37
  74. package/src/Processor/PBRT/PBRTTextureBake.js +154 -0
  75. package/src/Processor/PBRT/PFM.js +59 -0
  76. package/src/Processor/PackedRayBuffer.js +116 -9
  77. package/src/Processor/ParallelBVHBuilder.js +3 -6
  78. package/src/Processor/PhysicalSky.js +5 -4
  79. package/src/Processor/PlatformImageLoader.js +50 -6
  80. package/src/Processor/QueueManager.js +39 -5
  81. package/src/Processor/ReinsertionOptimizer.js +2 -2
  82. package/src/Processor/SceneProcessor.js +53 -62
  83. package/src/Processor/ShaderBuilder.js +6 -16
  84. package/src/Processor/SimpleSky.js +1 -62
  85. package/src/Processor/SolarLimb.js +3 -0
  86. package/src/Processor/SplitBLAS.js +1 -1
  87. package/src/Processor/StorageTexturePool.js +22 -1
  88. package/src/Processor/TLASBuilder.js +1 -3
  89. package/src/Processor/TextureBuckets.js +237 -0
  90. package/src/Processor/TextureCreator.js +181 -8
  91. package/src/Processor/ToneMapGPU.js +64 -15
  92. package/src/Processor/Workers/BVHRefitWorker.js +5 -2
  93. package/src/Processor/Workers/BVHSubtreeWorker.js +1 -34
  94. package/src/Processor/Workers/BVHWorker.js +5 -18
  95. package/src/Processor/Workers/CDFWorker.js +6 -183
  96. package/src/Processor/Workers/TexturesWorker.js +103 -18
  97. package/src/Processor/archiveFormats.js +7 -0
  98. package/src/Processor/utils.js +2 -1
  99. package/src/RayzeeRenderer.js +3899 -0
  100. package/src/RenderSettings.js +68 -62
  101. package/src/Stages/ASVGF.js +13 -14
  102. package/src/Stages/AutoExposure.js +17 -17
  103. package/src/Stages/BilateralFilter.js +2 -1
  104. package/src/Stages/Compositor.js +8 -23
  105. package/src/Stages/DenoiserSettings.js +182 -0
  106. package/src/Stages/EdgeFilter.js +2 -1
  107. package/src/Stages/MotionVector.js +1 -1
  108. package/src/Stages/NRD.js +11 -5
  109. package/src/Stages/NormalDepth.js +12 -8
  110. package/src/Stages/PathTracer.js +338 -43
  111. package/src/Stages/PathTracerStage.js +69 -66
  112. package/src/Stages/Variance.js +1 -1
  113. package/src/Storage/BLASCache.js +1 -1
  114. package/src/Storage/CDFCache.js +18 -17
  115. package/src/Storage/DownloadCache.js +1 -1
  116. package/src/Storage/SceneGraphCodec.js +46 -3
  117. package/src/Storage/SpillStore.js +1 -1
  118. package/src/Storage/StorageManager.js +45 -9
  119. package/src/Storage/areas.js +4 -0
  120. package/src/TSL/BVHTraversal.js +50 -25
  121. package/src/TSL/Bidirectional.js +204 -0
  122. package/src/TSL/BidirectionalLamps.js +132 -0
  123. package/src/TSL/Clearcoat.js +15 -6
  124. package/src/TSL/Common.js +20 -15
  125. package/src/TSL/ConnectKernel.js +147 -0
  126. package/src/TSL/Debugger.js +1 -1
  127. package/src/TSL/Displacement.js +4 -3
  128. package/src/TSL/EmissiveSampling.js +65 -18
  129. package/src/TSL/Environment.js +77 -106
  130. package/src/TSL/EnvironmentCDF.js +85 -39
  131. package/src/TSL/ExtendKernel.js +8 -3
  132. package/src/TSL/FinalWriteKernel.js +4 -4
  133. package/src/TSL/GenerateKernel.js +18 -4
  134. package/src/TSL/HitFacet.js +35 -5
  135. package/src/TSL/LightBVHSampling.js +40 -9
  136. package/src/TSL/LightGenerateKernel.js +293 -0
  137. package/src/TSL/LightGuide.js +198 -0
  138. package/src/TSL/LightSplatKernel.js +165 -0
  139. package/src/TSL/LightVisibility.js +111 -0
  140. package/src/TSL/LightsCore.js +13 -38
  141. package/src/TSL/LightsDirect.js +28 -29
  142. package/src/TSL/LightsIndirect.js +3 -1
  143. package/src/TSL/LightsSampling.js +239 -51
  144. package/src/TSL/MaterialEvaluation.js +113 -31
  145. package/src/TSL/MaterialProperties.js +44 -17
  146. package/src/TSL/MaterialTransmission.js +52 -47
  147. package/src/TSL/MergeKernel.js +218 -0
  148. package/src/TSL/PathTracerCore.js +65 -29
  149. package/src/TSL/Random.js +5 -1
  150. package/src/TSL/SceneResources.js +51 -0
  151. package/src/TSL/ShadeKernel.js +964 -101
  152. package/src/TSL/Struct.js +10 -0
  153. package/src/TSL/Sun.js +1 -1
  154. package/src/TSL/TextureSampling.js +66 -61
  155. package/src/addons/archives.js +14 -0
  156. package/src/addons/bidirectional.js +13 -0
  157. package/src/addons/color.js +32 -0
  158. package/src/addons/formats.js +16 -0
  159. package/src/addons/physicalSky.js +14 -0
  160. package/src/addons/storage.js +19 -0
  161. package/src/core.js +31 -0
  162. package/src/index.js +13 -23
  163. package/src/integrators/BidirectionalIntegrator.js +833 -0
  164. package/src/managers/AnimationManager.js +88 -6
  165. package/src/managers/CameraManager.js +103 -46
  166. package/src/managers/DenoisingManager.js +14 -10
  167. package/src/managers/EnvironmentManager.js +125 -103
  168. package/src/managers/GoboManager.js +9 -0
  169. package/src/managers/MaterialDataManager.js +48 -37
  170. package/src/managers/UniformManager.js +32 -10
  171. package/dist/ToneMapGPU-B6XIe3DU.js +0 -544
  172. package/dist/rolldown-runtime-CAFD8bLK.js +0 -11
  173. package/src/Processor/TreeletOptimizer.js +0 -574
@@ -5,13 +5,14 @@ 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)
12
+ * - neither → stored only; whoever needs it reads it
13
13
  * - `reset` → whether to reset accumulation after the change (default true)
14
- * - `after` → optional method to call on PathTracer after the uniform is set
14
+ *
15
+ * Other layers add their own keys with {@link RenderSettings#define}.
15
16
  */
16
17
  const SETTING_ROUTES = {
17
18
 
@@ -68,7 +69,6 @@ const SETTING_ROUTES = {
68
69
  panoramaLonRange: { handler: 'handlePanoramaLonRange', reset: true },
69
70
  panoramaLatRange: { handler: 'handlePanoramaLatRange', reset: true },
70
71
  interactionModeEnabled: { handler: 'handleInteractionModeEnabled', reset: false },
71
- interactionRenderScale: { handler: 'handleInteractionRenderScale', reset: false },
72
72
  maxSamples: { handler: 'handleMaxSamples', reset: false },
73
73
  transparentBackground: { handler: 'handleTransparentBackground' },
74
74
  backgroundColor: { handler: 'handleBackgroundColor', reset: true },
@@ -77,14 +77,17 @@ const SETTING_ROUTES = {
77
77
  renderLimitMode: { handler: 'handleRenderLimitMode' },
78
78
  renderTimeLimit: { handler: 'handleRenderTimeLimit', reset: false },
79
79
  renderMode: { handler: 'handleRenderMode' },
80
+ integrator: { handler: 'handleIntegrator', reset: true },
81
+ shadowRays: { handler: 'handleShadowRays', reset: true },
80
82
  environmentRotation: { handler: 'handleEnvironmentRotation' },
83
+ // Read when the kernels next build.
84
+ wavefrontSortMaterials: { handler: 'handleWavefrontSortMaterials', reset: false },
85
+ // No target: read when a model loads (setMaxTextureSize() also reprocesses the scene now).
86
+ maxTextureSize: { reset: false },
87
+ areaLightIntensityScale: { reset: false },
81
88
 
82
89
  };
83
90
 
84
- /**
85
- * Default keys to extract from ENGINE_DEFAULTS for initializing the values map.
86
- * Maps ENGINE_DEFAULTS key → RenderSettings key when they differ.
87
- */
88
91
  /** Provenance tags for getEffective(). Add-only — hosts branch on them. */
89
92
  export const SETTING_SOURCE = Object.freeze( {
90
93
  DEFAULT: 'default',
@@ -93,11 +96,6 @@ export const SETTING_SOURCE = Object.freeze( {
93
96
  MODE_PRESET: 'mode-preset',
94
97
  } );
95
98
 
96
- const DEFAULTS_KEY_MAP = {
97
- bounces: 'maxBounces',
98
- debugMode: 'visMode',
99
- };
100
-
101
99
  /**
102
100
  * Single source of truth for all render parameters.
103
101
  *
@@ -122,6 +120,12 @@ export class RenderSettings extends EventDispatcher {
122
120
 
123
121
  this._issues = issues;
124
122
 
123
+ /** Default values, kept for keys another layer defines later */
124
+ this._defaults = defaults;
125
+
126
+ /** @type {Map<string, Object>} - the core's routes and those other layers define */
127
+ this._routes = new Map( Object.entries( SETTING_ROUTES ) );
128
+
125
129
  /** @type {Map<string, *>} */
126
130
  this._values = new Map();
127
131
 
@@ -137,39 +141,57 @@ export class RenderSettings extends EventDispatcher {
137
141
  /** @type {Object<string, Function>} - Named handlers for multi-stage settings */
138
142
  this._handlers = {};
139
143
 
140
- /** @type {Object<string, Object>} - Named delegate managers */
141
- this._delegates = {};
142
-
143
144
  // Initialize values from ENGINE_DEFAULTS
144
145
  this._initDefaults( defaults );
145
146
 
146
147
  }
147
148
 
148
149
  /**
149
- * Wires internal references. Called by PathTracerApp after init().
150
+ * Wires the core's settings to their targets. Called by the renderer during init().
150
151
  *
151
152
  * @param {Object} params
152
- * @param {Object} params.stages - Pipeline stages { pathTracer, compositor, autoExposure, ... }
153
+ * @param {Object} params.stages - Pipeline stages { pathTracer, compositor }
153
154
  * @param {Function} params.resetCallback - Called to reset accumulation
154
155
  * @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
156
+ * @param {Function} [params.applyExposure] - Shows a new `exposure`
157
157
  * @param {Function} [params.onCameraProjection] - The camera's side of a `cameraProjection` change
158
158
  */
159
159
  bind( params ) {
160
160
 
161
161
  this._pathTracer = params.stages.pathTracer;
162
162
  this._resetCallback = params.resetCallback;
163
- this._delegates = {};
164
163
  this._handlers = this._buildHandlers( params );
165
164
 
166
165
  }
167
166
 
167
+ /**
168
+ * Adds a setting of another layer — the viewer's, or an add-on's — with the same provenance, events, session
169
+ * saving and reset as the core's. The layer brings its own default.
170
+ * @param {string} key
171
+ * @param {Object} route
172
+ * @param {*} [route.default] - the value until someone sets one; else the one this store was built with
173
+ * @param {function(*, *): void} route.apply - called with ( value, prev ) on every change, and by applyAll()
174
+ * @param {boolean} [route.reset=true] - reset accumulation after a change
175
+ */
176
+ define( key, { default: initial, apply, reset = true } ) {
177
+
178
+ if ( this._routes.has( key ) ) throw new Error( `setting "${key}" is already defined` );
179
+ this._routes.set( key, { apply, reset } );
180
+ const value = initial !== undefined ? initial : this._defaults[ key ];
181
+ if ( ! this._values.has( key ) && value !== undefined ) {
182
+
183
+ this._values.set( key, value );
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,33 @@ export class RenderSettings extends EventDispatcher {
274
283
 
275
284
  },
276
285
 
286
+ handleIntegrator: ( value ) => {
287
+
288
+ stages.pathTracer?.setIntegrator?.( value );
289
+
290
+ },
291
+
292
+ handleShadowRays: ( value ) => {
293
+
294
+ stages.pathTracer?.setShadowRays?.( value );
295
+
296
+ },
297
+
277
298
  handleEnvironmentRotation: ( value ) => {
278
299
 
279
300
  stages.pathTracer?.environment.setEnvironmentRotation( value );
280
301
 
281
302
  },
282
303
 
283
- handleInteractionModeEnabled: ( value ) => {
304
+ handleWavefrontSortMaterials: ( value ) => {
284
305
 
285
- stages.pathTracer?.setInteractionModeEnabled( value );
306
+ if ( stages.pathTracer ) stages.pathTracer.sortMaterials = value;
286
307
 
287
308
  },
288
309
 
289
- handleInteractionRenderScale: ( value ) => {
310
+ handleInteractionModeEnabled: ( value ) => {
290
311
 
291
- onInteractionRenderScale?.( value );
312
+ stages.pathTracer?.setInteractionModeEnabled( value );
292
313
 
293
314
  },
294
315
 
@@ -365,7 +386,7 @@ export class RenderSettings extends EventDispatcher {
365
386
  this._values.set( key, value );
366
387
  this._sources.set( key, source );
367
388
 
368
- const route = SETTING_ROUTES[ key ];
389
+ const route = this._routes.get( key );
369
390
  if ( ! route ) {
370
391
 
371
392
  this._reportUnknownKey( key );
@@ -410,7 +431,7 @@ export class RenderSettings extends EventDispatcher {
410
431
  out[ key ] = {
411
432
  value,
412
433
  source: this._sources.get( key ) ?? SETTING_SOURCE.DEFAULT,
413
- routed: SETTING_ROUTES[ key ] !== undefined,
434
+ routed: this._routes.has( key ),
414
435
  };
415
436
 
416
437
  }
@@ -431,7 +452,7 @@ export class RenderSettings extends EventDispatcher {
431
452
  const out = {};
432
453
  for ( const [ key, value ] of this._values ) {
433
454
 
434
- if ( this._sources.get( key ) !== SETTING_SOURCE.HOST || ! SETTING_ROUTES[ key ] ) continue;
455
+ if ( this._sources.get( key ) !== SETTING_SOURCE.HOST || ! this._routes.has( key ) ) continue;
435
456
  const portable = toPortable( value );
436
457
  if ( portable !== undefined ) out[ key ] = portable;
437
458
 
@@ -452,7 +473,7 @@ export class RenderSettings extends EventDispatcher {
452
473
  const unknown = [];
453
474
  for ( const [ key, value ] of Object.entries( values ?? {} ) ) {
454
475
 
455
- if ( SETTING_ROUTES[ key ] ) known[ key ] = fromPortable( value );
476
+ if ( this._routes.has( key ) ) known[ key ] = fromPortable( value );
456
477
  else unknown.push( key );
457
478
 
458
479
  }
@@ -470,7 +491,7 @@ export class RenderSettings extends EventDispatcher {
470
491
 
471
492
  for ( const [ key, value ] of this._values ) {
472
493
 
473
- const route = SETTING_ROUTES[ key ];
494
+ const route = this._routes.get( key );
474
495
  if ( ! route ) continue;
475
496
 
476
497
  // prev is undefined on initial apply — handlers should not rely on it
@@ -487,15 +508,14 @@ export class RenderSettings extends EventDispatcher {
487
508
  if ( route.uniform ) {
488
509
 
489
510
  this._pathTracer?.setUniform( route.uniform, value );
490
- if ( route.after ) this._pathTracer?.[ route.after ]?.();
491
511
 
492
512
  } else if ( route.handler ) {
493
513
 
494
514
  this._handlers[ route.handler ]?.( value, prev );
495
515
 
496
- } else if ( route.delegate ) {
516
+ } else {
497
517
 
498
- this._delegates[ route.delegate ]?.updateParam?.( route.param, value );
518
+ route.apply?.( value, prev );
499
519
 
500
520
  }
501
521
 
@@ -503,11 +523,9 @@ export class RenderSettings extends EventDispatcher {
503
523
 
504
524
  /**
505
525
  * Populates the values map from ENGINE_DEFAULTS.
506
- * Handles key renames via DEFAULTS_KEY_MAP.
507
526
  */
508
527
  _initDefaults( defaults ) {
509
528
 
510
- // Keys that exist in both SETTING_ROUTES and ENGINE_DEFAULTS (direct match)
511
529
  for ( const key of Object.keys( SETTING_ROUTES ) ) {
512
530
 
513
531
  if ( key in defaults ) {
@@ -519,18 +537,6 @@ export class RenderSettings extends EventDispatcher {
519
537
 
520
538
  }
521
539
 
522
- // Keys where ENGINE_DEFAULTS uses a different name
523
- for ( const [ defaultsKey, settingsKey ] of Object.entries( DEFAULTS_KEY_MAP ) ) {
524
-
525
- if ( defaultsKey in defaults ) {
526
-
527
- this._values.set( settingsKey, defaults[ defaultsKey ] );
528
- this._sources.set( settingsKey, SETTING_SOURCE.DEFAULT );
529
-
530
- }
531
-
532
- }
533
-
534
540
  }
535
541
 
536
542
  }
@@ -5,7 +5,8 @@ import { RenderTarget, TextureNode, StorageTexture } from 'three/webgpu';
5
5
  import { HalfFloatType, FloatType, RGBAFormat, NearestFilter, LinearFilter, Box2, Vector2 } from 'three';
6
6
  import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
7
7
  import { luminance } from '../TSL/Common.js';
8
- import { ALBEDO_EPS, MAX_STORAGE_TEXTURE_SIZE } from '../EngineDefaults.js';
8
+ import { MAX_STORAGE_TEXTURE_SIZE } from '../Processor/StorageTexturePool.js';
9
+ import { ALBEDO_EPS, ASVGF_QUALITY_PRESETS } from './DenoiserSettings.js';
9
10
 
10
11
  // Replace NaN/±Inf with a bounded value so one firefly can't permanently poison the
11
12
  // temporal EMA (mix() propagates NaN forever). Per-channel: NaN (x!=x) → 0, ±Inf → [0,1e7].
@@ -39,20 +40,20 @@ export class ASVGF extends RenderStage {
39
40
 
40
41
  this.renderer = renderer;
41
42
 
42
- this.temporalAlpha = uniform( options.temporalAlpha ?? 0.0 );
43
- // > 0 is required for firefly rejection, not just anti-lag — see ENGINE_DEFAULTS.
44
- this.gradientStrength = uniform( options.gradientStrength ?? 1.0 );
43
+ this.temporalAlpha = uniform( options.temporalAlpha ?? ASVGF_QUALITY_PRESETS.medium.temporalAlpha );
44
+ // > 0 is required for firefly rejection, not just anti-lag — see DENOISER_DEFAULTS.
45
+ this.gradientStrength = uniform( options.gradientStrength ?? ASVGF_QUALITY_PRESETS.medium.gradientStrength );
45
46
  // σ multiplier for the per-pixel noise floor (NRD luminanceSigmaScale ≈ 2).
46
- this.gradientSigmaScale = uniform( options.gradientSigmaScale ?? 2.0 );
47
+ this.gradientSigmaScale = uniform( options.gradientSigmaScale ?? ASVGF_QUALITY_PRESETS.medium.gradientSigmaScale );
47
48
  // Secondary relative floor on the normalised gradient (0 = rely on σ alone).
48
- this.gradientNoiseFloor = uniform( options.gradientNoiseFloor ?? 0.0 );
49
- this.maxAccumFrames = uniform( options.maxAccumFrames ?? 32.0 );
49
+ this.gradientNoiseFloor = uniform( options.gradientNoiseFloor ?? ASVGF_QUALITY_PRESETS.medium.gradientNoiseFloor );
50
+ this.maxAccumFrames = uniform( options.maxAccumFrames ?? ASVGF_QUALITY_PRESETS.medium.maxAccumFrames );
50
51
 
51
52
  this.resW = uniform( options.width || 1 );
52
53
  this.resH = uniform( options.height || 1 );
53
54
 
54
55
  this.temporalEnabledU = uniform( 1.0 );
55
- // 1.0 for one frame after asvgf:reset → forces a fresh sample so stale pre-reset
56
+ // 1.0 for one frame after pipeline:historyReset → forces a fresh sample so stale pre-reset
56
57
  // (wrong-scene) history isn't blended in (mirrors Variance's _needsWarmReset).
57
58
  this.forceResetU = uniform( 0.0 );
58
59
 
@@ -398,7 +399,7 @@ export class ASVGF extends RenderStage {
398
399
  const demodResult = vec4( currentLighting, 1.0 ).toVar();
399
400
  const modulatedResult = vec4( currentColor, currentAlpha ).toVar();
400
401
 
401
- // forceResetU skips the blend for one frame after asvgf:reset → re-anchors
402
+ // forceResetU skips the blend for one frame after pipeline:historyReset → re-anchors
402
403
  // history to the current (post-reset) scene instead of the stale ping-pong.
403
404
  If( temporalEnabledU.greaterThan( 0.5 ).and( forceResetU.lessThan( 0.5 ) ), () => {
404
405
 
@@ -647,9 +648,7 @@ export class ASVGF extends RenderStage {
647
648
 
648
649
  setupEventListeners() {
649
650
 
650
- this.on( 'asvgf:reset', () => this.resetTemporalData() );
651
-
652
- this.on( 'asvgf:updateParameters', ( data ) => this.updateParameters( data ) );
651
+ this.on( 'pipeline:historyReset', () => this.resetTemporalData() );
653
652
 
654
653
  }
655
654
 
@@ -720,7 +719,7 @@ export class ASVGF extends RenderStage {
720
719
 
721
720
  }
722
721
 
723
- // One-shot fresh re-anchor after asvgf:reset, threaded through the SINGLE
722
+ // One-shot fresh re-anchor after pipeline:historyReset, threaded through the SINGLE
724
723
  // writeNode dispatch (a dual-node warmup would alias the read target — see setSize).
725
724
  this.forceResetU.value = this._needsWarmReset ? 1.0 : 0.0;
726
725
  this.renderer.compute( writeNode );
@@ -865,7 +864,7 @@ export class ASVGF extends RenderStage {
865
864
 
866
865
  reset() {
867
866
 
868
- // No-op: motion vectors handle camera moves; explicit asvgf:reset
867
+ // No-op: motion vectors handle camera moves; explicit pipeline:historyReset
869
868
  // clears history on scene/mode change.
870
869
 
871
870
  }
@@ -7,6 +7,15 @@ import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
7
7
  import { luminance } from '../TSL/Common.js';
8
8
 
9
9
  // ── Histogram constants ────────────────────────────────────
10
+ export const AUTO_EXPOSURE_DEFAULTS = {
11
+ autoExposure: false,
12
+ autoExposureKeyValue: 0.18,
13
+ autoExposureMinExposure: 0.1,
14
+ autoExposureMaxExposure: 20.0,
15
+ autoExposureAdaptSpeedBright: 3.0,
16
+ autoExposureAdaptSpeedDark: 0.5,
17
+ };
18
+
10
19
  const NUM_BINS = 256;
11
20
  const MIN_LOG_LUM = - 8.0; // ln(~0.00034) — very dark
12
21
  const MAX_LOG_LUM = 6.0; // ln(~403) — bright specular
@@ -80,9 +89,8 @@ const adaptExposure = /*@__PURE__*/ wgslFn( `
80
89
  * Execution: ALWAYS
81
90
  *
82
91
  * Events listened:
83
- * pipeline:reset — reset temporal history
84
- * autoexposure:toggle — enable/disable
85
- * autoexposure:updateParameters — update key value, speeds, bounds, percentiles
92
+ * pipeline:reset — soft reset (keeps the exposure, discards an in-flight readback)
93
+ * pipeline:lightingChanged — a new model or environment: start the exposure history over
86
94
  *
87
95
  * Textures published: (none — publishes state, not textures)
88
96
  * Textures read: edgeFiltering:output > asvgf:output > pathtracer:color
@@ -104,11 +112,11 @@ export class AutoExposure extends RenderStage {
104
112
 
105
113
  // ── Adaptation uniforms ──────────────────────────
106
114
 
107
- this.keyValueU = uniform( options.keyValue ?? 0.18 );
108
- this.minExposureU = uniform( options.minExposure ?? 0.1 );
109
- this.maxExposureU = uniform( options.maxExposure ?? 20.0 );
110
- this.adaptSpeedBrightU = uniform( options.adaptSpeedBright ?? 3.0 );
111
- this.adaptSpeedDarkU = uniform( options.adaptSpeedDark ?? 0.5 );
115
+ this.keyValueU = uniform( options.keyValue ?? AUTO_EXPOSURE_DEFAULTS.autoExposureKeyValue );
116
+ this.minExposureU = uniform( options.minExposure ?? AUTO_EXPOSURE_DEFAULTS.autoExposureMinExposure );
117
+ this.maxExposureU = uniform( options.maxExposure ?? AUTO_EXPOSURE_DEFAULTS.autoExposureMaxExposure );
118
+ this.adaptSpeedBrightU = uniform( options.adaptSpeedBright ?? AUTO_EXPOSURE_DEFAULTS.autoExposureAdaptSpeedBright );
119
+ this.adaptSpeedDarkU = uniform( options.adaptSpeedDark ?? AUTO_EXPOSURE_DEFAULTS.autoExposureAdaptSpeedDark );
112
120
  this.epsilonU = uniform( options.epsilon ?? 0.0001 );
113
121
  this.deltaTimeU = uniform( 1.0 / 60.0 );
114
122
  this.isFirstFrameU = uniform( 1.0 ); // 1.0 = true
@@ -471,15 +479,7 @@ export class AutoExposure extends RenderStage {
471
479
  setupEventListeners() {
472
480
 
473
481
  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 ) );
482
+ this.on( 'pipeline:lightingChanged', () => this.resetHistory() );
483
483
 
484
484
  }
485
485
 
@@ -4,7 +4,8 @@ import { RenderTarget, TextureNode, StorageTexture } from 'three/webgpu';
4
4
  import { HalfFloatType, RGBAFormat, LinearFilter, Box2, Vector2 } from 'three';
5
5
  import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
6
6
  import { luminance } from '../TSL/Common.js';
7
- import { ALBEDO_EPS, MAX_STORAGE_TEXTURE_SIZE } from '../EngineDefaults.js';
7
+ import { MAX_STORAGE_TEXTURE_SIZE } from '../Processor/StorageTexturePool.js';
8
+ import { ALBEDO_EPS } from './DenoiserSettings.js';
8
9
 
9
10
  // SVGF bilateral edge-stopping weight. All three φ params are relative
10
11
  // tolerances (unitless fractions) so the filter is scale-invariant across
@@ -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;