rayzee 11.6.0 → 11.7.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 (38) hide show
  1. package/README.md +13 -14
  2. package/dist/{ArchiveImporter-iofnC8zB.js → ArchiveImporter-DYcRXeKE.js} +2 -2
  3. package/dist/{BidirectionalIntegrator-CqAilt2I.js → BidirectionalIntegrator-BvjRpbTP.js} +2 -2
  4. package/dist/{NeuralRetouch-DFI4pOjO.js → NeuralRetouch-ClaMiKYg.js} +1 -1
  5. package/dist/{NeuralSuperRes-ChCiiilS.js → NeuralSuperRes-WNEXun9s.js} +1 -1
  6. package/dist/{PathTracer-BX4sJLx7.js → PathTracer-B9wZPPVL.js} +6 -8
  7. package/dist/{PhysicalSky-Biv39eTA.js → PhysicalSky-DcjItqKi.js} +1 -1
  8. package/dist/{RayzeeRenderer-D8XRKU3A.js → RayzeeRenderer-p-NeE6E2.js} +2 -3
  9. package/dist/addons/archives.es.js +1 -1
  10. package/dist/addons/bidirectional.es.js +1 -1
  11. package/dist/addons/physical-sky.es.js +1 -1
  12. package/dist/rayzee-core.es.js +3 -3
  13. package/dist/rayzee.es.js +865 -1591
  14. package/dist/rayzee.umd.js +87 -134
  15. package/dist/{sceneCachePolicy-W5PLbzuR.js → sceneCachePolicy-B9w3BnaP.js} +1 -1
  16. package/package.json +1 -1
  17. package/src/Passes/OIDNDenoiser.js +9 -11
  18. package/src/PathTracerApp.js +6 -17
  19. package/src/Pipeline/BindingAudit.js +2 -3
  20. package/src/Pipeline/PipelineContext.js +0 -1
  21. package/src/Pipeline/RenderPipeline.js +1 -2
  22. package/src/Pipeline/RenderStage.js +1 -1
  23. package/src/Processor/PackedRayBuffer.js +2 -2
  24. package/src/Processor/StorageTexturePool.js +1 -1
  25. package/src/RayzeeRenderer.js +1 -1
  26. package/src/Stages/DenoiserSettings.js +5 -81
  27. package/src/Stages/MotionVector.js +21 -215
  28. package/src/Stages/NormalDepth.js +5 -5
  29. package/src/Stages/PathTracer.js +1 -1
  30. package/src/Stages/PathTracerStage.js +4 -17
  31. package/src/TSL/FinalWriteKernel.js +2 -2
  32. package/src/TSL/ShadeKernel.js +3 -3
  33. package/src/index.js +1 -1
  34. package/src/managers/DenoisingManager.js +78 -187
  35. package/src/Stages/ASVGF.js +0 -932
  36. package/src/Stages/BilateralFilter.js +0 -486
  37. package/src/Stages/EdgeFilter.js +0 -545
  38. package/src/Stages/Variance.js +0 -443
@@ -1594,7 +1594,7 @@ var vt = class {
1594
1594
  samples: this.samples.slice()
1595
1595
  };
1596
1596
  }
1597
- }, yt = "11.6.0", $ = 1e4, bt = 15e5;
1597
+ }, yt = "11.7.0", $ = 1e4, bt = 15e5;
1598
1598
  function xt(e, t, n = $) {
1599
1599
  return e >= n && t / bt < e / 3;
1600
1600
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rayzee",
3
- "version": "11.6.0",
3
+ "version": "11.7.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",
@@ -55,8 +55,8 @@ const MODEL_CONFIG = {
55
55
  DEFAULT_OPTIONS: {
56
56
  enableOIDN: true,
57
57
  oidnQuality: 'fast',
58
- // A cap on the frame, not a tile size: a frame that fits is one tile, with no overlap.
59
- // It bounds the network's activation memory (~430 MB at 1024²).
58
+ // A cap on the frame, not a tile size: a frame no larger in area than this square is one
59
+ // tile, with no overlap. The area bounds the network's activation memory.
60
60
  tileSize: 1024
61
61
  }
62
62
  };
@@ -382,16 +382,14 @@ export class OIDNDenoiser extends EventDispatcher {
382
382
  */
383
383
  _resolveTileSize() {
384
384
 
385
- const longest = Math.max( this._renderWidth, this._renderHeight );
386
- if ( ! longest ) return this.maxTileSize;
385
+ if ( ! this._renderWidth || ! this._renderHeight ) return this.maxTileSize;
387
386
 
388
- // The cap is on the frame, so the border never splits a frame that fits one tile.
389
- if ( longest <= this.maxTileSize ) {
390
-
391
- const input = oidnInputSize( this._renderWidth, this._renderHeight );
392
- return Math.max( input.width, input.height );
393
-
394
- }
387
+ // One tile for any frame no larger in area than the square the cap allows: oidn-web's memory
388
+ // follows the tile's area, not its longest side, so a wide frame needs no split. The cap is on
389
+ // the frame, so the border never splits a frame that fits.
390
+ const input = oidnInputSize( this._renderWidth, this._renderHeight );
391
+ const largest = oidnInputSize( this.maxTileSize, this.maxTileSize );
392
+ if ( input.width * input.height <= largest.width * largest.height ) return Math.max( input.width, input.height );
395
393
 
396
394
  return Math.max( OIDN_TILE_ALIGNMENT, Math.floor( this.maxTileSize / OIDN_TILE_ALIGNMENT ) * OIDN_TILE_ALIGNMENT );
397
395
 
@@ -2,11 +2,7 @@ import { Box3, Vector3 } from 'three';
2
2
  import { RayzeeRenderer, describeAdapter, RENDER_CHECKPOINT_VERSION } from './RayzeeRenderer.js';
3
3
  import { NormalDepth } from './Stages/NormalDepth.js';
4
4
  import { MotionVector } from './Stages/MotionVector.js';
5
- import { ASVGF } from './Stages/ASVGF.js';
6
5
  import { NRD } from './Stages/NRD.js';
7
- import { Variance } from './Stages/Variance.js';
8
- import { BilateralFilter } from './Stages/BilateralFilter.js';
9
- import { EdgeFilter } from './Stages/EdgeFilter.js';
10
6
  import { AutoExposure, AUTO_EXPOSURE_DEFAULTS } from './Stages/AutoExposure.js';
11
7
  import { LocalExposure, LOCAL_EXPOSURE_DEFAULTS } from './Stages/LocalExposure.js';
12
8
  import { PRODUCTION_RENDER_CONFIG, INTERACTIVE_RENDER_CONFIG, modePresetSettings } from './EngineDefaults.js';
@@ -151,17 +147,12 @@ export class PathTracerApp extends RayzeeRenderer {
151
147
  const { renderer, stages } = this;
152
148
  stages.normalDepth = new NormalDepth( renderer, { pathTracer: stages.pathTracer } );
153
149
  stages.motionVector = new MotionVector( renderer, this.camera, { pathTracer: stages.pathTracer } );
154
- stages.asvgf = new ASVGF( renderer, { enabled: false } );
155
150
  stages.nrd = new NRD( renderer, { enabled: false, pathTracer: stages.pathTracer } );
156
- stages.variance = new Variance( renderer, { enabled: false } );
157
- stages.bilateralFilter = new BilateralFilter( renderer, { enabled: false } );
158
- stages.edgeFilter = new EdgeFilter( renderer, { enabled: false } );
159
151
  stages.autoExposure = new AutoExposure( renderer, { enabled: AUTO_EXPOSURE_DEFAULTS.autoExposure } );
160
152
  stages.localExposure = new LocalExposure( renderer, { enabled: LOCAL_EXPOSURE_DEFAULTS.localExposure } );
161
153
 
162
154
  return [
163
- stages.normalDepth, stages.motionVector, stages.nrd, stages.asvgf,
164
- stages.variance, stages.bilateralFilter, stages.edgeFilter, stages.autoExposure, stages.localExposure,
155
+ stages.normalDepth, stages.motionVector, stages.nrd, stages.autoExposure, stages.localExposure,
165
156
  ];
166
157
 
167
158
  }
@@ -318,7 +309,7 @@ export class PathTracerApp extends RayzeeRenderer {
318
309
 
319
310
  _displaySources() {
320
311
 
321
- return [ 'oidn:output', 'edgeFiltering:output', 'bilateralFiltering:output', 'asvgf:output', 'nrd:output' ];
312
+ return [ 'oidn:output', 'nrd:output' ];
322
313
 
323
314
  }
324
315
 
@@ -338,8 +329,10 @@ export class PathTracerApp extends RayzeeRenderer {
338
329
 
339
330
  this.cameraManager.applyProjection( value );
340
331
  // MotionVector unprojects through projectionMatrixInverse, which is meaningless once every pixel is its
341
- // own direction: fall back to the spatial-only denoiser rather than leaving no strategy.
342
- if ( value === 'equirectangular' && this.denoisingManager?.requiresMotionVectors ) this.denoisingManager.setDenoiserStrategy( 'edgeaware' );
332
+ // own direction: hand the view to OIDN, which needs none, rather than leaving no denoiser.
333
+ if ( value === 'equirectangular' && this.denoisingManager?.requiresMotionVectors ) this.denoisingManager.setDenoiserStrategy( 'oidn' );
334
+ // OIDN's motion history is off in a panorama and back on outside one.
335
+ else this.denoisingManager?._syncGBufferStages?.();
343
336
 
344
337
  },
345
338
  };
@@ -1106,11 +1099,7 @@ export class PathTracerApp extends RayzeeRenderer {
1106
1099
  pathTracer: this.stages.pathTracer,
1107
1100
  normalDepth: this.stages.normalDepth,
1108
1101
  motionVector: this.stages.motionVector,
1109
- asvgf: this.stages.asvgf,
1110
1102
  nrd: this.stages.nrd,
1111
- variance: this.stages.variance,
1112
- bilateralFilter: this.stages.bilateralFilter,
1113
- edgeFilter: this.stages.edgeFilter,
1114
1103
  autoExposure: this.stages.autoExposure,
1115
1104
  compositor: this.stages.compositor,
1116
1105
  },
@@ -3,13 +3,12 @@
3
3
  *
4
4
  * Two TextureNodes still holding the default EmptyTexture when a stage's kernel is first
5
5
  * compiled can share one GPU binding, which then resolves to whichever is assigned last.
6
- * Nothing throws — the aliased node reads a real texture, just not its own. BilateralFilter
7
- * shipped this way, reading ASVGF's history counter as its variance.
6
+ * Nothing throws — the aliased node reads a real texture, just not its own.
8
7
  *
9
8
  * Rule enforced: every TextureNode a kernel reads must hold its real texture before that
10
9
  * kernel is first dispatched. StorageTexture-typed nodes are exempt — `textureLoad` codegen
11
10
  * only emits the required `level` parameter while the node still holds EmptyTexture, so those
12
- * are deliberately bound after compile (see ASVGF.render).
11
+ * are deliberately bound after compile.
13
12
  *
14
13
  * Off by default; the bench harness turns it on.
15
14
  */
@@ -43,7 +43,6 @@ export class PipelineContext {
43
43
 
44
44
  // Render modes
45
45
  renderMode: 0, // 0 = interactive, 1 = production (full-frame in both)
46
- interactionMode: false,
47
46
  isComplete: false,
48
47
 
49
48
  // Tile rendering
@@ -23,8 +23,7 @@ import { ISSUE_CODES } from '../EngineIssues.js';
23
23
  *
24
24
  * // Add stages in execution order
25
25
  * pipeline.addStage(new PathTracer(...));
26
- * pipeline.addStage(new ASVGF(...));
27
- * pipeline.addStage(new EdgeFilter(...));
26
+ * pipeline.addStage(new NRD(...));
28
27
  *
29
28
  * // Render all stages
30
29
  * pipeline.render(writeBuffer);
@@ -12,7 +12,7 @@ export const StageExecutionMode = {
12
12
 
13
13
  /**
14
14
  * PER_CYCLE - Execute only when tile rendering cycle completes
15
- * Use for: Post-processing, denoisers, filters (ASVGF, EdgeAwareFiltering, OIDN)
15
+ * Use for: Post-processing, denoisers, filters (NRD, OIDN)
16
16
  *
17
17
  * Complete cycle means:
18
18
  * - Progressive mode (renderMode=0): Every frame
@@ -424,7 +424,7 @@ export const writeMediumStack = ( buf, id, stackDepth, transTraversals, ior1, io
424
424
  ), ior1, ior2, ior3 ) );
425
425
 
426
426
  // Region 7: Beer-Lambert sigmaA (.xyz) of the active medium + DDFA feature-throughput (.w).
427
- // .xyz absorption is gated on stackDepth>0; .w carries the OIDN/ASVGF see-through aux tint (see below).
427
+ // .xyz absorption is gated on stackDepth>0; .w carries the OIDN/NRD see-through aux tint (see below).
428
428
  // Both writers RMW-preserve the other half so sigmaA (live in glass) and featTP never clobber each other.
429
429
  export const readMediumSigmaA = ( buf, id ) => buf.element( soa( id, RAY.MEDIUM_SIGMA_A ) ).xyz;
430
430
 
@@ -436,7 +436,7 @@ export const writeMediumSigmaA = ( buf, id, sigmaA ) => {
436
436
  };
437
437
 
438
438
  // DDFA (Deferred Denoising-Feature Aux) feature-throughput: a clean per-ray tint carried through smooth
439
- // glass/mirror, committed into the OIDN/ASVGF albedo guide at the first diffuse-enough surface. Rides the
439
+ // glass/mirror, committed into the OIDN/NRD albedo guide at the first diffuse-enough surface. Rides the
440
440
  // otherwise-dead MEDIUM_SIGMA_A.w, packed 10/10/10 into 30 bits (top 2 bits zero ⇒ the float bit-pattern is
441
441
  // always finite — never NaN/Inf). LDR [0,1] per channel; final albedo re-quantizes to unorm16 anyway.
442
442
  const pack30 = ( tp ) => {
@@ -7,7 +7,7 @@
7
7
  * - 1 MRT RenderTarget (3 attachments) used as the readable copy
8
8
  * - After each compute dispatch, copyTextureToTexture() transfers data
9
9
  * from StorageTextures → RenderTarget textures
10
- * - Downstream stages (ASVGF, display, OIDN) read from the RenderTarget
10
+ * - Downstream stages (NRD, display, OIDN) read from the RenderTarget
11
11
  * - Previous-frame reads in the path tracer sample from RenderTarget textures
12
12
  * via texture() (not storageTexture().toReadOnly())
13
13
  */
@@ -2730,7 +2730,7 @@ export class RayzeeRenderer extends EventDispatcher {
2730
2730
  * accumulation
2731
2731
  * @returns {Promise<{data: Float32Array|Uint8ClampedArray, width: number, height: number, colorSpace: string,
2732
2732
  * source: string, toneMappedOn?: 'gpu'|'cpu'}>} `source` is what was read: `'accumulation'`, or the
2733
- * denoiser that published it (`'oidn'`, `'asvgf'`, `'nrd'`, `'edgeFiltering'`, `'bilateralFiltering'`).
2733
+ * denoiser that published it (`'oidn'`, `'nrd'`).
2734
2734
  * `toneMappedOn` is set for `'srgb'` only.
2735
2735
  */
2736
2736
  async renderToBuffer( { colorSpace = 'srgb', preserveAlpha = false, source = 'accumulation' } = {} ) {
@@ -4,57 +4,12 @@
4
4
  export const GBUFFER_MISS_DEPTH = 65504.0;
5
5
  export const GBUFFER_MISS_THRESHOLD = 6e4;
6
6
 
7
- // Albedo demodulation safety floor. ASVGF and BilateralFilter MUST use the
8
- // same value — demod (`color / safeAlbedo`) and remod (`lighting * safeAlbedo`)
9
- // only round-trip exactly when both sides agree.
7
+ // Albedo demodulation safety floor. Demod (`color / safeAlbedo`) and remod (`lighting * safeAlbedo`)
8
+ // only round-trip exactly when both sides use the same value.
10
9
  export const ALBEDO_EPS = 0.01;
11
10
 
12
- export const ASVGF_QUALITY_PRESETS = {
13
- // phiColor / phiDepth are RELATIVE tolerances (fractions). Bigger = more
14
- // permissive. The adaptive temporal gradient (gradientStrength > 0) is always
15
- // on: it measures real change in units of noise σ (gradientSigmaScale), so a
16
- // static scene reads ~0 (no convergence penalty) and only moving lights / anim
17
- // / disocclusion drop history. See ASVGF._buildGradientCompute.
18
- low: {
19
- temporalAlpha: 0.1,
20
- gradientStrength: 0.8,
21
- gradientSigmaScale: 2.5,
22
- gradientNoiseFloor: 0.05,
23
- atrousIterations: 3,
24
- phiColor: 1.0,
25
- phiNormal: 64.0,
26
- phiDepth: 0.1,
27
- phiLuminance: 6.0,
28
- maxAccumFrames: 16,
29
- varianceBoost: 0.5
30
- },
31
- medium: {
32
- temporalAlpha: 0.03,
33
- gradientStrength: 1.0,
34
- gradientSigmaScale: 2.5,
35
- gradientNoiseFloor: 0.05,
36
- atrousIterations: 4,
37
- phiColor: 0.5,
38
- phiNormal: 128.0,
39
- phiDepth: 0.05,
40
- phiLuminance: 4.0,
41
- maxAccumFrames: 64,
42
- varianceBoost: 1.0
43
- },
44
- high: {
45
- temporalAlpha: 0.0,
46
- gradientStrength: 1.0,
47
- gradientSigmaScale: 2.5,
48
- gradientNoiseFloor: 0.05,
49
- atrousIterations: 6,
50
- phiColor: 0.3,
51
- phiNormal: 256.0,
52
- phiDepth: 0.02,
53
- phiLuminance: 2.0,
54
- maxAccumFrames: 128,
55
- varianceBoost: 1.5
56
- }
57
- };
11
+ // The live view's denoisers, for setDenoiserStrategy.
12
+ export const DENOISER_STRATEGIES = Object.freeze( [ 'none', 'nrd', 'oidn' ] );
58
13
 
59
14
  // normHitDist = hitDist / (A + B·viewZ). A constant, not a uniform: the Shade write and the NRD
60
15
  // decode must agree, and the normalization is a pure round trip.
@@ -122,21 +77,9 @@ export const NRD_QUALITY_PRESETS = {
122
77
  },
123
78
  };
124
79
 
125
- const ASVGF_MEDIUM = ASVGF_QUALITY_PRESETS.medium;
126
-
127
80
  // What the live denoisers, the final OIDN pass and the AI upscaler start with; a host's own state seeds from these.
128
81
  export const DENOISER_DEFAULTS = {
129
- denoiserStrategy: 'none', // the live view's denoiser: 'none' | 'edgeaware' | 'asvgf' | 'nrd' | 'oidn'
130
-
131
- // EdgeAware denoiser (spatial-only SVGF à-trous). filterStrength: final blend
132
- // (0 = raw, 1 = filtered). edgeAtrousIterations: à-trous passes (step 1,2,4,8,16).
133
- // edgePhiLuminance: variance-scaled luminance edge-stop. edgePhiNormal: normal cone
134
- // exponent. edgePhiDepth: RELATIVE depth tolerance (fraction of ray distance).
135
- filterStrength: 1.0,
136
- edgeAtrousIterations: 5,
137
- edgePhiLuminance: 4.0,
138
- edgePhiNormal: 64.0,
139
- edgePhiDepth: 0.1,
82
+ denoiserStrategy: 'none', // the live view's denoiser, one of DENOISER_STRATEGIES
140
83
 
141
84
  enableOIDN: false,
142
85
  oidnQuality: 'fast',
@@ -157,25 +100,6 @@ export const DENOISER_DEFAULTS = {
157
100
  upscalerQuality: 'fast',
158
101
  upscalerHdr: true,
159
102
 
160
- // ASVGF runs its quality preset whenever it is switched on, so its values are that preset's.
161
- enableASVGF: false,
162
- asvgfQualityPreset: 'medium',
163
- asvgfTemporalAlpha: ASVGF_MEDIUM.temporalAlpha,
164
- asvgfAtrousIterations: ASVGF_MEDIUM.atrousIterations,
165
- asvgfPhiColor: ASVGF_MEDIUM.phiColor,
166
- asvgfPhiNormal: ASVGF_MEDIUM.phiNormal,
167
- asvgfPhiDepth: ASVGF_MEDIUM.phiDepth,
168
- asvgfPhiLuminance: ASVGF_MEDIUM.phiLuminance,
169
- asvgfVarianceBoost: ASVGF_MEDIUM.varianceBoost,
170
- asvgfMaxAccumFrames: ASVGF_MEDIUM.maxAccumFrames,
171
- // Must be > 0: the gradient also rejects fireflies before the EMA smears them across
172
- // ~1/alpha frames. At 0 the denoiser measures ~3x worse than no denoiser at 1 spp.
173
- asvgfGradientStrength: ASVGF_MEDIUM.gradientStrength,
174
- asvgfGradientSigmaScale: ASVGF_MEDIUM.gradientSigmaScale,
175
- asvgfGradientNoiseFloor: ASVGF_MEDIUM.gradientNoiseFloor,
176
- asvgfDebugMode: 0,
177
- showAsvgfHeatmap: false,
178
-
179
103
  // NRD (ReBLUR port) real-time denoiser — see NRD_DEFAULTS / NRD_QUALITY_PRESETS.
180
104
  nrdQualityPreset: 'medium',
181
105
  nrdDebugMode: 0,