rayzee 10.0.0 → 11.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/README.md +252 -44
  2. package/dist/ActiveColor-YvuQq44O.js +13 -0
  3. package/dist/ArchiveImporter-Hn35o6Z5.js +5145 -0
  4. package/dist/AssetConfig-DSEntE65.js +30 -0
  5. package/dist/BidirectionalIntegrator-CBw8hkeu.js +946 -0
  6. package/dist/BufferLayout-D_IBo2ci.js +150 -0
  7. package/dist/ColorManagement-oeEk7oSu.js +1488 -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-dDDGj9Av.js +97 -0
  12. package/dist/{NeuralRetouch-CYgkQY8Z.js → NeuralRetouch-BzNpiVHZ.js} +8 -6
  13. package/dist/{NeuralSuperRes-PkgDLQcD.js → NeuralSuperRes-Bk7bHg2B.js} +55 -120
  14. package/dist/PathTracer-72XufKAr.js +29976 -0
  15. package/dist/PhysicalSky-BgjdV88k.js +1219 -0
  16. package/dist/RayzeeRenderer-1QRO97eq.js +3551 -0
  17. package/dist/SolarLimb-CPaeZVwz.js +721 -0
  18. package/dist/ToneMapGPU-CjU3osDd.js +177 -0
  19. package/dist/ViewTransforms-CYN7bq2w.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-tnAoUL1j.js +94 -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 +2551 -44024
  33. package/dist/rayzee.umd.js +528 -487
  34. package/dist/sceneCachePolicy-C67jbci-.js +443 -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/Color/ViewTransforms.js +5 -1
  41. package/src/EngineDefaults.js +62 -1029
  42. package/src/EngineEvents.js +2 -0
  43. package/src/EngineIssues.js +2 -0
  44. package/src/Headless.js +6 -5
  45. package/src/Passes/AIUpscaler.js +58 -141
  46. package/src/Passes/OIDNDenoiser.js +92 -65
  47. package/src/Passes/OIDNTemporalHistory.js +1 -1
  48. package/src/PathTracerApp.js +620 -4026
  49. package/src/Pipeline/PipelineContext.js +0 -4
  50. package/src/Platform.js +36 -0
  51. package/src/Processor/ArchiveCache.js +20 -7
  52. package/src/Processor/ArchiveImporter.js +1265 -0
  53. package/src/Processor/ArchiveReader.js +22 -4
  54. package/src/Processor/AssetLoader.js +327 -1763
  55. package/src/Processor/AtmosphereModel.js +1 -2
  56. package/src/Processor/BVHBuilder.js +14 -126
  57. package/src/Processor/BVHLeafFold.js +4 -6
  58. package/src/Processor/BVHRefitter.js +67 -46
  59. package/src/Processor/BufferLayout.js +291 -0
  60. package/src/Processor/EmissiveTriangleBuilder.js +1 -1
  61. package/src/Processor/EnvironmentExactTable.js +187 -0
  62. package/src/Processor/EquirectHDRInfo.js +30 -223
  63. package/src/Processor/FileFormats.js +116 -0
  64. package/src/Processor/GLTFDecoders.js +85 -0
  65. package/src/Processor/GLTFDiffuseTransmission.js +63 -0
  66. package/src/Processor/GeometryExtractor.js +15 -5
  67. package/src/Processor/HostMemory.js +7 -1
  68. package/src/Processor/IESParser.js +47 -35
  69. package/src/Processor/InstanceTable.js +1 -1
  70. package/src/Processor/KernelManager.js +35 -2
  71. package/src/Processor/MaterialPacking.js +10 -8
  72. package/src/Processor/PBRT/PBRTMaterials.js +254 -42
  73. package/src/Processor/PBRT/PBRTParser.js +49 -19
  74. package/src/Processor/PBRT/PBRTScattering.js +93 -0
  75. package/src/Processor/PBRT/PBRTSceneBuilder.js +1050 -75
  76. package/src/Processor/PBRT/PBRTTextureBake.js +179 -0
  77. package/src/Processor/PBRT/PFM.js +59 -0
  78. package/src/Processor/PackedRayBuffer.js +116 -9
  79. package/src/Processor/ParallelBVHBuilder.js +3 -6
  80. package/src/Processor/PhysicalSky.js +5 -4
  81. package/src/Processor/PlatformImageLoader.js +50 -6
  82. package/src/Processor/QueueManager.js +39 -5
  83. package/src/Processor/ReinsertionOptimizer.js +2 -2
  84. package/src/Processor/SceneMetadata.js +30 -5
  85. package/src/Processor/SceneProcessor.js +53 -62
  86. package/src/Processor/ShaderBuilder.js +6 -16
  87. package/src/Processor/SimpleSky.js +1 -62
  88. package/src/Processor/SolarLimb.js +3 -0
  89. package/src/Processor/SplitBLAS.js +1 -1
  90. package/src/Processor/StorageTexturePool.js +22 -1
  91. package/src/Processor/TLASBuilder.js +1 -3
  92. package/src/Processor/TextureBuckets.js +237 -0
  93. package/src/Processor/TextureCreator.js +181 -8
  94. package/src/Processor/ToneMapGPU.js +64 -15
  95. package/src/Processor/Workers/BVHRefitWorker.js +5 -2
  96. package/src/Processor/Workers/BVHSubtreeWorker.js +1 -34
  97. package/src/Processor/Workers/BVHWorker.js +5 -18
  98. package/src/Processor/Workers/CDFWorker.js +6 -183
  99. package/src/Processor/Workers/TexturesWorker.js +103 -18
  100. package/src/Processor/archiveFormats.js +7 -0
  101. package/src/Processor/utils.js +2 -1
  102. package/src/RayzeeRenderer.js +3900 -0
  103. package/src/RenderSettings.js +68 -62
  104. package/src/Stages/ASVGF.js +13 -14
  105. package/src/Stages/AutoExposure.js +17 -17
  106. package/src/Stages/BilateralFilter.js +2 -1
  107. package/src/Stages/Compositor.js +8 -23
  108. package/src/Stages/DenoiserSettings.js +182 -0
  109. package/src/Stages/EdgeFilter.js +2 -1
  110. package/src/Stages/MotionVector.js +1 -1
  111. package/src/Stages/NRD.js +11 -5
  112. package/src/Stages/NormalDepth.js +12 -8
  113. package/src/Stages/PathTracer.js +336 -43
  114. package/src/Stages/PathTracerStage.js +69 -66
  115. package/src/Stages/Variance.js +1 -1
  116. package/src/Storage/BLASCache.js +1 -1
  117. package/src/Storage/CDFCache.js +18 -17
  118. package/src/Storage/DownloadCache.js +1 -1
  119. package/src/Storage/SceneGraphCodec.js +46 -3
  120. package/src/Storage/SpillStore.js +1 -1
  121. package/src/Storage/StorageManager.js +45 -9
  122. package/src/Storage/areas.js +4 -0
  123. package/src/TSL/BVHTraversal.js +50 -25
  124. package/src/TSL/Bidirectional.js +208 -0
  125. package/src/TSL/BidirectionalLamps.js +132 -0
  126. package/src/TSL/Clearcoat.js +15 -6
  127. package/src/TSL/Common.js +20 -15
  128. package/src/TSL/ConnectKernel.js +167 -0
  129. package/src/TSL/Debugger.js +1 -1
  130. package/src/TSL/Displacement.js +4 -3
  131. package/src/TSL/EmissiveSampling.js +65 -18
  132. package/src/TSL/Environment.js +77 -106
  133. package/src/TSL/EnvironmentCDF.js +85 -39
  134. package/src/TSL/ExtendKernel.js +8 -3
  135. package/src/TSL/FinalWriteKernel.js +4 -4
  136. package/src/TSL/GenerateKernel.js +18 -4
  137. package/src/TSL/HitFacet.js +35 -5
  138. package/src/TSL/LightBVHSampling.js +40 -9
  139. package/src/TSL/LightGenerateKernel.js +293 -0
  140. package/src/TSL/LightGuide.js +198 -0
  141. package/src/TSL/LightSplatKernel.js +180 -0
  142. package/src/TSL/LightVisibility.js +111 -0
  143. package/src/TSL/LightsCore.js +13 -38
  144. package/src/TSL/LightsDirect.js +28 -29
  145. package/src/TSL/LightsIndirect.js +3 -1
  146. package/src/TSL/LightsSampling.js +239 -51
  147. package/src/TSL/MaterialEvaluation.js +113 -31
  148. package/src/TSL/MaterialProperties.js +44 -17
  149. package/src/TSL/MaterialTransmission.js +52 -47
  150. package/src/TSL/MergeKernel.js +224 -0
  151. package/src/TSL/PathTracerCore.js +65 -29
  152. package/src/TSL/Random.js +5 -1
  153. package/src/TSL/SceneResources.js +51 -0
  154. package/src/TSL/ShadeKernel.js +985 -101
  155. package/src/TSL/Struct.js +10 -0
  156. package/src/TSL/Sun.js +1 -1
  157. package/src/TSL/TextureSampling.js +66 -61
  158. package/src/addons/archives.js +14 -0
  159. package/src/addons/bidirectional.js +13 -0
  160. package/src/addons/color.js +32 -0
  161. package/src/addons/formats.js +16 -0
  162. package/src/addons/physicalSky.js +14 -0
  163. package/src/addons/storage.js +19 -0
  164. package/src/core.js +31 -0
  165. package/src/index.js +13 -23
  166. package/src/integrators/BidirectionalIntegrator.js +838 -0
  167. package/src/managers/AnimationManager.js +88 -6
  168. package/src/managers/CameraManager.js +103 -46
  169. package/src/managers/DenoisingManager.js +14 -10
  170. package/src/managers/EnvironmentManager.js +125 -103
  171. package/src/managers/GoboManager.js +9 -0
  172. package/src/managers/MaterialDataManager.js +48 -37
  173. package/src/managers/UniformManager.js +32 -10
  174. package/dist/ToneMapGPU-B6XIe3DU.js +0 -544
  175. package/dist/rolldown-runtime-CAFD8bLK.js +0 -11
  176. package/src/Processor/TreeletOptimizer.js +0 -574
@@ -111,6 +111,7 @@ export class PBRTParser {
111
111
  instanceCount: 0,
112
112
  skippedInstances: 0,
113
113
  objects: new Map(),
114
+ media: new Map(),
114
115
  transformTimes: { start: 0, end: 1 },
115
116
  hasMotion: false,
116
117
  warnings: []
@@ -122,14 +123,13 @@ export class PBRTParser {
122
123
  this.activeTransform = BOTH;
123
124
  this._ctmSource = null;
124
125
  this._ctmValue = null;
125
- this.state = { material: null, areaLight: null, reverseOrientation: false };
126
+ this.state = { material: null, areaLight: null, reverseOrientation: false, interior: null };
126
127
  this.attributeStack = [];
127
128
  this.transformStack = [];
128
129
  this.coordSystems = new Map();
129
130
 
130
131
  // Object capture (ObjectBegin/End)
131
132
  this.currentObject = null; // name being captured, or null
132
- this.objectBeginCTM = null; // CTM frame at ObjectBegin
133
133
 
134
134
  // Directory stack for resolving nested Includes
135
135
  this.dirStack = [ '' ];
@@ -275,7 +275,8 @@ export class PBRTParser {
275
275
  activeTransform: this.activeTransform,
276
276
  material: this.state.material,
277
277
  areaLight: this.state.areaLight,
278
- reverseOrientation: this.state.reverseOrientation
278
+ reverseOrientation: this.state.reverseOrientation,
279
+ interior: this.state.interior
279
280
  } );
280
281
 
281
282
  }
@@ -287,7 +288,7 @@ export class PBRTParser {
287
288
  this.ctm = s.ctm;
288
289
  this.ctmEnd = s.ctmEnd;
289
290
  this.activeTransform = s.activeTransform;
290
- this.state = { material: s.material, areaLight: s.areaLight, reverseOrientation: s.reverseOrientation };
291
+ this.state = { material: s.material, areaLight: s.areaLight, reverseOrientation: s.reverseOrientation, interior: s.interior };
291
292
 
292
293
  }
293
294
 
@@ -602,15 +603,33 @@ export class PBRTParser {
602
603
  this.ir.film = {
603
604
  xresolution: this._num( params.xresolution, 1280 ),
604
605
  yresolution: this._num( params.yresolution, 720 ),
606
+ resolutionGiven: Boolean( params.xresolution || params.yresolution ),
605
607
  filename: this._str( params.filename, null )
606
608
  };
607
609
  break;
608
610
 
609
611
  }
610
612
 
613
+ // What the scene asks the renderer for; reported, not applied (PBRTSceneBuilder renderRequest).
614
+ case 'Integrator': {
615
+
616
+ this._expectString( 'Integrator type' );
617
+ const params = this._parseParams();
618
+ if ( params.maxdepth ) this.ir.integrator = { maxdepth: this._num( params.maxdepth, 5 ) };
619
+ break;
620
+
621
+ }
622
+
623
+ case 'Sampler': {
624
+
625
+ this._expectString( 'Sampler type' );
626
+ const params = this._parseParams();
627
+ if ( params.pixelsamples ) this.ir.sampler = { pixelsamples: this._num( params.pixelsamples, 16 ) };
628
+ break;
629
+
630
+ }
631
+
611
632
  // Consumed for completeness; not used by the engine.
612
- case 'Integrator':
613
- case 'Sampler':
614
633
  case 'PixelFilter':
615
634
  case 'Filter':
616
635
  case 'Accelerator':
@@ -624,7 +643,7 @@ export class PBRTParser {
624
643
  this.ctm = M.identity();
625
644
  this.ctmEnd = null;
626
645
  this.activeTransform = BOTH;
627
- this.state = { material: null, areaLight: null, reverseOrientation: false };
646
+ this.state = { material: null, areaLight: null, reverseOrientation: false, interior: null };
628
647
  break;
629
648
  case 'WorldEnd': break; // legacy v3
630
649
 
@@ -673,14 +692,21 @@ export class PBRTParser {
673
692
 
674
693
  case 'MediumInterface': {
675
694
 
676
- // up to two strings (inside/outside)
677
- if ( this._peek() && this._peek().type === TokenType.STRING ) this._next();
678
- if ( this._peek() && this._peek().type === TokenType.STRING ) this._next();
695
+ // "interior" "exterior"; a single name is both. Only the interior colours a shape.
696
+ const interior = this._peek()?.type === TokenType.STRING ? this._next().value : '';
697
+ if ( this._peek()?.type === TokenType.STRING ) this._next();
698
+ this.state.interior = interior || null;
679
699
  break;
680
700
 
681
701
  }
682
702
 
683
- case 'MakeNamedMedium': this._skipNamedAndParams(); break;
703
+ case 'MakeNamedMedium': {
704
+
705
+ const mediumName = this._expectString( 'MakeNamedMedium name' );
706
+ this.ir.media.set( mediumName, this._parseParams() );
707
+ break;
708
+
709
+ }
684
710
 
685
711
  // ── materials ──
686
712
  case 'Material': {
@@ -748,13 +774,17 @@ export class PBRTParser {
748
774
 
749
775
  const type = this._expectString( 'Shape type' );
750
776
  const params = this._parseParams();
777
+ // pbrt: a shape of alpha 0 is never hit, and an area light on it emits nothing.
778
+ const alpha = params.alpha;
779
+ if ( alpha?.type === 'float' && alpha.value[ 0 ] <= 0 ) break;
751
780
  const shape = {
752
781
  type,
753
782
  params,
754
783
  ctm: this._ctmSnapshot(),
755
784
  material: this.state.material,
756
785
  areaLight: this.state.areaLight,
757
- reverseOrientation: this.state.reverseOrientation
786
+ reverseOrientation: this.state.reverseOrientation,
787
+ interior: this.state.interior
758
788
  };
759
789
  const end = this.currentObject === null ? this._ctmEndSnapshot() : null;
760
790
  if ( end ) shape.ctmEnd = end;
@@ -776,7 +806,6 @@ export class PBRTParser {
776
806
  // pbrt implicitly pushes graphics state.
777
807
  this._pushGraphicsState();
778
808
  this.currentObject = objName;
779
- this.objectBeginCTM = this.ctm.slice();
780
809
  if ( ! this.ir.objects.has( objName ) ) this.ir.objects.set( objName, [] );
781
810
  break;
782
811
 
@@ -785,7 +814,6 @@ export class PBRTParser {
785
814
  case 'ObjectEnd': {
786
815
 
787
816
  this.currentObject = null;
788
- this.objectBeginCTM = null;
789
817
  this._popGraphicsState();
790
818
  break;
791
819
 
@@ -824,8 +852,8 @@ export class PBRTParser {
824
852
 
825
853
  if ( this.currentObject !== null ) {
826
854
 
827
- // Store relative to the ObjectBegin frame so instances can re-place it.
828
- shape.relativeCTM = M.multiply( M.invert( this.objectBeginCTM ), shape.ctm );
855
+ // pbrt keeps a template shape's whole transform and puts each placement's on top of it,
856
+ // whatever the transform was at ObjectBegin (kroken defines under one and places at Identity).
829
857
  this.ir.objects.get( this.currentObject ).push( shape );
830
858
 
831
859
  } else {
@@ -880,7 +908,7 @@ export class PBRTParser {
880
908
 
881
909
  if ( ! this.instanceIncludes || this.currentObject !== null ) return null;
882
910
  if ( this.ctmEnd !== null || this.activeTransform !== BOTH || this.state.areaLight ) return null;
883
- return `${dir}\0${path}\0${this._stateId( this.state.material )}\0${this.state.reverseOrientation}`;
911
+ return `${dir}\0${path}\0${this._stateId( this.state.material )}\0${this.state.reverseOrientation}\0${this.state.interior}`;
884
912
 
885
913
  }
886
914
 
@@ -902,7 +930,8 @@ export class PBRTParser {
902
930
  attributes: this.attributeStack.length,
903
931
  transforms: this.transformStack.length,
904
932
  material: this.state.material,
905
- reverseOrientation: this.state.reverseOrientation
933
+ reverseOrientation: this.state.reverseOrientation,
934
+ interior: this.state.interior
906
935
  };
907
936
 
908
937
  }
@@ -912,7 +941,8 @@ export class PBRTParser {
912
941
  return this._effects === before.effects && this.ctmEnd === null && this.activeTransform === BOTH &&
913
942
  sameMatrix( this.ctm, before.ctm ) && this.attributeStack.length === before.attributes &&
914
943
  this.transformStack.length === before.transforms && this.state.material === before.material &&
915
- this.state.areaLight === null && this.state.reverseOrientation === before.reverseOrientation;
944
+ this.state.areaLight === null && this.state.reverseOrientation === before.reverseOrientation &&
945
+ this.state.interior === before.interior;
916
946
 
917
947
  }
918
948
 
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Scattering coefficients for pbrt's `subsurface` material: its named media and the inversion from a diffuse
3
+ * reflectance to the albedo that produces it.
4
+ */
5
+
6
+ // pbrt-v4's table (media.cpp): [ σ′s, σa ] in mm⁻¹, from Jensen et al. 2001 and Narasimhan et al. 2006.
7
+ const MEASURED = {
8
+ 'Apple': [[ 2.29, 2.39, 1.97 ], [ 0.0030, 0.0034, 0.046 ]],
9
+ 'Chicken1': [[ 0.15, 0.21, 0.38 ], [ 0.015, 0.077, 0.19 ]],
10
+ 'Chicken2': [[ 0.19, 0.25, 0.32 ], [ 0.018, 0.088, 0.20 ]],
11
+ 'Cream': [[ 7.38, 5.47, 3.15 ], [ 0.0002, 0.0028, 0.0163 ]],
12
+ 'Ketchup': [[ 0.18, 0.07, 0.03 ], [ 0.061, 0.97, 1.45 ]],
13
+ 'Marble': [[ 2.19, 2.62, 3.00 ], [ 0.0021, 0.0041, 0.0071 ]],
14
+ 'Potato': [[ 0.68, 0.70, 0.55 ], [ 0.0024, 0.0090, 0.12 ]],
15
+ 'Skimmilk': [[ 0.70, 1.22, 1.90 ], [ 0.0014, 0.0025, 0.0142 ]],
16
+ 'Skin1': [[ 0.74, 0.88, 1.01 ], [ 0.032, 0.17, 0.48 ]],
17
+ 'Skin2': [[ 1.09, 1.59, 1.79 ], [ 0.013, 0.070, 0.145 ]],
18
+ 'Spectralon': [[ 11.6, 20.4, 14.9 ], [ 0.00, 0.00, 0.00 ]],
19
+ 'Wholemilk': [[ 2.55, 3.21, 3.77 ], [ 0.0011, 0.0024, 0.014 ]],
20
+ 'Lowfat Milk': [[ 0.89187, 1.5136, 2.532 ], [ 0.002875, 0.00575, 0.0115 ]],
21
+ 'Reduced Milk': [[ 2.4858, 3.1669, 4.5214 ], [ 0.0025556, 0.0051111, 0.012778 ]],
22
+ 'Regular Milk': [[ 4.5513, 5.8294, 7.136 ], [ 0.0015333, 0.0046, 0.019933 ]],
23
+ 'Espresso': [[ 0.72378, 0.84557, 1.0247 ], [ 4.7984, 6.5751, 8.8493 ]],
24
+ 'Mint Mocha Coffee': [[ 0.31602, 0.38538, 0.48131 ], [ 3.772, 5.8228, 7.82 ]],
25
+ 'Lowfat Soy Milk': [[ 0.30576, 0.34233, 0.61664 ], [ 0.0014375, 0.0071875, 0.035937 ]],
26
+ 'Regular Soy Milk': [[ 0.59223, 0.73866, 1.4693 ], [ 0.0019167, 0.0095833, 0.065167 ]],
27
+ 'Lowfat Chocolate Milk': [[ 0.64925, 0.83916, 1.1057 ], [ 0.0115, 0.0368, 0.1564 ]],
28
+ 'Regular Chocolate Milk': [[ 1.4585, 2.1289, 2.9527 ], [ 0.010063, 0.043125, 0.14375 ]],
29
+ 'Coke': [[ 8.9053e-05, 8.372e-05, 0 ], [ 0.10014, 0.16503, 0.2468 ]],
30
+ 'Pepsi': [[ 6.1697e-05, 4.2564e-05, 0 ], [ 0.091641, 0.14158, 0.20729 ]],
31
+ 'Sprite': [[ 6.0306e-06, 6.4139e-06, 6.5504e-06 ], [ 0.001886, 0.0018308, 0.0020025 ]],
32
+ 'Gatorade': [[ 0.0024574, 0.003007, 0.0037325 ], [ 0.024794, 0.019289, 0.008878 ]],
33
+ 'Chardonnay': [[ 1.7982e-05, 1.3758e-05, 1.2023e-05 ], [ 0.010782, 0.011855, 0.023997 ]],
34
+ 'White Zinfandel': [[ 1.7501e-05, 1.9069e-05, 1.288e-05 ], [ 0.012072, 0.016184, 0.019843 ]],
35
+ 'Merlot': [[ 2.1129e-05, 0, 0 ], [ 0.11632, 0.25191, 0.29434 ]],
36
+ 'Budweiser Beer': [[ 2.4356e-05, 2.4079e-05, 1.0564e-05 ], [ 0.011492, 0.024911, 0.057786 ]],
37
+ 'Coors Light Beer': [[ 5.0922e-05, 4.301e-05, 0 ], [ 0.006164, 0.013984, 0.034983 ]],
38
+ 'Clorox': [[ 0.0024035, 0.0031373, 0.003991 ], [ 0.0033542, 0.014892, 0.026297 ]],
39
+ 'Apple Juice': [[ 0.00013612, 0.00015836, 0.000227 ], [ 0.012957, 0.023741, 0.052184 ]],
40
+ 'Cranberry Juice': [[ 0.00010402, 0.00011646, 7.8139e-05 ], [ 0.039437, 0.094223, 0.12426 ]],
41
+ 'Grape Juice': [[ 5.382e-05, 0, 0 ], [ 0.10404, 0.23958, 0.29325 ]],
42
+ 'Ruby Grapefruit Juice': [[ 0.011002, 0.010927, 0.011036 ], [ 0.085867, 0.18314, 0.25262 ]],
43
+ 'White Grapefruit Juice': [[ 0.22826, 0.23998, 0.32748 ], [ 0.0138, 0.018831, 0.056781 ]],
44
+ 'Shampoo': [[ 0.0007176, 0.0008303, 0.0009016 ], [ 0.014107, 0.045693, 0.061717 ]],
45
+ 'Strawberry Shampoo': [[ 0.00015671, 0.00015947, 1.518e-05 ], [ 0.01449, 0.05796, 0.075823 ]],
46
+ 'Head & Shoulders Shampoo': [[ 0.023805, 0.028804, 0.034306 ], [ 0.084621, 0.15688, 0.20365 ]],
47
+ 'Lemon Tea Powder': [[ 0.040224, 0.045264, 0.051081 ], [ 2.4288, 4.5757, 7.2127 ]],
48
+ 'Orange Powder': [[ 0.00015617, 0.00017482, 0.0001762 ], [ 0.001449, 0.003441, 0.007863 ]],
49
+ 'Pink Lemonade Powder': [[ 0.00012103, 0.00013073, 0.00012528 ], [ 0.001165, 0.002366, 0.003195 ]],
50
+ 'Cappuccino Powder': [[ 1.8436, 2.5851, 2.1662 ], [ 35.844, 49.547, 61.084 ]],
51
+ 'Salt Powder': [[ 0.027333, 0.032451, 0.031979 ], [ 0.28415, 0.3257, 0.34148 ]],
52
+ 'Sugar Powder': [[ 0.00022272, 0.00025513, 0.000271 ], [ 0.012638, 0.031051, 0.050124 ]],
53
+ 'Suisse Mocha Powder': [[ 2.7979, 3.5452, 4.3365 ], [ 17.502, 27.004, 35.433 ]],
54
+ 'Pacific Ocean Surface Water': [[ 0.0001764, 0.00032095, 0.00019617 ], [ 0.031845, 0.031324, 0.030147 ]],
55
+ };
56
+
57
+ /** A named medium's `{ sigmaS, sigmaA }` (σ′s with g = 0), or null. */
58
+ export function namedScattering( name ) {
59
+
60
+ const entry = MEASURED[ name ];
61
+ return entry ? { sigmaS: entry[ 0 ].slice(), sigmaA: entry[ 1 ].slice() } : null;
62
+
63
+ }
64
+
65
+ /**
66
+ * Total diffuse reflectance of a half space of reduced albedo α′ and relative index η under the classical dipole
67
+ * (Jensen et al. 2001): (α′ / 2) (1 + e^(−4/3 A √(3(1 − α′)))) e^(−√(3(1 − α′))).
68
+ */
69
+ export function dipoleReflectance( albedo, eta ) {
70
+
71
+ const fdr = - 1.440 / ( eta * eta ) + 0.710 / eta + 0.668 + 0.0636 * eta;
72
+ const A = ( 1 + fdr ) / ( 1 - fdr );
73
+ const s = Math.sqrt( 3 * ( 1 - albedo ) );
74
+ return albedo / 2 * ( 1 + Math.exp( - 4 / 3 * A * s ) ) * Math.exp( - s );
75
+
76
+ }
77
+
78
+ /** The reduced albedo whose dipole reflectance is `reflectance` (pbrt inverts its own table the same way). */
79
+ export function albedoForReflectance( reflectance, eta ) {
80
+
81
+ const target = Math.min( Math.max( reflectance, 0 ), dipoleReflectance( 1, eta ) );
82
+ let lo = 0, hi = 1;
83
+ for ( let i = 0; i < 48; i ++ ) {
84
+
85
+ const mid = ( lo + hi ) / 2;
86
+ if ( dipoleReflectance( mid, eta ) < target ) lo = mid;
87
+ else hi = mid;
88
+
89
+ }
90
+
91
+ return ( lo + hi ) / 2;
92
+
93
+ }