three-gpu-pathtracer 0.0.20 → 0.0.21

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 (75) hide show
  1. package/README.md +111 -464
  2. package/build/index.module.js +5691 -5312
  3. package/build/index.module.js.map +1 -1
  4. package/build/index.umd.cjs +5369 -5003
  5. package/build/index.umd.cjs.map +1 -1
  6. package/package.json +12 -6
  7. package/src/core/PathTracingRenderer.js +59 -46
  8. package/src/core/PathTracingSceneGenerator.js +245 -10
  9. package/src/core/WebGLPathTracer.js +472 -0
  10. package/src/core/utils/BakedGeometry.js +35 -0
  11. package/src/core/utils/BufferAttributeUtils.js +64 -0
  12. package/src/{utils → core/utils}/GeometryPreparationUtils.js +35 -35
  13. package/src/core/utils/MeshDiff.js +102 -0
  14. package/src/core/utils/StaticGeometryGenerator.js +285 -0
  15. package/src/core/utils/convertToStaticGeometry.js +344 -0
  16. package/src/core/utils/mergeGeometries.js +218 -0
  17. package/src/core/utils/sceneUpdateUtils.js +96 -0
  18. package/src/index.d.ts +274 -0
  19. package/src/index.js +4 -20
  20. package/src/materials/MaterialBase.js +4 -0
  21. package/src/materials/fullscreen/ClampedInterpolationMaterial.js +112 -0
  22. package/src/materials/fullscreen/DenoiseMaterial.js +4 -0
  23. package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +73 -76
  24. package/src/materials/pathtracing/glsl/{attenuateHit.glsl.js → attenuate_hit_function.glsl.js} +1 -1
  25. package/src/materials/pathtracing/glsl/{cameraUtils.glsl.js → camera_util_functions.glsl.js} +1 -1
  26. package/src/materials/pathtracing/glsl/{directLightContribution.glsl.js → direct_light_contribution_function.glsl.js} +1 -1
  27. package/src/materials/pathtracing/glsl/{getSurfaceRecord.glsl.js → get_surface_record_function.glsl.js} +1 -1
  28. package/src/materials/pathtracing/glsl/index.js +6 -0
  29. package/src/materials/pathtracing/glsl/{renderStructs.glsl.js → render_structs.glsl.js} +1 -1
  30. package/src/materials/pathtracing/glsl/{traceScene.glsl.js → trace_scene_function.glsl.js} +1 -3
  31. package/src/materials/surface/AmbientOcclusionMaterial.js +8 -8
  32. package/src/objects/PhysicalSpotLight.js +2 -2
  33. package/src/shader/bsdf/{bsdfSampling.glsl.js → bsdf_functions.glsl.js} +19 -72
  34. package/src/shader/bsdf/{fog.glsl.js → fog_functions.glsl.js} +1 -1
  35. package/src/shader/bsdf/{ggx.glsl.js → ggx_functions.glsl.js} +1 -1
  36. package/src/shader/bsdf/index.js +5 -0
  37. package/src/shader/bsdf/{iridescence.glsl.js → iridescence_functions.glsl.js} +1 -1
  38. package/src/shader/bsdf/{sheen.glsl.js → sheen_functions.glsl.js} +1 -1
  39. package/src/shader/bvh/index.js +2 -0
  40. package/src/shader/{structs/fogMaterialBvh.glsl.js → bvh/inside_fog_volume_function.glsl.js} +1 -1
  41. package/src/shader/{common/bvhAnyHit.glsl.js → bvh/ray_any_hit_function.glsl.js} +1 -1
  42. package/src/shader/common/{fresnel.glsl.js → fresnel_functions.glsl.js} +1 -1
  43. package/src/shader/common/index.js +5 -0
  44. package/src/shader/common/{math.glsl.js → math_functions.glsl.js} +1 -1
  45. package/src/shader/common/{intersectShapes.glsl.js → shape_intersection_functions.glsl.js} +1 -1
  46. package/src/shader/common/{arraySamplerTexelFetch.glsl.js → texture_sample_functions.glsl.js} +1 -1
  47. package/src/shader/common/{utils.glsl.js → util_functions.glsl.js} +1 -1
  48. package/src/shader/rand/index.js +3 -0
  49. package/src/shader/rand/pcg.glsl.js +1 -1
  50. package/src/shader/rand/sobol.glsl.js +4 -4
  51. package/src/shader/rand/{stratifiedTexture.glsl.js → stratified.glsl.js} +7 -2
  52. package/src/shader/sampling/{equirectSampling.glsl.js → equirect_sampling_functions.glsl.js} +1 -2
  53. package/src/shader/sampling/index.js +3 -0
  54. package/src/shader/sampling/{lightSampling.glsl.js → light_sampling_functions.glsl.js} +3 -3
  55. package/src/shader/sampling/{shapeSampling.glsl.js → shape_sampling_functions.glsl.js} +1 -1
  56. package/src/shader/structs/{cameraStruct.glsl.js → camera_struct.glsl.js} +1 -1
  57. package/src/shader/structs/{equirectStruct.glsl.js → equirect_struct.glsl.js} +1 -1
  58. package/src/shader/structs/index.js +5 -0
  59. package/src/shader/structs/{lightsStruct.glsl.js → lights_struct.glsl.js} +1 -1
  60. package/src/shader/structs/{materialStruct.glsl.js → material_struct.glsl.js} +2 -2
  61. package/src/shader/structs/surface_record_struct.glsl.js +63 -0
  62. package/src/uniforms/EquirectHdrInfoUniform.js +16 -11
  63. package/src/uniforms/LightsInfoUniformStruct.js +21 -10
  64. package/src/uniforms/MaterialsTexture.js +27 -86
  65. package/src/uniforms/RenderTarget2DArray.js +60 -20
  66. package/src/utils/BlurredEnvMapGenerator.js +12 -5
  67. package/src/utils/SobolNumberMapGenerator.js +3 -3
  68. package/src/utils/bufferToHash.js +22 -0
  69. package/src/core/DynamicPathTracingSceneGenerator.js +0 -164
  70. package/src/core/MaterialReducer.js +0 -256
  71. package/src/materials/pathtracing/LambertPathTracingMaterial.js +0 -297
  72. package/src/uniforms/IESProfilesTexture.js +0 -100
  73. package/src/uniforms/utils.js +0 -30
  74. package/src/utils/IESLoader.js +0 -327
  75. package/src/workers/PathTracingSceneWorker.js +0 -52
@@ -1,4 +1,4 @@
1
- export const bvhAnyHitGLSL = /* glsl */`
1
+ export const ray_any_hit_function = /* glsl */`
2
2
 
3
3
  bool bvhIntersectAnyHit(
4
4
  vec3 rayOrigin, vec3 rayDirection,
@@ -1,4 +1,4 @@
1
- export const fresnelGLSL = /* glsl */`
1
+ export const fresnel_functions = /* glsl */`
2
2
 
3
3
  bool totalInternalReflection( float cosTheta, float eta ) {
4
4
 
@@ -0,0 +1,5 @@
1
+ export * from './fresnel_functions.glsl.js';
2
+ export * from './math_functions.glsl.js';
3
+ export * from './shape_intersection_functions.glsl.js';
4
+ export * from './texture_sample_functions.glsl.js';
5
+ export * from './util_functions.glsl.js';
@@ -1,4 +1,4 @@
1
- export const mathGLSL = /* glsl */`
1
+ export const math_functions = /* glsl */`
2
2
 
3
3
  // Fast arccos approximation used to remove banding artifacts caused by numerical errors in acos.
4
4
  // This is a cubic Lagrange interpolating polynomial for x = [-1, -1/2, 0, 1/2, 1].
@@ -1,4 +1,4 @@
1
- export const intersectShapesGLSL = /* glsl */`
1
+ export const shape_intersection_functions = /* glsl */`
2
2
 
3
3
  // Finds the point where the ray intersects the plane defined by u and v and checks if this point
4
4
  // falls in the bounds of the rectangle on that same plane.
@@ -1,5 +1,5 @@
1
1
 
2
- export const arraySamplerTexelFetchGLSL = /*glsl */`
2
+ export const texture_sample_functions = /*glsl */`
3
3
 
4
4
  // add texel fetch functions for texture arrays
5
5
  vec4 texelFetch1D( sampler2DArray tex, int layer, uint index ) {
@@ -1,4 +1,4 @@
1
- export const utilsGLSL = /* glsl */`
1
+ export const util_functions = /* glsl */`
2
2
 
3
3
  // TODO: possibly this should be renamed something related to material or path tracing logic
4
4
 
@@ -0,0 +1,3 @@
1
+ export * from './pcg.glsl.js';
2
+ export * from './sobol.glsl.js';
3
+ export * from './stratified.glsl.js';
@@ -1,4 +1,4 @@
1
- export const pcgGLSL = /* glsl */`
1
+ export const pcg_functions = /* glsl */`
2
2
 
3
3
  // https://www.shadertoy.com/view/wltcRS
4
4
  uvec4 WHITE_NOISE_SEED;
@@ -105,7 +105,7 @@ function generateSobolSampleFunctions( dim = 1 ) {
105
105
 
106
106
  }
107
107
 
108
- export const sobolCommonGLSL = /* glsl */`
108
+ export const sobol_common = /* glsl */`
109
109
 
110
110
  // Utils
111
111
  const float SOBOL_FACTOR = 1.0 / 16777216.0;
@@ -130,7 +130,7 @@ export const sobolCommonGLSL = /* glsl */`
130
130
 
131
131
  `;
132
132
 
133
- export const sobolGenerationGLSL = /* glsl */`
133
+ export const sobol_point_generation = /* glsl */`
134
134
 
135
135
  const uint SOBOL_DIRECTIONS_1[ 32 ] = uint[ 32 ](
136
136
  0x80000000u, 0xc0000000u, 0xa0000000u, 0xf0000000u,
@@ -197,7 +197,7 @@ export const sobolGenerationGLSL = /* glsl */`
197
197
 
198
198
  }
199
199
 
200
- // NOTEL this sobol "direction" is also available but we can't write out 5 components
200
+ // NOTE: this sobol "direction" is also available but we can't write out 5 components
201
201
  // uint x = index & 0x00ffffffu;
202
202
  uint x = sobolReverseBits( getMaskedSobol( index, SOBOL_DIRECTIONS_1 ) ) & 0x00ffffffu;
203
203
  uint y = sobolReverseBits( getMaskedSobol( index, SOBOL_DIRECTIONS_2 ) ) & 0x00ffffffu;
@@ -210,7 +210,7 @@ export const sobolGenerationGLSL = /* glsl */`
210
210
 
211
211
  `;
212
212
 
213
- export const sobolSamplingGLSL = /* glsl */`
213
+ export const sobol_functions = /* glsl */`
214
214
 
215
215
  // Seeds
216
216
  uniform sampler2D sobolTexture;
@@ -1,4 +1,4 @@
1
- export const stratifiedTextureGLSL = /* glsl */`
1
+ export const stratified_functions = /* glsl */`
2
2
 
3
3
  uniform sampler2D stratifiedTexture;
4
4
  uniform sampler2D stratifiedOffsetTexture;
@@ -38,7 +38,12 @@ export const stratifiedTextureGLSL = /* glsl */`
38
38
 
39
39
  // tile the small noise texture across the entire screen
40
40
  ivec2 noiseSize = ivec2( textureSize( stratifiedOffsetTexture, 0 ) );
41
- pixelSeed = texelFetch( stratifiedOffsetTexture, ivec2( screenCoord.xy ) % noiseSize, 0 );
41
+ ivec2 pixel = ivec2( screenCoord.xy ) % noiseSize;
42
+ vec2 pixelWidth = 1.0 / vec2( noiseSize );
43
+ vec2 uv = vec2( pixel ) * pixelWidth + pixelWidth * 0.5;
44
+
45
+ // note that using "texelFetch" here seems to break Android for some reason
46
+ pixelSeed = texture( stratifiedOffsetTexture, uv );
42
47
 
43
48
  }
44
49
 
@@ -1,4 +1,4 @@
1
- export const equirectSamplingGLSL = /* glsl */`
1
+ export const equirect_functions = /* glsl */`
2
2
 
3
3
  // samples the the given environment map in the given direction
4
4
  vec3 sampleEquirectColor( sampler2D envMap, vec3 direction ) {
@@ -65,5 +65,4 @@ export const equirectSamplingGLSL = /* glsl */`
65
65
  return float( resolution.x * resolution.y ) * pdf * equirectDirectionPdf( direction );
66
66
 
67
67
  }
68
-
69
68
  `;
@@ -0,0 +1,3 @@
1
+ export * from './equirect_sampling_functions.glsl.js';
2
+ export * from './light_sampling_functions.glsl.js';
3
+ export * from './shape_sampling_functions.glsl.js';
@@ -1,4 +1,4 @@
1
- export const lightSamplingGLSL = /* glsl */`
1
+ export const light_sampling_functions = /* glsl */`
2
2
 
3
3
  float getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {
4
4
 
@@ -26,9 +26,9 @@ export const lightSamplingGLSL = /* glsl */`
26
26
  float getPhotometricAttenuation( sampler2DArray iesProfiles, int iesProfile, vec3 posToLight, vec3 lightDir, vec3 u, vec3 v ) {
27
27
 
28
28
  float cosTheta = dot( posToLight, lightDir );
29
- float angle = acos( cosTheta ) * ( 1.0 / PI );
29
+ float angle = acos( cosTheta ) / PI;
30
30
 
31
- return texture2D( iesProfiles, vec3( 0.0, angle, iesProfile ) ).r;
31
+ return texture2D( iesProfiles, vec3( angle, 0.0, iesProfile ) ).r;
32
32
 
33
33
  }
34
34
 
@@ -1,4 +1,4 @@
1
- export const shapeSamplingGLSL = /* glsl */`
1
+ export const shape_sampling_functions = /* glsl */`
2
2
 
3
3
  vec3 sampleHemisphere( vec3 n, vec2 uv ) {
4
4
 
@@ -1,4 +1,4 @@
1
- export const cameraStructGLSL = /* glsl */`
1
+ export const camera_struct = /* glsl */`
2
2
 
3
3
  struct PhysicalCamera {
4
4
 
@@ -1,4 +1,4 @@
1
- export const equirectStructGLSL = /* glsl */`
1
+ export const equirect_struct = /* glsl */`
2
2
 
3
3
  struct EquirectHdrInfo {
4
4
 
@@ -0,0 +1,5 @@
1
+ export * from './camera_struct.glsl.js';
2
+ export * from './equirect_struct.glsl.js';
3
+ export * from './lights_struct.glsl.js';
4
+ export * from './material_struct.glsl.js';
5
+ export * from './surface_record_struct.glsl.js';
@@ -1,4 +1,4 @@
1
- export const lightsStructGLSL = /* glsl */`
1
+ export const lights_struct = /* glsl */`
2
2
 
3
3
  #define RECT_AREA_LIGHT_TYPE 0
4
4
  #define CIRC_AREA_LIGHT_TYPE 1
@@ -1,4 +1,4 @@
1
- export const materialStructGLSL = /* glsl */ `
1
+ export const material_struct = /* glsl */ `
2
2
 
3
3
  struct Material {
4
4
 
@@ -176,7 +176,7 @@ export const materialStructGLSL = /* glsl */ `
176
176
  m.side = s13.a;
177
177
 
178
178
  m.matte = bool( s14.r );
179
- m.castShadow = ! bool( s14.g );
179
+ m.castShadow = bool( s14.g );
180
180
  m.vertexColors = bool( int( s14.b ) & 1 );
181
181
  m.flatShading = bool( int( s14.b ) & 2 );
182
182
  m.fogVolume = bool( int( s14.b ) & 4 );
@@ -0,0 +1,63 @@
1
+ export const surface_record_struct = /* glsl */`
2
+
3
+ struct SurfaceRecord {
4
+
5
+ // surface type
6
+ bool volumeParticle;
7
+
8
+ // geometry
9
+ vec3 faceNormal;
10
+ bool frontFace;
11
+ vec3 normal;
12
+ mat3 normalBasis;
13
+ mat3 normalInvBasis;
14
+
15
+ // cached properties
16
+ float eta;
17
+ float f0;
18
+
19
+ // material
20
+ float roughness;
21
+ float filteredRoughness;
22
+ float metalness;
23
+ vec3 color;
24
+ vec3 emission;
25
+
26
+ // transmission
27
+ float ior;
28
+ float transmission;
29
+ bool thinFilm;
30
+ vec3 attenuationColor;
31
+ float attenuationDistance;
32
+
33
+ // clearcoat
34
+ vec3 clearcoatNormal;
35
+ mat3 clearcoatBasis;
36
+ mat3 clearcoatInvBasis;
37
+ float clearcoat;
38
+ float clearcoatRoughness;
39
+ float filteredClearcoatRoughness;
40
+
41
+ // sheen
42
+ float sheen;
43
+ vec3 sheenColor;
44
+ float sheenRoughness;
45
+
46
+ // iridescence
47
+ float iridescence;
48
+ float iridescenceIor;
49
+ float iridescenceThickness;
50
+
51
+ // specular
52
+ vec3 specularColor;
53
+ float specularIntensity;
54
+ };
55
+
56
+ struct ScatterRecord {
57
+ float specularPdf;
58
+ float pdf;
59
+ vec3 direction;
60
+ vec3 color;
61
+ };
62
+
63
+ `;
@@ -136,15 +136,15 @@ export class EquirectHdrInfoUniform {
136
136
 
137
137
  // Default to a white texture and associated weights so we don't
138
138
  // just render black initially.
139
- const whiteTex = new DataTexture( toHalfFloatArray( new Float32Array( [ 1, 1, 1, 1 ] ) ), 1, 1 );
140
- whiteTex.type = HalfFloatType;
141
- whiteTex.format = RGBAFormat;
142
- whiteTex.minFilter = LinearFilter;
143
- whiteTex.magFilter = LinearFilter;
144
- whiteTex.wrapS = RepeatWrapping;
145
- whiteTex.wrapT = RepeatWrapping;
146
- whiteTex.generateMipmaps = false;
147
- whiteTex.needsUpdate = true;
139
+ const blackTex = new DataTexture( toHalfFloatArray( new Float32Array( [ 0, 0, 0, 0 ] ) ), 1, 1 );
140
+ blackTex.type = HalfFloatType;
141
+ blackTex.format = RGBAFormat;
142
+ blackTex.minFilter = LinearFilter;
143
+ blackTex.magFilter = LinearFilter;
144
+ blackTex.wrapS = RepeatWrapping;
145
+ blackTex.wrapT = RepeatWrapping;
146
+ blackTex.generateMipmaps = false;
147
+ blackTex.needsUpdate = true;
148
148
 
149
149
  // Stores a map of [0, 1] value -> cumulative importance row & pdf
150
150
  // used to sampling a random value to a relevant row to sample from
@@ -166,10 +166,15 @@ export class EquirectHdrInfoUniform {
166
166
  conditionalWeights.generateMipmaps = false;
167
167
  conditionalWeights.needsUpdate = true;
168
168
 
169
- this.map = whiteTex;
169
+ this.map = blackTex;
170
170
  this.marginalWeights = marginalWeights;
171
171
  this.conditionalWeights = conditionalWeights;
172
- this.totalSum = 1;
172
+ this.totalSum = 0;
173
+
174
+ // TODO: Add support for float or half float types here. We need to pass this into
175
+ // the preprocess function and ensure our CDF and MDF textures are appropriately sized
176
+ // Ideally we wouldn't upscale a bit depth if we didn't need to.
177
+ // this.type = HalfFloatType;
173
178
 
174
179
  }
175
180
 
@@ -1,4 +1,5 @@
1
1
  import { DataTexture, RGBAFormat, ClampToEdgeWrapping, FloatType, Vector3, Quaternion, Matrix4, NearestFilter } from 'three';
2
+ import { bufferToHash } from '../utils/bufferToHash.js';
2
3
 
3
4
  const LIGHT_PIXELS = 6;
4
5
  const RECT_AREA_LIGHT = 0;
@@ -6,6 +7,14 @@ const CIRC_AREA_LIGHT = 1;
6
7
  const SPOT_LIGHT = 2;
7
8
  const DIR_LIGHT = 3;
8
9
  const POINT_LIGHT = 4;
10
+
11
+ const u = new Vector3();
12
+ const v = new Vector3();
13
+ const m = new Matrix4();
14
+ const worldQuaternion = new Quaternion();
15
+ const eye = new Vector3();
16
+ const target = new Vector3();
17
+ const up = new Vector3( 0, 1, 0 );
9
18
  export class LightsInfoUniformStruct {
10
19
 
11
20
  constructor() {
@@ -42,14 +51,6 @@ export class LightsInfoUniformStruct {
42
51
 
43
52
  const floatArray = tex.image.data;
44
53
 
45
- const u = new Vector3();
46
- const v = new Vector3();
47
- const m = new Matrix4();
48
- const worldQuaternion = new Quaternion();
49
- const eye = new Vector3();
50
- const target = new Vector3();
51
- const up = new Vector3( 0, 1, 0 );
52
-
53
54
  for ( let i = 0, l = lights.length; i < l; i ++ ) {
54
55
 
55
56
  const l = lights[ i ];
@@ -172,7 +173,7 @@ export class LightsInfoUniformStruct {
172
173
  floatArray[ baseIndex + ( index ++ ) ] = Math.cos( l.angle * ( 1 - l.penumbra ) );
173
174
 
174
175
  // iesProfile
175
- floatArray[ baseIndex + ( index ++ ) ] = l.iesTexture ? iesTextures.indexOf( l.iesTexture ) : - 1;
176
+ floatArray[ baseIndex + ( index ++ ) ] = l.iesMap ? iesTextures.indexOf( l.iesMap ) : - 1;
176
177
 
177
178
  } else if ( l.isPointLight ) {
178
179
 
@@ -210,9 +211,19 @@ export class LightsInfoUniformStruct {
210
211
 
211
212
  }
212
213
 
213
- tex.needsUpdate = true;
214
214
  this.count = lights.length;
215
215
 
216
+ const hash = bufferToHash( floatArray.buffer );
217
+ if ( this.hash !== hash ) {
218
+
219
+ this.hash = hash;
220
+ tex.needsUpdate = true;
221
+ return true;
222
+
223
+ }
224
+
225
+ return false;
226
+
216
227
  }
217
228
 
218
229
  }
@@ -1,12 +1,10 @@
1
1
  import { DataTexture, RGBAFormat, ClampToEdgeWrapping, FloatType, FrontSide, BackSide, DoubleSide, NearestFilter } from 'three';
2
- import { reduceTexturesToUniqueSources, getTextureHash } from './utils.js';
2
+ import { getTextureHash } from '../core/utils/sceneUpdateUtils.js';
3
+ import { bufferToHash } from '../utils/bufferToHash.js';
3
4
 
4
5
  const MATERIAL_PIXELS = 45;
5
6
  const MATERIAL_STRIDE = MATERIAL_PIXELS * 4;
6
7
 
7
- const MATTE_OFFSET = 14 * 4 + 0; // s14.r
8
- const SHADOW_OFFSET = 14 * 4 + 1; // s14.g
9
-
10
8
  class MaterialFeatures {
11
9
 
12
10
  constructor() {
@@ -56,44 +54,10 @@ export class MaterialsTexture extends DataTexture {
56
54
  this.minFilter = NearestFilter;
57
55
  this.magFilter = NearestFilter;
58
56
  this.generateMipmaps = false;
59
- this.threeCompatibilityTransforms = false;
60
57
  this.features = new MaterialFeatures();
61
58
 
62
59
  }
63
60
 
64
- setCastShadow( materialIndex, cast ) {
65
-
66
- // invert the shadow value so we default to "true" when initializing a material
67
- const array = this.image.data;
68
- const index = materialIndex * MATERIAL_STRIDE + SHADOW_OFFSET;
69
- array[ index ] = ! cast ? 1 : 0;
70
-
71
- }
72
-
73
- getCastShadow( materialIndex ) {
74
-
75
- const array = this.image.data;
76
- const index = materialIndex * MATERIAL_STRIDE + SHADOW_OFFSET;
77
- return ! Boolean( array[ index ] );
78
-
79
- }
80
-
81
- setMatte( materialIndex, matte ) {
82
-
83
- const array = this.image.data;
84
- const index = materialIndex * MATERIAL_STRIDE + MATTE_OFFSET;
85
- array[ index ] = matte ? 1 : 0;
86
-
87
- }
88
-
89
- getMatte( materialIndex ) {
90
-
91
- const array = this.image.data;
92
- const index = materialIndex * MATERIAL_STRIDE + MATTE_OFFSET;
93
- return Boolean( array[ index ] );
94
-
95
- }
96
-
97
61
  updateFrom( materials, textures ) {
98
62
 
99
63
  function getTexture( material, key, def = - 1 ) {
@@ -101,7 +65,7 @@ export class MaterialsTexture extends DataTexture {
101
65
  if ( key in material && material[ key ] ) {
102
66
 
103
67
  const hash = getTextureHash( material[ key ] );
104
- return uniqueTextureLookup[ hash ];
68
+ return textureLookUp[ hash ];
105
69
 
106
70
  } else {
107
71
 
@@ -117,50 +81,18 @@ export class MaterialsTexture extends DataTexture {
117
81
 
118
82
  }
119
83
 
120
- function getUVTransformTexture( material ) {
121
-
122
- // https://github.com/mrdoob/three.js/blob/f3a832e637c98a404c64dae8174625958455e038/src/renderers/webgl/WebGLMaterials.js#L204-L306
123
- // https://threejs.org/docs/#api/en/textures/Texture.offset
124
- // fallback order of textures to use as a common uv transform
125
- return material.map ||
126
- material.specularMap ||
127
- material.displacementMap ||
128
- material.normalMap ||
129
- material.bumpMap ||
130
- material.roughnessMap ||
131
- material.metalnessMap ||
132
- material.alphaMap ||
133
- material.emissiveMap ||
134
- material.clearcoatMap ||
135
- material.clearcoatNormalMap ||
136
- material.clearcoatRoughnessMap ||
137
- material.iridescenceMap ||
138
- material.iridescenceThicknessMap ||
139
- material.specularIntensityMap ||
140
- material.specularColorMap ||
141
- material.transmissionMap ||
142
- material.thicknessMap ||
143
- material.sheenColorMap ||
144
- material.sheenRoughnessMap ||
145
- null;
146
-
147
- }
148
-
149
84
  function writeTextureMatrixToArray( material, textureKey, array, offset ) {
150
85
 
151
- let texture;
152
- if ( threeCompatibilityTransforms ) {
86
+ const texture = material[ textureKey ] && material[ textureKey ].isTexture ? material[ textureKey ] : null;
153
87
 
154
- texture = getUVTransformTexture( material );
155
-
156
- } else {
88
+ // check if texture exists
89
+ if ( texture ) {
157
90
 
158
- texture = material[ textureKey ] && material[ textureKey ].isTexture ? material[ textureKey ] : null;
91
+ if ( texture.matrixAutoUpdate ) {
159
92
 
160
- }
93
+ texture.updateMatrix();
161
94
 
162
- // check if texture exists
163
- if ( texture ) {
95
+ }
164
96
 
165
97
  const elements = texture.matrix.elements;
166
98
 
@@ -187,14 +119,13 @@ export class MaterialsTexture extends DataTexture {
187
119
  let index = 0;
188
120
  const pixelCount = materials.length * MATERIAL_PIXELS;
189
121
  const dimension = Math.ceil( Math.sqrt( pixelCount ) ) || 1;
190
- const { threeCompatibilityTransforms, image, features } = this;
122
+ const { image, features } = this;
191
123
 
192
- // get the list of textures with unique sources
193
- const uniqueTextures = reduceTexturesToUniqueSources( textures );
194
- const uniqueTextureLookup = {};
195
- for ( let i = 0, l = uniqueTextures.length; i < l; i ++ ) {
124
+ // index the list of textures based on shareable source
125
+ const textureLookUp = {};
126
+ for ( let i = 0, l = textures.length; i < l; i ++ ) {
196
127
 
197
- uniqueTextureLookup[ getTextureHash( uniqueTextures[ i ] ) ] = i;
128
+ textureLookUp[ getTextureHash( textures[ i ] ) ] = i;
198
129
 
199
130
  }
200
131
 
@@ -446,8 +377,8 @@ export class MaterialsTexture extends DataTexture {
446
377
  }
447
378
 
448
379
  // sample 14
449
- index ++; // matte
450
- index ++; // shadow
380
+ floatArray[ index ++ ] = Number( getField( m, 'matte', false ) ); // matte
381
+ floatArray[ index ++ ] = Number( getField( m, 'castShadow', true ) ); // shadow
451
382
  floatArray[ index ++ ] = Number( m.vertexColors ) | ( Number( m.flatShading ) << 1 ); // vertexColors & flatShading
452
383
  floatArray[ index ++ ] = Number( m.transparent ); // transparent
453
384
 
@@ -498,7 +429,17 @@ export class MaterialsTexture extends DataTexture {
498
429
 
499
430
  }
500
431
 
501
- this.needsUpdate = true;
432
+ // check if the contents have changed
433
+ const hash = bufferToHash( floatArray.buffer );
434
+ if ( this.hash !== hash ) {
435
+
436
+ this.hash = hash;
437
+ this.needsUpdate = true;
438
+ return true;
439
+
440
+ }
441
+
442
+ return false;
502
443
 
503
444
  }
504
445