rayzee 6.0.1 → 6.2.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 (43) hide show
  1. package/README.md +5 -0
  2. package/dist/assets/TexturesWorker-DBqGmVdR.js.map +1 -1
  3. package/dist/rayzee.es.js +2421 -2078
  4. package/dist/rayzee.es.js.map +1 -1
  5. package/dist/rayzee.umd.js +55 -52
  6. package/dist/rayzee.umd.js.map +1 -1
  7. package/package.json +2 -2
  8. package/src/EngineDefaults.js +3 -0
  9. package/src/PathTracerApp.js +18 -8
  10. package/src/Pipeline/RenderStage.js +3 -0
  11. package/src/Processor/IESParser.js +340 -0
  12. package/src/Processor/LightSerializer.js +32 -4
  13. package/src/Processor/SceneProcessor.js +0 -1
  14. package/src/Processor/ShaderBuilder.js +40 -1
  15. package/src/Processor/Workers/TexturesWorker.js +1 -1
  16. package/src/RenderSettings.js +3 -0
  17. package/src/Stages/NormalDepth.js +3 -19
  18. package/src/Stages/PathTracer.js +15 -9
  19. package/src/TSL/BVHTraversal.js +4 -6
  20. package/src/TSL/Common.js +1 -1
  21. package/src/TSL/Debugger.js +0 -2
  22. package/src/TSL/EmissiveSampling.js +20 -22
  23. package/src/TSL/Environment.js +60 -14
  24. package/src/TSL/Fresnel.js +13 -4
  25. package/src/TSL/LightsCore.js +238 -5
  26. package/src/TSL/LightsDirect.js +16 -5
  27. package/src/TSL/LightsIndirect.js +4 -37
  28. package/src/TSL/LightsSampling.js +119 -185
  29. package/src/TSL/MaterialEvaluation.js +25 -14
  30. package/src/TSL/MaterialProperties.js +14 -34
  31. package/src/TSL/MaterialTransmission.js +18 -37
  32. package/src/TSL/PathTracer.js +25 -7
  33. package/src/TSL/PathTracerCore.js +144 -139
  34. package/src/TSL/Struct.js +7 -1
  35. package/src/TSL/TextureSampling.js +2 -2
  36. package/src/index.js +2 -0
  37. package/src/managers/AnimationManager.js +3 -6
  38. package/src/managers/DenoisingManager.js +1 -1
  39. package/src/managers/GoboManager.js +277 -0
  40. package/src/managers/IESManager.js +268 -0
  41. package/src/managers/LightManager.js +33 -1
  42. package/src/managers/TransformManager.js +3 -3
  43. package/src/managers/UniformManager.js +5 -5
package/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Rayzee Engine
2
2
 
3
+ [![npm](https://img.shields.io/npm/v/rayzee?label=npm)](https://www.npmjs.com/package/rayzee)
4
+ [![minzipped size](https://img.shields.io/badge/minzipped-138%20KB-blue)](https://www.npmjs.com/package/rayzee)
5
+ [![downloads](https://img.shields.io/npm/dw/rayzee?label=downloads)](https://www.npmjs.com/package/rayzee)
6
+ [![jsDelivr](https://img.shields.io/jsdelivr/npm/hm/rayzee?label=jsDelivr)](https://www.jsdelivr.com/package/npm/rayzee)
7
+
3
8
  A real-time WebGPU path tracing engine built on Three.js. Framework-agnostic — use it with React, Vue, vanilla JS, or any other setup.
4
9
 
5
10
  ## Installation
@@ -1 +1 @@
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 ( error ) {\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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"}
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":"YAAA,IAAI,EAAQ,EAGN,EAAgB,CACrB,sBAAuB,IAAM,KAAO,KACpC,sBAAuB,KACvB,WAAY,EACZ,oBAAqB,GACrB,qBAAsB,GACtB,CAED,KAAK,UAAY,eAAiB,EAAI,CAErC,GAAM,CAAE,WAAU,iBAAgB,SAAS,mBAAsB,EAAE,KAEnE,GAAI,CAGI,GAEN,EAAkB,EAAgB,CAInC,IAAM,EAAS,MAAM,EAAiB,EAAU,EAAgB,EAAQ,CAGxE,KAAK,YAAa,EAAQ,CAAE,EAAO,KAAM,CAAE,OAElC,EAAQ,CAEjB,QAAQ,MAAO,4BAA6B,EAAO,CACnD,KAAK,YAAa,CAAE,MAAO,EAAM,QAAS,CAAE,GAM9C,SAAS,EAAkB,EAAiB,CAG3C,IAAM,EAAO,KAAK,IAAK,EAAgB,EAAc,sBAAuB,CAC5E,EAAS,IAAI,gBAAiB,EAAM,EAAM,CAC1C,EAAM,EAAO,WAAY,KAAM,CAC9B,mBAAoB,GACpB,MAAO,GACP,eAAgB,GAChB,CAAE,CAIJ,eAAe,EAAiB,EAAU,EAAgB,EAAS,CAGlE,IAAM,EAAa,EAA4B,EAAU,EAAgB,CACnE,EAAiB,EAAW,SAAW,EAAW,UAAY,EAAS,OAAS,EAEtF,GAAK,EAAiB,EAAc,sBAGnC,OADA,QAAQ,IAAK,kCAAmC,EAAiB,KAAO,MAAO,QAAS,EAAG,CAAC,+BAAgC,CACrH,MAAM,EAAyB,EAAU,EAAgB,EAAQ,CAIzE,OAAS,EAAT,CAEC,IAAK,kBACJ,OAAO,MAAM,EAA2B,EAAU,EAAgB,CACnE,IAAK,sBACJ,OAAO,MAAM,EAA+B,EAAU,EAAgB,CACvE,IAAK,oBACJ,OAAO,MAAM,EAA6B,EAAU,EAAgB,CACrE,QACC,OAAO,MAAM,EAA2B,EAAU,EAAgB,EAMrE,eAAe,EAAyB,EAAU,EAAgB,EAAS,CAG1E,GAAM,CAAE,WAAU,aADC,EAA4B,EAAU,EAAgB,CAEnE,EAAQ,EAAS,OAGjB,EAAY,EAA2B,EAAU,EAAW,EAAO,CACnE,EAAY,KAAK,KAAM,EAAQ,EAAW,CAEhD,QAAQ,IAAK,cAAc,EAAM,eAAe,EAAU,mBAAmB,EAAU,gBAAiB,CACxG,QAAQ,IAAK,uBAAuB,EAAS,GAAG,EAAU,4BAA6B,EAAW,EAAY,EAAY,EAAI,KAAO,MAAO,QAAS,EAAG,CAAC,IAAK,CAG9J,IAAI,EACJ,GAAI,CAEH,EAAO,IAAI,WAAY,EAAW,EAAY,EAAQ,EAAG,MAElD,CAKP,OAFA,QAAQ,KAAM,6DAA8D,CAErE,MAAM,EAA8B,EADjB,EAA4B,EAAU,EAAgB,CACR,EAAQ,CAKjF,IAAM,EAAkB,EAAW,EAAY,EAAY,EACvD,EAEJ,GAAI,CAEH,EAAc,IAAI,WAAY,EAAiB,MAExC,CAIP,OAFA,QAAQ,KAAM,uDAAwD,CAE/D,MAAM,EAA8B,EADjB,EAA4B,EAAU,EAAgB,CACR,EAAQ,CAKjF,IAAM,IAAI,EAAa,EAAG,EAAa,EAAW,IAAgB,CAEjE,IAAM,EAAW,EAAa,EACxB,EAAS,KAAK,IAAK,EAAW,EAAW,EAAO,CAChD,EAAkB,EAAS,EAG3B,EAAc,MAAM,EAFJ,EAAS,MAAO,EAAU,EAAQ,CAIvD,EACA,EACA,EAAY,SAAU,EAAG,EAAW,EAAY,EAAkB,EAAG,CACrE,CAGK,EAAS,EAAW,EAAW,EAAY,EAC3C,EAAW,EAAkB,EAAW,EAAY,EAC1D,EAAK,IAAK,IAAI,WAAY,EAAY,KAAK,MAAO,EAAG,EAAU,CAAE,CAAE,EAAQ,CAItE,EAAa,GAAM,GAEvB,MAAM,IAAI,QAAS,GAAW,WAAY,EAAS,EAAG,CAAE,CAM1D,MAAO,CACN,KAAM,EAAK,OACX,MAAO,EACP,OAAQ,EACR,QACA,CAIF,SAAS,EAA2B,EAAU,EAAW,EAAgB,CAExE,GAAK,CAAE,EAAc,oBAEpB,OAAO,KAAK,IAAK,EAAc,WAAY,EAAe,CAM3D,IAAM,EADkB,EAAW,EAAY,GACN,KAAO,MAG5C,EAqBJ,MAnBA,CAcC,EAdI,GAAgB,EAED,GAER,GAAgB,EAER,EAER,GAAgB,GAER,EAIA,EAKb,KAAK,IAAK,EAAkB,EAAe,EAAc,WAAa,EAAG,CAIjF,eAAe,EAA8B,EAAU,EAAU,EAAW,EAAe,EAGrF,EAAO,QAAU,GAAY,EAAO,SAAW,KAEnD,EAAO,MAAQ,EACf,EAAO,OAAS,GAKjB,IAAM,EAAkB,EAAW,EAAY,EAG/C,EAAI,sBAAwB,GAC5B,EAAI,sBAAwB,OAG5B,IAAM,IAAI,EAAI,EAAG,EAAI,EAAS,OAAQ,IAAO,CAE5C,IAAM,EAAc,EAAU,GAE9B,GAAI,CAGH,MAAM,EAA+B,EAAa,EADnC,EAAI,EACqD,EAAU,EAAW,OAEpF,EAAQ,CAEjB,QAAQ,KAAM,6BAA6B,EAAE,GAAI,EAAO,CAExD,IAAM,EAAS,EAAI,EACnB,EAAa,KAAM,EAAG,EAAQ,EAAS,EAAiB,EAM1D,MAAO,CACN,KAAM,EAAa,OACnB,MAAO,EACP,OAAQ,EACR,MAAO,EAAS,OAChB,CAIF,eAAe,EAA+B,EAAa,EAAY,EAAQ,EAAU,EAAY,CAEpG,IAAI,EAEJ,GAAK,EAAY,UAAY,EAAY,OAGxC,EAAc,EAAY,eAEf,EAAY,aAAe,EAAY,KAAO,CAGzD,IAAM,EAAY,IAAI,UACrB,IAAI,kBAAmB,EAAY,KAAM,CACzC,EAAY,MACZ,EAAY,OACZ,CAED,EAAc,MAAM,kBAAmB,EAAW,CACjD,YAAa,EACb,aAAc,EACd,cAAe,OACf,CAAE,SAEQ,EAAY,OAAS,CAGhC,IAAM,EAAO,IAAI,KAAM,CAAE,EAAY,KAAM,CAAE,CAC7C,EAAc,MAAM,kBAAmB,EAAM,CAC5C,YAAa,EACb,aAAc,EACd,cAAe,OACf,CAAE,MAIH,MAAU,MAAO,8BAA+B,CAKjD,EAAI,UAAW,EAAG,EAAG,EAAU,EAAW,CAC1C,EAAI,UAAW,EAAa,EAAG,EAAG,EAAU,EAAW,CAGvD,IAAM,EAAY,EAAI,aAAc,EAAG,EAAG,EAAU,EAAW,CAG/D,EAAW,IAAK,EAAU,KAAM,EAAQ,EAGnC,EAAY,aAAe,EAAY,SAE3C,EAAY,OAAO,CAMrB,eAAe,EAAqB,EAAU,EAAU,EAAY,CAEnE,IAAI,EACJ,GAAI,CAEH,EAAO,IAAI,WAAY,EAAW,EAAY,EAAS,OAAS,EAAG,OAE1D,EAAQ,CAEjB,QAAQ,KAAM,+EAAgF,CAC9F,IAAM,EAAY,KAAK,IAAK,EAAG,KAAK,MAAO,EAAW,EAAG,CAAE,CACrD,EAAa,KAAK,IAAK,EAAG,KAAK,MAAO,EAAY,EAAG,CAAE,CAE7D,GAAK,IAAc,GAAY,IAAe,EAE7C,MAAM,EAIP,OAAO,MAAM,EAAqB,EAAU,EAAW,EAAY,CAIpE,OAAO,MAAM,EAA8B,EAAU,EAAU,EAAW,EAAM,CAIjF,eAAe,EAAsB,EAAa,EAAO,EAAY,EAAU,EAAY,CAG1F,MAAM,EAA+B,EAAa,EADnC,EAAW,EAAY,EAAI,EAC4B,EAAU,EAAW,CAI5F,eAAe,EAA2B,EAAU,EAAiB,CAGpE,GAAM,CAAE,WAAU,aADC,EAA4B,EAAU,EAAgB,EAIpE,EAAO,QAAU,GAAY,EAAO,SAAW,KAEnD,EAAO,MAAQ,EACf,EAAO,OAAS,GAIjB,IAAM,EAAQ,EAAS,OAGnB,EACJ,GAAI,CAEH,EAAO,IAAI,WAAY,EAAW,EAAY,EAAQ,EAAG,OAEhD,EAAQ,CAIjB,OAFA,QAAQ,MAAO,oCAAqC,EAAO,CAEpD,MAAM,EAAyB,EAAU,EAAgB,kBAAmB,CAKpF,EAAI,sBAAwB,GAC5B,EAAI,sBAAwB,OAE5B,IAAM,IAAI,EAAI,EAAG,EAAI,EAAS,OAAQ,IAAO,CAE5C,IAAM,EAAc,EAAU,GAE9B,GAAI,CAEH,MAAM,EAAsB,EAAa,EAAG,EAAM,EAAU,EAAW,OAE9D,EAAQ,CAEjB,QAAQ,KAAM,6BAA6B,EAAE,GAAI,EAAO,CAExD,IAAM,EAAS,EAAW,EAAY,EAAI,EAC1C,EAAK,KAAM,EAAG,EAAQ,EAAS,EAAW,EAAY,EAAG,EAM3D,MAAO,CACN,KAAM,EAAK,OACX,MAAO,EACP,OAAQ,EACR,QACA,CAIF,eAAe,EAA8B,EAAU,EAAY,EAAS,CAE3E,GAAM,CAAE,WAAU,aAAc,EAIhC,OAHA,QAAQ,IAAK,6BAA6B,EAAS,GAAG,IAAa,CAG5D,MAAM,EAAqB,EAAU,EAAU,EAAW,EAAQ,CAI1E,eAAe,EAA+B,EAAU,EAAiB,CAGxE,GAAM,CAAE,WAAU,aADC,EAA4B,EAAU,EAAgB,EAIpE,EAAO,QAAU,GAAY,EAAO,SAAW,KAEnD,EAAO,MAAQ,EACf,EAAO,OAAS,GAIjB,IAAM,EAAQ,EAAS,OAGnB,EACJ,GAAI,CAEH,EAAO,IAAI,WAAY,EAAW,EAAY,EAAQ,EAAG,OAEhD,EAAQ,CAIjB,OAFA,QAAQ,MAAO,oCAAqC,EAAO,CAEpD,MAAM,EAAyB,EAAU,EAAgB,sBAAuB,CAKxF,EAAI,sBAAwB,GAC5B,EAAI,sBAAwB,OAE5B,IAAM,IAAI,EAAI,EAAG,EAAI,EAAS,OAAQ,IAAO,CAE5C,IAAM,EAAc,EAAU,GAE9B,GAAI,CAEH,IAAI,EAEJ,GAAK,EAAY,OAAS,CAGzB,IAAM,EAAO,IAAI,KAAM,CAAE,EAAY,KAAM,CAAE,CAC7C,EAAc,MAAM,kBAAmB,EAAM,CAC5C,YAAa,EACb,aAAc,EACd,cAAe,OACf,CAAE,KAEG,CAGN,IAAM,EAAY,IAAI,UACrB,IAAI,kBAAmB,EAAY,KAAM,CACzC,EAAY,MACZ,EAAY,OACZ,CACD,EAAc,MAAM,kBAAmB,EAAW,CACjD,YAAa,EACb,aAAc,EACd,cAAe,OACf,CAAE,CAKJ,EAAI,UAAW,EAAG,EAAG,EAAU,EAAW,CAC1C,EAAI,UAAW,EAAa,EAAG,EAAG,CAGlC,IAAM,EAAY,EAAI,aAAc,EAAG,EAAG,EAAU,EAAW,CAGzD,EAAS,EAAW,EAAY,EAAI,EAC1C,EAAK,IAAK,EAAU,KAAM,EAAQ,CAGlC,EAAY,OAAO,OAEV,EAAQ,CAEjB,QAAQ,KAAM,6BAA6B,EAAE,GAAI,EAAO,CAExD,IAAM,EAAS,EAAW,EAAY,EAAI,EAC1C,EAAK,KAAM,EAAG,EAAQ,EAAS,EAAW,EAAY,EAAG,EAM3D,MAAO,CACN,KAAM,EAAK,OACX,MAAO,EACP,OAAQ,EACR,QACA,CAIF,eAAe,EAA6B,EAAU,EAAiB,CAGtE,GAAM,CAAE,WAAU,aADC,EAA4B,EAAU,EAAgB,CAGnE,EAAQ,EAAS,OAGnB,EACJ,GAAI,CAEH,EAAO,IAAI,WAAY,EAAW,EAAY,EAAQ,EAAG,OAEhD,EAAQ,CAIjB,OAFA,QAAQ,MAAO,oCAAqC,EAAO,CAEpD,MAAM,EAAyB,EAAU,EAAgB,oBAAqB,CAKtF,IAAM,EAAY,KAAK,IAAK,EAA2B,EAAU,EAAW,EAAS,OAAQ,CAAE,EAAS,OAAQ,CAEhH,IAAM,IAAI,EAAa,EAAG,EAAa,EAAS,OAAQ,GAAc,EAAY,CAEjF,IAAM,EAAW,KAAK,IAAK,EAAa,EAAW,EAAS,OAAQ,CAC9D,EAAgB,EAAE,CAGxB,IAAM,IAAI,EAAI,EAAY,EAAI,EAAU,IAAO,CAE9C,IAAM,EAAc,EAAU,GAE1B,EACJ,GAAK,EAAY,OAAS,CAEzB,IAAM,EAAO,IAAI,KAAM,CAAE,EAAY,KAAM,CAAE,CAC7C,EAAgB,kBAAmB,EAAM,CACxC,YAAa,EACb,aAAc,EACd,cAAe,OACf,CAAE,KAEG,CAEN,IAAM,EAAY,IAAI,UACrB,IAAI,kBAAmB,EAAY,KAAM,CACzC,EAAY,MACZ,EAAY,OACZ,CACD,EAAgB,kBAAmB,EAAW,CAC7C,YAAa,EACb,aAAc,EACd,cAAe,OACf,CAAE,CAIJ,EAAc,KACb,EAAc,KAAM,IAAY,CAAE,SAAQ,MAAO,EAAG,EAAI,CACxD,CAKF,IAAM,EAAU,MAAM,QAAQ,IAAK,EAAe,CAGlD,EAAO,MAAQ,EACf,EAAO,OAAS,EAChB,EAAI,sBAAwB,GAE5B,IAAM,GAAM,CAAE,SAAQ,WAAW,EAAU,CAE1C,EAAI,UAAW,EAAG,EAAG,EAAU,EAAW,CAC1C,EAAI,UAAW,EAAQ,EAAG,EAAG,CAE7B,IAAM,EAAY,EAAI,aAAc,EAAG,EAAG,EAAU,EAAW,CACzD,EAAS,EAAW,EAAY,EAAI,EAC1C,EAAK,IAAK,EAAU,KAAM,EAAQ,CAElC,EAAO,OAAO,EAMhB,MAAO,CACN,KAAM,EAAK,OACX,MAAO,EACP,OAAQ,EACR,QACA,CAIF,SAAS,EAA4B,EAAU,EAAiB,CAE/D,IAAI,EAAW,EACX,EAAY,EAEhB,IAAM,IAAI,KAAW,EAEpB,EAAW,KAAK,IAAK,EAAU,EAAQ,OAAS,EAAG,CACnD,EAAY,KAAK,IAAK,EAAW,EAAQ,QAAU,EAAG,CAavD,IARA,EAAqB,GAAG,KAAK,KAAM,KAAK,KAAM,EAAU,CAAE,CAC1D,EAAsB,GAAG,KAAK,KAAM,KAAK,KAAM,EAAW,CAAE,CAG5D,EAAW,KAAK,IAAK,EAAU,EAAgB,EAAc,sBAAuB,CACpF,EAAY,KAAK,IAAK,EAAW,EAAgB,EAAc,sBAAuB,CAG9E,GAAY,EAAiB,GAAK,GAAa,EAAiB,GAEvE,EAAW,KAAK,IAAK,EAAG,KAAK,MAAO,EAAW,EAAG,CAAE,CACpD,EAAY,KAAK,IAAK,EAAG,KAAK,MAAO,EAAY,EAAG,CAAE,CAIvD,MAAO,CAAE,WAAU,YAAW,CAI/B,SAAS,EAA4B,EAAU,EAAiB,CAG/D,IAAM,EAAW,EAA4B,EAAU,EAAgB,CAEvE,MAAO,CACN,SAAU,KAAK,IAAK,EAAG,KAAK,MAAO,EAAS,SAAW,EAAG,CAAE,CAC5D,UAAW,KAAK,IAAK,EAAG,KAAK,MAAO,EAAS,UAAY,EAAG,CAAE,CAC9D"}