super-three 0.160.0 → 0.161.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 (145) hide show
  1. package/LICENSE +1 -1
  2. package/build/three.cjs +380 -109
  3. package/build/three.module.js +381 -109
  4. package/build/three.module.min.js +1 -1
  5. package/examples/jsm/Addons.js +5 -1
  6. package/examples/jsm/capabilities/WebGPU.js +13 -9
  7. package/examples/jsm/controls/OrbitControls.js +102 -13
  8. package/examples/jsm/curves/NURBSUtils.js +59 -4
  9. package/examples/jsm/curves/NURBSVolume.js +62 -0
  10. package/examples/jsm/exporters/USDZExporter.js +8 -7
  11. package/examples/jsm/helpers/TextureHelper.js +3 -3
  12. package/examples/jsm/loaders/3DMLoader.js +44 -43
  13. package/examples/jsm/loaders/DDSLoader.js +1 -0
  14. package/examples/jsm/loaders/KTX2Loader.js +20 -5
  15. package/examples/jsm/loaders/LUT3dlLoader.js +78 -46
  16. package/examples/jsm/loaders/LUTCubeLoader.js +81 -67
  17. package/examples/jsm/loaders/LUTImageLoader.js +3 -2
  18. package/examples/jsm/loaders/MaterialXLoader.js +115 -16
  19. package/examples/jsm/loaders/SVGLoader.js +4 -3
  20. package/examples/jsm/loaders/VRMLLoader.js +1 -1
  21. package/examples/jsm/materials/MeshPostProcessingMaterial.js +144 -0
  22. package/examples/jsm/misc/Timer.js +13 -4
  23. package/examples/jsm/nodes/Nodes.js +16 -5
  24. package/examples/jsm/nodes/accessors/BufferAttributeNode.js +5 -3
  25. package/examples/jsm/nodes/accessors/CameraNode.js +9 -4
  26. package/examples/jsm/nodes/accessors/CubeTextureNode.js +12 -1
  27. package/examples/jsm/nodes/accessors/StorageBufferNode.js +27 -0
  28. package/examples/jsm/nodes/accessors/TextureStoreNode.js +56 -3
  29. package/examples/jsm/nodes/accessors/VertexColorNode.js +70 -0
  30. package/examples/jsm/nodes/core/AttributeNode.js +1 -1
  31. package/examples/jsm/nodes/core/NodeBuilder.js +23 -18
  32. package/examples/jsm/nodes/core/NodeFrame.js +16 -8
  33. package/examples/jsm/nodes/core/constants.js +1 -0
  34. package/examples/jsm/nodes/display/AfterImageNode.js +148 -0
  35. package/examples/jsm/nodes/display/AnamorphicNode.js +148 -0
  36. package/examples/jsm/nodes/display/ColorAdjustmentNode.js +3 -0
  37. package/examples/jsm/nodes/display/GaussianBlurNode.js +33 -13
  38. package/examples/jsm/nodes/display/PassNode.js +3 -2
  39. package/examples/jsm/nodes/display/ToneMappingNode.js +46 -3
  40. package/examples/jsm/nodes/display/ViewportDepthTextureNode.js +1 -4
  41. package/examples/jsm/nodes/display/ViewportNode.js +0 -2
  42. package/examples/jsm/nodes/display/ViewportSharedTextureNode.js +4 -4
  43. package/examples/jsm/nodes/fog/FogNode.js +2 -1
  44. package/examples/jsm/nodes/lighting/AmbientLightNode.js +1 -1
  45. package/examples/jsm/nodes/lighting/AnalyticLightNode.js +13 -5
  46. package/examples/jsm/nodes/lighting/LightingContextNode.js +1 -1
  47. package/examples/jsm/nodes/lighting/LightsNode.js +1 -1
  48. package/examples/jsm/nodes/materials/Line2NodeMaterial.js +18 -30
  49. package/examples/jsm/nodes/materials/Materials.js +1 -0
  50. package/examples/jsm/nodes/materials/MeshSSSNodeMaterial.js +84 -0
  51. package/examples/jsm/nodes/materials/NodeMaterial.js +6 -4
  52. package/examples/jsm/nodes/materials/SpriteNodeMaterial.js +1 -7
  53. package/examples/jsm/nodes/math/MathNode.js +12 -2
  54. package/examples/jsm/nodes/math/MathUtils.js +15 -0
  55. package/examples/jsm/nodes/math/OperatorNode.js +13 -5
  56. package/examples/jsm/nodes/math/TriNoise3D.js +71 -0
  57. package/examples/jsm/nodes/shadernode/ShaderNode.js +10 -1
  58. package/examples/jsm/nodes/utils/ArrayElementNode.js +6 -0
  59. package/examples/jsm/nodes/utils/JoinNode.js +2 -2
  60. package/examples/jsm/nodes/utils/LoopNode.js +3 -3
  61. package/examples/jsm/nodes/utils/ReflectorNode.js +227 -0
  62. package/examples/jsm/nodes/utils/RotateNode.js +68 -0
  63. package/examples/jsm/nodes/utils/RotateUVNode.js +1 -9
  64. package/examples/jsm/nodes/utils/SplitNode.js +4 -4
  65. package/examples/jsm/objects/GroundedSkybox.js +50 -0
  66. package/examples/jsm/objects/QuadMesh.js +8 -2
  67. package/examples/jsm/objects/Water2.js +8 -8
  68. package/examples/jsm/postprocessing/GTAOPass.js +11 -1
  69. package/examples/jsm/renderers/common/Backend.js +14 -0
  70. package/examples/jsm/renderers/common/Bindings.js +1 -1
  71. package/examples/jsm/renderers/common/DataMap.js +1 -1
  72. package/examples/jsm/renderers/common/Info.js +25 -1
  73. package/examples/jsm/renderers/common/Pipelines.js +8 -8
  74. package/examples/jsm/renderers/common/PostProcessing.js +2 -2
  75. package/examples/jsm/renderers/common/ProgrammableStage.js +3 -1
  76. package/examples/jsm/renderers/common/RenderObject.js +2 -0
  77. package/examples/jsm/renderers/common/Renderer.js +238 -22
  78. package/examples/jsm/renderers/common/StorageBufferAttribute.js +17 -0
  79. package/examples/jsm/renderers/common/Textures.js +25 -5
  80. package/examples/jsm/renderers/common/nodes/NodeBuilderState.js +2 -1
  81. package/examples/jsm/renderers/common/nodes/Nodes.js +4 -2
  82. package/examples/jsm/renderers/webgl/WebGLBackend.js +631 -270
  83. package/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js +37 -30
  84. package/examples/jsm/renderers/webgl/utils/WebGLAttributeUtils.js +89 -8
  85. package/examples/jsm/renderers/webgl/utils/WebGLConstants.js +11 -0
  86. package/examples/jsm/renderers/webgl/utils/WebGLState.js +197 -0
  87. package/examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js +377 -11
  88. package/examples/jsm/renderers/webgl/utils/WebGLUtils.js +2 -2
  89. package/examples/jsm/renderers/webgl-legacy/nodes/GLSL1NodeBuilder.js +1 -21
  90. package/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodeBuilder.js +2 -2
  91. package/examples/jsm/renderers/webgpu/WebGPUBackend.js +289 -102
  92. package/examples/jsm/renderers/webgpu/WebGPURenderer.js +7 -2
  93. package/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +56 -39
  94. package/examples/jsm/renderers/webgpu/utils/WebGPUAttributeUtils.js +9 -1
  95. package/examples/jsm/renderers/webgpu/utils/WebGPUPipelineUtils.js +38 -4
  96. package/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +85 -12
  97. package/examples/jsm/transpiler/AST.js +1 -1
  98. package/examples/jsm/transpiler/GLSLDecoder.js +1 -1
  99. package/examples/jsm/transpiler/ShaderToyDecoder.js +1 -1
  100. package/examples/jsm/transpiler/TSLEncoder.js +1 -1
  101. package/examples/jsm/utils/BufferGeometryUtils.js +23 -27
  102. package/examples/jsm/utils/SortUtils.js +2 -0
  103. package/examples/jsm/webxr/ARButton.js +12 -2
  104. package/examples/jsm/webxr/VRButton.js +12 -2
  105. package/examples/jsm/webxr/XRButton.js +12 -2
  106. package/examples/jsm/webxr/XRControllerModelFactory.js +6 -1
  107. package/examples/jsm/webxr/XRHandMeshModel.js +3 -1
  108. package/package.json +2 -2
  109. package/src/audio/Audio.js +1 -3
  110. package/src/cameras/PerspectiveCamera.js +35 -0
  111. package/src/constants.js +1 -2
  112. package/src/core/BufferAttribute.js +2 -1
  113. package/src/core/InterleavedBuffer.js +2 -1
  114. package/src/core/InterleavedBufferAttribute.js +20 -0
  115. package/src/materials/ShaderMaterial.js +2 -1
  116. package/src/math/Triangle.js +0 -30
  117. package/src/objects/BatchedMesh.js +6 -7
  118. package/src/objects/SkinnedMesh.js +0 -8
  119. package/src/renderers/WebGLRenderer.js +6 -2
  120. package/src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl.js +9 -0
  121. package/src/renderers/shaders/ShaderChunk/clipping_planes_fragment.glsl.js +56 -11
  122. package/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js +15 -7
  123. package/src/renderers/shaders/ShaderLib/depth.glsl.js +1 -2
  124. package/src/renderers/shaders/ShaderLib/distanceRGBA.glsl.js +1 -2
  125. package/src/renderers/shaders/ShaderLib/linedashed.glsl.js +1 -1
  126. package/src/renderers/shaders/ShaderLib/meshbasic.glsl.js +1 -2
  127. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +1 -1
  128. package/src/renderers/shaders/ShaderLib/meshmatcap.glsl.js +1 -2
  129. package/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +3 -1
  130. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +1 -1
  131. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +1 -1
  132. package/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +1 -1
  133. package/src/renderers/shaders/ShaderLib/points.glsl.js +1 -1
  134. package/src/renderers/shaders/ShaderLib/sprite.glsl.js +1 -1
  135. package/src/renderers/webgl/WebGLAttributes.js +2 -2
  136. package/src/renderers/webgl/WebGLCubeMaps.js +1 -1
  137. package/src/renderers/webgl/WebGLProgram.js +30 -3
  138. package/src/renderers/webgl/WebGLPrograms.js +19 -11
  139. package/src/renderers/webgl/WebGLTextures.js +90 -16
  140. package/src/renderers/webxr/WebXRDepthSensing.js +105 -0
  141. package/src/renderers/webxr/WebXRManager.js +46 -0
  142. package/src/textures/Source.js +1 -0
  143. package/build/three.js +0 -54519
  144. package/build/three.min.js +0 -7
  145. package/examples/jsm/objects/GroundProjectedSkybox.js +0 -172
@@ -120,17 +120,32 @@ class KTX2Loader extends Loader {
120
120
 
121
121
  }
122
122
 
123
+ async detectSupportAsync( renderer ) {
124
+
125
+ this.workerConfig = {
126
+ astcSupported: await renderer.hasFeatureAsync( 'texture-compression-astc' ),
127
+ etc1Supported: await renderer.hasFeatureAsync( 'texture-compression-etc1' ),
128
+ etc2Supported: await renderer.hasFeatureAsync( 'texture-compression-etc2' ),
129
+ dxtSupported: await renderer.hasFeatureAsync( 'texture-compression-bc' ),
130
+ bptcSupported: await renderer.hasFeatureAsync( 'texture-compression-bptc' ),
131
+ pvrtcSupported: await renderer.hasFeatureAsync( 'texture-compression-pvrtc' )
132
+ };
133
+
134
+ return this;
135
+
136
+ }
137
+
123
138
  detectSupport( renderer ) {
124
139
 
125
140
  if ( renderer.isWebGPURenderer === true ) {
126
141
 
127
142
  this.workerConfig = {
128
143
  astcSupported: renderer.hasFeature( 'texture-compression-astc' ),
129
- etc1Supported: false,
144
+ etc1Supported: renderer.hasFeature( 'texture-compression-etc1' ),
130
145
  etc2Supported: renderer.hasFeature( 'texture-compression-etc2' ),
131
146
  dxtSupported: renderer.hasFeature( 'texture-compression-bc' ),
132
- bptcSupported: false,
133
- pvrtcSupported: false
147
+ bptcSupported: renderer.hasFeature( 'texture-compression-bptc' ),
148
+ pvrtcSupported: renderer.hasFeature( 'texture-compression-pvrtc' )
134
149
  };
135
150
 
136
151
  } else {
@@ -865,8 +880,8 @@ async function createRawTexture( container ) {
865
880
  if ( UNCOMPRESSED_FORMATS.has( FORMAT_MAP[ vkFormat ] ) ) {
866
881
 
867
882
  texture = container.pixelDepth === 0
868
- ? new DataTexture( mipmaps[ 0 ].data, container.pixelWidth, container.pixelHeight )
869
- : new Data3DTexture( mipmaps[ 0 ].data, container.pixelWidth, container.pixelHeight, container.pixelDepth );
883
+ ? new DataTexture( mipmaps[ 0 ].data, container.pixelWidth, container.pixelHeight )
884
+ : new Data3DTexture( mipmaps[ 0 ].data, container.pixelWidth, container.pixelHeight, container.pixelDepth );
870
885
 
871
886
  } else {
872
887
 
@@ -1,18 +1,42 @@
1
1
  // http://download.autodesk.com/us/systemdocs/help/2011/lustre/index.html?url=./files/WSc4e151a45a3b785a24c3d9a411df9298473-7ffd.htm,topicNumber=d0e9492
2
2
  // https://community.foundry.com/discuss/topic/103636/format-spec-for-3dl?mode=Post&postID=895258
3
+
3
4
  import {
4
- Loader,
5
- FileLoader,
5
+ ClampToEdgeWrapping,
6
6
  DataTexture,
7
7
  Data3DTexture,
8
+ FileLoader,
9
+ FloatType,
10
+ LinearFilter,
11
+ Loader,
8
12
  RGBAFormat,
9
13
  UnsignedByteType,
10
- ClampToEdgeWrapping,
11
- LinearFilter,
12
14
  } from 'three';
13
15
 
14
16
  export class LUT3dlLoader extends Loader {
15
17
 
18
+ constructor( manager ) {
19
+
20
+ super( manager );
21
+
22
+ this.type = UnsignedByteType;
23
+
24
+ }
25
+
26
+ setType( type ) {
27
+
28
+ if ( type !== UnsignedByteType && type !== FloatType ) {
29
+
30
+ throw new Error( 'LUT3dlLoader: Unsupported type' );
31
+
32
+ }
33
+
34
+ this.type = type;
35
+
36
+ return this;
37
+
38
+ }
39
+
16
40
  load( url, onLoad, onProgress, onError ) {
17
41
 
18
42
  const loader = new FileLoader( this.manager );
@@ -44,80 +68,88 @@ export class LUT3dlLoader extends Loader {
44
68
 
45
69
  }
46
70
 
47
- parse( str ) {
71
+ parse( input ) {
72
+
73
+ const regExpGridInfo = /^[\d ]+$/m;
74
+ const regExpDataPoints = /^([\d.e+-]+) +([\d.e+-]+) +([\d.e+-]+) *$/gm;
48
75
 
49
- // remove empty lines and comment lints
50
- str = str
51
- .replace( /^#.*?(\n|\r)/gm, '' )
52
- .replace( /^\s*?(\n|\r)/gm, '' )
53
- .trim();
76
+ // The first line describes the positions of values on the LUT grid.
77
+ let result = regExpGridInfo.exec( input );
54
78
 
55
- const lines = str.split( /[\n\r]+/g );
79
+ if ( result === null ) {
56
80
 
57
- // first line is the positions on the grid that are provided by the LUT
58
- const gridLines = lines[ 0 ].trim().split( /\s+/g ).map( e => parseFloat( e ) );
81
+ throw new Error( 'LUT3dlLoader: Missing grid information' );
82
+
83
+ }
84
+
85
+ const gridLines = result[ 0 ].trim().split( /\s+/g ).map( Number );
59
86
  const gridStep = gridLines[ 1 ] - gridLines[ 0 ];
60
87
  const size = gridLines.length;
88
+ const sizeSq = size ** 2;
61
89
 
62
- for ( let i = 1, l = gridLines.length; i < l; i ++ ) {
90
+ for ( let i = 1, l = gridLines.length; i < l; ++ i ) {
63
91
 
64
92
  if ( gridStep !== ( gridLines[ i ] - gridLines[ i - 1 ] ) ) {
65
93
 
66
- throw new Error( 'LUT3dlLoader: Inconsistent grid size not supported.' );
94
+ throw new Error( 'LUT3dlLoader: Inconsistent grid size' );
67
95
 
68
96
  }
69
97
 
70
98
  }
71
99
 
72
- const dataArray = new Array( size * size * size * 4 );
100
+ const dataFloat = new Float32Array( size ** 3 * 4 );
101
+ let maxValue = 0.0;
73
102
  let index = 0;
74
- let maxOutputValue = 0.0;
75
- for ( let i = 1, l = lines.length; i < l; i ++ ) {
76
103
 
77
- const line = lines[ i ].trim();
78
- const split = line.split( /\s/g );
104
+ while ( ( result = regExpDataPoints.exec( input ) ) !== null ) {
105
+
106
+ const r = Number( result[ 1 ] );
107
+ const g = Number( result[ 2 ] );
108
+ const b = Number( result[ 3 ] );
79
109
 
80
- const r = parseFloat( split[ 0 ] );
81
- const g = parseFloat( split[ 1 ] );
82
- const b = parseFloat( split[ 2 ] );
83
- maxOutputValue = Math.max( maxOutputValue, r, g, b );
110
+ maxValue = Math.max( maxValue, r, g, b );
84
111
 
85
112
  const bLayer = index % size;
86
113
  const gLayer = Math.floor( index / size ) % size;
87
- const rLayer = Math.floor( index / ( size * size ) ) % size;
114
+ const rLayer = Math.floor( index / ( sizeSq ) ) % size;
88
115
 
89
- // b grows first, then g, then r
90
- const pixelIndex = bLayer * size * size + gLayer * size + rLayer;
91
- dataArray[ 4 * pixelIndex + 0 ] = r;
92
- dataArray[ 4 * pixelIndex + 1 ] = g;
93
- dataArray[ 4 * pixelIndex + 2 ] = b;
94
- dataArray[ 4 * pixelIndex + 3 ] = 1.0;
95
- index += 1;
116
+ // b grows first, then g, then r.
117
+ const d4 = ( bLayer * sizeSq + gLayer * size + rLayer ) * 4;
118
+ dataFloat[ d4 + 0 ] = r;
119
+ dataFloat[ d4 + 1 ] = g;
120
+ dataFloat[ d4 + 2 ] = b;
121
+
122
+ ++ index;
96
123
 
97
124
  }
98
125
 
99
- // Find the apparent bit depth of the stored RGB values and map the
100
- // values to [ 0, 255 ].
101
- const bits = Math.ceil( Math.log2( maxOutputValue ) );
102
- const maxBitValue = Math.pow( 2.0, bits );
103
- for ( let i = 0, l = dataArray.length; i < l; i += 4 ) {
126
+ // Determine the bit depth to scale the values to [0.0, 1.0].
127
+ const bits = Math.ceil( Math.log2( maxValue ) );
128
+ const maxBitValue = Math.pow( 2, bits );
129
+
130
+ const data = this.type === UnsignedByteType ? new Uint8Array( dataFloat.length ) : dataFloat;
131
+ const scale = this.type === UnsignedByteType ? 255 : 1;
132
+
133
+ for ( let i = 0, l = data.length; i < l; i += 4 ) {
134
+
135
+ const i1 = i + 1;
136
+ const i2 = i + 2;
137
+ const i3 = i + 3;
104
138
 
105
- const r = dataArray[ i + 0 ];
106
- const g = dataArray[ i + 1 ];
107
- const b = dataArray[ i + 2 ];
108
- dataArray[ i + 0 ] = 255 * r / maxBitValue; // r
109
- dataArray[ i + 1 ] = 255 * g / maxBitValue; // g
110
- dataArray[ i + 2 ] = 255 * b / maxBitValue; // b
139
+ // Note: data is dataFloat when type is FloatType.
140
+ data[ i ] = dataFloat[ i ] / maxBitValue * scale;
141
+ data[ i1 ] = dataFloat[ i1 ] / maxBitValue * scale;
142
+ data[ i2 ] = dataFloat[ i2 ] / maxBitValue * scale;
143
+ data[ i3 ] = scale;
111
144
 
112
145
  }
113
146
 
114
- const data = new Uint8Array( dataArray );
115
147
  const texture = new DataTexture();
116
148
  texture.image.data = data;
117
149
  texture.image.width = size;
118
150
  texture.image.height = size * size;
119
151
  texture.format = RGBAFormat;
120
- texture.type = UnsignedByteType;
152
+ texture.type = this.type;
121
153
  texture.magFilter = LinearFilter;
122
154
  texture.minFilter = LinearFilter;
123
155
  texture.wrapS = ClampToEdgeWrapping;
@@ -131,7 +163,7 @@ export class LUT3dlLoader extends Loader {
131
163
  texture3D.image.height = size;
132
164
  texture3D.image.depth = size;
133
165
  texture3D.format = RGBAFormat;
134
- texture3D.type = UnsignedByteType;
166
+ texture3D.type = this.type;
135
167
  texture3D.magFilter = LinearFilter;
136
168
  texture3D.minFilter = LinearFilter;
137
169
  texture3D.wrapS = ClampToEdgeWrapping;
@@ -1,18 +1,41 @@
1
1
  // https://wwwimages2.adobe.com/content/dam/acom/en/products/speedgrade/cc/pdfs/cube-lut-specification-1.0.pdf
2
2
 
3
3
  import {
4
- Loader,
5
- FileLoader,
6
- Vector3,
4
+ ClampToEdgeWrapping,
7
5
  DataTexture,
8
6
  Data3DTexture,
9
- UnsignedByteType,
10
- ClampToEdgeWrapping,
7
+ FileLoader,
8
+ FloatType,
11
9
  LinearFilter,
10
+ Loader,
11
+ UnsignedByteType,
12
+ Vector3,
12
13
  } from 'three';
13
14
 
14
15
  export class LUTCubeLoader extends Loader {
15
16
 
17
+ constructor( manager ) {
18
+
19
+ super( manager );
20
+
21
+ this.type = UnsignedByteType;
22
+
23
+ }
24
+
25
+ setType( type ) {
26
+
27
+ if ( type !== UnsignedByteType && type !== FloatType ) {
28
+
29
+ throw new Error( 'LUTCubeLoader: Unsupported type' );
30
+
31
+ }
32
+
33
+ this.type = type;
34
+
35
+ return this;
36
+
37
+ }
38
+
16
39
  load( url, onLoad, onProgress, onError ) {
17
40
 
18
41
  const loader = new FileLoader( this.manager );
@@ -44,72 +67,63 @@ export class LUTCubeLoader extends Loader {
44
67
 
45
68
  }
46
69
 
47
- parse( str ) {
70
+ parse( input ) {
48
71
 
49
- // Remove empty lines and comments
50
- str = str
51
- .replace( /^#.*?(\n|\r)/gm, '' )
52
- .replace( /^\s*?(\n|\r)/gm, '' )
53
- .trim();
72
+ const regExpTitle = /TITLE +"([^"]*)"/;
73
+ const regExpSize = /LUT_3D_SIZE +(\d+)/;
74
+ const regExpDomainMin = /DOMAIN_MIN +([\d.]+) +([\d.]+) +([\d.]+)/;
75
+ const regExpDomainMax = /DOMAIN_MAX +([\d.]+) +([\d.]+) +([\d.]+)/;
76
+ const regExpDataPoints = /^([\d.e+-]+) +([\d.e+-]+) +([\d.e+-]+) *$/gm;
77
+
78
+ let result = regExpTitle.exec( input );
79
+ const title = ( result !== null ) ? result[ 1 ] : null;
80
+
81
+ result = regExpSize.exec( input );
82
+
83
+ if ( result === null ) {
84
+
85
+ throw new Error( 'LUTCubeLoader: Missing LUT_3D_SIZE information' );
86
+
87
+ }
88
+
89
+ const size = Number( result[ 1 ] );
90
+ const length = size ** 3 * 4;
91
+ const data = this.type === UnsignedByteType ? new Uint8Array( length ) : new Float32Array( length );
54
92
 
55
- let title = null;
56
- let size = null;
57
93
  const domainMin = new Vector3( 0, 0, 0 );
58
94
  const domainMax = new Vector3( 1, 1, 1 );
59
95
 
60
- const lines = str.split( /[\n\r]+/g );
61
- let data = null;
62
-
63
- let currIndex = 0;
64
- for ( let i = 0, l = lines.length; i < l; i ++ ) {
65
-
66
- const line = lines[ i ].trim();
67
- const split = line.split( /\s/g );
68
-
69
- switch ( split[ 0 ] ) {
70
-
71
- case 'TITLE':
72
- title = line.substring( 7, line.length - 1 );
73
- break;
74
- case 'LUT_3D_SIZE':
75
- // TODO: A .CUBE LUT file specifies floating point values and could be represented with
76
- // more precision than can be captured with Uint8Array.
77
- const sizeToken = split[ 1 ];
78
- size = parseFloat( sizeToken );
79
- data = new Uint8Array( size * size * size * 4 );
80
- break;
81
- case 'DOMAIN_MIN':
82
- domainMin.x = parseFloat( split[ 1 ] );
83
- domainMin.y = parseFloat( split[ 2 ] );
84
- domainMin.z = parseFloat( split[ 3 ] );
85
- break;
86
- case 'DOMAIN_MAX':
87
- domainMax.x = parseFloat( split[ 1 ] );
88
- domainMax.y = parseFloat( split[ 2 ] );
89
- domainMax.z = parseFloat( split[ 3 ] );
90
- break;
91
- default:
92
- const r = parseFloat( split[ 0 ] );
93
- const g = parseFloat( split[ 1 ] );
94
- const b = parseFloat( split[ 2 ] );
95
-
96
- if (
97
- r > 1.0 || r < 0.0 ||
98
- g > 1.0 || g < 0.0 ||
99
- b > 1.0 || b < 0.0
100
- ) {
101
-
102
- throw new Error( 'LUTCubeLoader : Non normalized values not supported.' );
103
-
104
- }
105
-
106
- data[ currIndex + 0 ] = r * 255;
107
- data[ currIndex + 1 ] = g * 255;
108
- data[ currIndex + 2 ] = b * 255;
109
- data[ currIndex + 3 ] = 255;
110
- currIndex += 4;
96
+ result = regExpDomainMin.exec( input );
111
97
 
112
- }
98
+ if ( result !== null ) {
99
+
100
+ domainMin.set( Number( result[ 1 ] ), Number( result[ 2 ] ), Number( result[ 3 ] ) );
101
+
102
+ }
103
+
104
+ result = regExpDomainMax.exec( input );
105
+
106
+ if ( result !== null ) {
107
+
108
+ domainMax.set( Number( result[ 1 ] ), Number( result[ 2 ] ), Number( result[ 3 ] ) );
109
+
110
+ }
111
+
112
+ if ( domainMin.x > domainMax.x || domainMin.y > domainMax.y || domainMin.z > domainMax.z ) {
113
+
114
+ throw new Error( 'LUTCubeLoader: Invalid input domain' );
115
+
116
+ }
117
+
118
+ const scale = this.type === UnsignedByteType ? 255 : 1;
119
+ let i = 0;
120
+
121
+ while ( ( result = regExpDataPoints.exec( input ) ) !== null ) {
122
+
123
+ data[ i ++ ] = Number( result[ 1 ] ) * scale;
124
+ data[ i ++ ] = Number( result[ 2 ] ) * scale;
125
+ data[ i ++ ] = Number( result[ 3 ] ) * scale;
126
+ data[ i ++ ] = scale;
113
127
 
114
128
  }
115
129
 
@@ -117,7 +131,7 @@ export class LUTCubeLoader extends Loader {
117
131
  texture.image.data = data;
118
132
  texture.image.width = size;
119
133
  texture.image.height = size * size;
120
- texture.type = UnsignedByteType;
134
+ texture.type = this.type;
121
135
  texture.magFilter = LinearFilter;
122
136
  texture.minFilter = LinearFilter;
123
137
  texture.wrapS = ClampToEdgeWrapping;
@@ -130,7 +144,7 @@ export class LUTCubeLoader extends Loader {
130
144
  texture3D.image.width = size;
131
145
  texture3D.image.height = size;
132
146
  texture3D.image.depth = size;
133
- texture3D.type = UnsignedByteType;
147
+ texture3D.type = this.type;
134
148
  texture3D.magFilter = LinearFilter;
135
149
  texture3D.minFilter = LinearFilter;
136
150
  texture3D.wrapS = ClampToEdgeWrapping;
@@ -12,9 +12,10 @@ import {
12
12
  export class LUTImageLoader extends Loader {
13
13
 
14
14
  constructor( flipVertical = false ) {
15
- //The NeutralLUT.png has green at the bottom for Unreal ang green at the top for Unity URP Color Lookup
15
+
16
+ //The NeutralLUT.png has green at the bottom for Unreal ang green at the top for Unity URP Color Lookup
16
17
  //post-processing. If you're using lut image strips from a Unity pipeline then pass true to the constructor
17
-
18
+
18
19
  super();
19
20
 
20
21
  this.flip = flipVertical;
@@ -6,9 +6,10 @@ import {
6
6
  } from 'three';
7
7
 
8
8
  import {
9
- MeshPhysicalNodeMaterial,
9
+ MeshBasicNodeMaterial, MeshPhysicalNodeMaterial,
10
10
  float, bool, int, vec2, vec3, vec4, color, texture,
11
- positionLocal,
11
+ positionLocal, positionWorld, uv, vertexColor,
12
+ normalLocal, normalWorld, tangentLocal, tangentWorld,
12
13
  add, sub, mul, div, mod, abs, sign, floor, ceil, round, pow, sin, cos, tan,
13
14
  asin, acos, atan2, sqrt, exp, clamp, min, max, normalize, length, dot, cross, normalMap,
14
15
  remap, smoothstep, luminance, mx_rgbtohsv, mx_hsvtorgb,
@@ -39,26 +40,34 @@ class MXElement {
39
40
 
40
41
  // Ref: https://github.com/mrdoob/three.js/issues/24674
41
42
 
43
+ const mx_add = ( in1, in2 = float( 0 ) ) => add( in1, in2 );
44
+ const mx_subtract = ( in1, in2 = float( 0 ) ) => sub( in1, in2 );
45
+ const mx_multiply = ( in1, in2 = float( 1 ) ) => mul( in1, in2 );
46
+ const mx_divide = ( in1, in2 = float( 1 ) ) => div( in1, in2 );
47
+ const mx_modulo = ( in1, in2 = float( 1 ) ) => mod( in1, in2 );
48
+ const mx_power = ( in1, in2 = float( 1 ) ) => pow( in1, in2 );
49
+ const mx_atan2 = ( in1 = float( 0 ), in2 = float( 1 ) ) => atan2( in1, in2 );
50
+
42
51
  const MXElements = [
43
52
 
44
53
  // << Math >>
45
- new MXElement( 'add', add, [ 'in1', 'in2' ] ),
46
- new MXElement( 'subtract', sub, [ 'in1', 'in2' ] ),
47
- new MXElement( 'multiply', mul, [ 'in1', 'in2' ] ),
48
- new MXElement( 'divide', div, [ 'in1', 'in2' ] ),
49
- new MXElement( 'modulo', mod, [ 'in1', 'in2' ] ),
54
+ new MXElement( 'add', mx_add, [ 'in1', 'in2' ] ),
55
+ new MXElement( 'subtract', mx_subtract, [ 'in1', 'in2' ] ),
56
+ new MXElement( 'multiply', mx_multiply, [ 'in1', 'in2' ] ),
57
+ new MXElement( 'divide', mx_divide, [ 'in1', 'in2' ] ),
58
+ new MXElement( 'modulo', mx_modulo, [ 'in1', 'in2' ] ),
50
59
  new MXElement( 'absval', abs, [ 'in1', 'in2' ] ),
51
60
  new MXElement( 'sign', sign, [ 'in1', 'in2' ] ),
52
61
  new MXElement( 'floor', floor, [ 'in1', 'in2' ] ),
53
62
  new MXElement( 'ceil', ceil, [ 'in1', 'in2' ] ),
54
63
  new MXElement( 'round', round, [ 'in1', 'in2' ] ),
55
- new MXElement( 'power', pow, [ 'in1', 'in2' ] ),
64
+ new MXElement( 'power', mx_power, [ 'in1', 'in2' ] ),
56
65
  new MXElement( 'sin', sin, [ 'in' ] ),
57
66
  new MXElement( 'cos', cos, [ 'in' ] ),
58
67
  new MXElement( 'tan', tan, [ 'in' ] ),
59
68
  new MXElement( 'asin', asin, [ 'in' ] ),
60
69
  new MXElement( 'acos', acos, [ 'in' ] ),
61
- new MXElement( 'atan2', atan2, [ 'in1', 'in2' ] ),
70
+ new MXElement( 'atan2', mx_atan2, [ 'in1', 'in2' ] ),
62
71
  new MXElement( 'sqrt', sqrt, [ 'in' ] ),
63
72
  //new MtlXElement( 'ln', ... ),
64
73
  new MXElement( 'exp', exp, [ 'in' ] ),
@@ -141,6 +150,20 @@ class MaterialXLoader extends Loader {
141
150
 
142
151
  load( url, onLoad, onProgress, onError ) {
143
152
 
153
+ const _onError = function ( e ) {
154
+
155
+ if ( onError ) {
156
+
157
+ onError( e );
158
+
159
+ } else {
160
+
161
+ console.error( e );
162
+
163
+ }
164
+
165
+ };
166
+
144
167
  new FileLoader( this.manager )
145
168
  .setPath( this.path )
146
169
  .load( url, async ( text ) => {
@@ -151,11 +174,11 @@ class MaterialXLoader extends Loader {
151
174
 
152
175
  } catch ( e ) {
153
176
 
154
- onError( e );
177
+ _onError( e );
155
178
 
156
179
  }
157
180
 
158
- }, onProgress, onError );
181
+ }, onProgress, _onError );
159
182
 
160
183
  return this;
161
184
 
@@ -312,7 +335,17 @@ class MaterialXNode {
312
335
 
313
336
  const filePrefix = this.getRecursiveAttribute( 'fileprefix' ) || '';
314
337
 
315
- const texture = this.materialX.textureLoader.load( filePrefix + this.value );
338
+ let loader = this.materialX.textureLoader;
339
+ const uri = filePrefix + this.value;
340
+
341
+ if ( uri ) {
342
+
343
+ const handler = this.materialX.manager.getHandler( uri );
344
+ if ( handler !== null ) loader = handler;
345
+
346
+ }
347
+
348
+ const texture = loader.load( uri );
316
349
  texture.wrapS = texture.wrapT = RepeatWrapping;
317
350
  texture.flipY = false;
318
351
 
@@ -376,7 +409,32 @@ class MaterialXNode {
376
409
 
377
410
  } else if ( element === 'position' ) {
378
411
 
379
- node = positionLocal;
412
+ const space = this.getAttribute( 'space' );
413
+ node = space === 'world' ? positionWorld : positionLocal;
414
+
415
+ } else if ( element === 'normal' ) {
416
+
417
+ const space = this.getAttribute( 'space' );
418
+ node = space === 'world' ? normalWorld : normalLocal;
419
+
420
+ } else if ( element === 'tangent' ) {
421
+
422
+ const space = this.getAttribute( 'space' );
423
+ node = space === 'world' ? tangentWorld : tangentLocal;
424
+
425
+ } else if ( element === 'texcoord' ) {
426
+
427
+ const indexNode = this.getChildByName( 'index' );
428
+ const index = indexNode ? parseInt( indexNode.value ) : 0;
429
+
430
+ node = uv( index );
431
+
432
+ } else if ( element === 'geomcolor' ) {
433
+
434
+ const indexNode = this.getChildByName( 'index' );
435
+ const index = indexNode ? parseInt( indexNode.value ) : 0;
436
+
437
+ node = vertexColor( index );
380
438
 
381
439
  } else if ( element === 'tiledimage' ) {
382
440
 
@@ -597,7 +655,7 @@ class MaterialXNode {
597
655
  let emissiveNode = null;
598
656
 
599
657
  if ( inputs.emission ) emissiveNode = inputs.emission;
600
- if ( inputs.emissionColor ) {
658
+ if ( inputs.emissionColor ) {
601
659
 
602
660
  emissiveNode = emissiveNode ? mul( emissiveNode, inputs.emissionColor ) : emissiveNode;
603
661
 
@@ -639,7 +697,28 @@ class MaterialXNode {
639
697
 
640
698
  }
641
699
 
642
- toMaterial() {
700
+ toBasicMaterial() {
701
+
702
+ const material = new MeshBasicNodeMaterial();
703
+ material.name = this.name;
704
+
705
+ for ( const nodeX of this.children.toReversed() ) {
706
+
707
+ if ( nodeX.name === 'out' ) {
708
+
709
+ material.colorNode = nodeX.getNode();
710
+
711
+ break;
712
+
713
+ }
714
+
715
+ }
716
+
717
+ return material;
718
+
719
+ }
720
+
721
+ toPhysicalMaterial() {
643
722
 
644
723
  const material = new MeshPhysicalNodeMaterial();
645
724
  material.name = this.name;
@@ -659,14 +738,34 @@ class MaterialXNode {
659
738
 
660
739
  const materials = {};
661
740
 
741
+ let isUnlit = true;
742
+
662
743
  for ( const nodeX of this.children ) {
663
744
 
664
745
  if ( nodeX.element === 'surfacematerial' ) {
665
746
 
666
- const material = nodeX.toMaterial();
747
+ const material = nodeX.toPhysicalMaterial();
667
748
 
668
749
  materials[ material.name ] = material;
669
750
 
751
+ isUnlit = false;
752
+
753
+ }
754
+
755
+ }
756
+
757
+ if ( isUnlit ) {
758
+
759
+ for ( const nodeX of this.children ) {
760
+
761
+ if ( nodeX.element === 'nodegraph' ) {
762
+
763
+ const material = nodeX.toBasicMaterial();
764
+
765
+ materials[ material.name ] = material;
766
+
767
+ }
768
+
670
769
  }
671
770
 
672
771
  }
@@ -2924,8 +2924,8 @@ class SVGLoader extends Loader {
2924
2924
  addVertex( currentPointL, u1, 0 );
2925
2925
 
2926
2926
  addVertex( lastPointR, u0, 1 );
2927
- addVertex( currentPointL, u1, 1 );
2928
- addVertex( currentPointR, u1, 0 );
2927
+ addVertex( currentPointL, u1, 0 );
2928
+ addVertex( currentPointR, u1, 1 );
2929
2929
 
2930
2930
  }
2931
2931
 
@@ -3082,7 +3082,8 @@ class SVGLoader extends Loader {
3082
3082
  } else {
3083
3083
 
3084
3084
  tempV2_3.toArray( vertices, 1 * 3 );
3085
- tempV2_3.toArray( vertices, 3 * 3 );
3085
+ // using tempV2_4 to update 3rd vertex if the uv.y of 3rd vertex is 1
3086
+ uvs[ 3 * 2 + 1 ] === 1 ? tempV2_4.toArray( vertices, 3 * 3 ) : tempV2_3.toArray( vertices, 3 * 3 );
3086
3087
  tempV2_4.toArray( vertices, 0 * 3 );
3087
3088
 
3088
3089
  }
@@ -126,7 +126,7 @@ class VRMLLoader extends Loader {
126
126
  // from http://gun.teipir.gr/VRML-amgem/spec/part1/concepts.html#SyntaxBasics
127
127
 
128
128
  const RouteIdentifier = createToken( { name: 'RouteIdentifier', pattern: /[^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*[\.][^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*/ } );
129
- const Identifier = createToken( { name: 'Identifier', pattern: /[^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*/, longer_alt: RouteIdentifier } );
129
+ const Identifier = createToken( { name: 'Identifier', pattern: /[^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]([^\0-\x20\x22\x27\x23\x2b\x2c\x2e\x5b\x5d\x5c\x7b\x7d])*/, longer_alt: RouteIdentifier } );
130
130
 
131
131
  // from http://gun.teipir.gr/VRML-amgem/spec/part1/nodesRef.html
132
132