rayzee 5.10.2 → 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.
- package/README.md +82 -22
- package/dist/assets/AIUpscalerWorker-AXN-lKWN.js +2 -0
- package/dist/assets/AIUpscalerWorker-AXN-lKWN.js.map +1 -0
- package/dist/rayzee.es.js +1299 -1843
- package/dist/rayzee.es.js.map +1 -1
- package/dist/rayzee.umd.js +50 -74
- package/dist/rayzee.umd.js.map +1 -1
- package/package.json +1 -4
- package/src/AssetConfig.js +56 -0
- package/src/EngineDefaults.js +5 -3
- package/src/EngineEvents.js +1 -0
- package/src/Passes/AIUpscaler.js +44 -22
- package/src/Passes/OIDNDenoiser.js +4 -104
- package/src/PathTracerApp.js +59 -63
- package/src/Processor/AssetLoader.js +5 -2
- package/src/Processor/TextureCreator.js +42 -15
- package/src/Processor/Workers/AIUpscalerWorker.js +21 -6
- package/src/Stages/ASVGF.js +6 -27
- package/src/Stages/AdaptiveSampling.js +10 -26
- package/src/Stages/PathTracer.js +4 -5
- package/src/TSL/BVHTraversal.js +2 -18
- package/src/TSL/Clearcoat.js +1 -2
- package/src/TSL/Common.js +0 -13
- package/src/TSL/EmissiveSampling.js +0 -16
- package/src/TSL/Environment.js +0 -7
- package/src/TSL/LightsDirect.js +3 -379
- package/src/TSL/LightsSampling.js +0 -171
- package/src/TSL/MaterialEvaluation.js +3 -103
- package/src/TSL/MaterialProperties.js +1 -56
- package/src/TSL/MaterialSampling.js +2 -284
- package/src/TSL/MaterialTransmission.js +0 -93
- package/src/TSL/Random.js +0 -23
- package/src/TSL/Struct.js +0 -21
- package/src/TSL/TextureSampling.js +0 -69
- package/src/index.js +5 -2
- package/src/managers/DenoisingManager.js +13 -5
- package/src/managers/OverlayManager.js +14 -2
- package/src/managers/VideoRenderManager.js +4 -4
- package/dist/assets/AIUpscalerWorker-D58dcMrY.js +0 -2
- package/dist/assets/AIUpscalerWorker-D58dcMrY.js.map +0 -1
- package/src/Processor/createRenderTargetHelper.js +0 -521
- package/src/TSL/RayIntersection.js +0 -162
- package/src/managers/helpers/StatsHelper.js +0 -45
|
@@ -351,7 +351,8 @@ class TextureCache {
|
|
|
351
351
|
const width = texture.image.width || 0;
|
|
352
352
|
const height = texture.image.height || 0;
|
|
353
353
|
const src = texture.image.src || texture.uuid || '';
|
|
354
|
-
|
|
354
|
+
const flipFlag = texture.flipY === false ? 'n' : 'f';
|
|
355
|
+
hash += `${width}x${height}_${src.slice( - 8 )}_${flipFlag}_`;
|
|
355
356
|
|
|
356
357
|
}
|
|
357
358
|
|
|
@@ -681,12 +682,16 @@ export class TextureCreator {
|
|
|
681
682
|
|
|
682
683
|
if ( ! texture?.image ) continue;
|
|
683
684
|
|
|
685
|
+
const flipY = texture.flipY !== false;
|
|
686
|
+
|
|
684
687
|
try {
|
|
685
688
|
|
|
686
689
|
// Option 1: Direct ImageBitmap transfer (when supported)
|
|
687
690
|
if ( typeof createImageBitmap !== 'undefined' && texture.image instanceof HTMLImageElement ) {
|
|
688
691
|
|
|
689
|
-
const bitmap = await createImageBitmap( texture.image
|
|
692
|
+
const bitmap = await createImageBitmap( texture.image, {
|
|
693
|
+
imageOrientation: flipY ? 'flipY' : 'none',
|
|
694
|
+
} );
|
|
690
695
|
texturesData.push( {
|
|
691
696
|
bitmap: bitmap,
|
|
692
697
|
width: texture.image.width,
|
|
@@ -696,16 +701,22 @@ export class TextureCreator {
|
|
|
696
701
|
|
|
697
702
|
} else { // Option 2: Efficient canvas-based transfer
|
|
698
703
|
|
|
699
|
-
const
|
|
704
|
+
const w = texture.image.width;
|
|
705
|
+
const h = texture.image.height;
|
|
706
|
+
const bitmap = await createImageBitmap( texture.image, {
|
|
707
|
+
imageOrientation: flipY ? 'flipY' : 'none',
|
|
708
|
+
} );
|
|
709
|
+
const pair = this.canvasPool.getCanvasWithContext( w, h );
|
|
700
710
|
|
|
701
|
-
pair.context.drawImage(
|
|
702
|
-
|
|
711
|
+
pair.context.drawImage( bitmap, 0, 0 );
|
|
712
|
+
bitmap.close();
|
|
713
|
+
const imageData = pair.context.getImageData( 0, 0, w, h );
|
|
703
714
|
|
|
704
715
|
// Transfer the underlying ArrayBuffer directly
|
|
705
716
|
texturesData.push( {
|
|
706
717
|
data: imageData.data.buffer, // Direct buffer transfer
|
|
707
|
-
width:
|
|
708
|
-
height:
|
|
718
|
+
width: w,
|
|
719
|
+
height: h,
|
|
709
720
|
isImageData: true
|
|
710
721
|
} );
|
|
711
722
|
|
|
@@ -759,11 +770,13 @@ export class TextureCreator {
|
|
|
759
770
|
for ( let i = batchStart; i < batchEnd; i ++ ) {
|
|
760
771
|
|
|
761
772
|
const texture = validTextures[ i ];
|
|
773
|
+
const flipY = texture.flipY !== false;
|
|
762
774
|
|
|
763
775
|
const bitmapPromise = createImageBitmap( texture.image, {
|
|
764
776
|
resizeWidth: maxWidth,
|
|
765
777
|
resizeHeight: maxHeight,
|
|
766
|
-
resizeQuality: 'high'
|
|
778
|
+
resizeQuality: 'high',
|
|
779
|
+
imageOrientation: flipY ? 'flipY' : 'none',
|
|
767
780
|
} );
|
|
768
781
|
|
|
769
782
|
batchPromises.push(
|
|
@@ -815,9 +828,16 @@ export class TextureCreator {
|
|
|
815
828
|
for ( let i = 0; i < validTextures.length; i ++ ) {
|
|
816
829
|
|
|
817
830
|
const texture = validTextures[ i ];
|
|
831
|
+
const bitmap = await createImageBitmap( texture.image, {
|
|
832
|
+
resizeWidth: maxWidth,
|
|
833
|
+
resizeHeight: maxHeight,
|
|
834
|
+
resizeQuality: 'high',
|
|
835
|
+
imageOrientation: texture.flipY !== false ? 'flipY' : 'none',
|
|
836
|
+
} );
|
|
818
837
|
|
|
819
838
|
pair.context.clearRect( 0, 0, maxWidth, maxHeight );
|
|
820
|
-
pair.context.drawImage(
|
|
839
|
+
pair.context.drawImage( bitmap, 0, 0 );
|
|
840
|
+
bitmap.close();
|
|
821
841
|
|
|
822
842
|
const imageData = pair.context.getImageData( 0, 0, maxWidth, maxHeight );
|
|
823
843
|
const offset = maxWidth * maxHeight * 4 * i;
|
|
@@ -853,9 +873,16 @@ export class TextureCreator {
|
|
|
853
873
|
for ( let i = 0; i < validTextures.length; i ++ ) {
|
|
854
874
|
|
|
855
875
|
const texture = validTextures[ i ];
|
|
876
|
+
const bitmap = await createImageBitmap( texture.image, {
|
|
877
|
+
resizeWidth: maxWidth,
|
|
878
|
+
resizeHeight: maxHeight,
|
|
879
|
+
resizeQuality: 'high',
|
|
880
|
+
imageOrientation: texture.flipY !== false ? 'flipY' : 'none',
|
|
881
|
+
} );
|
|
856
882
|
|
|
857
883
|
pair.context.clearRect( 0, 0, maxWidth, maxHeight );
|
|
858
|
-
pair.context.drawImage(
|
|
884
|
+
pair.context.drawImage( bitmap, 0, 0 );
|
|
885
|
+
bitmap.close();
|
|
859
886
|
|
|
860
887
|
const imageData = pair.context.getImageData( 0, 0, maxWidth, maxHeight );
|
|
861
888
|
const offset = maxWidth * maxHeight * 4 * i;
|
|
@@ -1301,7 +1328,7 @@ export class TextureCreator {
|
|
|
1301
1328
|
const mip = tex.mipmaps[ 0 ];
|
|
1302
1329
|
const idx = normalized.length;
|
|
1303
1330
|
normalized.push( null ); // placeholder — filled after Promise.all
|
|
1304
|
-
bitmapJobs.push( { index: idx, promise: _rawPixelsToBitmap( mip.data, mip.width, mip.height ) } );
|
|
1331
|
+
bitmapJobs.push( { index: idx, flipY: tex.flipY, promise: _rawPixelsToBitmap( mip.data, mip.width, mip.height ) } );
|
|
1305
1332
|
continue;
|
|
1306
1333
|
|
|
1307
1334
|
}
|
|
@@ -1323,7 +1350,7 @@ export class TextureCreator {
|
|
|
1323
1350
|
|
|
1324
1351
|
const idx = normalized.length;
|
|
1325
1352
|
normalized.push( null );
|
|
1326
|
-
bitmapJobs.push( { index: idx, promise: _rawPixelsToBitmap( tex.image.data, tex.image.width, tex.image.height ) } );
|
|
1353
|
+
bitmapJobs.push( { index: idx, flipY: tex.flipY, promise: _rawPixelsToBitmap( tex.image.data, tex.image.width, tex.image.height ) } );
|
|
1327
1354
|
continue;
|
|
1328
1355
|
|
|
1329
1356
|
}
|
|
@@ -1339,14 +1366,14 @@ export class TextureCreator {
|
|
|
1339
1366
|
|
|
1340
1367
|
for ( let i = 0; i < bitmapJobs.length; i ++ ) {
|
|
1341
1368
|
|
|
1342
|
-
const { index } = bitmapJobs[ i ];
|
|
1369
|
+
const { index, flipY } = bitmapJobs[ i ];
|
|
1343
1370
|
const result = results[ i ];
|
|
1344
1371
|
|
|
1345
1372
|
if ( result.status === 'fulfilled' ) {
|
|
1346
1373
|
|
|
1347
1374
|
const bitmap = result.value;
|
|
1348
1375
|
bitmapsToClose.push( bitmap );
|
|
1349
|
-
normalized[ index ] = { image: bitmap };
|
|
1376
|
+
normalized[ index ] = { image: bitmap, flipY };
|
|
1350
1377
|
|
|
1351
1378
|
} else {
|
|
1352
1379
|
|
|
@@ -1367,7 +1394,7 @@ export class TextureCreator {
|
|
|
1367
1394
|
const placeholder = new Uint8ClampedArray( [ 255, 255, 255, 255 ] );
|
|
1368
1395
|
const bitmap = await createImageBitmap( new ImageData( placeholder, 1, 1 ) );
|
|
1369
1396
|
bitmapsToClose.push( bitmap );
|
|
1370
|
-
normalized[ i ] = { image: bitmap };
|
|
1397
|
+
normalized[ i ] = { image: bitmap, flipY: false };
|
|
1371
1398
|
|
|
1372
1399
|
}
|
|
1373
1400
|
|
|
@@ -14,8 +14,13 @@
|
|
|
14
14
|
* { type: 'error', message, id? }
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
//
|
|
18
|
-
|
|
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 */
|
|
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 =
|
|
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
|
-
|
|
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(
|
|
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' ) {
|
package/src/Stages/ASVGF.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
307
|
-
*
|
|
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
|
-
*
|
|
347
|
-
* @
|
|
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
|
-
|
|
337
|
+
setHeatmapEnabled( enabled ) {
|
|
350
338
|
|
|
351
|
-
this.showAdaptiveSamplingHelper =
|
|
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
|
|
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
|
|
package/src/Stages/PathTracer.js
CHANGED
|
@@ -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 );
|
package/src/TSL/BVHTraversal.js
CHANGED
|
@@ -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,
|
package/src/TSL/Clearcoat.js
CHANGED
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
|
// ================================================================================
|
package/src/TSL/Environment.js
CHANGED
|
@@ -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 {
|