super-three 0.172.0 → 0.173.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 (178) hide show
  1. package/LICENSE +1 -1
  2. package/build/three.cjs +439 -380
  3. package/build/three.core.js +413 -41
  4. package/build/three.core.min.js +2 -2
  5. package/build/three.module.js +28 -344
  6. package/build/three.module.min.js +2 -2
  7. package/build/three.tsl.js +11 -3
  8. package/build/three.tsl.min.js +2 -2
  9. package/build/three.webgpu.js +7550 -1798
  10. package/build/three.webgpu.min.js +2 -2
  11. package/build/three.webgpu.nodes.js +7551 -1798
  12. package/build/three.webgpu.nodes.min.js +2 -2
  13. package/examples/jsm/animation/CCDIKSolver.js +6 -5
  14. package/examples/jsm/capabilities/WebGPU.js +1 -1
  15. package/examples/jsm/controls/ArcballControls.js +23 -21
  16. package/examples/jsm/exporters/GLTFExporter.js +26 -25
  17. package/examples/jsm/geometries/TextGeometry.js +1 -12
  18. package/examples/jsm/interactive/InteractiveGroup.js +108 -51
  19. package/examples/jsm/libs/demuxer_mp4.js +109 -0
  20. package/examples/jsm/loaders/GCodeLoader.js +3 -1
  21. package/examples/jsm/loaders/GLTFLoader.js +0 -2
  22. package/examples/jsm/loaders/TDSLoader.js +0 -1
  23. package/examples/jsm/materials/MeshGouraudMaterial.js +2 -0
  24. package/examples/jsm/misc/GPUComputationRenderer.js +6 -7
  25. package/examples/jsm/misc/ProgressiveLightMap.js +4 -3
  26. package/examples/jsm/misc/ProgressiveLightMapGPU.js +4 -3
  27. package/examples/jsm/misc/Volume.js +7 -5
  28. package/examples/jsm/misc/VolumeSlice.js +5 -3
  29. package/examples/jsm/objects/WaterMesh.js +25 -20
  30. package/examples/jsm/physics/JoltPhysics.js +7 -7
  31. package/examples/jsm/physics/RapierPhysics.js +4 -4
  32. package/examples/jsm/postprocessing/OutputPass.js +2 -0
  33. package/examples/jsm/shaders/OutputShader.js +5 -1
  34. package/examples/jsm/transpiler/GLSLDecoder.js +2 -2
  35. package/examples/jsm/transpiler/TSLEncoder.js +2 -0
  36. package/package.json +1 -1
  37. package/src/Three.Core.js +2 -0
  38. package/src/Three.TSL.js +9 -1
  39. package/src/cameras/ArrayCamera.js +1 -0
  40. package/src/constants.js +6 -1
  41. package/src/core/BufferAttribute.js +4 -0
  42. package/src/core/EventDispatcher.js +8 -6
  43. package/src/extras/ImageUtils.js +1 -11
  44. package/src/loaders/nodes/NodeObjectLoader.js +1 -1
  45. package/src/materials/nodes/MeshBasicNodeMaterial.js +1 -1
  46. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +1 -1
  47. package/src/materials/nodes/NodeMaterial.js +5 -5
  48. package/src/materials/nodes/NodeMaterials.js +0 -1
  49. package/src/materials/nodes/PointsNodeMaterial.js +109 -7
  50. package/src/materials/nodes/SpriteNodeMaterial.js +1 -1
  51. package/src/materials/nodes/VolumeNodeMaterial.js +3 -3
  52. package/src/materials/nodes/manager/NodeMaterialObserver.js +8 -0
  53. package/src/nodes/Nodes.js +4 -0
  54. package/src/nodes/TSL.js +4 -0
  55. package/src/nodes/accessors/Arrays.js +30 -8
  56. package/src/nodes/accessors/BatchNode.js +3 -3
  57. package/src/nodes/accessors/BufferAttributeNode.js +1 -1
  58. package/src/nodes/accessors/Camera.js +64 -3
  59. package/src/nodes/accessors/InstanceNode.js +1 -1
  60. package/src/nodes/accessors/MaterialNode.js +9 -9
  61. package/src/nodes/accessors/ModelViewProjectionNode.js +1 -1
  62. package/src/nodes/accessors/Normal.js +6 -2
  63. package/src/nodes/accessors/Object3DNode.js +0 -1
  64. package/src/nodes/accessors/Position.js +6 -6
  65. package/src/nodes/accessors/ReferenceBaseNode.js +2 -4
  66. package/src/nodes/accessors/ReferenceNode.js +2 -3
  67. package/src/nodes/accessors/StorageBufferNode.js +42 -5
  68. package/src/nodes/accessors/Tangent.js +2 -2
  69. package/src/nodes/accessors/Texture3DNode.js +1 -1
  70. package/src/nodes/accessors/TextureNode.js +12 -5
  71. package/src/nodes/accessors/UniformArrayNode.js +9 -3
  72. package/src/nodes/accessors/VelocityNode.js +0 -2
  73. package/src/nodes/code/ScriptableNode.js +3 -3
  74. package/src/nodes/core/ArrayNode.js +125 -0
  75. package/src/nodes/core/ConstNode.js +8 -0
  76. package/src/nodes/core/Node.js +14 -1
  77. package/src/nodes/core/NodeBuilder.js +229 -19
  78. package/src/nodes/core/NodeUtils.js +11 -1
  79. package/src/nodes/core/NodeVar.js +17 -1
  80. package/src/nodes/core/OutputStructNode.js +19 -9
  81. package/src/nodes/core/StackNode.js +20 -1
  82. package/src/nodes/core/StructNode.js +121 -0
  83. package/src/nodes/core/StructType.js +13 -0
  84. package/src/nodes/core/StructTypeNode.js +82 -21
  85. package/src/nodes/core/TempNode.js +1 -1
  86. package/src/nodes/core/VarNode.js +94 -7
  87. package/src/nodes/core/VaryingNode.js +19 -3
  88. package/src/nodes/display/BlendModes.js +88 -1
  89. package/src/nodes/display/BumpMapNode.js +6 -6
  90. package/src/nodes/display/NormalMapNode.js +6 -6
  91. package/src/nodes/display/PassNode.js +3 -1
  92. package/src/nodes/display/ScreenNode.js +9 -0
  93. package/src/nodes/fog/Fog.js +17 -0
  94. package/src/nodes/gpgpu/AtomicFunctionNode.js +20 -4
  95. package/src/nodes/gpgpu/ComputeBuiltinNode.js +8 -0
  96. package/src/nodes/gpgpu/WorkgroupInfoNode.js +1 -1
  97. package/src/nodes/lighting/ShadowNode.js +1 -1
  98. package/src/nodes/math/ConditionalNode.js +8 -1
  99. package/src/nodes/math/MathNode.js +14 -1
  100. package/src/nodes/math/OperatorNode.js +96 -18
  101. package/src/nodes/pmrem/PMREMUtils.js +1 -1
  102. package/src/nodes/shapes/Shapes.js +33 -0
  103. package/src/nodes/tsl/TSLBase.js +1 -0
  104. package/src/nodes/tsl/TSLCore.js +22 -2
  105. package/src/nodes/utils/ArrayElementNode.js +1 -1
  106. package/src/nodes/utils/LoopNode.js +8 -1
  107. package/src/nodes/utils/MemberNode.js +68 -0
  108. package/src/nodes/utils/StorageArrayElementNode.js +14 -0
  109. package/src/nodes/utils/Timer.js +21 -0
  110. package/src/objects/BatchedMesh.js +1 -1
  111. package/src/objects/Line.js +6 -6
  112. package/src/renderers/WebGLRenderer.js +7 -0
  113. package/src/renderers/common/Animation.js +23 -1
  114. package/src/renderers/common/Backend.js +58 -15
  115. package/src/renderers/common/Background.js +14 -0
  116. package/src/renderers/common/Binding.js +1 -1
  117. package/src/renderers/common/BufferUtils.js +1 -1
  118. package/src/renderers/common/BundleGroup.js +1 -1
  119. package/src/renderers/common/ChainMap.js +9 -7
  120. package/src/renderers/common/ClippingContext.js +1 -1
  121. package/src/renderers/common/Color4.js +7 -3
  122. package/src/renderers/common/Geometries.js +2 -23
  123. package/src/renderers/common/Info.js +1 -45
  124. package/src/renderers/common/Lighting.js +8 -6
  125. package/src/renderers/common/Pipelines.js +3 -3
  126. package/src/renderers/common/PostProcessing.js +24 -8
  127. package/src/renderers/common/QuadMesh.js +1 -1
  128. package/src/renderers/common/RenderBundles.js +9 -3
  129. package/src/renderers/common/RenderContext.js +37 -3
  130. package/src/renderers/common/RenderContexts.js +30 -17
  131. package/src/renderers/common/RenderList.js +2 -2
  132. package/src/renderers/common/RenderLists.js +9 -3
  133. package/src/renderers/common/RenderObject.js +76 -17
  134. package/src/renderers/common/RenderObjects.js +9 -7
  135. package/src/renderers/common/Renderer.js +86 -67
  136. package/src/renderers/common/SampledTexture.js +0 -1
  137. package/src/renderers/common/StorageBufferAttribute.js +1 -1
  138. package/src/renderers/common/StorageInstancedBufferAttribute.js +1 -1
  139. package/src/renderers/common/StorageTexture.js +1 -1
  140. package/src/renderers/common/Textures.js +14 -7
  141. package/src/renderers/common/TimestampQueryPool.js +39 -0
  142. package/src/renderers/common/Uniform.js +37 -1
  143. package/src/renderers/common/UniformsGroup.js +2 -0
  144. package/src/renderers/common/XRManager.js +1193 -0
  145. package/src/renderers/common/XRRenderTarget.js +74 -0
  146. package/src/renderers/common/extras/PMREMGenerator.js +53 -8
  147. package/src/renderers/common/nodes/NodeBuilderState.js +4 -4
  148. package/src/renderers/common/nodes/NodeLibrary.js +5 -5
  149. package/src/renderers/common/nodes/NodeSampledTexture.js +0 -1
  150. package/src/renderers/common/nodes/NodeUniform.js +54 -2
  151. package/src/renderers/common/nodes/Nodes.js +25 -18
  152. package/src/renderers/webgl/WebGLBackground.js +4 -0
  153. package/src/renderers/webgl-fallback/WebGLBackend.js +295 -110
  154. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +347 -17
  155. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +57 -0
  156. package/src/renderers/webgl-fallback/utils/WebGLCapabilities.js +28 -0
  157. package/src/renderers/webgl-fallback/utils/WebGLExtensions.js +45 -0
  158. package/src/renderers/webgl-fallback/utils/WebGLState.js +323 -11
  159. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +167 -21
  160. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +359 -0
  161. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +43 -0
  162. package/src/renderers/webgpu/WebGPUBackend.js +132 -149
  163. package/src/renderers/webgpu/WebGPURenderer.Nodes.js +6 -4
  164. package/src/renderers/webgpu/WebGPURenderer.js +5 -4
  165. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +615 -41
  166. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +85 -6
  167. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +85 -0
  168. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +102 -3
  169. package/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js +98 -1
  170. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +257 -9
  171. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +274 -0
  172. package/src/renderers/webgpu/utils/WebGPUUtils.js +86 -4
  173. package/src/renderers/webxr/WebXRManager.js +13 -2
  174. package/src/textures/VideoFrameTexture.js +35 -0
  175. package/examples/jsm/geometries/InstancedPointsGeometry.js +0 -176
  176. package/examples/jsm/objects/InstancedPoints.js +0 -19
  177. package/src/materials/nodes/InstancedPointsNodeMaterial.js +0 -209
  178. package/src/nodes/accessors/InstancedPointsMaterialNode.js +0 -37
@@ -5,7 +5,7 @@ import NodeVar from './NodeVar.js';
5
5
  import NodeCode from './NodeCode.js';
6
6
  import NodeCache from './NodeCache.js';
7
7
  import ParameterNode from './ParameterNode.js';
8
- import StructTypeNode from './StructTypeNode.js';
8
+ import StructType from './StructType.js';
9
9
  import FunctionNode from '../code/FunctionNode.js';
10
10
  import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
11
11
  import { getTypeFromLength } from './NodeUtils.js';
@@ -13,7 +13,7 @@ import { NodeUpdateType, defaultBuildStages, shaderStages } from './constants.js
13
13
 
14
14
  import {
15
15
  NumberNodeUniform, Vector2NodeUniform, Vector3NodeUniform, Vector4NodeUniform,
16
- ColorNodeUniform, Matrix3NodeUniform, Matrix4NodeUniform
16
+ ColorNodeUniform, Matrix2NodeUniform, Matrix3NodeUniform, Matrix4NodeUniform
17
17
  } from '../../renderers/common/nodes/NodeUniform.js';
18
18
 
19
19
  import { stack } from './StackNode.js';
@@ -177,7 +177,7 @@ class NodeBuilder {
177
177
  * @type {NodeMaterialObserver?}
178
178
  * @default null
179
179
  */
180
- this.monitor = null;
180
+ this.observer = null;
181
181
 
182
182
  /**
183
183
  * A reference to the current lights node.
@@ -497,6 +497,15 @@ class NodeBuilder {
497
497
 
498
498
  }
499
499
 
500
+ /**
501
+ * Returns the output struct name which is required by
502
+ * {@link module:OutputStructNode}.
503
+ *
504
+ * @abstract
505
+ * @return {String} The name of the output struct.
506
+ */
507
+ getOutputStructName() {}
508
+
500
509
  /**
501
510
  * Returns a bind group for the given group name and binding.
502
511
  *
@@ -1034,15 +1043,98 @@ class NodeBuilder {
1034
1043
  * @param {Texture} texture - The texture.
1035
1044
  * @param {String} textureProperty - The texture property name.
1036
1045
  * @param {String} uvSnippet - Snippet defining the texture coordinates.
1046
+ * @param {String?} depthSnippet - Snippet defining the 0-based texture array index to sample.
1037
1047
  * @param {String} levelSnippet - Snippet defining the mip level.
1038
1048
  * @return {String} The generated shader string.
1039
1049
  */
1040
- generateTextureLod( /* texture, textureProperty, uvSnippet, levelSnippet */ ) {
1050
+ generateTextureLod( /* texture, textureProperty, uvSnippet, depthSnippet, levelSnippet */ ) {
1041
1051
 
1042
1052
  console.warn( 'Abstract function.' );
1043
1053
 
1044
1054
  }
1045
1055
 
1056
+ /**
1057
+ * Generates the array declaration string.
1058
+ *
1059
+ * @param {String} type - The type.
1060
+ * @param {Number?} [count] - The count.
1061
+ * @return {String} The generated value as a shader string.
1062
+ */
1063
+ generateArrayDeclaration( type, count ) {
1064
+
1065
+ return this.getType( type ) + '[ ' + count + ' ]';
1066
+
1067
+ }
1068
+
1069
+ /**
1070
+ * Generates the array shader string for the given type and value.
1071
+ *
1072
+ * @param {String} type - The type.
1073
+ * @param {Number?} [count] - The count.
1074
+ * @param {Array<Node>?} [values=null] - The default values.
1075
+ * @return {String} The generated value as a shader string.
1076
+ */
1077
+ generateArray( type, count, values = null ) {
1078
+
1079
+ let snippet = this.generateArrayDeclaration( type, count ) + '( ';
1080
+
1081
+ for ( let i = 0; i < count; i ++ ) {
1082
+
1083
+ const value = values ? values[ i ] : null;
1084
+
1085
+ if ( value !== null ) {
1086
+
1087
+ snippet += value.build( this, type );
1088
+
1089
+ } else {
1090
+
1091
+ snippet += this.generateConst( type );
1092
+
1093
+ }
1094
+
1095
+ if ( i < count - 1 ) snippet += ', ';
1096
+
1097
+ }
1098
+
1099
+ snippet += ' )';
1100
+
1101
+ return snippet;
1102
+
1103
+ }
1104
+
1105
+ /**
1106
+ * Generates the struct shader string.
1107
+ *
1108
+ * @param {String} type - The type.
1109
+ * @param {Array<Object>} [membersLayout] - The count.
1110
+ * @param {Array<Node>?} [values=null] - The default values.
1111
+ * @return {String} The generated value as a shader string.
1112
+ */
1113
+ generateStruct( type, membersLayout, values = null ) {
1114
+
1115
+ const snippets = [];
1116
+
1117
+ for ( const member of membersLayout ) {
1118
+
1119
+ const { name, type } = member;
1120
+
1121
+ if ( values && values[ name ] && values[ name ].isNode ) {
1122
+
1123
+ snippets.push( values[ name ].build( this, type ) );
1124
+
1125
+ } else {
1126
+
1127
+ snippets.push( this.generateConst( type ) );
1128
+
1129
+ }
1130
+
1131
+ }
1132
+
1133
+ return type + '( ' + snippets.join( ', ' ) + ' )';
1134
+
1135
+ }
1136
+
1137
+
1046
1138
  /**
1047
1139
  * Generates the shader string for the given type and value.
1048
1140
  *
@@ -1211,11 +1303,11 @@ class NodeBuilder {
1211
1303
  }
1212
1304
 
1213
1305
  /**
1214
- * Whether the given texture needs a conversion to working color space.
1306
+ * Checks if the given texture requires a manual conversion to the working color space.
1215
1307
  *
1216
1308
  * @abstract
1217
1309
  * @param {Texture} texture - The texture to check.
1218
- * @return {Boolean} Whether a color space conversion is required or not.
1310
+ * @return {Boolean} Whether the given texture requires a conversion to working color space or not.
1219
1311
  */
1220
1312
  needsToWorkingColorSpace( /*texture*/ ) {
1221
1313
 
@@ -1310,9 +1402,16 @@ class NodeBuilder {
1310
1402
 
1311
1403
  if ( length === 1 ) return componentType;
1312
1404
 
1313
- const baseType = getTypeFromLength( length );
1405
+ let baseType = getTypeFromLength( length );
1314
1406
  const prefix = componentType === 'float' ? '' : componentType[ 0 ];
1315
1407
 
1408
+ // fix edge case for mat2x2 being same size as vec4
1409
+ if ( /mat2/.test( componentType ) === true ) {
1410
+
1411
+ baseType = baseType.replace( 'vec', 'mat' );
1412
+
1413
+ }
1414
+
1316
1415
  return prefix + baseType;
1317
1416
 
1318
1417
  }
@@ -1527,14 +1626,15 @@ class NodeBuilder {
1527
1626
  }
1528
1627
 
1529
1628
  /**
1530
- * Returns an instance of {@link StructTypeNode} for the given output struct node.
1629
+ * Returns an instance of {@link StructType} for the given output struct node.
1531
1630
  *
1532
1631
  * @param {OutputStructNode} node - The output struct node.
1533
- * @param {Array<String>} types - The output struct types.
1632
+ * @param {Array<Object>} membersLayout - The output struct types.
1633
+ * @param {String?} [name=null] - The name of the struct.
1534
1634
  * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
1535
- * @return {StructTypeNode} The struct type attribute.
1635
+ * @return {StructType} The struct type attribute.
1536
1636
  */
1537
- getStructTypeFromNode( node, types, shaderStage = this.shaderStage ) {
1637
+ getStructTypeFromNode( node, membersLayout, name = null, shaderStage = this.shaderStage ) {
1538
1638
 
1539
1639
  const nodeData = this.getDataFromNode( node, shaderStage );
1540
1640
 
@@ -1544,7 +1644,9 @@ class NodeBuilder {
1544
1644
 
1545
1645
  const index = this.structs.index ++;
1546
1646
 
1547
- structType = new StructTypeNode( 'StructType' + index, types );
1647
+ if ( name === null ) name = 'StructType' + index;
1648
+
1649
+ structType = new StructType( name, membersLayout );
1548
1650
 
1549
1651
  this.structs[ shaderStage ].push( structType );
1550
1652
 
@@ -1556,6 +1658,22 @@ class NodeBuilder {
1556
1658
 
1557
1659
  }
1558
1660
 
1661
+ /**
1662
+ * Returns an instance of {@link StructType} for the given output struct node.
1663
+ *
1664
+ * @param {OutputStructNode} node - The output struct node.
1665
+ * @param {Array<Object>} membersLayout - The output struct types.
1666
+ * @return {StructType} The struct type attribute.
1667
+ */
1668
+ getOutputStructTypeFromNode( node, membersLayout ) {
1669
+
1670
+ const structType = this.getStructTypeFromNode( node, membersLayout, 'OutputType', 'fragment' );
1671
+ structType.output = true;
1672
+
1673
+ return structType;
1674
+
1675
+ }
1676
+
1559
1677
  /**
1560
1678
  * Returns an instance of {@link NodeUniform} for the given uniform node.
1561
1679
  *
@@ -1587,6 +1705,23 @@ class NodeBuilder {
1587
1705
 
1588
1706
  }
1589
1707
 
1708
+ /**
1709
+ * Returns the array length.
1710
+ *
1711
+ * @param {Node} node - The node.
1712
+ * @return {Number?} The array length.
1713
+ */
1714
+ getArrayCount( node ) {
1715
+
1716
+ let count = null;
1717
+
1718
+ if ( node.isArrayNode ) count = node.count;
1719
+ else if ( node.isVarNode && node.node.isArrayNode ) count = node.node.count;
1720
+
1721
+ return count;
1722
+
1723
+ }
1724
+
1590
1725
  /**
1591
1726
  * Returns an instance of {@link NodeVar} for the given variable node.
1592
1727
  *
@@ -1594,9 +1729,11 @@ class NodeBuilder {
1594
1729
  * @param {String?} name - The variable's name.
1595
1730
  * @param {String} [type=node.getNodeType( this )] - The variable's type.
1596
1731
  * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
1732
+ * @param {Boolean} [readOnly=false] - Whether the variable is read-only or not.
1733
+ *
1597
1734
  * @return {NodeVar} The node variable.
1598
1735
  */
1599
- getVarFromNode( node, name = null, type = node.getNodeType( this ), shaderStage = this.shaderStage ) {
1736
+ getVarFromNode( node, name = null, type = node.getNodeType( this ), shaderStage = this.shaderStage, readOnly = false ) {
1600
1737
 
1601
1738
  const nodeData = this.getDataFromNode( node, shaderStage );
1602
1739
 
@@ -1604,13 +1741,30 @@ class NodeBuilder {
1604
1741
 
1605
1742
  if ( nodeVar === undefined ) {
1606
1743
 
1744
+ const idNS = readOnly ? '_const' : '_var';
1745
+
1607
1746
  const vars = this.vars[ shaderStage ] || ( this.vars[ shaderStage ] = [] );
1747
+ const id = this.vars[ idNS ] || ( this.vars[ idNS ] = 0 );
1608
1748
 
1609
- if ( name === null ) name = 'nodeVar' + vars.length;
1749
+ if ( name === null ) {
1610
1750
 
1611
- nodeVar = new NodeVar( name, type );
1751
+ name = ( readOnly ? 'nodeConst' : 'nodeVar' ) + id;
1612
1752
 
1613
- vars.push( nodeVar );
1753
+ this.vars[ idNS ] ++;
1754
+
1755
+ }
1756
+
1757
+ //
1758
+
1759
+ const count = this.getArrayCount( node );
1760
+
1761
+ nodeVar = new NodeVar( name, type, readOnly, count );
1762
+
1763
+ if ( ! readOnly ) {
1764
+
1765
+ vars.push( nodeVar );
1766
+
1767
+ }
1614
1768
 
1615
1769
  nodeData.variable = nodeVar;
1616
1770
 
@@ -1620,6 +1774,53 @@ class NodeBuilder {
1620
1774
 
1621
1775
  }
1622
1776
 
1777
+ /**
1778
+ * Returns whether a Node or its flow is deterministic, useful for use in `const`.
1779
+ *
1780
+ * @param {Node} node - The varying node.
1781
+ * @return {Boolean} Returns true if deterministic.
1782
+ */
1783
+ isDeterministic( node ) {
1784
+
1785
+ if ( node.isMathNode ) {
1786
+
1787
+ return this.isDeterministic( node.aNode ) &&
1788
+ ( node.bNode ? this.isDeterministic( node.bNode ) : true ) &&
1789
+ ( node.cNode ? this.isDeterministic( node.cNode ) : true );
1790
+
1791
+ } else if ( node.isOperatorNode ) {
1792
+
1793
+ return this.isDeterministic( node.aNode ) &&
1794
+ ( node.bNode ? this.isDeterministic( node.bNode ) : true );
1795
+
1796
+ } else if ( node.isArrayNode ) {
1797
+
1798
+ if ( node.values !== null ) {
1799
+
1800
+ for ( const n of node.values ) {
1801
+
1802
+ if ( ! this.isDeterministic( n ) ) {
1803
+
1804
+ return false;
1805
+
1806
+ }
1807
+
1808
+ }
1809
+
1810
+ }
1811
+
1812
+ return true;
1813
+
1814
+ } else if ( node.isConstNode ) {
1815
+
1816
+ return true;
1817
+
1818
+ }
1819
+
1820
+ return false;
1821
+
1822
+ }
1823
+
1623
1824
  /**
1624
1825
  * Returns an instance of {@link NodeVarying} for the given varying node.
1625
1826
  *
@@ -2073,11 +2274,12 @@ class NodeBuilder {
2073
2274
  *
2074
2275
  * @param {String} type - The variable's type.
2075
2276
  * @param {String} name - The variable's name.
2277
+ * @param {Number?} [count=null] - The array length.
2076
2278
  * @return {String} The shader string.
2077
2279
  */
2078
- getVar( type, name ) {
2280
+ getVar( type, name, count = null ) {
2079
2281
 
2080
- return `${ this.getType( type ) } ${ name }`;
2282
+ return `${ count !== null ? this.generateArrayDeclaration( type, count ) : this.getType( type ) } ${ name }`;
2081
2283
 
2082
2284
  }
2083
2285
 
@@ -2305,6 +2507,7 @@ class NodeBuilder {
2305
2507
  if ( type === 'vec3' || type === 'ivec3' || type === 'uvec3' ) return new Vector3NodeUniform( uniformNode );
2306
2508
  if ( type === 'vec4' || type === 'ivec4' || type === 'uvec4' ) return new Vector4NodeUniform( uniformNode );
2307
2509
  if ( type === 'color' ) return new ColorNodeUniform( uniformNode );
2510
+ if ( type === 'mat2' ) return new Matrix2NodeUniform( uniformNode );
2308
2511
  if ( type === 'mat3' ) return new Matrix3NodeUniform( uniformNode );
2309
2512
  if ( type === 'mat4' ) return new Matrix4NodeUniform( uniformNode );
2310
2513
 
@@ -2413,8 +2616,15 @@ class NodeBuilder {
2413
2616
 
2414
2617
  }
2415
2618
 
2416
- // deprecated
2619
+ // Deprecated
2417
2620
 
2621
+ /**
2622
+ * @function
2623
+ * @deprecated since r168. Use `new NodeMaterial()` instead, with targeted node material name.
2624
+ *
2625
+ * @param {String} [type='NodeMaterial'] - The node material type.
2626
+ * @throws {Error}
2627
+ */
2418
2628
  createNodeMaterial( type = 'NodeMaterial' ) { // @deprecated, r168
2419
2629
 
2420
2630
  throw new Error( `THREE.NodeBuilder: createNodeMaterial() was deprecated. Use new ${ type }() instead.` );
@@ -1,4 +1,5 @@
1
1
  import { Color } from '../../math/Color.js';
2
+ import { Matrix2 } from '../../math/Matrix2.js';
2
3
  import { Matrix3 } from '../../math/Matrix3.js';
3
4
  import { Matrix4 } from '../../math/Matrix4.js';
4
5
  import { Vector2 } from '../../math/Vector2.js';
@@ -95,7 +96,7 @@ export function getCacheKey( object, force = false ) {
95
96
 
96
97
  for ( const { property, childNode } of getNodeChildren( object ) ) {
97
98
 
98
- values.push( values, cyrb53( property.slice( 0, - 4 ) ), childNode.getCacheKey( force ) );
99
+ values.push( cyrb53( property.slice( 0, - 4 ) ), childNode.getCacheKey( force ) );
99
100
 
100
101
  }
101
102
 
@@ -229,6 +230,7 @@ export function getLengthFromType( type ) {
229
230
  if ( /vec2/.test( type ) ) return 2;
230
231
  if ( /vec3/.test( type ) ) return 3;
231
232
  if ( /vec4/.test( type ) ) return 4;
233
+ if ( /mat2/.test( type ) ) return 4;
232
234
  if ( /mat3/.test( type ) ) return 9;
233
235
  if ( /mat4/.test( type ) ) return 16;
234
236
 
@@ -281,6 +283,10 @@ export function getValueType( value ) {
281
283
 
282
284
  return 'vec4';
283
285
 
286
+ } else if ( value.isMatrix2 === true ) {
287
+
288
+ return 'mat2';
289
+
284
290
  } else if ( value.isMatrix3 === true ) {
285
291
 
286
292
  return 'mat3';
@@ -339,6 +345,10 @@ export function getValueFromType( type, ...params ) {
339
345
 
340
346
  return new Vector4( ...params );
341
347
 
348
+ } else if ( last4 === 'mat2' ) {
349
+
350
+ return new Matrix2( ...params );
351
+
342
352
  } else if ( last4 === 'mat3' ) {
343
353
 
344
354
  return new Matrix3( ...params );
@@ -11,8 +11,10 @@ class NodeVar {
11
11
  *
12
12
  * @param {String} name - The name of the variable.
13
13
  * @param {String} type - The type of the variable.
14
+ * @param {Boolean} [readOnly=false] - The read-only flag.
15
+ * @param {Number?} [count=null] - The size.
14
16
  */
15
- constructor( name, type ) {
17
+ constructor( name, type, readOnly = false, count = null ) {
16
18
 
17
19
  /**
18
20
  * This flag can be used for type testing.
@@ -37,6 +39,20 @@ class NodeVar {
37
39
  */
38
40
  this.type = type;
39
41
 
42
+ /**
43
+ * The read-only flag.
44
+ *
45
+ * @type {Boolean}
46
+ */
47
+ this.readOnly = readOnly;
48
+
49
+ /**
50
+ * The size.
51
+ *
52
+ * @type {Number?}
53
+ */
54
+ this.count = count;
55
+
40
56
  }
41
57
 
42
58
  }
@@ -44,24 +44,34 @@ class OutputStructNode extends Node {
44
44
 
45
45
  }
46
46
 
47
- setup( builder ) {
47
+ getNodeType( builder ) {
48
48
 
49
- super.setup( builder );
49
+ const properties = builder.getNodeProperties( this );
50
50
 
51
- const members = this.members;
52
- const types = [];
51
+ if ( properties.membersLayout === undefined ) {
53
52
 
54
- for ( let i = 0; i < members.length; i ++ ) {
53
+ const members = this.members;
54
+ const membersLayout = [];
55
+
56
+ for ( let i = 0; i < members.length; i ++ ) {
57
+
58
+ const name = 'm' + i;
59
+ const type = members[ i ].getNodeType( builder );
60
+
61
+ membersLayout.push( { name, type, index: i } );
62
+
63
+ }
55
64
 
56
- types.push( members[ i ].getNodeType( builder ) );
65
+ properties.membersLayout = membersLayout;
66
+ properties.structType = builder.getOutputStructTypeFromNode( this, properties.membersLayout );
57
67
 
58
68
  }
59
69
 
60
- this.nodeType = builder.getStructTypeFromNode( this, types ).name;
70
+ return properties.structType.name;
61
71
 
62
72
  }
63
73
 
64
- generate( builder, output ) {
74
+ generate( builder ) {
65
75
 
66
76
  const propertyName = builder.getOutputStructName();
67
77
  const members = this.members;
@@ -70,7 +80,7 @@ class OutputStructNode extends Node {
70
80
 
71
81
  for ( let i = 0; i < members.length; i ++ ) {
72
82
 
73
- const snippet = members[ i ].build( builder, output );
83
+ const snippet = members[ i ].build( builder );
74
84
 
75
85
  builder.addLineFlowCode( `${ structPrefix }m${ i } = ${ snippet }`, this );
76
86
 
@@ -76,6 +76,12 @@ class StackNode extends Node {
76
76
 
77
77
  }
78
78
 
79
+ getMemberType( builder, name ) {
80
+
81
+ return this.outputNode ? this.outputNode.getMemberType( builder, name ) : 'void';
82
+
83
+ }
84
+
79
85
  /**
80
86
  * Adds a node to this stack.
81
87
  *
@@ -157,8 +163,15 @@ class StackNode extends Node {
157
163
 
158
164
  }
159
165
 
160
- //
166
+ // Deprecated
161
167
 
168
+ /**
169
+ * @function
170
+ * @deprecated since r168. Use {@link StackNode#Else} instead.
171
+ *
172
+ * @param {...any} params
173
+ * @returns {StackNode}
174
+ */
162
175
  else( ...params ) { // @deprecated, r168
163
176
 
164
177
  console.warn( 'TSL.StackNode: .else() has been renamed to .Else().' );
@@ -166,6 +179,12 @@ class StackNode extends Node {
166
179
 
167
180
  }
168
181
 
182
+ /**
183
+ * @deprecated since r168. Use {@link StackNode#ElseIf} instead.
184
+ *
185
+ * @param {...any} params
186
+ * @returns {StackNode}
187
+ */
169
188
  elseif( ...params ) { // @deprecated, r168
170
189
 
171
190
  console.warn( 'TSL.StackNode: .elseif() has been renamed to .ElseIf().' );
@@ -0,0 +1,121 @@
1
+ import Node from './Node.js';
2
+ import StructTypeNode from './StructTypeNode.js';
3
+ import { nodeObject } from '../tsl/TSLCore.js';
4
+
5
+ /** @module StructNode **/
6
+
7
+ /**
8
+ * StructNode allows to create custom structures with multiple members.
9
+ * This can also be used to define structures in attribute and uniform data.
10
+ *
11
+ * ```js
12
+ * // Define a custom struct
13
+ * const BoundingBox = struct( { min: 'vec3', max: 'vec3' } );
14
+ *
15
+ * // Create a new instance of the struct
16
+ * const bb = BoundingBox( vec3( 0 ), vec3( 1 ) ); // style 1
17
+ * const bb = BoundingBox( { min: vec3( 0 ), max: vec3( 1 ) } ); // style 2
18
+ *
19
+ * // Access the struct members
20
+ * const min = bb.get( 'min' );
21
+ *
22
+ * // Assign a new value to a member
23
+ * min.assign( vec3() );
24
+ * ```
25
+ * @augments Node
26
+ */
27
+ class StructNode extends Node {
28
+
29
+ static get type() {
30
+
31
+ return 'StructNode';
32
+
33
+ }
34
+
35
+ constructor( structLayoutNode, values ) {
36
+
37
+ super( 'vec3' );
38
+
39
+ this.structLayoutNode = structLayoutNode;
40
+ this.values = values;
41
+
42
+ this.isStructNode = true;
43
+
44
+ }
45
+
46
+ getNodeType( builder ) {
47
+
48
+ return this.structLayoutNode.getNodeType( builder );
49
+
50
+ }
51
+
52
+ getMemberType( builder, name ) {
53
+
54
+ return this.structLayoutNode.getMemberType( builder, name );
55
+
56
+ }
57
+
58
+ generate( builder ) {
59
+
60
+ const nodeVar = builder.getVarFromNode( this );
61
+ const structType = nodeVar.type;
62
+ const propertyName = builder.getPropertyName( nodeVar );
63
+
64
+ builder.addLineFlowCode( `${ propertyName } = ${ builder.generateStruct( structType, this.structLayoutNode.membersLayout, this.values ) }`, this );
65
+
66
+ return nodeVar.name;
67
+
68
+ }
69
+
70
+ }
71
+
72
+ export default StructNode;
73
+
74
+ /**
75
+ * TSL function for creating a struct node.
76
+ *
77
+ * @function
78
+ * @param {Object} membersLayout - The layout of the struct members.
79
+ * @param {string} [name=null] - The name of the struct.
80
+ * @returns {Function} The struct function.
81
+ */
82
+ export const struct = ( membersLayout, name = null ) => {
83
+
84
+ const structLayout = new StructTypeNode( membersLayout, name );
85
+
86
+ const struct = ( ...params ) => {
87
+
88
+ let values = null;
89
+
90
+ if ( params.length > 0 ) {
91
+
92
+ if ( params[ 0 ].isNode ) {
93
+
94
+ values = {};
95
+
96
+ const names = Object.keys( membersLayout );
97
+
98
+ for ( let i = 0; i < params.length; i ++ ) {
99
+
100
+ values[ names[ i ] ] = params[ i ];
101
+
102
+ }
103
+
104
+ } else {
105
+
106
+ values = params[ 0 ];
107
+
108
+ }
109
+
110
+ }
111
+
112
+ return nodeObject( new StructNode( structLayout, values ) );
113
+
114
+ };
115
+
116
+ struct.layout = structLayout;
117
+ struct.isStruct = true;
118
+
119
+ return struct;
120
+
121
+ };
@@ -0,0 +1,13 @@
1
+ class StructType {
2
+
3
+ constructor( name, members ) {
4
+
5
+ this.name = name;
6
+ this.members = members;
7
+ this.output = false;
8
+
9
+ }
10
+
11
+ }
12
+
13
+ export default StructType;