rayzee 9.4.2 → 9.5.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 (144) hide show
  1. package/README.md +223 -21
  2. package/dist/ActiveColor-YvuQq44O.js +13 -0
  3. package/dist/ArchiveImporter-xuUJiklP.js +4301 -0
  4. package/dist/AssetConfig-DSEntE65.js +30 -0
  5. package/dist/BidirectionalIntegrator-C5PKjJoT.js +934 -0
  6. package/dist/ColorManagement-CheBCPaW.js +1488 -0
  7. package/dist/EngineDefaults-DH3bI5t-.js +844 -0
  8. package/dist/EngineEvents-Ci8dVWCP.js +73 -0
  9. package/dist/EngineIssues-CIZnXHsF.js +72 -0
  10. package/dist/FileFormats-sPGJeCRc.js +102 -0
  11. package/dist/Logger-BnHghprG.js +97 -0
  12. package/dist/{NeuralRetouch-vkdXXyK2.js → NeuralRetouch-CW11yLZ_.js} +8 -6
  13. package/dist/{NeuralSuperRes-FVqRJKQV.js → NeuralSuperRes-BekaecYg.js} +55 -120
  14. package/dist/PathTracer-Ccl9KOuF.js +29729 -0
  15. package/dist/PhysicalSky-Dv2PMFGW.js +1219 -0
  16. package/dist/RayzeeRenderer-BQxnzCTD.js +3542 -0
  17. package/dist/SolarLimb-ken-JbDK.js +721 -0
  18. package/dist/ToneMapGPU-BHi5JzIq.js +177 -0
  19. package/dist/ViewTransforms-D0rTLBsX.js +255 -0
  20. package/dist/WorkingMatrix-C6y233hT.js +27 -0
  21. package/dist/ZipReader-gDSWr0I5.js +98 -0
  22. package/dist/addons/archives.es.js +3 -0
  23. package/dist/addons/bidirectional.es.js +2 -0
  24. package/dist/addons/color.es.js +3 -0
  25. package/dist/addons/formats.es.js +2 -0
  26. package/dist/addons/physical-sky.es.js +2 -0
  27. package/dist/addons/storage.es.js +3 -0
  28. package/dist/archiveFormats-BZw7TiDp.js +75 -0
  29. package/dist/identity-DrQsGT2o.js +39 -0
  30. package/dist/openStorage-DwcBRUj7.js +820 -0
  31. package/dist/rayzee-core.es.js +12 -0
  32. package/dist/rayzee.es.js +2266 -44079
  33. package/dist/rayzee.umd.js +485 -473
  34. package/dist/sceneCachePolicy-BmwYOYDu.js +183 -0
  35. package/dist/shared-BGBcSxBQ.js +17 -0
  36. package/package.json +23 -2
  37. package/src/Color/ActiveColor.js +34 -0
  38. package/src/Color/BasicColor.js +147 -0
  39. package/src/Color/ColorManagement.js +7 -31
  40. package/src/EngineDefaults.js +22 -8
  41. package/src/EngineEvents.js +2 -0
  42. package/src/EngineIssues.js +1 -0
  43. package/src/PathTracerApp.js +617 -4016
  44. package/src/Pipeline/PipelineContext.js +0 -4
  45. package/src/Platform.js +36 -0
  46. package/src/Processor/ArchiveCache.js +1 -1
  47. package/src/Processor/ArchiveImporter.js +1259 -0
  48. package/src/Processor/AssetLoader.js +322 -1746
  49. package/src/Processor/AtmosphereModel.js +1 -2
  50. package/src/Processor/BVHBuilder.js +4 -95
  51. package/src/Processor/EnvironmentExactTable.js +187 -0
  52. package/src/Processor/EquirectHDRInfo.js +30 -223
  53. package/src/Processor/FileFormats.js +116 -0
  54. package/src/Processor/GLTFDecoders.js +85 -0
  55. package/src/Processor/GLTFDiffuseTransmission.js +63 -0
  56. package/src/Processor/GeometryExtractor.js +12 -1
  57. package/src/Processor/IESParser.js +47 -35
  58. package/src/Processor/KernelManager.js +35 -2
  59. package/src/Processor/MaterialPacking.js +8 -7
  60. package/src/Processor/PBRT/PBRTMaterials.js +129 -41
  61. package/src/Processor/PBRT/PBRTParser.js +30 -17
  62. package/src/Processor/PBRT/PBRTSceneBuilder.js +548 -37
  63. package/src/Processor/PBRT/PBRTTextureBake.js +154 -0
  64. package/src/Processor/PBRT/PFM.js +59 -0
  65. package/src/Processor/PackedRayBuffer.js +116 -9
  66. package/src/Processor/ParallelBVHBuilder.js +3 -6
  67. package/src/Processor/PhysicalSky.js +5 -4
  68. package/src/Processor/PlatformImageLoader.js +50 -6
  69. package/src/Processor/QueueManager.js +12 -3
  70. package/src/Processor/ReinsertionOptimizer.js +2 -2
  71. package/src/Processor/SceneProcessor.js +15 -55
  72. package/src/Processor/ShaderBuilder.js +6 -16
  73. package/src/Processor/SolarLimb.js +3 -0
  74. package/src/Processor/TextureCreator.js +1 -1
  75. package/src/Processor/Workers/BVHSubtreeWorker.js +1 -34
  76. package/src/Processor/Workers/BVHWorker.js +5 -18
  77. package/src/Processor/Workers/CDFWorker.js +6 -183
  78. package/src/Processor/archiveFormats.js +7 -0
  79. package/src/Processor/utils.js +2 -1
  80. package/src/RayzeeRenderer.js +3902 -0
  81. package/src/RenderSettings.js +49 -41
  82. package/src/Stages/ASVGF.js +5 -7
  83. package/src/Stages/AutoExposure.js +3 -12
  84. package/src/Stages/Compositor.js +8 -23
  85. package/src/Stages/NRD.js +9 -2
  86. package/src/Stages/NormalDepth.js +9 -6
  87. package/src/Stages/PathTracer.js +254 -38
  88. package/src/Stages/PathTracerStage.js +11 -16
  89. package/src/Storage/BLASCache.js +1 -1
  90. package/src/Storage/CDFCache.js +18 -17
  91. package/src/Storage/DownloadCache.js +1 -1
  92. package/src/Storage/SceneGraphCodec.js +46 -3
  93. package/src/Storage/SpillStore.js +1 -1
  94. package/src/Storage/StorageManager.js +2 -4
  95. package/src/Storage/areas.js +4 -0
  96. package/src/TSL/BVHTraversal.js +62 -24
  97. package/src/TSL/Bidirectional.js +204 -0
  98. package/src/TSL/BidirectionalLamps.js +132 -0
  99. package/src/TSL/Clearcoat.js +15 -6
  100. package/src/TSL/Common.js +19 -14
  101. package/src/TSL/ConnectKernel.js +147 -0
  102. package/src/TSL/Debugger.js +1 -1
  103. package/src/TSL/Displacement.js +4 -3
  104. package/src/TSL/EmissiveSampling.js +64 -17
  105. package/src/TSL/Environment.js +77 -106
  106. package/src/TSL/EnvironmentCDF.js +85 -39
  107. package/src/TSL/ExtendKernel.js +8 -3
  108. package/src/TSL/FinalWriteKernel.js +4 -4
  109. package/src/TSL/GenerateKernel.js +18 -4
  110. package/src/TSL/HitFacet.js +35 -5
  111. package/src/TSL/LightBVHSampling.js +40 -9
  112. package/src/TSL/LightGenerateKernel.js +293 -0
  113. package/src/TSL/LightGuide.js +198 -0
  114. package/src/TSL/LightSplatKernel.js +165 -0
  115. package/src/TSL/LightsCore.js +13 -38
  116. package/src/TSL/LightsDirect.js +28 -29
  117. package/src/TSL/LightsIndirect.js +3 -1
  118. package/src/TSL/LightsSampling.js +90 -38
  119. package/src/TSL/MaterialEvaluation.js +113 -31
  120. package/src/TSL/MaterialProperties.js +44 -17
  121. package/src/TSL/MaterialTransmission.js +52 -47
  122. package/src/TSL/MergeKernel.js +218 -0
  123. package/src/TSL/PathTracerCore.js +65 -29
  124. package/src/TSL/Random.js +4 -0
  125. package/src/TSL/SceneResources.js +51 -0
  126. package/src/TSL/ShadeKernel.js +881 -103
  127. package/src/TSL/Struct.js +10 -0
  128. package/src/TSL/Sun.js +1 -1
  129. package/src/TSL/TextureSampling.js +65 -60
  130. package/src/addons/archives.js +14 -0
  131. package/src/addons/bidirectional.js +13 -0
  132. package/src/addons/color.js +32 -0
  133. package/src/addons/formats.js +16 -0
  134. package/src/addons/physicalSky.js +14 -0
  135. package/src/addons/storage.js +19 -0
  136. package/src/core.js +35 -0
  137. package/src/index.js +3 -1
  138. package/src/integrators/BidirectionalIntegrator.js +832 -0
  139. package/src/managers/EnvironmentManager.js +85 -33
  140. package/src/managers/MaterialDataManager.js +42 -0
  141. package/src/managers/UniformManager.js +0 -1
  142. package/dist/ToneMapGPU-DKQM1pMd.js +0 -552
  143. package/dist/rolldown-runtime-CAFD8bLK.js +0 -11
  144. package/src/Processor/TreeletOptimizer.js +0 -574
@@ -116,14 +116,6 @@ export class SceneProcessor {
116
116
  enableTextureCache: true,
117
117
  maxConcurrentTextureTasks: Math.min( hardwareThreads(), 6 ),
118
118
  maxSceneBytes: MAX_SCENE_BYTES,
119
- // Treelet optimization configuration
120
- // Keep: `_buildBVH` sends `enabled: value !== false`, so undefined re-enables treelets.
121
- enableTreeletOptimization: false,
122
- treeletSize: 7, // 7 nodes gives 315 topologies for optimal enumeration
123
- treeletOptimizationPasses: 1,
124
- treeletMinImprovement: 0.01, // Minimum SAH improvement threshold
125
- // Above this triangle count the builder drops treelets to size 3.
126
- treeletComplexityThreshold: 50000,
127
119
  // Store the per-mesh BVHs of a scene whose build took at least this long (needs a sceneKey).
128
120
  sceneCache: true,
129
121
  sceneCacheMinBuildMs: SCENE_CACHE_MIN_BUILD_MS,
@@ -152,6 +144,8 @@ export class SceneProcessor {
152
144
  this.iridescenceThicknessMaps = [];
153
145
  this.specularIntensityMaps = [];
154
146
  this.specularColorMaps = [];
147
+ this.diffuseTransmissionMaps = [];
148
+ this.diffuseTransmissionColorMaps = [];
155
149
  this.directionalLights = [];
156
150
  this.cameras = [];
157
151
  this.spheres = [];
@@ -235,15 +229,6 @@ export class SceneProcessor {
235
229
  this.bvhBuilder = new BVHBuilder();
236
230
  this.bvhBuilder.maxLeafSize = this.config.maxLeafSize;
237
231
 
238
- // Configure treelet optimization
239
- this.bvhBuilder.setTreeletConfig( {
240
- enabled: this.config.enableTreeletOptimization,
241
- size: this.config.treeletSize,
242
- passes: this.config.treeletOptimizationPasses,
243
- minImprovement: this.config.treeletMinImprovement,
244
- complexityThreshold: this.config.treeletComplexityThreshold
245
- } );
246
-
247
232
  // Create and configure texture creator
248
233
  this.textureCreator = new TextureCreator( { maxTextureSize: this.config.maxTextureSize, issues: this.config.issues } );
249
234
  // The optimized TextureCreator will auto-detect capabilities and select optimal methods
@@ -877,6 +862,8 @@ export class SceneProcessor {
877
862
  this.iridescenceThicknessMaps = extractedData.iridescenceThicknessMaps;
878
863
  this.specularIntensityMaps = extractedData.specularIntensityMaps;
879
864
  this.specularColorMaps = extractedData.specularColorMaps;
865
+ this.diffuseTransmissionMaps = extractedData.diffuseTransmissionMaps ?? [];
866
+ this.diffuseTransmissionColorMaps = extractedData.diffuseTransmissionColorMaps ?? [];
880
867
  this.directionalLights = extractedData.directionalLights;
881
868
  this.cameras = extractedData.cameras;
882
869
 
@@ -1032,7 +1019,7 @@ export class SceneProcessor {
1032
1019
  }
1033
1020
 
1034
1021
  // Store all results, summing per-mesh split stats for one aggregate BVH line
1035
- const blasStats = { sah: 0, objMed: 0, spatMed: 0, failed: 0, treeletsImproved: 0, treeletsProcessed: 0 };
1022
+ const blasStats = { sah: 0, objMed: 0, spatMed: 0, failed: 0 };
1036
1023
 
1037
1024
  for ( const { m, range, result } of [ ...poolResults, ...parallelResults ] ) {
1038
1025
 
@@ -1043,8 +1030,6 @@ export class SceneProcessor {
1043
1030
  blasStats.objMed += st.objectMedianSplits ?? 0;
1044
1031
  blasStats.spatMed += st.spatialMedianSplits ?? 0;
1045
1032
  blasStats.failed += st.failedSplits ?? 0;
1046
- blasStats.treeletsImproved += st.treeletsImproved ?? 0;
1047
- blasStats.treeletsProcessed += st.treeletsProcessed ?? 0;
1048
1033
  this.performanceMetrics.blasWorkerTime += st.totalBuildTime ?? 0;
1049
1034
 
1050
1035
  }
@@ -1190,7 +1175,6 @@ export class SceneProcessor {
1190
1175
  `${fmt.n( table.setCount )} BLASes + TLAS`,
1191
1176
  `${fmt.n( this.bvh.recordCount )} nodes`,
1192
1177
  `SAH ${fmt.n( blasStats.sah )} · objMed ${blasStats.objMed} · spatMed ${blasStats.spatMed} · failed ${blasStats.failed}`,
1193
- blasStats.treeletsProcessed ? `treelets ${blasStats.treeletsImproved}/${blasStats.treeletsProcessed} improved` : null,
1194
1178
  fmt.ms( duration ),
1195
1179
  ] ) );
1196
1180
 
@@ -1218,13 +1202,6 @@ export class SceneProcessor {
1218
1202
 
1219
1203
  return {
1220
1204
  depth: this.config.bvhDepth,
1221
- treeletOptimization: {
1222
- enabled: this.config.enableTreeletOptimization !== false,
1223
- size: this.config.treeletSize,
1224
- passes: this.config.treeletOptimizationPasses,
1225
- minImprovement: this.config.treeletMinImprovement,
1226
- complexityThreshold: this.config.treeletComplexityThreshold
1227
- },
1228
1205
  reinsertionOptimization: {
1229
1206
  enabled: this.bvhBuilder.enableReinsertionOptimization,
1230
1207
  batchSizeRatio: this.bvhBuilder.reinsertionBatchSizeRatio,
@@ -1702,7 +1679,7 @@ export class SceneProcessor {
1702
1679
  * Each mesh is dispatched to an available BVHWorker; at most poolSize workers run concurrently.
1703
1680
  *
1704
1681
  * @param {Array<{m: number, range: {start: number, count: number}}>} tasks
1705
- * @param {Object} opts - Worker build options (depth, treeletOptimization, reinsertionOptimization)
1682
+ * @param {Object} opts - Worker build options (depth, reinsertionOptimization)
1706
1683
  * @param {Function} onProgress - Called with (completedCount) as builds finish
1707
1684
  * @returns {Promise<Array<{m, range, result}>>}
1708
1685
  * @private
@@ -1766,11 +1743,7 @@ export class SceneProcessor {
1766
1743
 
1767
1744
  const meshTriData = this.triangles.copyOf( range.start, range.count );
1768
1745
 
1769
- // Disable treelet for tiny meshes
1770
1746
  const triCount = range.count;
1771
- const treeletOpts = triCount <= 500
1772
- ? { ...opts.treeletOptimization, enabled: false }
1773
- : opts.treeletOptimization;
1774
1747
 
1775
1748
  worker._currentTask = { m, range };
1776
1749
  worker.postMessage( {
@@ -1781,7 +1754,6 @@ export class SceneProcessor {
1781
1754
  depth: opts.depth,
1782
1755
  reportProgress: false,
1783
1756
  sharedReorderBuffer: null,
1784
- treeletOptimization: treeletOpts,
1785
1757
  reinsertionOptimization: opts.reinsertionOptimization,
1786
1758
  maxLeafSize: opts.maxLeafSize,
1787
1759
  foldLeaves: opts.foldLeaves,
@@ -1824,7 +1796,7 @@ export class SceneProcessor {
1824
1796
  const result = {
1825
1797
  bvhData: data.bvhData,
1826
1798
  originalToBvh: data.originalToBvh || null,
1827
- splitStats: data.treeletStats || null,
1799
+ splitStats: data.splitStats || null,
1828
1800
  };
1829
1801
  onResult?.( m, range, result );
1830
1802
  results.push( { m, range, result } );
@@ -2041,11 +2013,12 @@ export class SceneProcessor {
2041
2013
 
2042
2014
  };
2043
2015
 
2044
- const srgbTypes = [ this.maps, this.emissiveMaps, this.sheenColorMaps, this.specularColorMaps ];
2016
+ const srgbTypes = [ this.maps, this.emissiveMaps, this.sheenColorMaps, this.specularColorMaps, this.diffuseTransmissionColorMaps ];
2045
2017
  const linearTypes = [
2046
2018
  this.normalMaps, this.bumpMaps, this.roughnessMaps, this.metalnessMaps, this.displacementMaps,
2047
2019
  this.anisotropyMaps, this.transmissionMaps, this.clearcoatMaps, this.clearcoatRoughnessMaps,
2048
2020
  this.sheenRoughnessMaps, this.iridescenceMaps, this.iridescenceThicknessMaps, this.specularIntensityMaps,
2021
+ this.diffuseTransmissionMaps,
2049
2022
  ];
2050
2023
 
2051
2024
  const srgbShapes = planTextureBuckets( poolSizes( srgbTypes ), cap, K );
@@ -2136,6 +2109,8 @@ export class SceneProcessor {
2136
2109
  iridescenceThickness: remapType( this.iridescenceThicknessMaps, linearLists, linearDedup, this._linearTexPacked, linearShapes ),
2137
2110
  specularIntensity: remapType( this.specularIntensityMaps, linearLists, linearDedup, this._linearTexPacked, linearShapes ),
2138
2111
  specularColor: remapType( this.specularColorMaps, srgbLists, srgbDedup, this._srgbTexPacked, srgbShapes ),
2112
+ diffuseTransmission: remapType( this.diffuseTransmissionMaps, linearLists, linearDedup, this._linearTexPacked, linearShapes ),
2113
+ diffuseTransmissionColor: remapType( this.diffuseTransmissionColorMaps, srgbLists, srgbDedup, this._srgbTexPacked, srgbShapes ),
2139
2114
  };
2140
2115
 
2141
2116
  return { srgbLists, linearLists, remap };
@@ -2170,6 +2145,8 @@ export class SceneProcessor {
2170
2145
  mat.iridescenceThicknessMap = fix( mat.iridescenceThicknessMap, remap.iridescenceThickness );
2171
2146
  mat.specularIntensityMap = fix( mat.specularIntensityMap, remap.specularIntensity );
2172
2147
  mat.specularColorMap = fix( mat.specularColorMap, remap.specularColor );
2148
+ mat.diffuseTransmissionMap = fix( mat.diffuseTransmissionMap, remap.diffuseTransmission );
2149
+ mat.diffuseTransmissionColorMap = fix( mat.diffuseTransmissionColorMap, remap.diffuseTransmissionColor );
2173
2150
 
2174
2151
  }
2175
2152
 
@@ -2265,6 +2242,8 @@ export class SceneProcessor {
2265
2242
  this.iridescenceThicknessMaps = [];
2266
2243
  this.specularIntensityMaps = [];
2267
2244
  this.specularColorMaps = [];
2245
+ this.diffuseTransmissionMaps = [];
2246
+ this.diffuseTransmissionColorMaps = [];
2268
2247
  this.directionalLights = [];
2269
2248
  this.cameras = [];
2270
2249
  this.spheres = [];
@@ -2477,15 +2456,6 @@ export class SceneProcessor {
2477
2456
 
2478
2457
  this.bvhBuilder.maxLeafSize = this.config.maxLeafSize;
2479
2458
 
2480
- // Update treelet optimization configuration
2481
- this.bvhBuilder.setTreeletConfig( {
2482
- enabled: this.config.enableTreeletOptimization,
2483
- size: this.config.treeletSize,
2484
- passes: this.config.treeletOptimizationPasses,
2485
- minImprovement: this.config.treeletMinImprovement,
2486
- complexityThreshold: this.config.treeletComplexityThreshold
2487
- } );
2488
-
2489
2459
  }
2490
2460
 
2491
2461
  // Note: TextureCreator auto-configures based on capabilities
@@ -3688,9 +3658,6 @@ export class SceneProcessor {
3688
3658
 
3689
3659
  };
3690
3660
 
3691
- // Disable treelet for tiny meshes
3692
- const treeletEnabled = entry.triCount > 500;
3693
-
3694
3661
  worker.postMessage( {
3695
3662
  triangleData: meshTriData.buffer,
3696
3663
  triangleByteOffset: meshTriData.byteOffset,
@@ -3706,13 +3673,6 @@ export class SceneProcessor {
3706
3673
  minBins: this.bvhBuilder.minBins,
3707
3674
  reportProgress: false,
3708
3675
  sharedReorderBuffer: null,
3709
- treeletOptimization: {
3710
- enabled: treeletEnabled,
3711
- size: this.config.treeletSize,
3712
- passes: this.config.treeletOptimizationPasses,
3713
- minImprovement: this.config.treeletMinImprovement,
3714
- complexityThreshold: this.config.treeletComplexityThreshold
3715
- },
3716
3676
  reinsertionOptimization: {
3717
3677
  enabled: this.bvhBuilder.enableReinsertionOptimization,
3718
3678
  batchSizeRatio: this.bvhBuilder.reinsertionBatchSizeRatio,
@@ -1,16 +1,13 @@
1
1
  /**
2
2
  * ShaderBuilder.js — shared scene texture-node factory for the path tracer.
3
3
  *
4
- * Creates the texture/storage nodes the wavefront kernels read (environment, material map
5
- * arrays, previous-frame MRT, adaptive-sampling, gobo/IES) and configures the module-level
6
- * shadow/alpha/gobo/IES shader state. Nodes are created once and updated in-place via
7
- * .value mutation to preserve compiled shader-graph references.
4
+ * Creates the texture/storage nodes the wavefront kernels read (environment, previous-frame MRT,
5
+ * adaptive-sampling, gobo/IES). Nodes are created once and updated in-place via .value mutation to
6
+ * preserve compiled shader-graph references.
8
7
  */
9
8
 
10
9
  import { texture } from 'three/tsl';
11
10
  import { LinearFilter, DataArrayTexture } from 'three';
12
- import { setAlphaShadowsUniform } from '../TSL/LightsDirect.js';
13
- import { setGoboMapsTexture, setIESProfilesTexture } from '../TSL/LightsCore.js';
14
11
  import { createLogger } from '../utils/Logger.js';
15
12
 
16
13
  const log = createLogger( 'shader' );
@@ -81,8 +78,7 @@ export class ShaderBuilder {
81
78
 
82
79
  }
83
80
 
84
- // Creates the shared scene texture nodes (env, material maps, prev-frame, adaptive, gobo, IES)
85
- // + configures the module-level shadow/alpha/gobo/IES shader state read by the wavefront kernels.
81
+ // Creates the shared scene texture nodes (env, prev-frame, adaptive, gobo, IES).
86
82
  // Call from setupMaterial before the kernels are built.
87
83
  createSceneTextureNodes( stage, storageTextures ) {
88
84
 
@@ -93,9 +89,6 @@ export class ShaderBuilder {
93
89
  // TSL params; emissive reads offset by stage.emissiveVec4Offset.
94
90
  const lightBufferStorage = stage.lightStorageNode;
95
91
 
96
- // Set alpha-shadow uniform (module-level in LightsDirect.js, read at runtime)
97
- setAlphaShadowsUniform( stage.uniforms.get( 'enableAlphaShadows' ) );
98
-
99
92
  const envTex = texture( stage.environment.environmentTexture );
100
93
 
101
94
  // Previous-frame texture nodes — initialized from readTarget textures
@@ -115,17 +108,14 @@ export class ShaderBuilder {
115
108
 
116
109
  };
117
110
 
118
- // Material map arrays (consolidated size buckets) are owned by PathTracer's
119
- // independent wavefront nodes + setMaterialBucketTextures/setShadowAlbedoMaps —
120
- // see PathTracer._buildWavefrontKernels. Nothing material-map related is bound here.
111
+ // Material map arrays (consolidated size buckets) are owned by PathTracer's independent wavefront
112
+ // nodes, handed to its kernels as SceneResources — see PathTracer._buildWavefrontKernels.
121
113
 
122
114
  // Spot light gobo array — placeholder until GoboManager populates it.
123
115
  const goboMapsTex = stage.goboMaps ? texture( stage.goboMaps ) : createArrayPlaceholder();
124
- setGoboMapsTexture( goboMapsTex );
125
116
 
126
117
  // Spot light IES profiles array — placeholder until IESManager populates it.
127
118
  const iesProfilesTex = stage.iesProfiles ? texture( stage.iesProfiles ) : createArrayPlaceholder();
128
- setIESProfilesTexture( iesProfilesTex );
129
119
 
130
120
  const result = {
131
121
  triStorage, bvhStorage, matStorage, lightBufferStorage,
@@ -0,0 +1,3 @@
1
+ // Hestroffer & Magnan 1998: I(µ)/I(1) = µ^α, α = −0.023 + 0.292 / λ[µm], at each primary's centroid. The core's sun
2
+ // (TSL/Sun.js) and the physical sky's disc average both read it.
3
+ export const LIMB_DARKENING_EXPONENT = [ 610, 550, 465 ].map( l => - 0.023 + 0.292 / ( l / 1000 ) );
@@ -6,7 +6,7 @@ import PackWorker from './Workers/PackWorker.js?worker&inline';
6
6
  import { resampleRGBA8 } from './ResampleRGBA8.js';
7
7
  import { ISSUE_CODES, EngineIssueError } from '../EngineIssues.js';
8
8
  import { linearToSRGB } from './ToneMapCPU.js';
9
- import { getActiveColorManagement } from '../Color/ColorManagement.js';
9
+ import { getActiveColorManagement } from '../Color/ActiveColor.js';
10
10
  import { createLogger } from '../utils/Logger.js';
11
11
  import { createWorker, hardwareThreads, hasWorkers } from '../Platform.js';
12
12
 
@@ -1,5 +1,4 @@
1
1
  import { BVHBuilder } from '../BVHBuilder.js';
2
- import { TreeletOptimizer } from '../TreeletOptimizer.js';
3
2
  import { ReinsertionOptimizer } from '../ReinsertionOptimizer.js';
4
3
 
5
4
  self.onmessage = function ( e ) {
@@ -9,7 +8,6 @@ self.onmessage = function ( e ) {
9
8
  sharedTriangleData, sharedCentroids, sharedBMin, sharedBMax, sharedIndices,
10
9
  triangleCount,
11
10
  maxLeafSize, numBins, maxBins, minBins,
12
- treeletConfig,
13
11
  reinsertionConfig,
14
12
  reportProgress
15
13
  } = e.data;
@@ -46,8 +44,7 @@ self.onmessage = function ( e ) {
46
44
  builder.splitStats = {
47
45
  sahSplits: 0, objectMedianSplits: 0, spatialMedianSplits: 0,
48
46
  failedSplits: 0, avgBinsUsed: 0, totalSplitAttempts: 0,
49
- mortonSortTime: 0, totalBuildTime: 0, treeletOptimizationTime: 0,
50
- treeletsProcessed: 0, treeletsImproved: 0, averageSAHImprovement: 0,
47
+ mortonSortTime: 0, totalBuildTime: 0,
51
48
  initTime: 0, sahBuildTime: 0, reorderTime: 0
52
49
  };
53
50
 
@@ -70,36 +67,6 @@ self.onmessage = function ( e ) {
70
67
  task.preMaxX, task.preMaxY, task.preMaxZ
71
68
  );
72
69
 
73
- // Treelet optimization on subtree
74
- if ( treeletConfig && treeletConfig.enabled && ( task.end - task.start ) > 1000 ) {
75
-
76
- const isLargeSubtree = ( task.end - task.start ) > 50000;
77
- const adaptiveSize = isLargeSubtree ? 3 : ( treeletConfig.size || 5 );
78
- const adaptiveMax = isLargeSubtree ? 10 : 20;
79
-
80
- const optimizer = new TreeletOptimizer( builder.traversalCost, builder.intersectionCost );
81
- optimizer.setTreeletSize( adaptiveSize );
82
- optimizer.setMinImprovement( treeletConfig.minImprovement || 0.02 );
83
- optimizer.setMaxTreelets( adaptiveMax );
84
-
85
- const passes = treeletConfig.passes || 1;
86
- for ( let pass = 0; pass < passes; pass ++ ) {
87
-
88
- try {
89
-
90
- optimizer.optimizeBVH( root, null );
91
-
92
- } catch ( err ) {
93
-
94
- console.error( `[BVHSubtreeWorker] Treelet pass ${pass + 1} error:`, err );
95
- break;
96
-
97
- }
98
-
99
- }
100
-
101
- }
102
-
103
70
  // Reinsertion optimization on subtree
104
71
  if ( reinsertionConfig && reinsertionConfig.enabled && ( task.end - task.start ) > 1000 ) {
105
72
 
@@ -41,19 +41,13 @@ function handlePhase1( data ) {
41
41
  sharedTriangleData, sharedCentroids, sharedBMin, sharedBMax,
42
42
  sharedIndices, sharedMortonCodes,
43
43
  triangleCount, depth, parallelDepth,
44
- reportProgress, treeletOptimization
44
+ reportProgress
45
45
  } = data;
46
46
 
47
47
  try {
48
48
 
49
49
  const builder = new BVHBuilder();
50
50
 
51
- if ( treeletOptimization ) {
52
-
53
- builder.setTreeletConfig( treeletOptimization );
54
-
55
- }
56
-
57
51
  const progressCallback = reportProgress ? ( progress ) => {
58
52
 
59
53
  self.postMessage( { type: 'progress', progress } );
@@ -77,8 +71,7 @@ function handlePhase1( data ) {
77
71
  builder.splitStats = {
78
72
  sahSplits: 0, objectMedianSplits: 0, spatialMedianSplits: 0,
79
73
  failedSplits: 0, avgBinsUsed: 0, totalSplitAttempts: 0,
80
- mortonSortTime: 0, totalBuildTime: 0, treeletOptimizationTime: 0,
81
- treeletsProcessed: 0, treeletsImproved: 0, averageSAHImprovement: 0,
74
+ mortonSortTime: 0, totalBuildTime: 0,
82
75
  initTime: 0, sahBuildTime: 0, reorderTime: 0
83
76
  };
84
77
 
@@ -193,7 +186,7 @@ function handleAssemble( data ) {
193
186
 
194
187
  function handleFullBuild( data ) {
195
188
 
196
- const { triangleData, triangleByteOffset, triangleByteLength, depth, reportProgress, treeletOptimization, reinsertionOptimization, sharedReorderBuffer, maxLeafSize, numBins, maxBins, minBins, foldLeaves: fold } = data;
189
+ const { triangleData, triangleByteOffset, triangleByteLength, depth, reportProgress, reinsertionOptimization, sharedReorderBuffer, maxLeafSize, numBins, maxBins, minBins, foldLeaves: fold } = data;
197
190
  const builder = new BVHBuilder();
198
191
  // Honor the build params forwarded from SceneProcessor (previously ignored → default leaf 8).
199
192
  if ( maxLeafSize !== undefined ) builder.maxLeafSize = maxLeafSize;
@@ -203,12 +196,6 @@ function handleFullBuild( data ) {
203
196
 
204
197
  try {
205
198
 
206
- if ( treeletOptimization ) {
207
-
208
- builder.setTreeletConfig( treeletOptimization );
209
-
210
- }
211
-
212
199
  if ( reinsertionOptimization ) {
213
200
 
214
201
  builder.setReinsertionConfig( reinsertionOptimization );
@@ -248,7 +235,7 @@ function handleFullBuild( data ) {
248
235
  bvhData,
249
236
  originalToBvh,
250
237
  triangleCount: inputTriangles.length / FPT,
251
- treeletStats: builder.splitStats
238
+ splitStats: builder.splitStats
252
239
  }, transferables );
253
240
 
254
241
  } else {
@@ -264,7 +251,7 @@ function handleFullBuild( data ) {
264
251
  triangles: reordered,
265
252
  originalToBvh,
266
253
  triangleCount,
267
- treeletStats: builder.splitStats
254
+ splitStats: builder.splitStats
268
255
  }, transferables );
269
256
 
270
257
  }
@@ -1,179 +1,11 @@
1
1
  /**
2
- * Web Worker for computing environment map CDF (Cumulative Distribution Function)
3
- * for importance sampling. Pure math — no Three.js dependencies.
2
+ * Web Worker for an environment map's sampling table (EnvironmentExactTable.js). Pure math — no Three.js dependencies.
4
3
  *
5
4
  * Input: { floatData: Float32Array, width, height }
6
- * Output: { marginalData: Float32Array, conditionalData: Float32Array, totalSum, width, height }
5
+ * Output: { width, height } and the table
7
6
  */
8
7
 
9
- function binarySearchFindClosestIndexOf( array, targetValue, offset, count ) {
10
-
11
- let lower = offset;
12
- let upper = offset + count - 1;
13
-
14
- while ( lower < upper ) {
15
-
16
- const mid = ( lower + upper ) >> 1;
17
-
18
- if ( array[ mid ] < targetValue ) {
19
-
20
- lower = mid + 1;
21
-
22
- } else {
23
-
24
- upper = mid;
25
-
26
- }
27
-
28
- }
29
-
30
- return lower - offset;
31
-
32
- }
33
-
34
- function buildCDF( floatData, width, height ) {
35
-
36
- const numPixels = width * height;
37
-
38
- // Pass 1: compute per-pixel luminance weighted by sin(theta) and raw total sum.
39
- // sin(theta) compensates for the equirectangular projection: pixels near the poles
40
- // cover less solid angle, so weighting by sin(theta) makes the CDF proportional to
41
- // luminance per solid angle rather than luminance per pixel.
42
- const pixelWeights = new Float32Array( numPixels );
43
- let rawTotalSum = 0.0;
44
-
45
- for ( let y = 0; y < height; y ++ ) {
46
-
47
- const sinTheta = Math.sin( Math.PI * ( y + 0.5 ) / height );
48
-
49
- for ( let x = 0; x < width; x ++ ) {
50
-
51
- const i = y * width + x;
52
- const r = floatData[ 4 * i ];
53
- const g = floatData[ 4 * i + 1 ];
54
- const b = floatData[ 4 * i + 2 ];
55
-
56
- // Luminance (Rec. 709) weighted by solid angle factor
57
- const w = ( 0.2126 * r + 0.7152 * g + 0.0722 * b ) * sinTheta;
58
- pixelWeights[ i ] = w;
59
- rawTotalSum += w;
60
-
61
- }
62
-
63
- }
64
-
65
- // MIS Compensation (Karlík et al. 2019, Eq. 14)
66
- // With equal sample allocation (c_I = 0.5): delta = 2*(1 - 0.5)*meanWeight = meanWeight
67
- // Subtracting mean sharpens the env map PDF, reducing oversampling
68
- // of dim regions already well-covered by BSDF sampling.
69
- const meanWeight = rawTotalSum / numPixels;
70
- let compensatedTotalSum = 0.0;
71
-
72
- for ( let i = 0; i < numPixels; i ++ ) {
73
-
74
- pixelWeights[ i ] = Math.max( 0, pixelWeights[ i ] - meanWeight );
75
- compensatedTotalSum += pixelWeights[ i ];
76
-
77
- }
78
-
79
- // Fall back to raw weights if compensation zeroed everything (uniform env map)
80
- const useCompensation = compensatedTotalSum > 0;
81
- const totalSumValue = useCompensation ? compensatedTotalSum : rawTotalSum;
82
- const compensationDelta = useCompensation ? meanWeight : 0;
83
-
84
- if ( ! useCompensation ) {
85
-
86
- // Restore raw sin-weighted luminance
87
- for ( let y = 0; y < height; y ++ ) {
88
-
89
- const sinTheta = Math.sin( Math.PI * ( y + 0.5 ) / height );
90
-
91
- for ( let x = 0; x < width; x ++ ) {
92
-
93
- const i = y * width + x;
94
- const r = floatData[ 4 * i ];
95
- const g = floatData[ 4 * i + 1 ];
96
- const b = floatData[ 4 * i + 2 ];
97
- pixelWeights[ i ] = ( 0.2126 * r + 0.7152 * g + 0.0722 * b ) * sinTheta;
98
-
99
- }
100
-
101
- }
102
-
103
- }
104
-
105
- // Pass 2: build conditional and marginal CDFs from (compensated) weights
106
- const cdfConditional = new Float32Array( numPixels );
107
- const cdfMarginal = new Float32Array( height );
108
-
109
- let cumulativeWeightMarginal = 0.0;
110
-
111
- for ( let y = 0; y < height; y ++ ) {
112
-
113
- let cumulativeRowWeight = 0.0;
114
- for ( let x = 0; x < width; x ++ ) {
115
-
116
- const i = y * width + x;
117
- cumulativeRowWeight += pixelWeights[ i ];
118
- cdfConditional[ i ] = cumulativeRowWeight;
119
-
120
- }
121
-
122
- // Normalize row CDF to [0, 1]
123
- if ( cumulativeRowWeight !== 0 ) {
124
-
125
- for ( let i = y * width, l = y * width + width; i < l; i ++ ) {
126
-
127
- cdfConditional[ i ] /= cumulativeRowWeight;
128
-
129
- }
130
-
131
- }
132
-
133
- cumulativeWeightMarginal += cumulativeRowWeight;
134
- cdfMarginal[ y ] = cumulativeWeightMarginal;
135
-
136
- }
137
-
138
- // Normalize marginal CDF to [0, 1]
139
- if ( cumulativeWeightMarginal !== 0 ) {
140
-
141
- for ( let i = 0, l = cdfMarginal.length; i < l; i ++ ) {
142
-
143
- cdfMarginal[ i ] /= cumulativeWeightMarginal;
144
-
145
- }
146
-
147
- }
148
-
149
- // Invert marginal CDF
150
- const marginalData = new Float32Array( height );
151
- for ( let i = 0; i < height; i ++ ) {
152
-
153
- const dist = ( i + 1 ) / height;
154
- const row = binarySearchFindClosestIndexOf( cdfMarginal, dist, 0, height );
155
- marginalData[ i ] = ( row + 0.5 ) / height;
156
-
157
- }
158
-
159
- // Invert conditional CDFs
160
- const conditionalData = new Float32Array( width * height );
161
- for ( let y = 0; y < height; y ++ ) {
162
-
163
- for ( let x = 0; x < width; x ++ ) {
164
-
165
- const i = y * width + x;
166
- const dist = ( x + 1 ) / width;
167
- const col = binarySearchFindClosestIndexOf( cdfConditional, dist, y * width, width );
168
- conditionalData[ i ] = ( col + 0.5 ) / width;
169
-
170
- }
171
-
172
- }
173
-
174
- return { marginalData, conditionalData, totalSum: totalSumValue, compensationDelta };
175
-
176
- }
8
+ import { buildExactEnvironmentTable } from '../EnvironmentExactTable.js';
177
9
 
178
10
  self.onmessage = function ( e ) {
179
11
 
@@ -181,19 +13,10 @@ self.onmessage = function ( e ) {
181
13
 
182
14
  try {
183
15
 
184
- const result = buildCDF( floatData, width, height );
185
-
186
- // Transfer arrays back zero-copy
16
+ const table = buildExactEnvironmentTable( floatData, width, height );
187
17
  self.postMessage(
188
- {
189
- marginalData: result.marginalData,
190
- conditionalData: result.conditionalData,
191
- totalSum: result.totalSum,
192
- compensationDelta: result.compensationDelta,
193
- width,
194
- height,
195
- },
196
- [ result.marginalData.buffer, result.conditionalData.buffer ]
18
+ { width, height, ...table },
19
+ [ table.exactConditional.buffer, table.exactMarginal.buffer, table.exactRowGuide.buffer, table.exactMarginalGuide.buffer ]
197
20
  );
198
21
 
199
22
  } catch ( error ) {
@@ -0,0 +1,7 @@
1
+ /** What the archive add-on reads, known before its code loads (rayzee/addons/archives; PathTracerApp loads it on first use). */
2
+ export const ARCHIVE_FORMATS = Object.freeze( {
3
+ 'zip': { type: 'archive', name: 'ZIP Archive' },
4
+ 'gz': { type: 'archive', name: 'Gzipped TAR Archive' },
5
+ 'tgz': { type: 'archive', name: 'Gzipped TAR Archive' },
6
+ 'tar': { type: 'archive', name: 'TAR Archive' },
7
+ } );
@@ -63,7 +63,8 @@ export function disposeMaterialTextures( material ) {
63
63
  const textures = [
64
64
  'alphaMap', 'aoMap', 'bumpMap', 'clearcoatMap', 'clearcoatNormalMap', 'clearcoatRoughnessMap', 'displacementMap',
65
65
  'emissiveMap', 'envMap', 'gradientMap', 'lightMap', 'map', 'metalnessMap', 'normalMap', 'roughnessMap', 'specularMap',
66
- 'sheenColorMap', 'sheenRoughnessMap', 'specularIntensityMap', 'specularColorMap', 'thicknessMap', 'transmissionMap'
66
+ 'sheenColorMap', 'sheenRoughnessMap', 'specularIntensityMap', 'specularColorMap', 'thicknessMap', 'transmissionMap',
67
+ 'diffuseTransmissionMap', 'diffuseTransmissionColorMap',
67
68
  ];
68
69
 
69
70
  textures.forEach( texture => {