rayzee 5.11.0 → 6.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 (41) hide show
  1. package/README.md +81 -24
  2. package/dist/assets/AIUpscalerWorker-AXN-lKWN.js +2 -0
  3. package/dist/assets/AIUpscalerWorker-AXN-lKWN.js.map +1 -0
  4. package/dist/rayzee.es.js +1233 -1803
  5. package/dist/rayzee.es.js.map +1 -1
  6. package/dist/rayzee.umd.js +50 -74
  7. package/dist/rayzee.umd.js.map +1 -1
  8. package/package.json +1 -4
  9. package/src/AssetConfig.js +56 -0
  10. package/src/EngineDefaults.js +5 -3
  11. package/src/EngineEvents.js +1 -0
  12. package/src/Passes/AIUpscaler.js +44 -22
  13. package/src/Passes/OIDNDenoiser.js +4 -104
  14. package/src/PathTracerApp.js +54 -65
  15. package/src/Processor/AssetLoader.js +5 -2
  16. package/src/Processor/Workers/AIUpscalerWorker.js +21 -6
  17. package/src/Stages/ASVGF.js +6 -27
  18. package/src/Stages/AdaptiveSampling.js +10 -26
  19. package/src/Stages/PathTracer.js +4 -5
  20. package/src/TSL/BVHTraversal.js +2 -18
  21. package/src/TSL/Clearcoat.js +1 -2
  22. package/src/TSL/Common.js +0 -13
  23. package/src/TSL/EmissiveSampling.js +0 -16
  24. package/src/TSL/Environment.js +0 -7
  25. package/src/TSL/LightsDirect.js +3 -379
  26. package/src/TSL/LightsSampling.js +0 -171
  27. package/src/TSL/MaterialEvaluation.js +3 -103
  28. package/src/TSL/MaterialProperties.js +1 -56
  29. package/src/TSL/MaterialSampling.js +2 -284
  30. package/src/TSL/MaterialTransmission.js +0 -93
  31. package/src/TSL/Random.js +0 -23
  32. package/src/TSL/Struct.js +0 -21
  33. package/src/TSL/TextureSampling.js +0 -69
  34. package/src/index.js +5 -2
  35. package/src/managers/DenoisingManager.js +13 -5
  36. package/src/managers/VideoRenderManager.js +4 -4
  37. package/dist/assets/AIUpscalerWorker-D58dcMrY.js +0 -2
  38. package/dist/assets/AIUpscalerWorker-D58dcMrY.js.map +0 -1
  39. package/src/Processor/createRenderTargetHelper.js +0 -521
  40. package/src/TSL/RayIntersection.js +0 -162
  41. package/src/managers/helpers/StatsHelper.js +0 -45
@@ -14,8 +14,13 @@
14
14
  * { type: 'error', message, id? }
15
15
  */
16
16
 
17
- // Loaded lazily via CDN to avoid bundling the 69 MB onnxruntime-web package
18
- const ORT_CDN_URL = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.24.3/dist/ort.webgpu.bundle.min.mjs';
17
+ // Asset config supplied via 'load' message from the main thread.
18
+ // Defaults match the upstream Rayzee deployment; override via configureAssets().
19
+ let _assetConfig = {
20
+ ortRuntimeUrl: 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.24.3/dist/ort.webgpu.bundle.min.mjs',
21
+ ortWasmPaths: 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.24.3/dist/',
22
+ cacheNamespace: 'rayzee',
23
+ };
19
24
 
20
25
  let ort = null;
21
26
 
@@ -23,17 +28,23 @@ async function getOrt() {
23
28
 
24
29
  if ( ort ) return ort;
25
30
 
26
- ort = await import( /* @vite-ignore */ ORT_CDN_URL );
31
+ ort = await import( /* @vite-ignore */ _assetConfig.ortRuntimeUrl );
27
32
 
28
33
  // WASM paths for CDN delivery — WebGPU EP still uses WASM for lightweight shape ops
29
- ort.env.wasm.wasmPaths = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.24.3/dist/';
34
+ ort.env.wasm.wasmPaths = _assetConfig.ortWasmPaths;
30
35
  ort.env.logLevel = 'error';
31
36
 
32
37
  return ort;
33
38
 
34
39
  }
35
40
 
36
- const IDB_NAME = 'ai-upscaler-models';
41
+ // IndexedDB names are namespaced so multiple consumers on the same origin don't collide.
42
+ function getIdbName() {
43
+
44
+ return `${_assetConfig.cacheNamespace}:ai-upscaler-models`;
45
+
46
+ }
47
+
37
48
  const IDB_STORE = 'models';
38
49
 
39
50
  let session = null;
@@ -45,7 +56,7 @@ function openDB() {
45
56
 
46
57
  return new Promise( ( resolve, reject ) => {
47
58
 
48
- const req = indexedDB.open( IDB_NAME, 1 );
59
+ const req = indexedDB.open( getIdbName(), 1 );
49
60
  req.onupgradeneeded = () => req.result.createObjectStore( IDB_STORE );
50
61
  req.onsuccess = () => resolve( req.result );
51
62
  req.onerror = () => reject( req.error );
@@ -204,6 +215,10 @@ self.onmessage = async ( e ) => {
204
215
 
205
216
  if ( type === 'load' ) {
206
217
 
218
+ // Apply asset overrides from main thread before any network or cache access
219
+ if ( e.data.ortRuntimeUrl ) _assetConfig.ortRuntimeUrl = e.data.ortRuntimeUrl;
220
+ if ( e.data.ortWasmPaths ) _assetConfig.ortWasmPaths = e.data.ortWasmPaths;
221
+ if ( e.data.cacheNamespace ) _assetConfig.cacheNamespace = e.data.cacheNamespace;
207
222
  await loadModel( e.data.url, e.data.sessionOptions );
208
223
 
209
224
  } else if ( type === 'infer' ) {
@@ -4,7 +4,6 @@ import { Fn, vec3, vec4, float, int, uint, ivec2, uvec2, uniform,
4
4
  import { RenderTarget, TextureNode, StorageTexture } from 'three/webgpu';
5
5
  import { HalfFloatType, FloatType, RGBAFormat, NearestFilter, LinearFilter } from 'three';
6
6
  import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
7
- import { createRenderTargetHelper } from '../Processor/createRenderTargetHelper.js';
8
7
  import { luminance } from '../TSL/Common.js';
9
8
 
10
9
  /**
@@ -25,7 +24,6 @@ export class ASVGF extends RenderStage {
25
24
  } );
26
25
 
27
26
  this.renderer = renderer;
28
- this.debugContainer = options.debugContainer || null;
29
27
 
30
28
  this.temporalAlpha = uniform( options.temporalAlpha ?? 0.1 );
31
29
  this.phiColor = uniform( options.phiColor ?? 10.0 );
@@ -101,17 +99,6 @@ export class ASVGF extends RenderStage {
101
99
 
102
100
  this._buildHeatmapCompute();
103
101
 
104
- this.heatmapHelper = createRenderTargetHelper( this.renderer, this.heatmapTarget, {
105
- width: 400,
106
- height: 400,
107
- position: 'bottom-right',
108
- theme: 'dark',
109
- title: 'ASVGF Debug',
110
- autoUpdate: false
111
- } );
112
- this.heatmapHelper.hide();
113
- ( this.debugContainer || document.body ).appendChild( this.heatmapHelper );
114
-
115
102
  this.frameCount = 0;
116
103
 
117
104
  }
@@ -568,7 +555,6 @@ export class ASVGF extends RenderStage {
568
555
 
569
556
  this.renderer.compute( this._heatmapComputeNode );
570
557
  this.renderer.copyTextureToTexture( this._heatmapStorageTex, this.heatmapTarget.texture );
571
- this.heatmapHelper.update();
572
558
 
573
559
  }
574
560
 
@@ -576,18 +562,14 @@ export class ASVGF extends RenderStage {
576
562
 
577
563
  }
578
564
 
579
- toggleHeatmap( enabled ) {
565
+ /**
566
+ * Enable or disable the heatmap compute pass. When enabled, the heatmap
567
+ * is rendered each frame to {@link this.heatmapTarget} (a public RenderTarget)
568
+ * for the host to display however it wants.
569
+ */
570
+ setHeatmapEnabled( enabled ) {
580
571
 
581
572
  this.showHeatmap = enabled;
582
- if ( enabled ) {
583
-
584
- this.heatmapHelper.show();
585
-
586
- } else {
587
-
588
- this.heatmapHelper.hide();
589
-
590
- }
591
573
 
592
574
  }
593
575
 
@@ -663,9 +645,6 @@ export class ASVGF extends RenderStage {
663
645
  this._heatmapMotionTexNode?.dispose();
664
646
  this._heatmapGradientTexNode?.dispose();
665
647
 
666
- // also removes the DOM node
667
- this.heatmapHelper?.dispose();
668
-
669
648
  }
670
649
 
671
650
  }
@@ -4,7 +4,6 @@ import { RenderTarget, TextureNode, StorageTexture } from 'three/webgpu';
4
4
  import { NearestFilter, LinearFilter, RGBAFormat, HalfFloatType, FloatType } from 'three';
5
5
  import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
6
6
  import { ENGINE_DEFAULTS as DEFAULT_STATE } from '../EngineDefaults.js';
7
- import { createRenderTargetHelper } from '../Processor/createRenderTargetHelper.js';
8
7
 
9
8
  // ── wgslFn helpers ──────────────────────────────────────────
10
9
 
@@ -150,7 +149,6 @@ export class AdaptiveSampling extends RenderStage {
150
149
  } );
151
150
 
152
151
  this.renderer = renderer;
153
- this.debugContainer = options.debugContainer || null;
154
152
  this.frameNumber = 0;
155
153
  this.delayByFrames = options.delayByFrames ?? 2;
156
154
  this.showAdaptiveSamplingHelper = false;
@@ -191,7 +189,8 @@ export class AdaptiveSampling extends RenderStage {
191
189
  this._heatmapStorageTex.minFilter = NearestFilter;
192
190
  this._heatmapStorageTex.magFilter = NearestFilter;
193
191
 
194
- // Heatmap render target — FloatType for clean CPU readback via createRenderTargetHelper
192
+ // Heatmap render target — FloatType, exposed as a public field for hosts to
193
+ // display via their own readback helper.
195
194
  this.heatmapTarget = new RenderTarget( w, h, {
196
195
  format: RGBAFormat,
197
196
  type: FloatType,
@@ -214,18 +213,6 @@ export class AdaptiveSampling extends RenderStage {
214
213
  this._buildCompute();
215
214
  this._buildHeatmapCompute();
216
215
 
217
- // Floating overlay for heatmap visualization
218
- this.helper = createRenderTargetHelper( this.renderer, this.heatmapTarget, {
219
- width: 400,
220
- height: 400,
221
- position: 'bottom-right',
222
- theme: 'dark',
223
- title: 'Adaptive Sampling',
224
- autoUpdate: false
225
- } );
226
- this.helper.hide();
227
- ( this.debugContainer || document.body ).appendChild( this.helper );
228
-
229
216
  }
230
217
 
231
218
  setupEventListeners() {
@@ -303,8 +290,8 @@ export class AdaptiveSampling extends RenderStage {
303
290
  * Reads the sampling guidance StorageTexture via textureLoad and maps
304
291
  * normalizedSamples to a smooth blue→cyan→green→yellow→red gradient.
305
292
  * Converged pixels are desaturated, brightness is modulated by variance.
306
- * Writes to _heatmapStorageTex, then copied to heatmapTarget for
307
- * createRenderTargetHelper display.
293
+ * Writes to _heatmapStorageTex, then copied to the public heatmapTarget
294
+ * RenderTarget so the host can display it.
308
295
  */
309
296
  _buildHeatmapCompute() {
310
297
 
@@ -343,13 +330,13 @@ export class AdaptiveSampling extends RenderStage {
343
330
  }
344
331
 
345
332
  /**
346
- * Toggle heatmap overlay visibility.
347
- * @param {boolean} val show/hide
333
+ * Enable or disable the heatmap compute pass. When enabled, the heatmap is
334
+ * rendered each frame to {@link this.heatmapTarget} (a public RenderTarget)
335
+ * for the host to display however it wants.
348
336
  */
349
- toggleHelper( val ) {
337
+ setHeatmapEnabled( enabled ) {
350
338
 
351
- this.showAdaptiveSamplingHelper = val;
352
- val ? this.helper.show() : this.helper.hide();
339
+ this.showAdaptiveSamplingHelper = enabled;
353
340
 
354
341
  }
355
342
 
@@ -387,12 +374,11 @@ export class AdaptiveSampling extends RenderStage {
387
374
  // (StorageTexture extends Texture, works as regular texture for sampling)
388
375
  context.setTexture( 'adaptiveSampling:output', this._outputStorageTex );
389
376
 
390
- // Render heatmap + update helper overlay if visualization enabled
377
+ // Render heatmap into public heatmapTarget when enabled
391
378
  if ( this.showAdaptiveSamplingHelper ) {
392
379
 
393
380
  this.renderer.compute( this._heatmapComputeNode );
394
381
  this.renderer.copyTextureToTexture( this._heatmapStorageTex, this.heatmapTarget.texture );
395
- this.helper.update();
396
382
 
397
383
  }
398
384
 
@@ -484,7 +470,6 @@ export class AdaptiveSampling extends RenderStage {
484
470
  this._outputStorageTex?.dispose();
485
471
  this.heatmapTarget?.dispose();
486
472
  this._varianceTexNode?.dispose();
487
- this.helper?.dispose();
488
473
 
489
474
  this._computeNode = null;
490
475
  this._heatmapComputeNode = null;
@@ -492,7 +477,6 @@ export class AdaptiveSampling extends RenderStage {
492
477
  this._outputStorageTex = null;
493
478
  this.heatmapTarget = null;
494
479
  this._varianceTexNode = null;
495
- this.helper = null;
496
480
 
497
481
  }
498
482
 
@@ -25,10 +25,7 @@ import { LightSerializer } from '../Processor/LightSerializer';
25
25
 
26
26
  // Constants
27
27
  import { ENGINE_DEFAULTS as DEFAULT_STATE } from '../EngineDefaults.js';
28
-
29
- // STBN atlases - original source: https://github.com/NVIDIA-RTX/STBN/blob/main/Assets/STBN.zip
30
- const stbnScalarAtlas = 'https://assets.rayzee.atulmourya.com/noise/stbn_scalar_atlas.png';
31
- const stbnVec2Atlas = 'https://assets.rayzee.atulmourya.com/noise/stbn_vec2_atlas.png';
28
+ import { getAssetConfig } from '../AssetConfig.js';
32
29
 
33
30
  /**
34
31
  * Data layout constants
@@ -50,7 +47,7 @@ const BVH_VEC4_PER_NODE = 4;
50
47
  * Events emitted:
51
48
  * - pathtracer:frameComplete - When a frame finishes rendering
52
49
  * - camera:moved - When camera position/orientation changes
53
- * - tile:changed - When current tile changes (for OverlayManager TileHelper)
50
+ * - tile:changed - When current tile changes (for OverlayManager TileHelper). @internal — payload carries internal tile coordinates and may change without notice.
54
51
  * - asvgf:reset - Request ASVGF to reset temporal data
55
52
  * - asvgf:updateParameters - Update ASVGF parameters
56
53
  * - asvgf:setTemporal - Enable/disable ASVGF temporal accumulation
@@ -397,6 +394,8 @@ export class PathTracer extends RenderStage {
397
394
 
398
395
  };
399
396
 
397
+ const { stbnScalarAtlas, stbnVec2Atlas } = getAssetConfig();
398
+
400
399
  loader.load( stbnScalarAtlas, ( tex ) => {
401
400
 
402
401
  this.stbnScalarTexture = configure( tex );
@@ -117,27 +117,11 @@ const fastRayAABBDst = wgslFn( `
117
117
  }
118
118
  ` );
119
119
 
120
- // ================================================================================
121
- // VISIBILITY FUNCTIONS
122
- // ================================================================================
123
-
124
- // Side culling — 1 buffer read (slot 10 only)
125
- // Per-mesh visibility handled at BLAS-pointer level; material visibility always 1.
126
- export const passesSideCulling = Fn( ( [ materialIndex, rayDirection, normal, materialBuffer ] ) => {
127
-
128
- const sideData = getDatafromStorageBuffer( materialBuffer, materialIndex, int( MATERIAL_SLOT.OPACITY_ALPHA ), int( MATERIAL_SLOTS ) );
129
- const side = int( sideData.g );
130
- const rayDotNormal = rayDirection.dot( normal );
131
- const doubleSide = side.equal( int( 2 ) );
132
- const frontSide = side.equal( int( 0 ) ).and( rayDotNormal.lessThan( - 0.0001 ) );
133
- const backSide = side.equal( int( 1 ) ).and( rayDotNormal.greaterThan( 0.0001 ) );
134
- return doubleSide.or( frontSide ).or( backSide );
135
-
136
- } );
137
-
138
120
  // ================================================================================
139
121
  // MAIN BVH TRAVERSAL
140
122
  // ================================================================================
123
+ // Side culling is performed inline inside traverseBVH/traverseBVHShadow using
124
+ // the per-triangle side flag stored in normalCData.w (slot 5, .w channel).
141
125
 
142
126
  export const traverseBVH = Fn( ( [
143
127
  ray,
@@ -1,6 +1,5 @@
1
1
  // Clearcoat BRDF - Ported from clearcoat.fs
2
- // Note: evaluateLayeredBRDF and calculateLayerAttenuation functions
3
- // are in MaterialEvaluation.js
2
+ // Note: evaluateLayeredBRDF lives in MaterialEvaluation.js
4
3
 
5
4
  import {
6
5
  Fn,
package/src/TSL/Common.js CHANGED
@@ -126,19 +126,6 @@ export const applyDithering = wgslFn( `
126
126
  }
127
127
  ` );
128
128
 
129
- // Firefly clamping — exact port of GLSL
130
- export const reduceFireflies = wgslFn( `
131
- fn reduceFireflies( color: vec3f, maxValue: f32 ) -> vec3f {
132
-
133
- let lum = dot( color, vec3f( 0.2126, 0.7152, 0.0722 ) );
134
- if ( lum > maxValue ) {
135
- return color * ( maxValue / lum );
136
- }
137
- return color;
138
-
139
- }
140
- ` );
141
-
142
129
  // Construct tangent-bitangent-normal matrix — exact port of GLSL
143
130
  export const constructTBN = wgslFn( `
144
131
  fn constructTBN( N: vec3f ) -> mat3x3f {
@@ -260,22 +260,6 @@ export const isEmissive = Fn( ( [ material ] ) => {
260
260
 
261
261
  } );
262
262
 
263
- // Calculate emissive power of a triangle
264
- export const calculateEmissivePower = Fn( ( [ material, area ] ) => {
265
-
266
- const result = float( 0.0 ).toVar();
267
-
268
- If( isEmissive( material ), () => {
269
-
270
- const avgEmissive = material.emissive.x.add( material.emissive.y ).add( material.emissive.z ).div( 3.0 );
271
- result.assign( avgEmissive.mul( material.emissiveIntensity ).mul( area ) );
272
-
273
- } );
274
-
275
- return result;
276
-
277
- } );
278
-
279
263
  // ================================================================================
280
264
  // TRIANGLE DATA ACCESS
281
265
  // ================================================================================
@@ -28,13 +28,6 @@ export const equirectUvToDirection = /*@__PURE__*/ wgslFn( `
28
28
  }
29
29
  ` );
30
30
 
31
- // Sample environment map color in a given direction
32
- export const sampleEquirectColor = Fn( ( [ environment, direction, environmentMatrix ] ) => {
33
-
34
- return texture( environment, equirectDirectionToUv( { direction, environmentMatrix } ), 0 ).rgb;
35
-
36
- } );
37
-
38
31
  // Calculate PDF for uniform sphere sampling with Jacobian
39
32
  export const equirectDirectionPdf = /*@__PURE__*/ wgslFn( `
40
33
  fn equirectDirectionPdf( direction: vec3f, environmentMatrix: mat4x4f ) -> f32 {