rayzee 6.5.0 → 7.1.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 (51) hide show
  1. package/README.md +24 -5
  2. package/dist/rayzee.es.js +7624 -7063
  3. package/dist/rayzee.es.js.map +1 -1
  4. package/dist/rayzee.umd.js +157 -236
  5. package/dist/rayzee.umd.js.map +1 -1
  6. package/package.json +1 -1
  7. package/src/EngineDefaults.js +26 -9
  8. package/src/PathTracerApp.js +118 -26
  9. package/src/Pipeline/PipelineContext.js +1 -2
  10. package/src/Pipeline/RenderPipeline.js +1 -1
  11. package/src/Pipeline/RenderStage.js +1 -1
  12. package/src/Processor/CameraOptimizer.js +0 -5
  13. package/src/Processor/GeometryExtractor.js +6 -0
  14. package/src/Processor/KernelManager.js +277 -0
  15. package/src/Processor/PackedRayBuffer.js +291 -0
  16. package/src/Processor/QueueManager.js +173 -0
  17. package/src/Processor/SceneProcessor.js +1 -0
  18. package/src/Processor/ShaderBuilder.js +11 -317
  19. package/src/Processor/StorageTexturePool.js +29 -15
  20. package/src/Processor/VRAMTracker.js +169 -0
  21. package/src/Processor/utils.js +11 -110
  22. package/src/RenderSettings.js +0 -3
  23. package/src/Stages/ASVGF.js +151 -78
  24. package/src/Stages/BilateralFilter.js +34 -10
  25. package/src/Stages/EdgeFilter.js +2 -3
  26. package/src/Stages/MotionVector.js +16 -9
  27. package/src/Stages/NormalDepth.js +17 -5
  28. package/src/Stages/PathTracer.js +671 -1456
  29. package/src/Stages/PathTracerStage.js +1451 -0
  30. package/src/Stages/SSRC.js +32 -15
  31. package/src/Stages/Variance.js +35 -12
  32. package/src/TSL/CompactKernel.js +110 -0
  33. package/src/TSL/DebugKernel.js +98 -0
  34. package/src/TSL/Environment.js +13 -11
  35. package/src/TSL/ExtendKernel.js +75 -0
  36. package/src/TSL/FinalWriteKernel.js +121 -0
  37. package/src/TSL/GenerateKernel.js +111 -0
  38. package/src/TSL/LightsSampling.js +2 -2
  39. package/src/TSL/PathTracerCore.js +43 -1039
  40. package/src/TSL/ShadeKernel.js +876 -0
  41. package/src/TSL/patches.js +81 -4
  42. package/src/index.js +3 -0
  43. package/src/managers/CameraManager.js +1 -1
  44. package/src/managers/DenoisingManager.js +40 -75
  45. package/src/managers/EnvironmentManager.js +30 -39
  46. package/src/managers/OverlayManager.js +7 -22
  47. package/src/managers/UniformManager.js +0 -3
  48. package/src/managers/helpers/TileHelper.js +2 -2
  49. package/src/Stages/AdaptiveSampling.js +0 -483
  50. package/src/TSL/PathTracer.js +0 -384
  51. package/src/managers/TileManager.js +0 -298
@@ -0,0 +1,169 @@
1
+ /**
2
+ * VRAMTracker.js — current/peak GPU memory accounting.
3
+ *
4
+ * Measures ACTUAL live bytes (attribute.array.byteLength, texture dims × format/type)
5
+ * rather than re-deriving allocation formulas, so it never drifts when strides,
6
+ * capacity rounding, or layouts change. Providers are thunks that read current state,
7
+ * so they survive reallocation (resize, scene/material/env reload). A per-pass WeakSet
8
+ * dedupes by resource identity, so overlapping registrations never double-count.
9
+ */
10
+
11
+ import {
12
+ RGBAFormat, RGBFormat, RGFormat, RedFormat,
13
+ FloatType, HalfFloatType, UnsignedByteType, ByteType,
14
+ UnsignedShortType, ShortType, UnsignedIntType, IntType,
15
+ } from 'three';
16
+
17
+ const CHANNELS = { [ RGBAFormat ]: 4, [ RGBFormat ]: 3, [ RGFormat ]: 2, [ RedFormat ]: 1 };
18
+ const TYPE_BYTES = {
19
+ [ FloatType ]: 4, [ HalfFloatType ]: 2,
20
+ [ UnsignedByteType ]: 1, [ ByteType ]: 1,
21
+ [ UnsignedShortType ]: 2, [ ShortType ]: 2,
22
+ [ UnsignedIntType ]: 4, [ IntType ]: 4,
23
+ };
24
+
25
+ function texelBytes( tex ) {
26
+
27
+ return ( CHANNELS[ tex.format ] ?? 4 ) * ( TYPE_BYTES[ tex.type ] ?? 4 );
28
+
29
+ }
30
+
31
+ /** Exact byte size of a storage/buffer attribute's backing typed array. */
32
+ export function bufferBytes( attr ) {
33
+
34
+ return attr?.array?.byteLength || 0;
35
+
36
+ }
37
+
38
+ /** Estimated GPU byte size of a Texture/StorageTexture/DataArrayTexture/RenderTarget. */
39
+ export function textureBytes( tex ) {
40
+
41
+ if ( ! tex ) return 0;
42
+
43
+ if ( tex.isRenderTarget ) {
44
+
45
+ const list = tex.textures?.length ? tex.textures : [ tex.texture ];
46
+ const w = tex.width || 0, h = tex.height || 0, d = tex.depth || 1;
47
+ let sum = 0;
48
+ for ( const t of list ) if ( t ) sum += w * h * d * texelBytes( t );
49
+ return sum;
50
+
51
+ }
52
+
53
+ const img = tex.image || {};
54
+ const w = img.width ?? tex.width ?? 0;
55
+ const h = img.height ?? tex.height ?? 0;
56
+ const d = img.depth ?? 1;
57
+ return w * h * d * texelBytes( tex );
58
+
59
+ }
60
+
61
+ export class VRAMTracker {
62
+
63
+ constructor() {
64
+
65
+ this._providers = [];
66
+ this.current = 0;
67
+ this.peak = 0;
68
+ this.byCategory = {};
69
+
70
+ }
71
+
72
+ /**
73
+ * @param {string} category - grouping label in the report
74
+ * @param {Function} fn - returns a resource or array of resources: buffer
75
+ * attributes (`.array`), textures/render targets (`.isTexture`/`.isRenderTarget`),
76
+ * or synthetic `{ bytes }` for sizes with no inspectable object. Return falsy to skip.
77
+ */
78
+ register( category, fn ) {
79
+
80
+ this._providers.push( { category, fn } );
81
+
82
+ }
83
+
84
+ measure() {
85
+
86
+ const seen = new WeakSet();
87
+ const byCategory = {};
88
+ let total = 0;
89
+
90
+ for ( const { category, fn } of this._providers ) {
91
+
92
+ let resources;
93
+ try {
94
+
95
+ resources = fn();
96
+
97
+ } catch {
98
+
99
+ resources = null;
100
+
101
+ }
102
+
103
+ if ( ! resources ) continue;
104
+
105
+ let bytes = 0;
106
+ for ( const r of ( Array.isArray( resources ) ? resources : [ resources ] ) ) {
107
+
108
+ bytes += this._resourceBytes( r, seen );
109
+
110
+ }
111
+
112
+ byCategory[ category ] = ( byCategory[ category ] || 0 ) + bytes;
113
+ total += bytes;
114
+
115
+ }
116
+
117
+ this.byCategory = byCategory;
118
+ this.current = total;
119
+ if ( total > this.peak ) this.peak = total;
120
+
121
+ return { current: total, peak: this.peak, byCategory };
122
+
123
+ }
124
+
125
+ _resourceBytes( r, seen ) {
126
+
127
+ if ( ! r ) return 0;
128
+
129
+ // synthetic { bytes } (e.g. attributeArray-backed histograms)
130
+ if ( typeof r.bytes === 'number' && ! r.isTexture && ! r.isRenderTarget ) return r.bytes;
131
+
132
+ // buffer attribute — dedupe by backing array (rw/ro nodes share one buffer)
133
+ if ( r.array && r.array.byteLength != null ) {
134
+
135
+ if ( seen.has( r.array ) ) return 0;
136
+ seen.add( r.array );
137
+ return r.array.byteLength;
138
+
139
+ }
140
+
141
+ // texture / render target — dedupe by object identity
142
+ if ( r.isRenderTarget || r.isTexture ) {
143
+
144
+ if ( seen.has( r ) ) return 0;
145
+ seen.add( r );
146
+ return textureBytes( r );
147
+
148
+ }
149
+
150
+ return 0;
151
+
152
+ }
153
+
154
+ /** Drop the high-water mark to the current value (call when a new render begins). */
155
+ resetPeak() {
156
+
157
+ this.peak = this.current;
158
+
159
+ }
160
+
161
+ getReport() {
162
+
163
+ const mb = ( b ) => ( b / 1048576 ).toFixed( 1 );
164
+ const parts = Object.entries( this.byCategory ).map( ( [ k, v ] ) => `${k}=${mb( v )}` );
165
+ return `VRAM current=${mb( this.current )}MB peak=${mb( this.peak )}MB [${parts.join( ' ' )}]`;
166
+
167
+ }
168
+
169
+ }
@@ -27,21 +27,10 @@ export const updateStats = ( statsUpdate ) => {
27
27
 
28
28
  };
29
29
 
30
- /**
31
- * Convert raw frameCount to user-facing sample count.
32
- * In tiled mode, one "sample pass" spans all tiles.
33
- */
30
+ // Raw frameCount is the user-facing sample count (one full-frame pass per frame).
34
31
  export function getDisplaySamples( pathTracerStage ) {
35
32
 
36
- const frameCount = pathTracerStage.frameCount || 0;
37
- if ( pathTracerStage.renderMode?.value === 1 && frameCount > 0 ) {
38
-
39
- const totalTiles = pathTracerStage.tileManager?.totalTilesCache || 1;
40
- return 1 + Math.floor( ( frameCount - 1 ) / totalTiles );
41
-
42
- }
43
-
44
- return frameCount;
33
+ return pathTracerStage.frameCount || 0;
45
34
 
46
35
  }
47
36
 
@@ -214,9 +203,9 @@ export function generateMaterialSpheres( rows = 5, columns = 5, spacing = 1.2 )
214
203
 
215
204
  // ── Path Tracer Utilities (formerly PathTracerUtils static class) ──
216
205
 
217
- export function updateCompletionThreshold( renderMode, maxFrames, totalTiles ) {
206
+ export function updateCompletionThreshold( renderMode, maxFrames ) {
218
207
 
219
- return renderMode === 1 ? totalTiles * maxFrames : maxFrames;
208
+ return maxFrames;
220
209
 
221
210
  }
222
211
 
@@ -335,33 +324,10 @@ export function areValuesEqual( a, b ) {
335
324
 
336
325
  }
337
326
 
338
- export function calculateAccumulationAlpha( frameValue, renderMode, totalTiles, isInteractionMode = false ) {
339
-
340
- if ( isInteractionMode ) {
341
-
342
- return 1.0;
343
-
344
- }
345
-
346
- if ( renderMode === 0 ) {
347
-
348
- return 1.0 / ( frameValue + 1 );
349
-
350
- } else {
351
-
352
- if ( frameValue === 0 ) {
353
-
354
- return 1.0;
355
-
356
- } else {
357
-
358
- const completedTileCycles = Math.floor( ( frameValue - 1 ) / totalTiles );
359
- const totalSamples = 1 + completedTileCycles;
360
- return 1.0 / ( totalSamples + 1 );
327
+ export function calculateAccumulationAlpha( frameValue, isInteractionMode = false ) {
361
328
 
362
- }
363
-
364
- }
329
+ // Full-frame progressive accumulation: each frame is one complete pass.
330
+ return isInteractionMode ? 1.0 : 1.0 / ( frameValue + 1 );
365
331
 
366
332
  }
367
333
 
@@ -416,12 +382,6 @@ export function optimizeShaderDefines( defines, state ) {
416
382
 
417
383
  const optimized = { ...defines };
418
384
 
419
- if ( ! state.useAdaptiveSampling ) {
420
-
421
- delete optimized.ENABLE_ADAPTIVE_SAMPLING;
422
-
423
- }
424
-
425
385
  if ( ! state.enableAccumulation ) {
426
386
 
427
387
  delete optimized.ENABLE_ACCUMULATION;
@@ -438,49 +398,6 @@ export function optimizeShaderDefines( defines, state ) {
438
398
 
439
399
  }
440
400
 
441
- export function calculateSpiralOrder( tiles, center = null ) {
442
-
443
- const totalTiles = tiles * tiles;
444
- const centerPoint = center || new Vector2( ( tiles - 1 ) / 2, ( tiles - 1 ) / 2 );
445
- const tilePositions = [];
446
-
447
- for ( let i = 0; i < totalTiles; i ++ ) {
448
-
449
- const x = i % tiles;
450
- const y = Math.floor( i / tiles );
451
- const distance = Math.sqrt(
452
- Math.pow( x - centerPoint.x, 2 ) +
453
- Math.pow( y - centerPoint.y, 2 )
454
- );
455
- const angle = Math.atan( y - centerPoint.y, x - centerPoint.x );
456
-
457
- tilePositions.push( {
458
- index: i,
459
- x,
460
- y,
461
- distance,
462
- angle
463
- } );
464
-
465
- }
466
-
467
- tilePositions.sort( ( a, b ) => {
468
-
469
- const distanceDiff = a.distance - b.distance;
470
- if ( Math.abs( distanceDiff ) < 0.01 ) {
471
-
472
- return a.angle - b.angle;
473
-
474
- }
475
-
476
- return distanceDiff;
477
-
478
- } );
479
-
480
- return tilePositions.map( pos => pos.index );
481
-
482
- }
483
-
484
401
  export function clamp( value, min, max ) {
485
402
 
486
403
  return Math.min( Math.max( value, min ), max );
@@ -493,31 +410,15 @@ export function lerp( a, b, t ) {
493
410
 
494
411
  }
495
412
 
496
- export function isRenderComplete( frameValue, renderMode, maxFrames, totalTiles ) {
497
-
498
- if ( renderMode === 0 ) {
499
-
500
- return frameValue >= maxFrames;
501
-
502
- } else {
503
-
504
- return frameValue >= maxFrames * totalTiles;
413
+ export function isRenderComplete( frameValue, renderMode, maxFrames ) {
505
414
 
506
- }
415
+ return frameValue >= maxFrames;
507
416
 
508
417
  }
509
418
 
510
- export function getCurrentSampleCount( frameValue, renderMode, totalTiles ) {
511
-
512
- if ( renderMode === 0 ) {
419
+ export function getCurrentSampleCount( frameValue ) {
513
420
 
514
- return frameValue;
515
-
516
- } else {
517
-
518
- return Math.floor( frameValue / totalTiles );
519
-
520
- }
421
+ return frameValue;
521
422
 
522
423
  }
523
424
 
@@ -40,8 +40,6 @@ const SETTING_ROUTES = {
40
40
  emissiveBoost: { uniform: 'emissiveBoost', reset: true },
41
41
  visMode: { uniform: 'visMode', reset: true },
42
42
  debugVisScale: { uniform: 'debugVisScale', reset: true },
43
- useAdaptiveSampling: { uniform: 'useAdaptiveSampling', reset: true },
44
- adaptiveSamplingMax: { uniform: 'adaptiveSamplingMax', reset: true },
45
43
 
46
44
  // ── Multi-stage / special handling ────────────────────────────
47
45
 
@@ -63,7 +61,6 @@ const SETTING_ROUTES = {
63
61
  */
64
62
  const DEFAULTS_KEY_MAP = {
65
63
  bounces: 'maxBounces',
66
- adaptiveSampling: 'useAdaptiveSampling',
67
64
  debugMode: 'visMode',
68
65
  };
69
66