three-gpu-pathtracer 0.0.12 → 0.0.13

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 (53) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +961 -886
  3. package/build/index.module.js +6850 -6481
  4. package/build/index.module.js.map +1 -1
  5. package/build/index.umd.cjs +6845 -6475
  6. package/build/index.umd.cjs.map +1 -1
  7. package/package.json +73 -72
  8. package/src/core/DynamicPathTracingSceneGenerator.js +119 -119
  9. package/src/core/MaterialReducer.js +256 -256
  10. package/src/core/PathTracingRenderer.js +346 -275
  11. package/src/core/PathTracingSceneGenerator.js +69 -69
  12. package/src/core/QuiltPathTracingRenderer.js +223 -0
  13. package/src/index.js +40 -39
  14. package/src/materials/AlphaDisplayMaterial.js +48 -48
  15. package/src/materials/AmbientOcclusionMaterial.js +199 -199
  16. package/src/materials/BlendMaterial.js +67 -67
  17. package/src/materials/DenoiseMaterial.js +142 -142
  18. package/src/materials/GraphMaterial.js +243 -243
  19. package/src/materials/LambertPathTracingMaterial.js +285 -285
  20. package/src/materials/MaterialBase.js +56 -56
  21. package/src/materials/PhysicalPathTracingMaterial.js +1013 -982
  22. package/src/objects/EquirectCamera.js +13 -13
  23. package/src/objects/PhysicalCamera.js +28 -28
  24. package/src/objects/PhysicalSpotLight.js +14 -14
  25. package/src/objects/ShapedAreaLight.js +12 -12
  26. package/src/shader/shaderEnvMapSampling.js +58 -58
  27. package/src/shader/shaderGGXFunctions.js +100 -100
  28. package/src/shader/shaderIridescenceFunctions.js +135 -130
  29. package/src/shader/shaderLayerTexelFetchFunctions.js +25 -25
  30. package/src/shader/shaderLightSampling.js +229 -229
  31. package/src/shader/shaderMaterialSampling.js +510 -506
  32. package/src/shader/shaderRandFunctions.js +57 -57
  33. package/src/shader/shaderSheenFunctions.js +98 -98
  34. package/src/shader/shaderSobolSampling.js +256 -256
  35. package/src/shader/shaderStructs.js +327 -325
  36. package/src/shader/shaderUtils.js +377 -361
  37. package/src/textures/GradientEquirectTexture.js +35 -35
  38. package/src/textures/ProceduralEquirectTexture.js +75 -75
  39. package/src/uniforms/AttributesTextureArray.js +35 -35
  40. package/src/uniforms/EquirectHdrInfoUniform.js +273 -259
  41. package/src/uniforms/FloatAttributeTextureArray.js +169 -169
  42. package/src/uniforms/IESProfilesTexture.js +100 -100
  43. package/src/uniforms/LightsInfoUniformStruct.js +212 -207
  44. package/src/uniforms/MaterialsTexture.js +426 -426
  45. package/src/uniforms/PhysicalCameraUniform.js +36 -36
  46. package/src/uniforms/RenderTarget2DArray.js +97 -97
  47. package/src/uniforms/utils.js +30 -30
  48. package/src/utils/BlurredEnvMapGenerator.js +116 -116
  49. package/src/utils/GeometryPreparationUtils.js +214 -214
  50. package/src/utils/IESLoader.js +325 -325
  51. package/src/utils/SobolNumberMapGenerator.js +80 -80
  52. package/src/utils/UVUnwrapper.js +101 -101
  53. package/src/workers/PathTracingSceneWorker.js +42 -42
@@ -1,426 +1,426 @@
1
- import { DataTexture, RGBAFormat, ClampToEdgeWrapping, FloatType, FrontSide, BackSide, DoubleSide } from 'three';
2
- import { reduceTexturesToUniqueSources, getTextureHash } from './utils.js';
3
-
4
- const MATERIAL_PIXELS = 45;
5
- const MATERIAL_STRIDE = MATERIAL_PIXELS * 4;
6
-
7
- const MATTE_OFFSET = 14 * 4 + 0; // s14.r
8
- const SHADOW_OFFSET = 14 * 4 + 1; // s14.g
9
-
10
- export class MaterialsTexture extends DataTexture {
11
-
12
- constructor() {
13
-
14
- super( new Float32Array( 4 ), 1, 1 );
15
-
16
- this.format = RGBAFormat;
17
- this.type = FloatType;
18
- this.wrapS = ClampToEdgeWrapping;
19
- this.wrapT = ClampToEdgeWrapping;
20
- this.generateMipmaps = false;
21
- this.threeCompatibilityTransforms = false;
22
-
23
- }
24
-
25
- setCastShadow( materialIndex, cast ) {
26
-
27
- // invert the shadow value so we default to "true" when initializing a material
28
- const array = this.image.data;
29
- const index = materialIndex * MATERIAL_STRIDE + SHADOW_OFFSET;
30
- array[ index ] = ! cast ? 1 : 0;
31
-
32
- }
33
-
34
- getCastShadow( materialIndex ) {
35
-
36
- const array = this.image.data;
37
- const index = materialIndex * MATERIAL_STRIDE + SHADOW_OFFSET;
38
- return ! Boolean( array[ index ] );
39
-
40
- }
41
-
42
- setMatte( materialIndex, matte ) {
43
-
44
- const array = this.image.data;
45
- const index = materialIndex * MATERIAL_STRIDE + MATTE_OFFSET;
46
- array[ index ] = matte ? 1 : 0;
47
-
48
- }
49
-
50
- getMatte( materialIndex ) {
51
-
52
- const array = this.image.data;
53
- const index = materialIndex * MATERIAL_STRIDE + MATTE_OFFSET;
54
- return Boolean( array[ index ] );
55
-
56
- }
57
-
58
- updateFrom( materials, textures ) {
59
-
60
- function getTexture( material, key, def = - 1 ) {
61
-
62
- if ( key in material && material[ key ] ) {
63
-
64
- const hash = getTextureHash( material[ key ] );
65
- return uniqueTextureLookup[ hash ];
66
-
67
- } else {
68
-
69
- return def;
70
-
71
- }
72
-
73
- }
74
-
75
- function getField( material, key, def ) {
76
-
77
- return key in material ? material[ key ] : def;
78
-
79
- }
80
-
81
- function getUVTransformTexture( material ) {
82
-
83
- // https://github.com/mrdoob/three.js/blob/f3a832e637c98a404c64dae8174625958455e038/src/renderers/webgl/WebGLMaterials.js#L204-L306
84
- // https://threejs.org/docs/#api/en/textures/Texture.offset
85
- // fallback order of textures to use as a common uv transform
86
- return material.map ||
87
- material.specularMap ||
88
- material.displacementMap ||
89
- material.normalMap ||
90
- material.bumpMap ||
91
- material.roughnessMap ||
92
- material.metalnessMap ||
93
- material.alphaMap ||
94
- material.emissiveMap ||
95
- material.clearcoatMap ||
96
- material.clearcoatNormalMap ||
97
- material.clearcoatRoughnessMap ||
98
- material.iridescenceMap ||
99
- material.iridescenceThicknessMap ||
100
- material.specularIntensityMap ||
101
- material.specularColorMap ||
102
- material.transmissionMap ||
103
- material.thicknessMap ||
104
- material.sheenColorMap ||
105
- material.sheenRoughnessMap ||
106
- null;
107
-
108
- }
109
-
110
- function writeTextureMatrixToArray( material, textureKey, array, offset ) {
111
-
112
- let texture;
113
- if ( threeCompatibilityTransforms ) {
114
-
115
- texture = getUVTransformTexture( material );
116
-
117
- } else {
118
-
119
- texture = material[ textureKey ] && material[ textureKey ].isTexture ? material[ textureKey ] : null;
120
-
121
- }
122
-
123
- // check if texture exists
124
- if ( texture ) {
125
-
126
- const elements = texture.matrix.elements;
127
-
128
- let i = 0;
129
-
130
- // first row
131
- array[ offset + i ++ ] = elements[ 0 ];
132
- array[ offset + i ++ ] = elements[ 3 ];
133
- array[ offset + i ++ ] = elements[ 6 ];
134
- i ++;
135
-
136
- // second row
137
- array[ offset + i ++ ] = elements[ 1 ];
138
- array[ offset + i ++ ] = elements[ 4 ];
139
- array[ offset + i ++ ] = elements[ 7 ];
140
- i ++;
141
-
142
- }
143
-
144
- return 8;
145
-
146
- }
147
-
148
- let index = 0;
149
- const pixelCount = materials.length * MATERIAL_PIXELS;
150
- const dimension = Math.ceil( Math.sqrt( pixelCount ) );
151
- const { threeCompatibilityTransforms, image } = this;
152
-
153
- // get the list of textures with unique sources
154
- const uniqueTextures = reduceTexturesToUniqueSources( textures );
155
- const uniqueTextureLookup = {};
156
- for ( let i = 0, l = uniqueTextures.length; i < l; i ++ ) {
157
-
158
- uniqueTextureLookup[ getTextureHash( uniqueTextures[ i ] ) ] = i;
159
-
160
- }
161
-
162
- if ( image.width !== dimension ) {
163
-
164
- this.dispose();
165
-
166
- image.data = new Float32Array( dimension * dimension * 4 );
167
- image.width = dimension;
168
- image.height = dimension;
169
-
170
- }
171
-
172
- const floatArray = image.data;
173
-
174
- // on some devices (Google Pixel 6) the "floatBitsToInt" function does not work correctly so we
175
- // can't encode texture ids that way.
176
- // const intArray = new Int32Array( floatArray.buffer );
177
-
178
- for ( let i = 0, l = materials.length; i < l; i ++ ) {
179
-
180
- const m = materials[ i ];
181
-
182
- // sample 0
183
- // color
184
- floatArray[ index ++ ] = m.color.r;
185
- floatArray[ index ++ ] = m.color.g;
186
- floatArray[ index ++ ] = m.color.b;
187
- floatArray[ index ++ ] = getTexture( m, 'map' );
188
-
189
- // sample 1
190
- // metalness & roughness
191
- floatArray[ index ++ ] = getField( m, 'metalness', 0.0 );
192
- floatArray[ index ++ ] = getTexture( m, 'metalnessMap' );
193
- floatArray[ index ++ ] = getField( m, 'roughness', 0.0 );
194
- floatArray[ index ++ ] = getTexture( m, 'roughnessMap' );
195
-
196
- // sample 2
197
- // transmission & emissiveIntensity
198
- // three.js assumes a default f0 of 0.04 if no ior is provided which equates to an ior of 1.5
199
- floatArray[ index ++ ] = getField( m, 'ior', 1.5 );
200
- floatArray[ index ++ ] = getField( m, 'transmission', 0.0 );
201
- floatArray[ index ++ ] = getTexture( m, 'transmissionMap' );
202
- floatArray[ index ++ ] = getField( m, 'emissiveIntensity', 0.0 );
203
-
204
- // sample 3
205
- // emission
206
- if ( 'emissive' in m ) {
207
-
208
- floatArray[ index ++ ] = m.emissive.r;
209
- floatArray[ index ++ ] = m.emissive.g;
210
- floatArray[ index ++ ] = m.emissive.b;
211
-
212
- } else {
213
-
214
- floatArray[ index ++ ] = 0.0;
215
- floatArray[ index ++ ] = 0.0;
216
- floatArray[ index ++ ] = 0.0;
217
-
218
- }
219
-
220
- floatArray[ index ++ ] = getTexture( m, 'emissiveMap' );
221
-
222
- // sample 4
223
- // normals
224
- floatArray[ index ++ ] = getTexture( m, 'normalMap' );
225
- if ( 'normalScale' in m ) {
226
-
227
- floatArray[ index ++ ] = m.normalScale.x;
228
- floatArray[ index ++ ] = m.normalScale.y;
229
-
230
- } else {
231
-
232
- floatArray[ index ++ ] = 1;
233
- floatArray[ index ++ ] = 1;
234
-
235
- }
236
-
237
- // clearcoat
238
- floatArray[ index ++ ] = getField( m, 'clearcoat', 0.0 );
239
- floatArray[ index ++ ] = getTexture( m, 'clearcoatMap' ); // sample 5
240
-
241
- floatArray[ index ++ ] = getField( m, 'clearcoatRoughness', 0.0 );
242
- floatArray[ index ++ ] = getTexture( m, 'clearcoatRoughnessMap' );
243
-
244
- floatArray[ index ++ ] = getTexture( m, 'clearcoatNormalMap' );
245
-
246
- // sample 6
247
- if ( 'clearcoatNormalScale' in m ) {
248
-
249
- floatArray[ index ++ ] = m.clearcoatNormalScale.x;
250
- floatArray[ index ++ ] = m.clearcoatNormalScale.y;
251
-
252
- } else {
253
-
254
- floatArray[ index ++ ] = 1;
255
- floatArray[ index ++ ] = 1;
256
-
257
- }
258
-
259
- index ++;
260
- index ++;
261
-
262
- // sample 7
263
- // sheen
264
- if ( 'sheenColor' in m ) {
265
-
266
- floatArray[ index ++ ] = m.sheenColor.r;
267
- floatArray[ index ++ ] = m.sheenColor.g;
268
- floatArray[ index ++ ] = m.sheenColor.b;
269
-
270
- } else {
271
-
272
- floatArray[ index ++ ] = 0.0;
273
- floatArray[ index ++ ] = 0.0;
274
- floatArray[ index ++ ] = 0.0;
275
-
276
- }
277
-
278
- floatArray[ index ++ ] = getTexture( m, 'sheenColorMap' );
279
-
280
- // sample 8
281
- floatArray[ index ++ ] = getField( m, 'sheenRoughness', 0.0 );
282
- floatArray[ index ++ ] = getTexture( m, 'sheenRoughnessMap' );
283
-
284
- // iridescence
285
- floatArray[ index ++ ] = getTexture( m, 'iridescenceMap' );
286
- floatArray[ index ++ ] = getTexture( m, 'iridescenceThicknessMap' );
287
-
288
- floatArray[ index ++ ] = getField( m, 'iridescence', 0.0 ); // sample 9
289
- floatArray[ index ++ ] = getField( m, 'iridescenceIOR', 1.3 );
290
-
291
- const iridescenceThicknessRange = getField( m, 'iridescenceThicknessRange', [ 100, 400 ] );
292
- floatArray[ index ++ ] = iridescenceThicknessRange[ 0 ];
293
- floatArray[ index ++ ] = iridescenceThicknessRange[ 1 ];
294
-
295
- // sample 10
296
- // specular color
297
- if ( 'specularColor' in m ) {
298
-
299
- floatArray[ index ++ ] = m.specularColor.r;
300
- floatArray[ index ++ ] = m.specularColor.g;
301
- floatArray[ index ++ ] = m.specularColor.b;
302
-
303
- } else {
304
-
305
- floatArray[ index ++ ] = 1.0;
306
- floatArray[ index ++ ] = 1.0;
307
- floatArray[ index ++ ] = 1.0;
308
-
309
- }
310
-
311
- floatArray[ index ++ ] = getTexture( m, 'specularColorMap' );
312
-
313
- // sample 11
314
- // specular intensity
315
- floatArray[ index ++ ] = getField( m, 'specularIntensity', 1.0 );
316
- floatArray[ index ++ ] = getTexture( m, 'specularIntensityMap' );
317
-
318
- // isThinFilm
319
- const isThinFilm = getField( m, 'thickness', 0.0 ) === 0.0 && getField( m, 'attenuationDistance', Infinity ) === Infinity;
320
- floatArray[ index ++ ] = Number( isThinFilm );
321
- index ++;
322
-
323
- // sample 12
324
- if ( 'attenuationColor' in m ) {
325
-
326
- floatArray[ index ++ ] = m.attenuationColor.r;
327
- floatArray[ index ++ ] = m.attenuationColor.g;
328
- floatArray[ index ++ ] = m.attenuationColor.b;
329
-
330
- } else {
331
-
332
- floatArray[ index ++ ] = 1.0;
333
- floatArray[ index ++ ] = 1.0;
334
- floatArray[ index ++ ] = 1.0;
335
-
336
- }
337
-
338
- floatArray[ index ++ ] = getField( m, 'attenuationDistance', Infinity );
339
-
340
- // sample 13
341
- // alphaMap
342
- floatArray[ index ++ ] = getTexture( m, 'alphaMap' );
343
-
344
- // side & matte
345
- floatArray[ index ++ ] = m.opacity;
346
- floatArray[ index ++ ] = m.alphaTest;
347
- if ( ! isThinFilm && m.transmission > 0.0 ) {
348
-
349
- floatArray[ index ++ ] = 0;
350
-
351
- } else {
352
-
353
- switch ( m.side ) {
354
-
355
- case FrontSide:
356
- floatArray[ index ++ ] = 1;
357
- break;
358
- case BackSide:
359
- floatArray[ index ++ ] = - 1;
360
- break;
361
- case DoubleSide:
362
- floatArray[ index ++ ] = 0;
363
- break;
364
-
365
- }
366
-
367
- }
368
-
369
- // sample 14
370
- index ++; // matte
371
- index ++; // shadow
372
- floatArray[ index ++ ] = Number( m.vertexColors ) | ( Number( m.flatShading ) << 1 ); // vertexColors & flatShading
373
- floatArray[ index ++ ] = Number( m.transparent ); // transparent
374
-
375
- // map transform 15
376
- index += writeTextureMatrixToArray( m, 'map', floatArray, index );
377
-
378
- // metalnessMap transform 17
379
- index += writeTextureMatrixToArray( m, 'metalnessMap', floatArray, index );
380
-
381
- // roughnessMap transform 19
382
- index += writeTextureMatrixToArray( m, 'roughnessMap', floatArray, index );
383
-
384
- // transmissionMap transform 21
385
- index += writeTextureMatrixToArray( m, 'transmissionMap', floatArray, index );
386
-
387
- // emissiveMap transform 22
388
- index += writeTextureMatrixToArray( m, 'emissiveMap', floatArray, index );
389
-
390
- // normalMap transform 25
391
- index += writeTextureMatrixToArray( m, 'normalMap', floatArray, index );
392
-
393
- // clearcoatMap transform 27
394
- index += writeTextureMatrixToArray( m, 'clearcoatMap', floatArray, index );
395
-
396
- // clearcoatNormalMap transform 29
397
- index += writeTextureMatrixToArray( m, 'clearcoatNormalMap', floatArray, index );
398
-
399
- // clearcoatRoughnessMap transform 31
400
- index += writeTextureMatrixToArray( m, 'clearcoatRoughnessMap', floatArray, index );
401
-
402
- // sheenColorMap transform 33
403
- index += writeTextureMatrixToArray( m, 'sheenColorMap', floatArray, index );
404
-
405
- // sheenRoughnessMap transform 35
406
- index += writeTextureMatrixToArray( m, 'sheenRoughnessMap', floatArray, index );
407
-
408
- // iridescenceMap transform 37
409
- index += writeTextureMatrixToArray( m, 'iridescenceMap', floatArray, index );
410
-
411
- // iridescenceThicknessMap transform 39
412
- index += writeTextureMatrixToArray( m, 'iridescenceThicknessMap', floatArray, index );
413
-
414
- // specularColorMap transform 41
415
- index += writeTextureMatrixToArray( m, 'specularColorMap', floatArray, index );
416
-
417
- // specularIntensityMap transform 43
418
- index += writeTextureMatrixToArray( m, 'specularIntensityMap', floatArray, index );
419
-
420
- }
421
-
422
- this.needsUpdate = true;
423
-
424
- }
425
-
426
- }
1
+ import { DataTexture, RGBAFormat, ClampToEdgeWrapping, FloatType, FrontSide, BackSide, DoubleSide } from 'three';
2
+ import { reduceTexturesToUniqueSources, getTextureHash } from './utils.js';
3
+
4
+ const MATERIAL_PIXELS = 45;
5
+ const MATERIAL_STRIDE = MATERIAL_PIXELS * 4;
6
+
7
+ const MATTE_OFFSET = 14 * 4 + 0; // s14.r
8
+ const SHADOW_OFFSET = 14 * 4 + 1; // s14.g
9
+
10
+ export class MaterialsTexture extends DataTexture {
11
+
12
+ constructor() {
13
+
14
+ super( new Float32Array( 4 ), 1, 1 );
15
+
16
+ this.format = RGBAFormat;
17
+ this.type = FloatType;
18
+ this.wrapS = ClampToEdgeWrapping;
19
+ this.wrapT = ClampToEdgeWrapping;
20
+ this.generateMipmaps = false;
21
+ this.threeCompatibilityTransforms = false;
22
+
23
+ }
24
+
25
+ setCastShadow( materialIndex, cast ) {
26
+
27
+ // invert the shadow value so we default to "true" when initializing a material
28
+ const array = this.image.data;
29
+ const index = materialIndex * MATERIAL_STRIDE + SHADOW_OFFSET;
30
+ array[ index ] = ! cast ? 1 : 0;
31
+
32
+ }
33
+
34
+ getCastShadow( materialIndex ) {
35
+
36
+ const array = this.image.data;
37
+ const index = materialIndex * MATERIAL_STRIDE + SHADOW_OFFSET;
38
+ return ! Boolean( array[ index ] );
39
+
40
+ }
41
+
42
+ setMatte( materialIndex, matte ) {
43
+
44
+ const array = this.image.data;
45
+ const index = materialIndex * MATERIAL_STRIDE + MATTE_OFFSET;
46
+ array[ index ] = matte ? 1 : 0;
47
+
48
+ }
49
+
50
+ getMatte( materialIndex ) {
51
+
52
+ const array = this.image.data;
53
+ const index = materialIndex * MATERIAL_STRIDE + MATTE_OFFSET;
54
+ return Boolean( array[ index ] );
55
+
56
+ }
57
+
58
+ updateFrom( materials, textures ) {
59
+
60
+ function getTexture( material, key, def = - 1 ) {
61
+
62
+ if ( key in material && material[ key ] ) {
63
+
64
+ const hash = getTextureHash( material[ key ] );
65
+ return uniqueTextureLookup[ hash ];
66
+
67
+ } else {
68
+
69
+ return def;
70
+
71
+ }
72
+
73
+ }
74
+
75
+ function getField( material, key, def ) {
76
+
77
+ return key in material ? material[ key ] : def;
78
+
79
+ }
80
+
81
+ function getUVTransformTexture( material ) {
82
+
83
+ // https://github.com/mrdoob/three.js/blob/f3a832e637c98a404c64dae8174625958455e038/src/renderers/webgl/WebGLMaterials.js#L204-L306
84
+ // https://threejs.org/docs/#api/en/textures/Texture.offset
85
+ // fallback order of textures to use as a common uv transform
86
+ return material.map ||
87
+ material.specularMap ||
88
+ material.displacementMap ||
89
+ material.normalMap ||
90
+ material.bumpMap ||
91
+ material.roughnessMap ||
92
+ material.metalnessMap ||
93
+ material.alphaMap ||
94
+ material.emissiveMap ||
95
+ material.clearcoatMap ||
96
+ material.clearcoatNormalMap ||
97
+ material.clearcoatRoughnessMap ||
98
+ material.iridescenceMap ||
99
+ material.iridescenceThicknessMap ||
100
+ material.specularIntensityMap ||
101
+ material.specularColorMap ||
102
+ material.transmissionMap ||
103
+ material.thicknessMap ||
104
+ material.sheenColorMap ||
105
+ material.sheenRoughnessMap ||
106
+ null;
107
+
108
+ }
109
+
110
+ function writeTextureMatrixToArray( material, textureKey, array, offset ) {
111
+
112
+ let texture;
113
+ if ( threeCompatibilityTransforms ) {
114
+
115
+ texture = getUVTransformTexture( material );
116
+
117
+ } else {
118
+
119
+ texture = material[ textureKey ] && material[ textureKey ].isTexture ? material[ textureKey ] : null;
120
+
121
+ }
122
+
123
+ // check if texture exists
124
+ if ( texture ) {
125
+
126
+ const elements = texture.matrix.elements;
127
+
128
+ let i = 0;
129
+
130
+ // first row
131
+ array[ offset + i ++ ] = elements[ 0 ];
132
+ array[ offset + i ++ ] = elements[ 3 ];
133
+ array[ offset + i ++ ] = elements[ 6 ];
134
+ i ++;
135
+
136
+ // second row
137
+ array[ offset + i ++ ] = elements[ 1 ];
138
+ array[ offset + i ++ ] = elements[ 4 ];
139
+ array[ offset + i ++ ] = elements[ 7 ];
140
+ i ++;
141
+
142
+ }
143
+
144
+ return 8;
145
+
146
+ }
147
+
148
+ let index = 0;
149
+ const pixelCount = materials.length * MATERIAL_PIXELS;
150
+ const dimension = Math.ceil( Math.sqrt( pixelCount ) );
151
+ const { threeCompatibilityTransforms, image } = this;
152
+
153
+ // get the list of textures with unique sources
154
+ const uniqueTextures = reduceTexturesToUniqueSources( textures );
155
+ const uniqueTextureLookup = {};
156
+ for ( let i = 0, l = uniqueTextures.length; i < l; i ++ ) {
157
+
158
+ uniqueTextureLookup[ getTextureHash( uniqueTextures[ i ] ) ] = i;
159
+
160
+ }
161
+
162
+ if ( image.width !== dimension ) {
163
+
164
+ this.dispose();
165
+
166
+ image.data = new Float32Array( dimension * dimension * 4 );
167
+ image.width = dimension;
168
+ image.height = dimension;
169
+
170
+ }
171
+
172
+ const floatArray = image.data;
173
+
174
+ // on some devices (Google Pixel 6) the "floatBitsToInt" function does not work correctly so we
175
+ // can't encode texture ids that way.
176
+ // const intArray = new Int32Array( floatArray.buffer );
177
+
178
+ for ( let i = 0, l = materials.length; i < l; i ++ ) {
179
+
180
+ const m = materials[ i ];
181
+
182
+ // sample 0
183
+ // color
184
+ floatArray[ index ++ ] = m.color.r;
185
+ floatArray[ index ++ ] = m.color.g;
186
+ floatArray[ index ++ ] = m.color.b;
187
+ floatArray[ index ++ ] = getTexture( m, 'map' );
188
+
189
+ // sample 1
190
+ // metalness & roughness
191
+ floatArray[ index ++ ] = getField( m, 'metalness', 0.0 );
192
+ floatArray[ index ++ ] = getTexture( m, 'metalnessMap' );
193
+ floatArray[ index ++ ] = getField( m, 'roughness', 0.0 );
194
+ floatArray[ index ++ ] = getTexture( m, 'roughnessMap' );
195
+
196
+ // sample 2
197
+ // transmission & emissiveIntensity
198
+ // three.js assumes a default f0 of 0.04 if no ior is provided which equates to an ior of 1.5
199
+ floatArray[ index ++ ] = getField( m, 'ior', 1.5 );
200
+ floatArray[ index ++ ] = getField( m, 'transmission', 0.0 );
201
+ floatArray[ index ++ ] = getTexture( m, 'transmissionMap' );
202
+ floatArray[ index ++ ] = getField( m, 'emissiveIntensity', 0.0 );
203
+
204
+ // sample 3
205
+ // emission
206
+ if ( 'emissive' in m ) {
207
+
208
+ floatArray[ index ++ ] = m.emissive.r;
209
+ floatArray[ index ++ ] = m.emissive.g;
210
+ floatArray[ index ++ ] = m.emissive.b;
211
+
212
+ } else {
213
+
214
+ floatArray[ index ++ ] = 0.0;
215
+ floatArray[ index ++ ] = 0.0;
216
+ floatArray[ index ++ ] = 0.0;
217
+
218
+ }
219
+
220
+ floatArray[ index ++ ] = getTexture( m, 'emissiveMap' );
221
+
222
+ // sample 4
223
+ // normals
224
+ floatArray[ index ++ ] = getTexture( m, 'normalMap' );
225
+ if ( 'normalScale' in m ) {
226
+
227
+ floatArray[ index ++ ] = m.normalScale.x;
228
+ floatArray[ index ++ ] = m.normalScale.y;
229
+
230
+ } else {
231
+
232
+ floatArray[ index ++ ] = 1;
233
+ floatArray[ index ++ ] = 1;
234
+
235
+ }
236
+
237
+ // clearcoat
238
+ floatArray[ index ++ ] = getField( m, 'clearcoat', 0.0 );
239
+ floatArray[ index ++ ] = getTexture( m, 'clearcoatMap' ); // sample 5
240
+
241
+ floatArray[ index ++ ] = getField( m, 'clearcoatRoughness', 0.0 );
242
+ floatArray[ index ++ ] = getTexture( m, 'clearcoatRoughnessMap' );
243
+
244
+ floatArray[ index ++ ] = getTexture( m, 'clearcoatNormalMap' );
245
+
246
+ // sample 6
247
+ if ( 'clearcoatNormalScale' in m ) {
248
+
249
+ floatArray[ index ++ ] = m.clearcoatNormalScale.x;
250
+ floatArray[ index ++ ] = m.clearcoatNormalScale.y;
251
+
252
+ } else {
253
+
254
+ floatArray[ index ++ ] = 1;
255
+ floatArray[ index ++ ] = 1;
256
+
257
+ }
258
+
259
+ index ++;
260
+ floatArray[ index ++ ] = getField( m, 'sheen', 0.0 );
261
+
262
+ // sample 7
263
+ // sheen
264
+ if ( 'sheenColor' in m ) {
265
+
266
+ floatArray[ index ++ ] = m.sheenColor.r;
267
+ floatArray[ index ++ ] = m.sheenColor.g;
268
+ floatArray[ index ++ ] = m.sheenColor.b;
269
+
270
+ } else {
271
+
272
+ floatArray[ index ++ ] = 0.0;
273
+ floatArray[ index ++ ] = 0.0;
274
+ floatArray[ index ++ ] = 0.0;
275
+
276
+ }
277
+
278
+ floatArray[ index ++ ] = getTexture( m, 'sheenColorMap' );
279
+
280
+ // sample 8
281
+ floatArray[ index ++ ] = getField( m, 'sheenRoughness', 0.0 );
282
+ floatArray[ index ++ ] = getTexture( m, 'sheenRoughnessMap' );
283
+
284
+ // iridescence
285
+ floatArray[ index ++ ] = getTexture( m, 'iridescenceMap' );
286
+ floatArray[ index ++ ] = getTexture( m, 'iridescenceThicknessMap' );
287
+
288
+ floatArray[ index ++ ] = getField( m, 'iridescence', 0.0 ); // sample 9
289
+ floatArray[ index ++ ] = getField( m, 'iridescenceIOR', 1.3 );
290
+
291
+ const iridescenceThicknessRange = getField( m, 'iridescenceThicknessRange', [ 100, 400 ] );
292
+ floatArray[ index ++ ] = iridescenceThicknessRange[ 0 ];
293
+ floatArray[ index ++ ] = iridescenceThicknessRange[ 1 ];
294
+
295
+ // sample 10
296
+ // specular color
297
+ if ( 'specularColor' in m ) {
298
+
299
+ floatArray[ index ++ ] = m.specularColor.r;
300
+ floatArray[ index ++ ] = m.specularColor.g;
301
+ floatArray[ index ++ ] = m.specularColor.b;
302
+
303
+ } else {
304
+
305
+ floatArray[ index ++ ] = 1.0;
306
+ floatArray[ index ++ ] = 1.0;
307
+ floatArray[ index ++ ] = 1.0;
308
+
309
+ }
310
+
311
+ floatArray[ index ++ ] = getTexture( m, 'specularColorMap' );
312
+
313
+ // sample 11
314
+ // specular intensity
315
+ floatArray[ index ++ ] = getField( m, 'specularIntensity', 1.0 );
316
+ floatArray[ index ++ ] = getTexture( m, 'specularIntensityMap' );
317
+
318
+ // isThinFilm
319
+ const isThinFilm = getField( m, 'thickness', 0.0 ) === 0.0 && getField( m, 'attenuationDistance', Infinity ) === Infinity;
320
+ floatArray[ index ++ ] = Number( isThinFilm );
321
+ index ++;
322
+
323
+ // sample 12
324
+ if ( 'attenuationColor' in m ) {
325
+
326
+ floatArray[ index ++ ] = m.attenuationColor.r;
327
+ floatArray[ index ++ ] = m.attenuationColor.g;
328
+ floatArray[ index ++ ] = m.attenuationColor.b;
329
+
330
+ } else {
331
+
332
+ floatArray[ index ++ ] = 1.0;
333
+ floatArray[ index ++ ] = 1.0;
334
+ floatArray[ index ++ ] = 1.0;
335
+
336
+ }
337
+
338
+ floatArray[ index ++ ] = getField( m, 'attenuationDistance', Infinity );
339
+
340
+ // sample 13
341
+ // alphaMap
342
+ floatArray[ index ++ ] = getTexture( m, 'alphaMap' );
343
+
344
+ // side & matte
345
+ floatArray[ index ++ ] = m.opacity;
346
+ floatArray[ index ++ ] = m.alphaTest;
347
+ if ( ! isThinFilm && m.transmission > 0.0 ) {
348
+
349
+ floatArray[ index ++ ] = 0;
350
+
351
+ } else {
352
+
353
+ switch ( m.side ) {
354
+
355
+ case FrontSide:
356
+ floatArray[ index ++ ] = 1;
357
+ break;
358
+ case BackSide:
359
+ floatArray[ index ++ ] = - 1;
360
+ break;
361
+ case DoubleSide:
362
+ floatArray[ index ++ ] = 0;
363
+ break;
364
+
365
+ }
366
+
367
+ }
368
+
369
+ // sample 14
370
+ index ++; // matte
371
+ index ++; // shadow
372
+ floatArray[ index ++ ] = Number( m.vertexColors ) | ( Number( m.flatShading ) << 1 ); // vertexColors & flatShading
373
+ floatArray[ index ++ ] = Number( m.transparent ); // transparent
374
+
375
+ // map transform 15
376
+ index += writeTextureMatrixToArray( m, 'map', floatArray, index );
377
+
378
+ // metalnessMap transform 17
379
+ index += writeTextureMatrixToArray( m, 'metalnessMap', floatArray, index );
380
+
381
+ // roughnessMap transform 19
382
+ index += writeTextureMatrixToArray( m, 'roughnessMap', floatArray, index );
383
+
384
+ // transmissionMap transform 21
385
+ index += writeTextureMatrixToArray( m, 'transmissionMap', floatArray, index );
386
+
387
+ // emissiveMap transform 22
388
+ index += writeTextureMatrixToArray( m, 'emissiveMap', floatArray, index );
389
+
390
+ // normalMap transform 25
391
+ index += writeTextureMatrixToArray( m, 'normalMap', floatArray, index );
392
+
393
+ // clearcoatMap transform 27
394
+ index += writeTextureMatrixToArray( m, 'clearcoatMap', floatArray, index );
395
+
396
+ // clearcoatNormalMap transform 29
397
+ index += writeTextureMatrixToArray( m, 'clearcoatNormalMap', floatArray, index );
398
+
399
+ // clearcoatRoughnessMap transform 31
400
+ index += writeTextureMatrixToArray( m, 'clearcoatRoughnessMap', floatArray, index );
401
+
402
+ // sheenColorMap transform 33
403
+ index += writeTextureMatrixToArray( m, 'sheenColorMap', floatArray, index );
404
+
405
+ // sheenRoughnessMap transform 35
406
+ index += writeTextureMatrixToArray( m, 'sheenRoughnessMap', floatArray, index );
407
+
408
+ // iridescenceMap transform 37
409
+ index += writeTextureMatrixToArray( m, 'iridescenceMap', floatArray, index );
410
+
411
+ // iridescenceThicknessMap transform 39
412
+ index += writeTextureMatrixToArray( m, 'iridescenceThicknessMap', floatArray, index );
413
+
414
+ // specularColorMap transform 41
415
+ index += writeTextureMatrixToArray( m, 'specularColorMap', floatArray, index );
416
+
417
+ // specularIntensityMap transform 43
418
+ index += writeTextureMatrixToArray( m, 'specularIntensityMap', floatArray, index );
419
+
420
+ }
421
+
422
+ this.needsUpdate = true;
423
+
424
+ }
425
+
426
+ }