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.
- package/README.md +24 -5
- package/dist/rayzee.es.js +7624 -7063
- package/dist/rayzee.es.js.map +1 -1
- package/dist/rayzee.umd.js +157 -236
- package/dist/rayzee.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/EngineDefaults.js +26 -9
- package/src/PathTracerApp.js +118 -26
- package/src/Pipeline/PipelineContext.js +1 -2
- package/src/Pipeline/RenderPipeline.js +1 -1
- package/src/Pipeline/RenderStage.js +1 -1
- package/src/Processor/CameraOptimizer.js +0 -5
- package/src/Processor/GeometryExtractor.js +6 -0
- package/src/Processor/KernelManager.js +277 -0
- package/src/Processor/PackedRayBuffer.js +291 -0
- package/src/Processor/QueueManager.js +173 -0
- package/src/Processor/SceneProcessor.js +1 -0
- package/src/Processor/ShaderBuilder.js +11 -317
- package/src/Processor/StorageTexturePool.js +29 -15
- package/src/Processor/VRAMTracker.js +169 -0
- package/src/Processor/utils.js +11 -110
- package/src/RenderSettings.js +0 -3
- package/src/Stages/ASVGF.js +151 -78
- package/src/Stages/BilateralFilter.js +34 -10
- package/src/Stages/EdgeFilter.js +2 -3
- package/src/Stages/MotionVector.js +16 -9
- package/src/Stages/NormalDepth.js +17 -5
- package/src/Stages/PathTracer.js +671 -1456
- package/src/Stages/PathTracerStage.js +1451 -0
- package/src/Stages/SSRC.js +32 -15
- package/src/Stages/Variance.js +35 -12
- package/src/TSL/CompactKernel.js +110 -0
- package/src/TSL/DebugKernel.js +98 -0
- package/src/TSL/Environment.js +13 -11
- package/src/TSL/ExtendKernel.js +75 -0
- package/src/TSL/FinalWriteKernel.js +121 -0
- package/src/TSL/GenerateKernel.js +111 -0
- package/src/TSL/LightsSampling.js +2 -2
- package/src/TSL/PathTracerCore.js +43 -1039
- package/src/TSL/ShadeKernel.js +876 -0
- package/src/TSL/patches.js +81 -4
- package/src/index.js +3 -0
- package/src/managers/CameraManager.js +1 -1
- package/src/managers/DenoisingManager.js +40 -75
- package/src/managers/EnvironmentManager.js +30 -39
- package/src/managers/OverlayManager.js +7 -22
- package/src/managers/UniformManager.js +0 -3
- package/src/managers/helpers/TileHelper.js +2 -2
- package/src/Stages/AdaptiveSampling.js +0 -483
- package/src/TSL/PathTracer.js +0 -384
- 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
|
+
}
|
package/src/Processor/utils.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
206
|
+
export function updateCompletionThreshold( renderMode, maxFrames ) {
|
|
218
207
|
|
|
219
|
-
return
|
|
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,
|
|
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
|
|
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
|
|
511
|
-
|
|
512
|
-
if ( renderMode === 0 ) {
|
|
419
|
+
export function getCurrentSampleCount( frameValue ) {
|
|
513
420
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
} else {
|
|
517
|
-
|
|
518
|
-
return Math.floor( frameValue / totalTiles );
|
|
519
|
-
|
|
520
|
-
}
|
|
421
|
+
return frameValue;
|
|
521
422
|
|
|
522
423
|
}
|
|
523
424
|
|
package/src/RenderSettings.js
CHANGED
|
@@ -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
|
|