@plastic-software/three 0.181.2 → 0.182.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 (253) hide show
  1. package/README.md +3 -4
  2. package/build/three.cjs +1192 -522
  3. package/build/three.core.js +345 -219
  4. package/build/three.core.min.js +1 -1
  5. package/build/three.module.js +864 -328
  6. package/build/three.module.min.js +1 -1
  7. package/build/three.tsl.js +15 -3
  8. package/build/three.tsl.min.js +1 -1
  9. package/build/three.webgpu.js +3660 -1545
  10. package/build/three.webgpu.min.js +1 -1
  11. package/build/three.webgpu.nodes.js +3659 -1544
  12. package/build/three.webgpu.nodes.min.js +1 -1
  13. package/examples/jsm/controls/MapControls.js +55 -1
  14. package/examples/jsm/controls/OrbitControls.js +6 -6
  15. package/examples/jsm/controls/TrackballControls.js +6 -6
  16. package/examples/jsm/csm/CSM.js +2 -1
  17. package/examples/jsm/environments/RoomEnvironment.js +2 -0
  18. package/examples/jsm/geometries/DecalGeometry.js +1 -1
  19. package/examples/jsm/helpers/LightProbeHelperGPU.js +1 -1
  20. package/examples/jsm/helpers/TextureHelperGPU.js +1 -1
  21. package/examples/jsm/inspector/Inspector.js +53 -9
  22. package/examples/jsm/inspector/RendererInspector.js +12 -2
  23. package/examples/jsm/inspector/tabs/Console.js +2 -2
  24. package/examples/jsm/inspector/tabs/Parameters.js +2 -2
  25. package/examples/jsm/inspector/tabs/Performance.js +2 -2
  26. package/examples/jsm/inspector/tabs/Viewer.js +4 -4
  27. package/examples/jsm/inspector/ui/Profiler.js +1836 -31
  28. package/examples/jsm/inspector/ui/Style.js +948 -13
  29. package/examples/jsm/inspector/ui/Tab.js +188 -1
  30. package/examples/jsm/inspector/ui/Values.js +17 -1
  31. package/examples/jsm/loaders/3DMLoader.js +5 -4
  32. package/examples/jsm/loaders/DRACOLoader.js +5 -5
  33. package/examples/jsm/loaders/FBXLoader.js +0 -2
  34. package/examples/jsm/loaders/HDRLoader.js +0 -1
  35. package/examples/jsm/loaders/KTX2Loader.js +16 -0
  36. package/examples/jsm/loaders/LDrawLoader.js +2 -3
  37. package/examples/jsm/loaders/PCDLoader.js +1 -0
  38. package/examples/jsm/loaders/SVGLoader.js +1 -1
  39. package/examples/jsm/loaders/TDSLoader.js +0 -2
  40. package/examples/jsm/loaders/TGALoader.js +0 -2
  41. package/examples/jsm/loaders/UltraHDRLoader.js +110 -137
  42. package/examples/jsm/loaders/VOXLoader.js +660 -117
  43. package/examples/jsm/loaders/VRMLLoader.js +2 -2
  44. package/examples/jsm/loaders/usd/USDCParser.js +1 -1
  45. package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +1 -1
  46. package/examples/jsm/materials/MeshGouraudMaterial.js +0 -1
  47. package/examples/jsm/materials/WoodNodeMaterial.js +11 -11
  48. package/examples/jsm/math/Octree.js +131 -1
  49. package/examples/jsm/misc/Volume.js +0 -1
  50. package/examples/jsm/misc/VolumeSlice.js +0 -1
  51. package/examples/jsm/objects/SkyMesh.js +13 -3
  52. package/examples/jsm/physics/AmmoPhysics.js +12 -7
  53. package/examples/jsm/physics/JoltPhysics.js +3 -1
  54. package/examples/jsm/physics/RapierPhysics.js +3 -1
  55. package/examples/jsm/postprocessing/OutputPass.js +9 -0
  56. package/examples/jsm/postprocessing/RenderPass.js +10 -0
  57. package/examples/jsm/postprocessing/UnrealBloomPass.js +48 -18
  58. package/examples/jsm/renderers/Projector.js +268 -30
  59. package/examples/jsm/renderers/SVGRenderer.js +191 -58
  60. package/examples/jsm/shaders/UnpackDepthRGBAShader.js +2 -4
  61. package/examples/jsm/transpiler/AST.js +44 -0
  62. package/examples/jsm/transpiler/GLSLDecoder.js +61 -4
  63. package/examples/jsm/transpiler/ShaderToyDecoder.js +2 -0
  64. package/examples/jsm/transpiler/TSLEncoder.js +46 -3
  65. package/examples/jsm/transpiler/TranspilerUtils.js +3 -3
  66. package/examples/jsm/transpiler/WGSLEncoder.js +27 -0
  67. package/examples/jsm/tsl/display/AnaglyphPassNode.js +2 -0
  68. package/examples/jsm/tsl/display/BloomNode.js +11 -1
  69. package/examples/jsm/tsl/display/GTAONode.js +3 -2
  70. package/examples/jsm/tsl/display/PixelationPassNode.js +2 -1
  71. package/examples/jsm/tsl/display/SSGINode.js +7 -19
  72. package/examples/jsm/tsl/display/SSRNode.js +1 -1
  73. package/examples/jsm/tsl/display/SSSNode.js +4 -2
  74. package/examples/jsm/tsl/display/StereoCompositePassNode.js +8 -1
  75. package/examples/jsm/tsl/display/TRAANode.js +265 -114
  76. package/examples/jsm/tsl/display/radialBlur.js +68 -0
  77. package/examples/jsm/utils/ShadowMapViewer.js +24 -10
  78. package/examples/jsm/utils/ShadowMapViewerGPU.js +1 -1
  79. package/examples/jsm/utils/WebGPUTextureUtils.js +1 -1
  80. package/package.json +14 -12
  81. package/src/Three.Core.js +1 -0
  82. package/src/Three.TSL.js +14 -2
  83. package/src/animation/AnimationUtils.js +1 -12
  84. package/src/animation/KeyframeTrack.js +1 -1
  85. package/src/animation/tracks/BooleanKeyframeTrack.js +1 -1
  86. package/src/animation/tracks/ColorKeyframeTrack.js +1 -1
  87. package/src/animation/tracks/NumberKeyframeTrack.js +1 -1
  88. package/src/animation/tracks/QuaternionKeyframeTrack.js +1 -1
  89. package/src/animation/tracks/StringKeyframeTrack.js +1 -1
  90. package/src/animation/tracks/VectorKeyframeTrack.js +1 -1
  91. package/src/constants.js +61 -5
  92. package/src/core/BufferGeometry.js +14 -2
  93. package/src/core/Raycaster.js +2 -2
  94. package/src/extras/PMREMGenerator.js +3 -10
  95. package/src/extras/TextureUtils.js +5 -1
  96. package/src/geometries/ExtrudeGeometry.js +2 -2
  97. package/src/geometries/PolyhedronGeometry.js +1 -1
  98. package/src/helpers/PointLightHelper.js +1 -1
  99. package/src/lights/DirectionalLight.js +13 -0
  100. package/src/lights/HemisphereLight.js +10 -0
  101. package/src/lights/Light.js +1 -11
  102. package/src/lights/LightProbe.js +0 -15
  103. package/src/lights/LightShadow.js +0 -3
  104. package/src/lights/PointLight.js +15 -0
  105. package/src/lights/PointLightShadow.js +0 -86
  106. package/src/lights/SpotLight.js +22 -1
  107. package/src/loaders/MaterialLoader.js +2 -1
  108. package/src/loaders/ObjectLoader.js +3 -1
  109. package/src/loaders/nodes/NodeLoader.js +2 -2
  110. package/src/materials/Material.js +2 -0
  111. package/src/materials/ShaderMaterial.js +20 -1
  112. package/src/materials/nodes/Line2NodeMaterial.js +2 -2
  113. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +3 -2
  114. package/src/materials/nodes/MeshStandardNodeMaterial.js +5 -4
  115. package/src/materials/nodes/NodeMaterial.js +59 -3
  116. package/src/materials/nodes/manager/NodeMaterialObserver.js +1 -1
  117. package/src/math/Matrix4.js +40 -40
  118. package/src/math/Sphere.js +1 -1
  119. package/src/math/Vector3.js +0 -2
  120. package/src/nodes/TSL.js +4 -1
  121. package/src/nodes/accessors/BatchNode.js +10 -10
  122. package/src/nodes/accessors/BufferAttributeNode.js +98 -12
  123. package/src/nodes/accessors/BufferNode.js +29 -2
  124. package/src/nodes/accessors/ClippingNode.js +4 -4
  125. package/src/nodes/accessors/CubeTextureNode.js +20 -1
  126. package/src/nodes/accessors/InstanceNode.js +69 -29
  127. package/src/nodes/accessors/MaterialNode.js +9 -1
  128. package/src/nodes/accessors/MaterialReferenceNode.js +1 -2
  129. package/src/nodes/accessors/ModelNode.js +1 -1
  130. package/src/nodes/accessors/Normal.js +2 -2
  131. package/src/nodes/accessors/ReferenceBaseNode.js +4 -4
  132. package/src/nodes/accessors/ReferenceNode.js +4 -4
  133. package/src/nodes/accessors/RendererReferenceNode.js +1 -2
  134. package/src/nodes/accessors/SkinningNode.js +15 -2
  135. package/src/nodes/accessors/StorageBufferNode.js +4 -2
  136. package/src/nodes/accessors/Tangent.js +1 -11
  137. package/src/nodes/accessors/Texture3DNode.js +26 -1
  138. package/src/nodes/accessors/UniformArrayNode.js +2 -2
  139. package/src/nodes/accessors/UserDataNode.js +1 -2
  140. package/src/nodes/accessors/VertexColorNode.js +1 -2
  141. package/src/nodes/code/FunctionNode.js +1 -2
  142. package/src/nodes/core/ArrayNode.js +20 -1
  143. package/src/nodes/core/AssignNode.js +2 -2
  144. package/src/nodes/core/AttributeNode.js +2 -2
  145. package/src/nodes/core/ContextNode.js +103 -4
  146. package/src/nodes/core/NodeBuilder.js +56 -14
  147. package/src/nodes/core/NodeFrame.js +12 -4
  148. package/src/nodes/core/NodeUtils.js +5 -5
  149. package/src/nodes/core/ParameterNode.js +1 -2
  150. package/src/nodes/core/PropertyNode.js +19 -3
  151. package/src/nodes/core/StackNode.js +56 -8
  152. package/src/nodes/core/StructNode.js +1 -2
  153. package/src/nodes/core/StructTypeNode.js +11 -17
  154. package/src/nodes/core/UniformNode.js +19 -4
  155. package/src/nodes/core/VarNode.js +46 -21
  156. package/src/nodes/display/NormalMapNode.js +37 -2
  157. package/src/nodes/display/PassNode.js +77 -7
  158. package/src/nodes/display/ScreenNode.js +1 -0
  159. package/src/nodes/functions/BSDF/BRDF_GGX_Multiscatter.js +3 -3
  160. package/src/nodes/functions/BSDF/DFGLUT.js +56 -0
  161. package/src/nodes/functions/BSDF/EnvironmentBRDF.js +2 -2
  162. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +1 -1
  163. package/src/nodes/functions/PhysicalLightingModel.js +102 -43
  164. package/src/nodes/gpgpu/ComputeBuiltinNode.js +1 -2
  165. package/src/nodes/gpgpu/SubgroupFunctionNode.js +1 -1
  166. package/src/nodes/gpgpu/WorkgroupInfoNode.js +2 -3
  167. package/src/nodes/lighting/AnalyticLightNode.js +53 -0
  168. package/src/nodes/lighting/LightsNode.js +2 -2
  169. package/src/nodes/lighting/PointShadowNode.js +141 -140
  170. package/src/nodes/lighting/ShadowFilterNode.js +53 -37
  171. package/src/nodes/lighting/ShadowNode.js +53 -19
  172. package/src/nodes/math/BitcountNode.js +433 -0
  173. package/src/nodes/math/PackFloatNode.js +98 -0
  174. package/src/nodes/math/UnpackFloatNode.js +96 -0
  175. package/src/nodes/pmrem/PMREMNode.js +1 -1
  176. package/src/nodes/tsl/TSLCore.js +4 -4
  177. package/src/nodes/utils/ArrayElementNode.js +13 -0
  178. package/src/nodes/utils/EventNode.js +1 -2
  179. package/src/nodes/utils/Packing.js +13 -1
  180. package/src/nodes/utils/PostProcessingUtils.js +33 -1
  181. package/src/nodes/utils/ReflectorNode.js +1 -1
  182. package/src/nodes/utils/SampleNode.js +1 -1
  183. package/src/nodes/utils/UVUtils.js +26 -0
  184. package/src/objects/BatchedMesh.js +5 -2
  185. package/src/objects/Line.js +1 -1
  186. package/src/objects/Mesh.js +1 -1
  187. package/src/objects/Points.js +1 -1
  188. package/src/objects/Skeleton.js +9 -0
  189. package/src/renderers/WebGLRenderer.js +145 -33
  190. package/src/renderers/common/Backend.js +8 -0
  191. package/src/renderers/common/Background.js +19 -9
  192. package/src/renderers/common/Binding.js +11 -0
  193. package/src/renderers/common/Bindings.js +7 -7
  194. package/src/renderers/common/Buffer.js +40 -0
  195. package/src/renderers/common/ChainMap.js +30 -6
  196. package/src/renderers/common/Geometries.js +12 -0
  197. package/src/renderers/common/RenderContexts.js +8 -1
  198. package/src/renderers/common/RenderObject.js +14 -1
  199. package/src/renderers/common/Renderer.js +53 -35
  200. package/src/renderers/common/Textures.js +1 -1
  201. package/src/renderers/common/UniformsGroup.js +1 -0
  202. package/src/renderers/common/XRManager.js +1 -0
  203. package/src/renderers/common/extras/PMREMGenerator.js +2 -8
  204. package/src/renderers/common/nodes/NodeUniformBuffer.js +52 -0
  205. package/src/renderers/shaders/DFGLUTData.js +19 -34
  206. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +5 -2
  207. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +8 -4
  208. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +90 -51
  209. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +194 -186
  210. package/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js +1 -1
  211. package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +1 -1
  212. package/src/renderers/shaders/ShaderChunk.js +3 -3
  213. package/src/renderers/shaders/ShaderLib/depth.glsl.js +3 -0
  214. package/src/renderers/shaders/ShaderLib/{distanceRGBA.glsl.js → distance.glsl.js} +1 -2
  215. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +0 -1
  216. package/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +1 -2
  217. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +0 -1
  218. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +4 -9
  219. package/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +0 -1
  220. package/src/renderers/shaders/ShaderLib/shadow.glsl.js +0 -1
  221. package/src/renderers/shaders/ShaderLib/vsm.glsl.js +4 -6
  222. package/src/renderers/shaders/ShaderLib.js +3 -3
  223. package/src/renderers/webgl/WebGLCapabilities.js +3 -4
  224. package/src/renderers/webgl/WebGLLights.js +18 -1
  225. package/src/renderers/webgl/WebGLOutput.js +267 -0
  226. package/src/renderers/webgl/WebGLProgram.js +43 -107
  227. package/src/renderers/webgl/WebGLPrograms.js +35 -45
  228. package/src/renderers/webgl/WebGLShadowMap.js +188 -25
  229. package/src/renderers/webgl/WebGLState.js +20 -20
  230. package/src/renderers/webgl/WebGLTextures.js +89 -28
  231. package/src/renderers/webgl/WebGLUniforms.js +40 -3
  232. package/src/renderers/webgl/WebGLUtils.js +6 -2
  233. package/src/renderers/webgl-fallback/WebGLBackend.js +79 -13
  234. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +59 -7
  235. package/src/renderers/webgl-fallback/utils/WebGLState.js +18 -3
  236. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +5 -3
  237. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +9 -9
  238. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +6 -2
  239. package/src/renderers/webgpu/WebGPUBackend.js +61 -4
  240. package/src/renderers/webgpu/WebGPURenderer.js +1 -1
  241. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +65 -23
  242. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +4 -17
  243. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +354 -186
  244. package/src/renderers/webgpu/utils/WebGPUConstants.js +2 -0
  245. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +20 -7
  246. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +40 -17
  247. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +7 -7
  248. package/src/renderers/webgpu/utils/WebGPUUtils.js +7 -5
  249. package/src/textures/CubeDepthTexture.js +76 -0
  250. package/src/textures/Source.js +1 -1
  251. package/src/textures/Texture.js +1 -1
  252. package/src/utils.js +13 -1
  253. package/src/nodes/functions/BSDF/DFGApprox.js +0 -71
@@ -29,12 +29,14 @@ import {
29
29
  */
30
30
 
31
31
 
32
- // Calculating this SRGB powers is extremely slow for 4K images and can be sufficiently precalculated for a 3-4x speed boost
33
- const SRGB_TO_LINEAR = Array( 1024 )
34
- .fill( 0 )
35
- .map( ( _, value ) =>
36
- Math.pow( ( value / 255 ) * 0.9478672986 + 0.0521327014, 2.4 )
37
- );
32
+ // Pre-calculated sRGB to linear lookup table for values 0-1023
33
+ const SRGB_TO_LINEAR = new Float64Array( 1024 );
34
+ for ( let i = 0; i < 1024; i ++ ) {
35
+
36
+ // (1/255) * 0.9478672986 = 0.003717127
37
+ SRGB_TO_LINEAR[ i ] = Math.pow( i * 0.003717127 + 0.0521327014, 2.4 );
38
+
39
+ }
38
40
 
39
41
  /**
40
42
  * A loader for the Ultra HDR Image Format.
@@ -120,53 +122,69 @@ class UltraHDRLoader extends Loader {
120
122
  };
121
123
  const textDecoder = new TextDecoder();
122
124
 
123
- const data = new DataView( buffer );
125
+ const bytes = new Uint8Array( buffer );
124
126
 
125
- let byteOffset = 0;
126
127
  const sections = [];
127
128
 
128
- while ( byteOffset < data.byteLength ) {
129
+ // JPEG segment-aware scanner using length headers
130
+ let offset = 0;
129
131
 
130
- const byte = data.getUint8( byteOffset );
132
+ while ( offset < bytes.length - 1 ) {
131
133
 
132
- if ( byte === 0xff ) {
134
+ // Find marker prefix
135
+ if ( bytes[ offset ] !== 0xff ) {
133
136
 
134
- const leadingByte = data.getUint8( byteOffset + 1 );
137
+ offset ++;
138
+ continue;
135
139
 
136
- if (
137
- [
138
- /* Valid section headers */
139
- 0xd8, // SOI
140
- 0xe0, // APP0
141
- 0xe1, // APP1
142
- 0xe2, // APP2
143
- ].includes( leadingByte )
144
- ) {
140
+ }
145
141
 
146
- sections.push( {
147
- sectionType: leadingByte,
148
- section: [ byte, leadingByte ],
149
- sectionOffset: byteOffset + 2,
150
- } );
142
+ const markerType = bytes[ offset + 1 ];
151
143
 
152
- byteOffset += 2;
144
+ // SOI (0xD8) - Start of Image, no length field
145
+ if ( markerType === 0xd8 ) {
153
146
 
154
- } else {
147
+ sections.push( {
148
+ sectionType: markerType,
149
+ section: bytes.subarray( offset, offset + 2 ),
150
+ sectionOffset: offset + 2,
151
+ } );
155
152
 
156
- sections[ sections.length - 1 ].section.push( byte, leadingByte );
153
+ offset += 2;
154
+ continue;
157
155
 
158
- byteOffset += 2;
156
+ }
159
157
 
160
- }
158
+ // APP0-APP2 segments have length headers
159
+ if ( markerType === 0xe0 || markerType === 0xe1 || markerType === 0xe2 ) {
160
+
161
+ // Length is stored as big-endian 16-bit value (includes length bytes, excludes marker)
162
+ const segmentLength = ( bytes[ offset + 2 ] << 8 ) | bytes[ offset + 3 ];
163
+ const segmentEnd = offset + 2 + segmentLength;
164
+
165
+ sections.push( {
166
+ sectionType: markerType,
167
+ section: bytes.subarray( offset, segmentEnd ),
168
+ sectionOffset: offset + 2,
169
+ } );
170
+
171
+ offset = segmentEnd;
172
+ continue;
161
173
 
162
- } else {
174
+ }
163
175
 
164
- sections[ sections.length - 1 ].section.push( byte );
176
+ // Skip other markers with length fields (0xC0-0xFE range, except RST and EOI)
177
+ if ( markerType >= 0xc0 && markerType <= 0xfe && markerType !== 0xd9 && ( markerType < 0xd0 || markerType > 0xd7 ) ) {
165
178
 
166
- byteOffset ++;
179
+ const segmentLength = ( bytes[ offset + 2 ] << 8 ) | bytes[ offset + 3 ];
180
+ offset += 2 + segmentLength;
181
+ continue;
167
182
 
168
183
  }
169
184
 
185
+ // EOI (0xD9) or RST markers (0xD0-0xD7) - no length field
186
+ offset += 2;
187
+
170
188
  }
171
189
 
172
190
  let primaryImage, gainmapImage;
@@ -190,9 +208,7 @@ class UltraHDRLoader extends Loader {
190
208
 
191
209
  /* Data Sections - MPF / EXIF / ICC Profile */
192
210
 
193
- const sectionData = new DataView(
194
- new Uint8Array( section.slice( 2 ) ).buffer
195
- );
211
+ const sectionData = new DataView( section.buffer, section.byteOffset + 2, section.byteLength - 2 );
196
212
  const sectionHeader = sectionData.getUint32( 2, false );
197
213
 
198
214
  if ( sectionHeader === 0x4d504600 ) {
@@ -243,13 +259,13 @@ class UltraHDRLoader extends Loader {
243
259
  6;
244
260
 
245
261
  primaryImage = new Uint8Array(
246
- data.buffer,
262
+ buffer,
247
263
  primaryImageOffset,
248
264
  primaryImageSize
249
265
  );
250
266
 
251
267
  gainmapImage = new Uint8Array(
252
- data.buffer,
268
+ buffer,
253
269
  gainmapImageOffset,
254
270
  gainmapImageSize
255
271
  );
@@ -423,19 +439,22 @@ class UltraHDRLoader extends Loader {
423
439
 
424
440
  _srgbToLinear( value ) {
425
441
 
426
- if ( value / 255 < 0.04045 ) {
442
+ // 0.04045 * 255 = 10.31475
443
+ if ( value < 10.31475 ) {
427
444
 
428
- return ( value / 255 ) * 0.0773993808;
445
+ // (1/255) * 0.0773993808
446
+ return value * 0.000303527;
429
447
 
430
448
  }
431
449
 
432
450
  if ( value < 1024 ) {
433
451
 
434
- return SRGB_TO_LINEAR[ ~ ~ value ];
452
+ return SRGB_TO_LINEAR[ value | 0 ];
435
453
 
436
454
  }
437
455
 
438
- return Math.pow( ( value / 255 ) * 0.9478672986 + 0.0521327014, 2.4 );
456
+ // (1/255) * 0.9478672986 = 0.003717127
457
+ return Math.pow( value * 0.003717127 + 0.0521327014, 2.4 );
439
458
 
440
459
  }
441
460
 
@@ -447,46 +466,14 @@ class UltraHDRLoader extends Loader {
447
466
  onError
448
467
  ) {
449
468
 
450
- const getImageDataFromBuffer = ( buffer ) =>
451
- new Promise( ( resolve, reject ) => {
452
-
453
- const imageLoader = document.createElement( 'img' );
454
-
455
- imageLoader.onload = () => {
456
-
457
- const image = {
458
- width: imageLoader.naturalWidth,
459
- height: imageLoader.naturalHeight,
460
- source: imageLoader,
461
- };
462
-
463
- URL.revokeObjectURL( imageLoader.src );
464
-
465
- resolve( image );
469
+ const decodeImage = ( data ) => createImageBitmap( new Blob( [ data ], { type: 'image/jpeg' } ) );
466
470
 
467
- };
468
-
469
- imageLoader.onerror = () => {
470
-
471
- URL.revokeObjectURL( imageLoader.src );
472
-
473
- reject();
474
-
475
- };
476
-
477
- imageLoader.src = URL.createObjectURL(
478
- new Blob( [ buffer ], { type: 'image/jpeg' } )
479
- );
480
-
481
- } );
482
-
483
- Promise.all( [
484
- getImageDataFromBuffer( sdrBuffer ),
485
- getImageDataFromBuffer( gainmapBuffer ),
486
- ] )
471
+ Promise.all( [ decodeImage( sdrBuffer ), decodeImage( gainmapBuffer ) ] )
487
472
  .then( ( [ sdrImage, gainmapImage ] ) => {
488
473
 
489
- const sdrImageAspect = sdrImage.width / sdrImage.height;
474
+ const sdrWidth = sdrImage.width;
475
+ const sdrHeight = sdrImage.height;
476
+ const sdrImageAspect = sdrWidth / sdrHeight;
490
477
  const gainmapImageAspect = gainmapImage.width / gainmapImage.height;
491
478
 
492
479
  if ( sdrImageAspect !== gainmapImageAspect ) {
@@ -505,58 +492,42 @@ class UltraHDRLoader extends Loader {
505
492
  colorSpace: 'srgb',
506
493
  } );
507
494
 
508
- canvas.width = sdrImage.width;
509
- canvas.height = sdrImage.height;
495
+ canvas.width = sdrWidth;
496
+ canvas.height = sdrHeight;
510
497
 
511
498
  /* Use out-of-the-box interpolation of Canvas API to scale gainmap to fit the SDR resolution */
512
499
  ctx.drawImage(
513
- gainmapImage.source,
500
+ gainmapImage,
514
501
  0,
515
502
  0,
516
503
  gainmapImage.width,
517
504
  gainmapImage.height,
518
505
  0,
519
506
  0,
520
- sdrImage.width,
521
- sdrImage.height
507
+ sdrWidth,
508
+ sdrHeight
522
509
  );
523
510
  const gainmapImageData = ctx.getImageData(
524
511
  0,
525
512
  0,
526
- sdrImage.width,
527
- sdrImage.height,
513
+ sdrWidth,
514
+ sdrHeight,
528
515
  { colorSpace: 'srgb' }
529
516
  );
530
517
 
531
- ctx.drawImage( sdrImage.source, 0, 0 );
518
+ ctx.drawImage( sdrImage, 0, 0 );
532
519
  const sdrImageData = ctx.getImageData(
533
520
  0,
534
521
  0,
535
- sdrImage.width,
536
- sdrImage.height,
522
+ sdrWidth,
523
+ sdrHeight,
537
524
  { colorSpace: 'srgb' }
538
525
  );
539
526
 
540
527
  /* HDR Recovery formula - https://developer.android.com/media/platform/hdr-image-format#use_the_gain_map_to_create_adapted_HDR_rendition */
541
- let hdrBuffer;
542
-
543
- if ( this.type === HalfFloatType ) {
544
528
 
545
- hdrBuffer = new Uint16Array( sdrImageData.data.length ).fill( 23544 );
546
-
547
- } else {
548
-
549
- hdrBuffer = new Float32Array( sdrImageData.data.length ).fill( 255 );
550
-
551
- }
552
-
553
- const maxDisplayBoost = Math.sqrt(
554
- Math.pow(
555
- /* 1.8 instead of 2 near-perfectly rectifies approximations introduced by precalculated SRGB_TO_LINEAR values */
556
- 1.8,
557
- xmpMetadata.hdrCapacityMax
558
- )
559
- );
529
+ /* 1.8 instead of 2 near-perfectly rectifies approximations introduced by precalculated SRGB_TO_LINEAR values */
530
+ const maxDisplayBoost = 1.8 ** ( xmpMetadata.hdrCapacityMax * 0.5 );
560
531
  const unclampedWeightFactor =
561
532
  ( Math.log2( maxDisplayBoost ) - xmpMetadata.hdrCapacityMin ) /
562
533
  ( xmpMetadata.hdrCapacityMax - xmpMetadata.hdrCapacityMin );
@@ -564,62 +535,64 @@ class UltraHDRLoader extends Loader {
564
535
  Math.max( unclampedWeightFactor, 0.0 ),
565
536
  1.0
566
537
  );
567
- const useGammaOne = xmpMetadata.gamma === 1.0;
568
538
 
569
- for (
570
- let pixelIndex = 0;
571
- pixelIndex < sdrImageData.data.length;
572
- pixelIndex += 4
573
- ) {
539
+ const sdrData = sdrImageData.data;
540
+ const gainmapData = gainmapImageData.data;
541
+ const dataLength = sdrData.length;
542
+ const gainMapMin = xmpMetadata.gainMapMin;
543
+ const gainMapMax = xmpMetadata.gainMapMax;
544
+ const offsetSDR = xmpMetadata.offsetSDR;
545
+ const offsetHDR = xmpMetadata.offsetHDR;
546
+ const invGamma = 1.0 / xmpMetadata.gamma;
547
+ const useGammaOne = xmpMetadata.gamma === 1.0;
548
+ const isHalfFloat = this.type === HalfFloatType;
549
+ const toHalfFloat = DataUtils.toHalfFloat;
550
+ const srgbToLinear = this._srgbToLinear;
574
551
 
575
- const x = ( pixelIndex / 4 ) % sdrImage.width;
576
- const y = Math.floor( pixelIndex / 4 / sdrImage.width );
552
+ const hdrBuffer = isHalfFloat
553
+ ? new Uint16Array( dataLength ).fill( 15360 )
554
+ : new Float32Array( dataLength ).fill( 1.0 );
577
555
 
578
- for ( let channelIndex = 0; channelIndex < 3; channelIndex ++ ) {
556
+ for ( let i = 0; i < dataLength; i += 4 ) {
579
557
 
580
- const sdrValue = sdrImageData.data[ pixelIndex + channelIndex ];
558
+ for ( let c = 0; c < 3; c ++ ) {
581
559
 
582
- const gainmapIndex = ( y * sdrImage.width + x ) * 4 + channelIndex;
583
- const gainmapValue = gainmapImageData.data[ gainmapIndex ] / 255.0;
560
+ const idx = i + c;
561
+ const sdrValue = sdrData[ idx ];
562
+ const gainmapValue = gainmapData[ idx ] * 0.00392156862745098; // 1/255
584
563
 
585
- /* Gamma is 1.0 by default */
586
564
  const logRecovery = useGammaOne
587
565
  ? gainmapValue
588
- : Math.pow( gainmapValue, 1.0 / xmpMetadata.gamma );
566
+ : Math.pow( gainmapValue, invGamma );
589
567
 
590
- const logBoost =
591
- xmpMetadata.gainMapMin * ( 1.0 - logRecovery ) +
592
- xmpMetadata.gainMapMax * logRecovery;
568
+ const logBoost = gainMapMin + ( gainMapMax - gainMapMin ) * logRecovery;
593
569
 
594
570
  const hdrValue =
595
- ( sdrValue + xmpMetadata.offsetSDR ) *
571
+ ( sdrValue + offsetSDR ) *
596
572
  ( logBoost * weightFactor === 0.0
597
573
  ? 1.0
598
574
  : Math.pow( 2, logBoost * weightFactor ) ) -
599
- xmpMetadata.offsetHDR;
575
+ offsetHDR;
600
576
 
601
577
  const linearHDRValue = Math.min(
602
- Math.max( this._srgbToLinear( hdrValue ), 0 ),
578
+ Math.max( srgbToLinear( hdrValue ), 0 ),
603
579
  65504
604
580
  );
605
581
 
606
- hdrBuffer[ pixelIndex + channelIndex ] =
607
- this.type === HalfFloatType
608
- ? DataUtils.toHalfFloat( linearHDRValue )
609
- : linearHDRValue;
582
+ hdrBuffer[ idx ] = isHalfFloat
583
+ ? toHalfFloat( linearHDRValue )
584
+ : linearHDRValue;
610
585
 
611
586
  }
612
587
 
613
588
  }
614
589
 
615
- onSuccess( hdrBuffer, sdrImage.width, sdrImage.height );
590
+ onSuccess( hdrBuffer, sdrWidth, sdrHeight );
616
591
 
617
592
  } )
618
- .catch( () => {
593
+ .catch( ( e ) => {
619
594
 
620
- throw new Error(
621
- 'THREE.UltraHDRLoader Error: Could not parse UltraHDR images'
622
- );
595
+ onError( e );
623
596
 
624
597
  } );
625
598