rayzee 7.5.1 → 7.6.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 +1 -1
- package/dist/assets/{TexturesWorker-DBqGmVdR.js → TexturesWorker-6mlBy4Dm.js} +2 -2
- package/dist/assets/TexturesWorker-6mlBy4Dm.js.map +1 -0
- package/dist/rayzee.es.js +1360 -1332
- package/dist/rayzee.es.js.map +1 -1
- package/dist/rayzee.umd.js +14 -14
- package/dist/rayzee.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/EngineDefaults.js +10 -1
- package/src/PathTracerApp.js +44 -0
- package/src/Processor/SceneProcessor.js +14 -2
- package/src/Processor/TextureCreator.js +27 -2
- package/src/Processor/Workers/TexturesWorker.js +3 -3
- package/src/TSL/Displacement.js +6 -6
- package/src/TSL/TextureSampling.js +3 -3
- package/dist/assets/TexturesWorker-DBqGmVdR.js.map +0 -1
package/package.json
CHANGED
package/src/EngineDefaults.js
CHANGED
|
@@ -10,6 +10,11 @@ export const ENGINE_DEFAULTS = {
|
|
|
10
10
|
canvasWidth: 512,
|
|
11
11
|
canvasHeight: 512,
|
|
12
12
|
|
|
13
|
+
// Max material-texture dimension (longest edge) used when processing a scene's
|
|
14
|
+
// textures into GPU arrays. Larger = sharper textures but ~quadratic VRAM. Clamped
|
|
15
|
+
// to TEXTURE_CONSTANTS.MAX_TEXTURE_SIZE (hardware ceiling). Applied at scene load.
|
|
16
|
+
maxTextureSize: 4096,
|
|
17
|
+
|
|
13
18
|
toneMapping: 4,
|
|
14
19
|
exposure: 1,
|
|
15
20
|
saturation: 1.2,
|
|
@@ -483,7 +488,11 @@ export const TEXTURE_CONSTANTS = {
|
|
|
483
488
|
BUFFER_POOL_SIZE: 20,
|
|
484
489
|
CANVAS_POOL_SIZE: 12,
|
|
485
490
|
CACHE_SIZE_LIMIT: 50,
|
|
486
|
-
|
|
491
|
+
// Hardware ceiling for a single texture-array dimension (WebGPU maxTextureDimension2D
|
|
492
|
+
// guaranteed minimum). The configurable maxTextureSize setting is clamped to this.
|
|
493
|
+
MAX_TEXTURE_SIZE: 8192,
|
|
494
|
+
// Default cap applied when no maxTextureSize is supplied (engine standalone use).
|
|
495
|
+
DEFAULT_MAX_TEXTURE_SIZE: 4096
|
|
487
496
|
};
|
|
488
497
|
|
|
489
498
|
// Default texture matrix for materials
|
package/src/PathTracerApp.js
CHANGED
|
@@ -103,6 +103,8 @@ export class PathTracerApp extends EventDispatcher {
|
|
|
103
103
|
this.assetLoader = null;
|
|
104
104
|
this._sdf = null;
|
|
105
105
|
this._animRefitInFlight = false;
|
|
106
|
+
// Max material-texture dimension (longest edge); applied on each scene build.
|
|
107
|
+
this._maxTextureSize = DEFAULT_STATE.maxTextureSize;
|
|
106
108
|
|
|
107
109
|
// ── Pipeline & stages ──
|
|
108
110
|
this.pipeline = null;
|
|
@@ -667,6 +669,47 @@ export class PathTracerApp extends EventDispatcher {
|
|
|
667
669
|
|
|
668
670
|
}
|
|
669
671
|
|
|
672
|
+
/**
|
|
673
|
+
* Set the max material-texture dimension (longest edge) used when processing a
|
|
674
|
+
* scene's textures into GPU arrays. Clamped to the hardware ceiling. Larger =
|
|
675
|
+
* sharper textures, ~quadratic VRAM. By default reprocesses the current scene so
|
|
676
|
+
* the change is visible without a manual reload.
|
|
677
|
+
* @param {number} size
|
|
678
|
+
* @param {Object} [opts]
|
|
679
|
+
* @param {boolean} [opts.reprocess=true] - Rebuild the current scene now.
|
|
680
|
+
* @returns {Promise<void>}
|
|
681
|
+
*/
|
|
682
|
+
async setMaxTextureSize( size, { reprocess = true } = {} ) {
|
|
683
|
+
|
|
684
|
+
const prev = this._maxTextureSize;
|
|
685
|
+
const clamped = this._sdf?.setMaxTextureSize( size );
|
|
686
|
+
this._maxTextureSize = clamped ?? size;
|
|
687
|
+
if ( typeof this.stages?.pathTracer?.sdfs?.setMaxTextureSize === 'function' ) {
|
|
688
|
+
|
|
689
|
+
this.stages.pathTracer.sdfs.setMaxTextureSize( this._maxTextureSize );
|
|
690
|
+
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// Reprocess the loaded scene so the new cap takes effect immediately.
|
|
694
|
+
if ( reprocess && this._maxTextureSize !== prev && this._sdf?.triangleData && ! this._loadingInProgress ) {
|
|
695
|
+
|
|
696
|
+
this._loadingInProgress = true;
|
|
697
|
+
try {
|
|
698
|
+
|
|
699
|
+
await this.loadSceneData();
|
|
700
|
+
this.reset();
|
|
701
|
+
this.dispatchEvent( { type: 'TexturesReprocessed', maxTextureSize: this._maxTextureSize } );
|
|
702
|
+
|
|
703
|
+
} finally {
|
|
704
|
+
|
|
705
|
+
this._loadingInProgress = false;
|
|
706
|
+
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
}
|
|
712
|
+
|
|
670
713
|
/** Shared pipeline: load asset → sync controls → build BVH → reset → dispatch events */
|
|
671
714
|
async _loadWithSceneRebuild( loadFn, eventPayload ) {
|
|
672
715
|
|
|
@@ -730,6 +773,7 @@ export class PathTracerApp extends EventDispatcher {
|
|
|
730
773
|
|
|
731
774
|
// Build BVH
|
|
732
775
|
timer.start( 'BVH build (SceneProcessor)' );
|
|
776
|
+
this._sdf.setMaxTextureSize( this._maxTextureSize );
|
|
733
777
|
await this._sdf.buildBVH( this.meshScene );
|
|
734
778
|
timer.end( 'BVH build (SceneProcessor)' );
|
|
735
779
|
|
|
@@ -9,7 +9,7 @@ import { GeometryExtractor } from './GeometryExtractor.js';
|
|
|
9
9
|
import { EmissiveTriangleBuilder } from './EmissiveTriangleBuilder.js';
|
|
10
10
|
import { updateLoading } from '../Processor/utils.js';
|
|
11
11
|
import { BuildTimer } from './BuildTimer.js';
|
|
12
|
-
import { TRIANGLE_DATA_LAYOUT } from '../EngineDefaults.js';
|
|
12
|
+
import { TRIANGLE_DATA_LAYOUT, TEXTURE_CONSTANTS } from '../EngineDefaults.js';
|
|
13
13
|
import { fetchAsWorker } from './Workers/fetchAsWorker.js';
|
|
14
14
|
import BVH_WORKER_URL from './Workers/BVHWorker.js?worker&url';
|
|
15
15
|
import BVH_REFIT_WORKER_URL from './Workers/BVHRefitWorker.js?worker&url';
|
|
@@ -41,6 +41,7 @@ export class SceneProcessor {
|
|
|
41
41
|
verbose: false,
|
|
42
42
|
useFloat32Array: true,
|
|
43
43
|
textureQuality: 'adaptive', // 'low', 'medium', 'high', 'adaptive'
|
|
44
|
+
maxTextureSize: TEXTURE_CONSTANTS.DEFAULT_MAX_TEXTURE_SIZE, // longest-edge cap for material textures
|
|
44
45
|
enableTextureCache: true,
|
|
45
46
|
maxConcurrentTextureTasks: Math.min( navigator.hardwareConcurrency || 4, 6 ),
|
|
46
47
|
// Treelet optimization configuration
|
|
@@ -109,6 +110,17 @@ export class SceneProcessor {
|
|
|
109
110
|
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Set the max material-texture dimension applied on the next scene build.
|
|
115
|
+
* @param {number} size - Longest-edge cap (clamped to the hardware ceiling).
|
|
116
|
+
*/
|
|
117
|
+
setMaxTextureSize( size ) {
|
|
118
|
+
|
|
119
|
+
this.config.maxTextureSize = size;
|
|
120
|
+
return this.textureCreator?.setMaxTextureSize( size );
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
|
|
112
124
|
/**
|
|
113
125
|
* Initialize processing components with configuration
|
|
114
126
|
* @private
|
|
@@ -131,7 +143,7 @@ export class SceneProcessor {
|
|
|
131
143
|
} );
|
|
132
144
|
|
|
133
145
|
// Create and configure texture creator
|
|
134
|
-
this.textureCreator = new TextureCreator();
|
|
146
|
+
this.textureCreator = new TextureCreator( { maxTextureSize: this.config.maxTextureSize } );
|
|
135
147
|
// The optimized TextureCreator will auto-detect capabilities and select optimal methods
|
|
136
148
|
|
|
137
149
|
// Create emissive triangle builder for direct lighting
|
|
@@ -446,6 +446,11 @@ export class TextureCreator {
|
|
|
446
446
|
this.maxConcurrentWorkers = TEXTURE_CONSTANTS.MAX_CONCURRENT_WORKERS;
|
|
447
447
|
this.activeWorkers = 0;
|
|
448
448
|
|
|
449
|
+
// Longest-edge cap for material-texture arrays. Clamped to the hardware ceiling.
|
|
450
|
+
this.maxTextureSize = this._clampTextureSize(
|
|
451
|
+
options.maxTextureSize ?? TEXTURE_CONSTANTS.DEFAULT_MAX_TEXTURE_SIZE
|
|
452
|
+
);
|
|
453
|
+
|
|
449
454
|
// Initialize high-performance components
|
|
450
455
|
this.canvasPool = new CanvasPool();
|
|
451
456
|
this.bufferPool = new SmartBufferPool( {
|
|
@@ -460,6 +465,25 @@ export class TextureCreator {
|
|
|
460
465
|
|
|
461
466
|
}
|
|
462
467
|
|
|
468
|
+
_clampTextureSize( size ) {
|
|
469
|
+
|
|
470
|
+
const n = Math.floor( Number( size ) || TEXTURE_CONSTANTS.DEFAULT_MAX_TEXTURE_SIZE );
|
|
471
|
+
return Math.max( TEXTURE_CONSTANTS.MIN_TEXTURE_WIDTH, Math.min( n, TEXTURE_CONSTANTS.MAX_TEXTURE_SIZE ) );
|
|
472
|
+
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
setMaxTextureSize( size ) {
|
|
476
|
+
|
|
477
|
+
const clamped = this._clampTextureSize( size );
|
|
478
|
+
if ( clamped === this.maxTextureSize ) return clamped; // unchanged — keep cache
|
|
479
|
+
this.maxTextureSize = clamped;
|
|
480
|
+
// Cache keys don't encode size — drop cached arrays so a new cap takes effect.
|
|
481
|
+
this.textureCache?.dispose();
|
|
482
|
+
this.textureCache = new TextureCache();
|
|
483
|
+
return this.maxTextureSize;
|
|
484
|
+
|
|
485
|
+
}
|
|
486
|
+
|
|
463
487
|
detectCapabilities() {
|
|
464
488
|
|
|
465
489
|
return {
|
|
@@ -656,7 +680,7 @@ export class TextureCreator {
|
|
|
656
680
|
|
|
657
681
|
worker.postMessage( {
|
|
658
682
|
textures: texturesData,
|
|
659
|
-
maxTextureSize:
|
|
683
|
+
maxTextureSize: this.maxTextureSize,
|
|
660
684
|
method: 'direct-transfer'
|
|
661
685
|
}, transferables );
|
|
662
686
|
|
|
@@ -1256,7 +1280,8 @@ export class TextureCreator {
|
|
|
1256
1280
|
maxWidth = Math.pow( 2, Math.ceil( Math.log2( maxWidth ) ) );
|
|
1257
1281
|
maxHeight = Math.pow( 2, Math.ceil( Math.log2( maxHeight ) ) );
|
|
1258
1282
|
|
|
1259
|
-
while
|
|
1283
|
+
// Halve only while a dimension exceeds the cap (preserves native res up to the cap).
|
|
1284
|
+
while ( maxWidth > this.maxTextureSize || maxHeight > this.maxTextureSize ) {
|
|
1260
1285
|
|
|
1261
1286
|
maxWidth = Math.max( 1, Math.floor( maxWidth / 2 ) );
|
|
1262
1287
|
maxHeight = Math.max( 1, Math.floor( maxHeight / 2 ) );
|
|
@@ -3,7 +3,7 @@ let canvas, ctx;
|
|
|
3
3
|
// Memory limits and chunking configuration
|
|
4
4
|
const MEMORY_LIMITS = {
|
|
5
5
|
MAX_BYTES_PER_TEXTURE: 256 * 1024 * 1024, // 256MB per texture array
|
|
6
|
-
MAX_TEXTURE_DIMENSION:
|
|
6
|
+
MAX_TEXTURE_DIMENSION: 8192, // Hardware ceiling (WebGPU maxTextureDimension2D guaranteed min); the per-scene maxTextureSize setting is the actual knob
|
|
7
7
|
CHUNK_SIZE: 8, // Optimized: Process textures in chunks of 8 for better memory locality
|
|
8
8
|
ADAPTIVE_CHUNK_SIZE: true, // Enable adaptive chunk sizing based on texture dimensions
|
|
9
9
|
MEMORY_SAFETY_FACTOR: 0.8 // Use only 80% of estimated available memory
|
|
@@ -627,8 +627,8 @@ function calculateOptimalDimensions( textures, maxTextureSize ) {
|
|
|
627
627
|
maxWidth = Math.min( maxWidth, maxTextureSize, MEMORY_LIMITS.MAX_TEXTURE_DIMENSION );
|
|
628
628
|
maxHeight = Math.min( maxHeight, maxTextureSize, MEMORY_LIMITS.MAX_TEXTURE_DIMENSION );
|
|
629
629
|
|
|
630
|
-
//
|
|
631
|
-
while ( maxWidth
|
|
630
|
+
// Halve only while a dimension exceeds the cap (preserves native res up to the cap).
|
|
631
|
+
while ( maxWidth > maxTextureSize || maxHeight > maxTextureSize ) {
|
|
632
632
|
|
|
633
633
|
maxWidth = Math.max( 1, Math.floor( maxWidth / 2 ) );
|
|
634
634
|
maxHeight = Math.max( 1, Math.floor( maxHeight / 2 ) );
|
package/src/TSL/Displacement.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Fn, float, vec2, int, If, Loop, abs, normalize, dot, max } from 'three/tsl';
|
|
1
|
+
import { Fn, float, vec2, int, If, Loop, abs, normalize, dot, max, textureSize } from 'three/tsl';
|
|
2
2
|
|
|
3
3
|
import { struct } from './patches.js';
|
|
4
4
|
import { getDatafromStorageBuffer } from './Common.js';
|
|
@@ -8,7 +8,6 @@ import { sampleDisplacementMap } from './TextureSampling.js';
|
|
|
8
8
|
const MAX_MARCH_STEPS = 32;
|
|
9
9
|
const MIN_MARCH_STEPS = 16;
|
|
10
10
|
const BINARY_STEPS = 5;
|
|
11
|
-
const NORMAL_TEXEL_SIZE = 1.0 / 1024.0;
|
|
12
11
|
const TRI_STRIDE = 8;
|
|
13
12
|
|
|
14
13
|
export const DisplacementResult = struct( {
|
|
@@ -194,14 +193,15 @@ export const refineDisplacedIntersection = Fn( ( [
|
|
|
194
193
|
);
|
|
195
194
|
const displacedHeight = finalHeight.sub( 0.5 ).mul( scale );
|
|
196
195
|
|
|
197
|
-
// Compute displaced normal from height-field gradients using UV tangent vectors
|
|
198
|
-
|
|
196
|
+
// Compute displaced normal from height-field gradients using UV tangent vectors.
|
|
197
|
+
// Finite-difference step = one texel of the actual displacement-array dimensions.
|
|
198
|
+
const texel = vec2( 1.0 ).div( vec2( textureSize( displacementMaps ) ) ).toVar();
|
|
199
199
|
const hC = finalHeight;
|
|
200
200
|
const hU = sampleDisplacementMap(
|
|
201
|
-
displacementMaps, material.displacementMapIndex, finalUV.add( vec2(
|
|
201
|
+
displacementMaps, material.displacementMapIndex, finalUV.add( vec2( texel.x, 0.0 ) ), material.displacementTransform,
|
|
202
202
|
);
|
|
203
203
|
const hV = sampleDisplacementMap(
|
|
204
|
-
displacementMaps, material.displacementMapIndex, finalUV.add( vec2( 0.0,
|
|
204
|
+
displacementMaps, material.displacementMapIndex, finalUV.add( vec2( 0.0, texel.y ) ), material.displacementTransform,
|
|
205
205
|
);
|
|
206
206
|
|
|
207
207
|
// Perturb normal using actual tangent/bitangent from UV parameterization
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Fn, wgslFn, float, vec2, vec3, vec4, int, If, normalize, cross, abs, mix, clamp, texture } from 'three/tsl';
|
|
1
|
+
import { Fn, wgslFn, float, vec2, vec3, vec4, int, If, normalize, cross, abs, mix, clamp, texture, textureSize } from 'three/tsl';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
UVCache,
|
|
@@ -283,8 +283,8 @@ export const processBump = Fn( ( [ bumpMaps, currentNormal, material, uvCache ]
|
|
|
283
283
|
|
|
284
284
|
If( material.bumpMapIndex.greaterThanEqual( int( 0 ) ).and( material.bumpScale.greaterThan( 0.0 ) ), () => {
|
|
285
285
|
|
|
286
|
-
//
|
|
287
|
-
const texelSize = vec2( 1.0
|
|
286
|
+
// Texel size from the actual bump-array dimensions (finite-difference step).
|
|
287
|
+
const texelSize = vec2( 1.0 ).div( vec2( textureSize( bumpMaps ) ) ).toVar();
|
|
288
288
|
|
|
289
289
|
const h_c = texture( bumpMaps, uvCache.bumpUV ).depth( int( material.bumpMapIndex ) ).r;
|
|
290
290
|
const h_u = texture( bumpMaps, vec2( uvCache.bumpUV.x.add( texelSize.x ), uvCache.bumpUV.y ) ).depth( int( material.bumpMapIndex ) ).r;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TexturesWorker-DBqGmVdR.js","names":[],"sources":["../../src/Processor/Workers/TexturesWorker.js"],"sourcesContent":["let canvas, ctx;\n\n// Memory limits and chunking configuration\nconst MEMORY_LIMITS = {\n\tMAX_BYTES_PER_TEXTURE: 256 * 1024 * 1024, // 256MB per texture array\n\tMAX_TEXTURE_DIMENSION: 4096, // Maximum dimension for a single texture\n\tCHUNK_SIZE: 8, // Optimized: Process textures in chunks of 8 for better memory locality\n\tADAPTIVE_CHUNK_SIZE: true, // Enable adaptive chunk sizing based on texture dimensions\n\tMEMORY_SAFETY_FACTOR: 0.8 // Use only 80% of estimated available memory\n};\n\nself.onmessage = async function ( e ) {\n\n\tconst { textures, maxTextureSize, method = 'direct-transfer' } = e.data;\n\n\ttry {\n\n\t\t// Initialize on first use\n\t\tif ( ! canvas ) {\n\n\t\t\tinitializeWorker( maxTextureSize );\n\n\t\t}\n\n\t\tconst result = await processTextures( textures, maxTextureSize, method );\n\n\t\t// Transfer ownership for zero-copy\n\t\tself.postMessage( result, [ result.data ] );\n\n\t} catch ( error ) {\n\n\t\tconsole.error( 'Worker processing failed:', error );\n\t\tself.postMessage( { error: error.message } );\n\n\t}\n\n};\n\nfunction initializeWorker( maxTextureSize ) {\n\n\t// Initialize OffscreenCanvas with optimal settings\n\tconst size = Math.min( maxTextureSize, MEMORY_LIMITS.MAX_TEXTURE_DIMENSION );\n\tcanvas = new OffscreenCanvas( size, size );\n\tctx = canvas.getContext( '2d', {\n\t\twillReadFrequently: true,\n\t\talpha: true,\n\t\tdesynchronized: true\n\t} );\n\n}\n\nasync function processTextures( textures, maxTextureSize, method ) {\n\n\t// Check if we need to use chunked processing\n\tconst dimensions = calculateOptimalDimensions( textures, maxTextureSize );\n\tconst estimatedBytes = dimensions.maxWidth * dimensions.maxHeight * textures.length * 4;\n\n\tif ( estimatedBytes > MEMORY_LIMITS.MAX_BYTES_PER_TEXTURE ) {\n\n\t\tconsole.log( `Large texture array detected (${( estimatedBytes / 1024 / 1024 ).toFixed( 2 )}MB), using chunked processing` );\n\t\treturn await processTexturesInChunks( textures, maxTextureSize, method );\n\n\t}\n\n\tswitch ( method ) {\n\n\t\tcase 'direct-transfer':\n\t\t\treturn await processWithDirectTransfer( textures, maxTextureSize );\n\t\tcase 'offscreen-optimized':\n\t\t\treturn await processWithOffscreenOptimized( textures, maxTextureSize );\n\t\tcase 'imageBitmap-batch':\n\t\t\treturn await processWithImageBitmapBatch( textures, maxTextureSize );\n\t\tdefault:\n\t\t\treturn await processWithDirectTransfer( textures, maxTextureSize );\n\n\t}\n\n}\n\nasync function processTexturesInChunks( textures, maxTextureSize, method ) {\n\n\tconst dimensions = calculateOptimalDimensions( textures, maxTextureSize );\n\tconst { maxWidth, maxHeight } = dimensions;\n\tconst depth = textures.length;\n\n\t// Optimize chunk size based on texture dimensions and memory constraints\n\tconst chunkSize = calculateOptimalChunkSize( maxWidth, maxHeight, depth );\n\tconst numChunks = Math.ceil( depth / chunkSize );\n\n\tconsole.log( `Processing ${depth} textures in ${numChunks} chunks of up to ${chunkSize} textures each` );\n\tconsole.log( `Texture dimensions: ${maxWidth}x${maxHeight}, Est. memory per chunk: ${( maxWidth * maxHeight * chunkSize * 4 / 1024 / 1024 ).toFixed( 2 )}MB` );\n\n\t// Allocate the full output array\n\tlet data;\n\ttry {\n\n\t\tdata = new Uint8Array( maxWidth * maxHeight * depth * 4 );\n\n\t} catch {\n\n\t\t// If full allocation fails, fall back to reduced dimensions\n\t\tconsole.warn( 'Failed to allocate full texture array, reducing dimensions' );\n\t\tconst reducedDimensions = calculateReducedDimensions( textures, maxTextureSize );\n\t\treturn await processWithReducedDimensions( textures, reducedDimensions, method );\n\n\t}\n\n\t// Pre-allocate chunk buffer for reuse\n\tconst chunkBufferSize = maxWidth * maxHeight * chunkSize * 4;\n\tlet chunkBuffer;\n\n\ttry {\n\n\t\tchunkBuffer = new Uint8Array( chunkBufferSize );\n\n\t} catch {\n\n\t\tconsole.warn( 'Failed to allocate chunk buffer, reducing dimensions' );\n\t\tconst reducedDimensions = calculateReducedDimensions( textures, maxTextureSize );\n\t\treturn await processWithReducedDimensions( textures, reducedDimensions, method );\n\n\t}\n\n\t// Process each chunk with optimized memory reuse\n\tfor ( let chunkIndex = 0; chunkIndex < numChunks; chunkIndex ++ ) {\n\n\t\tconst startIdx = chunkIndex * chunkSize;\n\t\tconst endIdx = Math.min( startIdx + chunkSize, depth );\n\t\tconst actualChunkSize = endIdx - startIdx;\n\t\tconst chunkTextures = textures.slice( startIdx, endIdx );\n\n\t\tconst chunkResult = await processTextureChunkOptimized(\n\t\t\tchunkTextures,\n\t\t\tmaxWidth,\n\t\t\tmaxHeight,\n\t\t\tchunkBuffer.subarray( 0, maxWidth * maxHeight * actualChunkSize * 4 )\n\t\t);\n\n\t\t// Copy chunk data to main array\n\t\tconst offset = startIdx * maxWidth * maxHeight * 4;\n\t\tconst copySize = actualChunkSize * maxWidth * maxHeight * 4;\n\t\tdata.set( new Uint8Array( chunkResult.data.slice( 0, copySize ) ), offset );\n\n\t\t// Micro-yield to prevent blocking the thread\n\n\t\tif ( chunkIndex % 2 === 1 ) { // Yield every 2 chunks instead of every chunk\n\n\t\t\tawait new Promise( resolve => setTimeout( resolve, 0 ) );\n\n\t\t}\n\n\t}\n\n\treturn {\n\t\tdata: data.buffer,\n\t\twidth: maxWidth,\n\t\theight: maxHeight,\n\t\tdepth\n\t};\n\n}\n\nfunction calculateOptimalChunkSize( maxWidth, maxHeight, totalTextures ) {\n\n\tif ( ! MEMORY_LIMITS.ADAPTIVE_CHUNK_SIZE ) {\n\n\t\treturn Math.min( MEMORY_LIMITS.CHUNK_SIZE, totalTextures );\n\n\t}\n\n\t// Calculate memory per texture in MB\n\tconst bytesPerTexture = maxWidth * maxHeight * 4;\n\tconst mbPerTexture = bytesPerTexture / ( 1024 * 1024 );\n\n\t// Adaptive chunk sizing based on texture size\n\tlet optimalChunkSize;\n\n\tif ( mbPerTexture <= 1 ) { // Small textures (<=1MB)\n\n\t\toptimalChunkSize = 16; // Process more at once\n\n\t} else if ( mbPerTexture <= 4 ) { // Medium textures (1-4MB)\n\n\t\toptimalChunkSize = 8; // Balanced approach\n\n\t} else if ( mbPerTexture <= 16 ) { // Large textures (4-16MB)\n\n\t\toptimalChunkSize = 4; // Conservative\n\n\t} else { // Very large textures (>16MB)\n\n\t\toptimalChunkSize = 2; // Very conservative\n\n\t}\n\n\t// Don't exceed total texture count or configured limits\n\treturn Math.min( optimalChunkSize, totalTextures, MEMORY_LIMITS.CHUNK_SIZE * 2 );\n\n}\n\nasync function processTextureChunkOptimized( textures, maxWidth, maxHeight, outputBuffer ) {\n\n\t// Resize canvas for this chunk if needed\n\tif ( canvas.width !== maxWidth || canvas.height !== maxHeight ) {\n\n\t\tcanvas.width = maxWidth;\n\t\tcanvas.height = maxHeight;\n\n\t}\n\n\t// Use provided buffer to avoid allocation\n\tconst bytesPerTexture = maxWidth * maxHeight * 4;\n\n\t// Optimize context settings once per chunk\n\tctx.imageSmoothingEnabled = true;\n\tctx.imageSmoothingQuality = 'high';\n\n\t// Process textures with optimized single texture processing\n\tfor ( let i = 0; i < textures.length; i ++ ) {\n\n\t\tconst textureData = textures[ i ];\n\n\t\ttry {\n\n\t\t\tconst offset = i * bytesPerTexture;\n\t\t\tawait processSingleTextureOptimized( textureData, outputBuffer, offset, maxWidth, maxHeight );\n\n\t\t} catch ( error ) {\n\n\t\t\tconsole.warn( `Failed to process texture ${i}:`, error );\n\t\t\t// Fill with transparent pixels as fallback\n\t\t\tconst offset = i * bytesPerTexture;\n\t\t\toutputBuffer.fill( 0, offset, offset + bytesPerTexture );\n\n\t\t}\n\n\t}\n\n\treturn {\n\t\tdata: outputBuffer.buffer,\n\t\twidth: maxWidth,\n\t\theight: maxHeight,\n\t\tdepth: textures.length\n\t};\n\n}\n\nasync function processSingleTextureOptimized( textureData, outputData, offset, maxWidth, maxHeight ) {\n\n\tlet imageBitmap;\n\n\tif ( textureData.isDirect && textureData.bitmap ) {\n\n\t\t// Direct ImageBitmap transfer - no conversion needed!\n\t\timageBitmap = textureData.bitmap;\n\n\t} else if ( textureData.isImageData && textureData.data ) {\n\n\t\t// Direct ImageData transfer - minimal conversion\n\t\tconst imageData = new ImageData(\n\t\t\tnew Uint8ClampedArray( textureData.data ),\n\t\t\ttextureData.width,\n\t\t\ttextureData.height\n\t\t);\n\n\t\timageBitmap = await createImageBitmap( imageData, {\n\t\t\tresizeWidth: maxWidth,\n\t\t\tresizeHeight: maxHeight,\n\t\t\tresizeQuality: 'high'\n\t\t} );\n\n\t} else if ( textureData.isBlob ) {\n\n\t\t// Legacy blob processing (fallback)\n\t\tconst blob = new Blob( [ textureData.data ] );\n\t\timageBitmap = await createImageBitmap( blob, {\n\t\t\tresizeWidth: maxWidth,\n\t\t\tresizeHeight: maxHeight,\n\t\t\tresizeQuality: 'high'\n\t\t} );\n\n\t} else {\n\n\t\tthrow new Error( 'Unknown texture data format' );\n\n\t}\n\n\t// Clear and draw to canvas\n\tctx.clearRect( 0, 0, maxWidth, maxHeight );\n\tctx.drawImage( imageBitmap, 0, 0, maxWidth, maxHeight );\n\n\t// Get image data efficiently\n\tconst imageData = ctx.getImageData( 0, 0, maxWidth, maxHeight );\n\n\t// Copy directly to the specified offset in output buffer\n\toutputData.set( imageData.data, offset );\n\n\t// Clean up ImageBitmap if we created it\n\tif ( textureData.isImageData || textureData.isBlob ) {\n\n\t\timageBitmap.close();\n\n\t}\n\n}\n\nasync function processTextureChunk( textures, maxWidth, maxHeight ) {\n\n\tlet data;\n\ttry {\n\n\t\tdata = new Uint8Array( maxWidth * maxHeight * textures.length * 4 );\n\n\t} catch ( error ) {\n\n\t\tconsole.warn( 'Failed to allocate texture array in processTextureChunk, reducing dimensions' );\n\t\tconst nextWidth = Math.max( 1, Math.floor( maxWidth / 2 ) );\n\t\tconst nextHeight = Math.max( 1, Math.floor( maxHeight / 2 ) );\n\n\t\tif ( nextWidth === maxWidth && nextHeight === maxHeight ) {\n\n\t\t\tthrow error;\n\n\t\t}\n\n\t\treturn await processTextureChunk( textures, nextWidth, nextHeight );\n\n\t}\n\n\treturn await processTextureChunkOptimized( textures, maxWidth, maxHeight, data );\n\n}\n\nasync function processSingleTexture( textureData, index, outputData, maxWidth, maxHeight ) {\n\n\tconst offset = maxWidth * maxHeight * 4 * index;\n\tawait processSingleTextureOptimized( textureData, outputData, offset, maxWidth, maxHeight );\n\n}\n\nasync function processWithDirectTransfer( textures, maxTextureSize ) {\n\n\tconst dimensions = calculateOptimalDimensions( textures, maxTextureSize );\n\tconst { maxWidth, maxHeight } = dimensions;\n\n\t// Resize canvas if needed\n\tif ( canvas.width !== maxWidth || canvas.height !== maxHeight ) {\n\n\t\tcanvas.width = maxWidth;\n\t\tcanvas.height = maxHeight;\n\n\t}\n\n\tconst depth = textures.length;\n\n\t// Try to allocate memory with fallback\n\tlet data;\n\ttry {\n\n\t\tdata = new Uint8Array( maxWidth * maxHeight * depth * 4 );\n\n\t} catch ( error ) {\n\n\t\tconsole.error( 'Failed to allocate texture array:', error );\n\t\t// Fall back to chunked processing\n\t\treturn await processTexturesInChunks( textures, maxTextureSize, 'direct-transfer' );\n\n\t}\n\n\t// Optimize context settings for batch processing\n\tctx.imageSmoothingEnabled = true;\n\tctx.imageSmoothingQuality = 'high';\n\n\tfor ( let i = 0; i < textures.length; i ++ ) {\n\n\t\tconst textureData = textures[ i ];\n\n\t\ttry {\n\n\t\t\tawait processSingleTexture( textureData, i, data, maxWidth, maxHeight );\n\n\t\t} catch ( error ) {\n\n\t\t\tconsole.warn( `Failed to process texture ${i}:`, error );\n\t\t\t// Fill with transparent pixels as fallback\n\t\t\tconst offset = maxWidth * maxHeight * 4 * i;\n\t\t\tdata.fill( 0, offset, offset + maxWidth * maxHeight * 4 );\n\n\t\t}\n\n\t}\n\n\treturn {\n\t\tdata: data.buffer,\n\t\twidth: maxWidth,\n\t\theight: maxHeight,\n\t\tdepth\n\t};\n\n}\n\nasync function processWithReducedDimensions( textures, dimensions, method ) {\n\n\tconst { maxWidth, maxHeight } = dimensions;\n\tconsole.log( `Using reduced dimensions: ${maxWidth}x${maxHeight}` );\n\n\t// Process with reduced dimensions\n\treturn await processTextureChunk( textures, maxWidth, maxHeight, method );\n\n}\n\nasync function processWithOffscreenOptimized( textures, maxTextureSize ) {\n\n\tconst dimensions = calculateOptimalDimensions( textures, maxTextureSize );\n\tconst { maxWidth, maxHeight } = dimensions;\n\n\t// Resize canvas if needed\n\tif ( canvas.width !== maxWidth || canvas.height !== maxHeight ) {\n\n\t\tcanvas.width = maxWidth;\n\t\tcanvas.height = maxHeight;\n\n\t}\n\n\tconst depth = textures.length;\n\n\t// Try to allocate memory with fallback\n\tlet data;\n\ttry {\n\n\t\tdata = new Uint8Array( maxWidth * maxHeight * depth * 4 );\n\n\t} catch ( error ) {\n\n\t\tconsole.error( 'Failed to allocate texture array:', error );\n\t\t// Fall back to chunked processing\n\t\treturn await processTexturesInChunks( textures, maxTextureSize, 'offscreen-optimized' );\n\n\t}\n\n\t// Optimize context settings for batch processing\n\tctx.imageSmoothingEnabled = true;\n\tctx.imageSmoothingQuality = 'high';\n\n\tfor ( let i = 0; i < textures.length; i ++ ) {\n\n\t\tconst textureData = textures[ i ];\n\n\t\ttry {\n\n\t\t\tlet imageBitmap;\n\n\t\t\tif ( textureData.isBlob ) {\n\n\t\t\t\t// Create ImageBitmap from blob data\n\t\t\t\tconst blob = new Blob( [ textureData.data ] );\n\t\t\t\timageBitmap = await createImageBitmap( blob, {\n\t\t\t\t\tresizeWidth: maxWidth,\n\t\t\t\t\tresizeHeight: maxHeight,\n\t\t\t\t\tresizeQuality: 'high'\n\t\t\t\t} );\n\n\t\t\t} else {\n\n\t\t\t\t// Handle direct image data\n\t\t\t\tconst imageData = new ImageData(\n\t\t\t\t\tnew Uint8ClampedArray( textureData.data ),\n\t\t\t\t\ttextureData.width,\n\t\t\t\t\ttextureData.height\n\t\t\t\t);\n\t\t\t\timageBitmap = await createImageBitmap( imageData, {\n\t\t\t\t\tresizeWidth: maxWidth,\n\t\t\t\t\tresizeHeight: maxHeight,\n\t\t\t\t\tresizeQuality: 'high'\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\t// Clear and draw to canvas\n\t\t\tctx.clearRect( 0, 0, maxWidth, maxHeight );\n\t\t\tctx.drawImage( imageBitmap, 0, 0 );\n\n\t\t\t// Get image data efficiently\n\t\t\tconst imageData = ctx.getImageData( 0, 0, maxWidth, maxHeight );\n\n\t\t\t// Copy to output array\n\t\t\tconst offset = maxWidth * maxHeight * 4 * i;\n\t\t\tdata.set( imageData.data, offset );\n\n\t\t\t// Clean up ImageBitmap\n\t\t\timageBitmap.close();\n\n\t\t} catch ( error ) {\n\n\t\t\tconsole.warn( `Failed to process texture ${i}:`, error );\n\t\t\t// Fill with transparent pixels as fallback\n\t\t\tconst offset = maxWidth * maxHeight * 4 * i;\n\t\t\tdata.fill( 0, offset, offset + maxWidth * maxHeight * 4 );\n\n\t\t}\n\n\t}\n\n\treturn {\n\t\tdata: data.buffer,\n\t\twidth: maxWidth,\n\t\theight: maxHeight,\n\t\tdepth\n\t};\n\n}\n\nasync function processWithImageBitmapBatch( textures, maxTextureSize ) {\n\n\tconst dimensions = calculateOptimalDimensions( textures, maxTextureSize );\n\tconst { maxWidth, maxHeight } = dimensions;\n\n\tconst depth = textures.length;\n\n\t// Try to allocate memory with fallback\n\tlet data;\n\ttry {\n\n\t\tdata = new Uint8Array( maxWidth * maxHeight * depth * 4 );\n\n\t} catch ( error ) {\n\n\t\tconsole.error( 'Failed to allocate texture array:', error );\n\t\t// Fall back to chunked processing\n\t\treturn await processTexturesInChunks( textures, maxTextureSize, 'imageBitmap-batch' );\n\n\t}\n\n\t// Process in batches for memory efficiency - optimized batch size\n\tconst batchSize = Math.min( calculateOptimalChunkSize( maxWidth, maxHeight, textures.length ), textures.length );\n\n\tfor ( let batchStart = 0; batchStart < textures.length; batchStart += batchSize ) {\n\n\t\tconst batchEnd = Math.min( batchStart + batchSize, textures.length );\n\t\tconst batchPromises = [];\n\n\t\t// Create all ImageBitmaps for this batch in parallel\n\t\tfor ( let i = batchStart; i < batchEnd; i ++ ) {\n\n\t\t\tconst textureData = textures[ i ];\n\n\t\t\tlet bitmapPromise;\n\t\t\tif ( textureData.isBlob ) {\n\n\t\t\t\tconst blob = new Blob( [ textureData.data ] );\n\t\t\t\tbitmapPromise = createImageBitmap( blob, {\n\t\t\t\t\tresizeWidth: maxWidth,\n\t\t\t\t\tresizeHeight: maxHeight,\n\t\t\t\t\tresizeQuality: 'high'\n\t\t\t\t} );\n\n\t\t\t} else {\n\n\t\t\t\tconst imageData = new ImageData(\n\t\t\t\t\tnew Uint8ClampedArray( textureData.data ),\n\t\t\t\t\ttextureData.width,\n\t\t\t\t\ttextureData.height\n\t\t\t\t);\n\t\t\t\tbitmapPromise = createImageBitmap( imageData, {\n\t\t\t\t\tresizeWidth: maxWidth,\n\t\t\t\t\tresizeHeight: maxHeight,\n\t\t\t\t\tresizeQuality: 'high'\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tbatchPromises.push(\n\t\t\t\tbitmapPromise.then( bitmap => ( { bitmap, index: i } ) )\n\t\t\t);\n\n\t\t}\n\n\t\t// Wait for all bitmaps in this batch\n\t\tconst bitmaps = await Promise.all( batchPromises );\n\n\t\t// Process each bitmap\n\t\tcanvas.width = maxWidth;\n\t\tcanvas.height = maxHeight;\n\t\tctx.imageSmoothingEnabled = false; // Fast processing for batches\n\n\t\tfor ( const { bitmap, index } of bitmaps ) {\n\n\t\t\tctx.clearRect( 0, 0, maxWidth, maxHeight );\n\t\t\tctx.drawImage( bitmap, 0, 0 );\n\n\t\t\tconst imageData = ctx.getImageData( 0, 0, maxWidth, maxHeight );\n\t\t\tconst offset = maxWidth * maxHeight * 4 * index;\n\t\t\tdata.set( imageData.data, offset );\n\n\t\t\tbitmap.close();\n\n\t\t}\n\n\t}\n\n\treturn {\n\t\tdata: data.buffer,\n\t\twidth: maxWidth,\n\t\theight: maxHeight,\n\t\tdepth\n\t};\n\n}\n\nfunction calculateOptimalDimensions( textures, maxTextureSize ) {\n\n\tlet maxWidth = 0;\n\tlet maxHeight = 0;\n\n\tfor ( let texture of textures ) {\n\n\t\tmaxWidth = Math.max( maxWidth, texture.width || 0 );\n\t\tmaxHeight = Math.max( maxHeight, texture.height || 0 );\n\n\t}\n\n\t// Round to power of 2 for optimal GPU performance\n\tmaxWidth = Math.pow( 2, Math.ceil( Math.log2( maxWidth ) ) );\n\tmaxHeight = Math.pow( 2, Math.ceil( Math.log2( maxHeight ) ) );\n\n\t// Respect texture size limits\n\tmaxWidth = Math.min( maxWidth, maxTextureSize, MEMORY_LIMITS.MAX_TEXTURE_DIMENSION );\n\tmaxHeight = Math.min( maxHeight, maxTextureSize, MEMORY_LIMITS.MAX_TEXTURE_DIMENSION );\n\n\t// Additional safety check\n\twhile ( maxWidth >= maxTextureSize / 2 || maxHeight >= maxTextureSize / 2 ) {\n\n\t\tmaxWidth = Math.max( 1, Math.floor( maxWidth / 2 ) );\n\t\tmaxHeight = Math.max( 1, Math.floor( maxHeight / 2 ) );\n\n\t}\n\n\treturn { maxWidth, maxHeight };\n\n}\n\nfunction calculateReducedDimensions( textures, maxTextureSize ) {\n\n\t// Calculate dimensions but reduce by factor of 2 for memory safety\n\tconst original = calculateOptimalDimensions( textures, maxTextureSize );\n\n\treturn {\n\t\tmaxWidth: Math.max( 1, Math.floor( original.maxWidth / 2 ) ),\n\t\tmaxHeight: Math.max( 1, Math.floor( original.maxHeight / 2 ) )\n\t};\n\n}\n\n"],"mappings":"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"}
|