@unikia/upe-renderer 0.186.110 → 0.187.11

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 (506) hide show
  1. package/README.md +5 -7
  2. package/UPSTREAM.md +4 -4
  3. package/build/three.core.js +853 -277
  4. package/build/three.module.js +1098 -1280
  5. package/build/three.tsl.js +41938 -686
  6. package/build/three.webgpu.js +10604 -49055
  7. package/build/three.webgpu.nodes.js +9249 -5788
  8. package/examples/jsm/Addons.js +2 -0
  9. package/examples/jsm/animation/CCDIKSolver.js +17 -5
  10. package/examples/jsm/controls/FirstPersonControls.js +1 -1
  11. package/examples/jsm/controls/OrbitControls.js +27 -14
  12. package/examples/jsm/csm/CSMShader.js +74 -3
  13. package/examples/jsm/curves/CurveExtras.js +4 -4
  14. package/examples/jsm/curves/NURBSCurve.js +14 -0
  15. package/examples/jsm/exporters/EXRExporter.js +673 -16
  16. package/examples/jsm/exporters/GLTFExporter.js +4 -4
  17. package/examples/jsm/exporters/KTX2Exporter.js +1 -1
  18. package/examples/jsm/exporters/OBJExporter.js +48 -5
  19. package/examples/jsm/exporters/PLYExporter.js +22 -11
  20. package/examples/jsm/generators/CityGenerator.js +3 -2
  21. package/examples/jsm/generators/city/SkyscraperGenerator.js +63 -21
  22. package/examples/jsm/gpgpu/BitonicSort.js +30 -23
  23. package/examples/jsm/helpers/VertexTangentsHelper.js +1 -1
  24. package/examples/jsm/inspector/Extension.js +1 -1
  25. package/examples/jsm/inspector/Inspector.js +6 -46
  26. package/examples/jsm/inspector/RendererInspector.js +43 -8
  27. package/examples/jsm/inspector/Storage.js +49 -0
  28. package/examples/jsm/inspector/extensions/color-grading/ColorGrading.js +32 -27
  29. package/examples/jsm/inspector/tabs/Parameters.js +5 -1
  30. package/examples/jsm/inspector/tabs/Performance.js +22 -7
  31. package/examples/jsm/inspector/tabs/Settings.js +1 -1
  32. package/examples/jsm/inspector/tabs/Timeline.js +83 -7
  33. package/examples/jsm/inspector/tabs/Viewer.js +25 -10
  34. package/examples/jsm/inspector/ui/Profiler.js +1 -1
  35. package/examples/jsm/inspector/ui/Style.js +21 -53
  36. package/examples/jsm/inspector/ui/Values.js +28 -3
  37. package/examples/jsm/libs/fflate.module.js +83 -56
  38. package/examples/jsm/libs/mikktspace.README.md +27 -0
  39. package/examples/jsm/libs/mikktspace.module.js +721 -109
  40. package/examples/jsm/lighting/ClusteredLighting.js +100 -2
  41. package/examples/jsm/lighting/LightMapper.js +295 -0
  42. package/examples/jsm/lighting/LightProbeGrid.js +242 -139
  43. package/examples/jsm/lighting/LightProbeGridWebGL.js +30 -14
  44. package/examples/jsm/lighting/vxgi/VXGIConeTracer.js +54 -5
  45. package/examples/jsm/lighting/vxgi/VXGIIrradiance.js +43 -0
  46. package/examples/jsm/lighting/vxgi/VXGINode.js +13 -56
  47. package/examples/jsm/lighting/vxgi/VXGISceneCollector.js +316 -1
  48. package/examples/jsm/lighting/vxgi/VXGIVolume.js +69 -59
  49. package/examples/jsm/lights/SunLight.js +9 -4
  50. package/examples/jsm/lights/SunLightNode.js +3 -3
  51. package/examples/jsm/lines/LineMaterial.js +26 -10
  52. package/examples/jsm/loaders/3DMLoader.js +10 -1
  53. package/examples/jsm/loaders/3MFLoader.js +5 -1
  54. package/examples/jsm/loaders/AMFLoader.js +2 -0
  55. package/examples/jsm/loaders/BVHLoader.js +2 -0
  56. package/examples/jsm/loaders/ColladaLoader.js +8 -0
  57. package/examples/jsm/loaders/DDSLoader.js +1 -1
  58. package/examples/jsm/loaders/DRACOLoader.js +5 -1
  59. package/examples/jsm/loaders/EXRLoader.js +120 -104
  60. package/examples/jsm/loaders/FBXLoader.js +4 -0
  61. package/examples/jsm/loaders/FontLoader.js +2 -0
  62. package/examples/jsm/loaders/GCodeLoader.js +5 -9
  63. package/examples/jsm/loaders/GLTFLoader.js +112 -31
  64. package/examples/jsm/loaders/GaussianSplatPLYLoader.js +2 -0
  65. package/examples/jsm/loaders/HDRCubeTextureLoader.js +3 -0
  66. package/examples/jsm/loaders/IESLoader.js +46 -12
  67. package/examples/jsm/loaders/JXLLoader.js +159 -0
  68. package/examples/jsm/loaders/KMZLoader.js +6 -0
  69. package/examples/jsm/loaders/KSPLATLoader.js +2 -0
  70. package/examples/jsm/loaders/KTX2Loader.js +49 -4
  71. package/examples/jsm/loaders/KTXLoader.js +5 -3
  72. package/examples/jsm/loaders/LDrawLoader.js +15 -22
  73. package/examples/jsm/loaders/LUT3dlLoader.js +5 -1
  74. package/examples/jsm/loaders/LUTCubeLoader.js +6 -2
  75. package/examples/jsm/loaders/LUTImageLoader.js +2 -0
  76. package/examples/jsm/loaders/LWOLoader.js +6 -0
  77. package/examples/jsm/loaders/MD2Loader.js +2 -0
  78. package/examples/jsm/loaders/MDDLoader.js +4 -0
  79. package/examples/jsm/loaders/MTLLoader.js +8 -0
  80. package/examples/jsm/loaders/MaterialXLoader.js +57 -5
  81. package/examples/jsm/loaders/NRRDLoader.js +4 -2
  82. package/examples/jsm/loaders/OBJLoader.js +10 -4
  83. package/examples/jsm/loaders/PCDLoader.js +6 -2
  84. package/examples/jsm/loaders/PDBLoader.js +5 -3
  85. package/examples/jsm/loaders/PLYLoader.js +39 -15
  86. package/examples/jsm/loaders/PVRLoader.js +2 -2
  87. package/examples/jsm/loaders/SPLATLoader.js +2 -0
  88. package/examples/jsm/loaders/SPZLoader.js +2 -0
  89. package/examples/jsm/loaders/STLLoader.js +3 -1
  90. package/examples/jsm/loaders/SVGLoader.js +27 -49
  91. package/examples/jsm/loaders/TDSLoader.js +4 -0
  92. package/examples/jsm/loaders/TGALoader.js +6 -5
  93. package/examples/jsm/loaders/TTFLoader.js +2 -0
  94. package/examples/jsm/loaders/USDLoader.js +14 -0
  95. package/examples/jsm/loaders/UltraHDRLoader.js +2 -0
  96. package/examples/jsm/loaders/VOXLoader.js +3 -0
  97. package/examples/jsm/loaders/VRMLLoader.js +4 -0
  98. package/examples/jsm/loaders/VTKLoader.js +2 -0
  99. package/examples/jsm/loaders/XYZLoader.js +2 -0
  100. package/examples/jsm/loaders/collada/ColladaComposer.js +15 -8
  101. package/examples/jsm/loaders/materialx/MaterialXDocument.js +610 -138
  102. package/examples/jsm/loaders/materialx/MaterialXInterfaceValidation.js +12 -95
  103. package/examples/jsm/loaders/materialx/MaterialXLog.js +4 -0
  104. package/examples/jsm/loaders/materialx/MaterialXNodeDefs.js +99 -0
  105. package/examples/jsm/loaders/materialx/MaterialXNodeInterfaceRegistry.js +760 -1
  106. package/examples/jsm/loaders/materialx/MaterialXNodeLibrary.js +222 -372
  107. package/examples/jsm/loaders/materialx/MaterialXSurfaceMappings.js +163 -259
  108. package/examples/jsm/loaders/materialx/MaterialXUtils.js +25 -0
  109. package/examples/jsm/loaders/materialx/compile/MaterialXCompileRegistry.js +161 -159
  110. package/examples/jsm/loaders/usd/USDAParser.js +56 -47
  111. package/examples/jsm/loaders/usd/USDComposer.js +25 -30
  112. package/examples/jsm/math/ColorConverter.js +7 -3
  113. package/examples/jsm/math/Lut.js +2 -2
  114. package/examples/jsm/math/OBB.js +3 -3
  115. package/examples/jsm/math/Octree.js +20 -17
  116. package/examples/jsm/objects/GaussianSplat.js +5 -4
  117. package/examples/jsm/objects/Reflector.js +5 -0
  118. package/examples/jsm/objects/SkyMesh.js +14 -7
  119. package/examples/jsm/objects/Water2Mesh.js +2 -2
  120. package/examples/jsm/physics/RapierPhysics.js +2 -2
  121. package/examples/jsm/pipelines/MeshletDrawingPipeline.js +5571 -0
  122. package/examples/jsm/pipelines/VisibilityBufferDrawingPipeline.js +954 -0
  123. package/examples/jsm/postprocessing/BokehPass.js +1 -1
  124. package/examples/jsm/postprocessing/GTAOPass.js +26 -18
  125. package/examples/jsm/renderers/SVGRenderer.js +3 -2
  126. package/examples/jsm/shaders/GTAOShader.js +7 -4
  127. package/examples/jsm/shaders/PoissonDenoiseShader.js +1 -10
  128. package/examples/jsm/tsl/WebGLNodesHandler.js +21 -9
  129. package/examples/jsm/tsl/display/AfterImageNode.js +3 -3
  130. package/examples/jsm/tsl/display/BilateralBlurNode.js +3 -3
  131. package/examples/jsm/tsl/display/BloomNode.js +3 -3
  132. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +8 -19
  133. package/examples/jsm/tsl/display/DenoiseNode.js +5 -5
  134. package/examples/jsm/tsl/display/DepthOfFieldNode.js +3 -3
  135. package/examples/jsm/tsl/display/DotScreenNode.js +3 -3
  136. package/examples/jsm/tsl/display/FSR1Node.js +3 -3
  137. package/examples/jsm/tsl/display/FXAANode.js +3 -10
  138. package/examples/jsm/tsl/display/FilmNode.js +3 -3
  139. package/examples/jsm/tsl/display/GTAONode.js +33 -25
  140. package/examples/jsm/tsl/display/GaussianBlurNode.js +3 -3
  141. package/examples/jsm/tsl/display/GodraysNode.js +5 -19
  142. package/examples/jsm/tsl/display/ImportanceSampledEnvironment.js +8 -4
  143. package/examples/jsm/tsl/display/LensflareNode.js +3 -3
  144. package/examples/jsm/tsl/display/Lut3DNode.js +3 -3
  145. package/examples/jsm/tsl/display/OITPassNode.js +0 -11
  146. package/examples/jsm/tsl/display/OutlineNode.js +107 -5
  147. package/examples/jsm/tsl/display/PixelationPassNode.js +85 -193
  148. package/examples/jsm/tsl/display/RGBShiftNode.js +3 -3
  149. package/examples/jsm/tsl/display/RecurrentDenoiseNode.js +23 -126
  150. package/examples/jsm/tsl/display/SMAANode.js +3 -3
  151. package/examples/jsm/tsl/display/SSAONode.js +6 -20
  152. package/examples/jsm/tsl/display/SSGINode.js +36 -29
  153. package/examples/jsm/tsl/display/SSRNode.js +135 -63
  154. package/examples/jsm/tsl/display/SSSNode.js +6 -20
  155. package/examples/jsm/tsl/display/SharpenNode.js +3 -3
  156. package/examples/jsm/tsl/display/SobelOperatorNode.js +3 -3
  157. package/examples/jsm/tsl/display/TAAUNode.js +10 -42
  158. package/examples/jsm/tsl/display/TRAANode.js +11 -43
  159. package/examples/jsm/tsl/display/TemporalReprojectNode.js +42 -47
  160. package/examples/jsm/tsl/display/TransitionNode.js +3 -3
  161. package/examples/jsm/tsl/display/lensDirt.js +30 -0
  162. package/examples/jsm/tsl/lighting/ClusteredLightsNode.js +482 -121
  163. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +41 -140
  164. package/examples/jsm/tsl/lighting/LightProbeGridNode.js +72 -25
  165. package/examples/jsm/tsl/lighting/data/AmbientLightDataNode.js +6 -0
  166. package/examples/jsm/tsl/lighting/data/DirectionalLightDataNode.js +6 -0
  167. package/examples/jsm/tsl/lighting/data/HemisphereLightDataNode.js +6 -0
  168. package/examples/jsm/tsl/lighting/data/PointLightDataNode.js +6 -0
  169. package/examples/jsm/tsl/lighting/data/SpotLightDataNode.js +6 -0
  170. package/examples/jsm/tsl/shadows/TileShadowNode.js +102 -14
  171. package/examples/jsm/tsl/utils/Raymarching.js +1 -1
  172. package/examples/jsm/tsl/utils/SoftParticles.js +5 -12
  173. package/examples/jsm/tsl/utils/SpecularHelpers.js +47 -70
  174. package/examples/jsm/tsl/utils/TAAUtils.js +6 -17
  175. package/examples/jsm/utils/BufferGeometryUtils.js +110 -88
  176. package/examples/jsm/utils/MeshletGeometryUtils.js +417 -0
  177. package/examples/jsm/utils/SceneOptimizer.js +2 -1
  178. package/examples/jsm/utils/SceneUtils.js +1 -1
  179. package/examples/jsm/utils/unwrapUVs.js +865 -0
  180. package/examples/jsm/webxr/XREstimatedLight.js +11 -4
  181. package/package.json +3 -3
  182. package/src/Three.TSL.js +2 -683
  183. package/src/Three.WebGPU.Nodes.js +2 -1
  184. package/src/Three.WebGPU.js +2 -1
  185. package/src/animation/AnimationAction.js +1 -1
  186. package/src/animation/AnimationUtils.js +1 -3
  187. package/src/animation/KeyframeTrack.js +19 -0
  188. package/src/cameras/ArrayCamera.js +12 -0
  189. package/src/cameras/CubeCamera.js +3 -3
  190. package/src/constants.js +1 -9
  191. package/src/core/BufferAttribute.js +57 -21
  192. package/src/core/BufferGeometry.js +5 -13
  193. package/src/core/Clock.js +1 -1
  194. package/src/core/InterleavedBuffer.js +28 -18
  195. package/src/core/InterleavedBufferAttribute.js +54 -20
  196. package/src/core/Object3D.js +19 -9
  197. package/src/core/Raycaster.js +2 -0
  198. package/src/core/RenderTarget.js +11 -5
  199. package/src/core/UniformsGroup.js +7 -3
  200. package/src/extras/PMREMGenerator.js +392 -685
  201. package/src/extras/core/Curve.js +4 -0
  202. package/src/extras/core/CurvePath.js +13 -0
  203. package/src/extras/core/ShapePath.js +1 -1
  204. package/src/geometries/EdgesGeometry.js +12 -10
  205. package/src/geometries/LatheGeometry.js +2 -0
  206. package/src/helpers/PolarGridHelper.js +1 -1
  207. package/src/lights/Light.js +11 -0
  208. package/src/lights/LightProbe.js +2 -0
  209. package/src/lights/LightShadow.js +2 -0
  210. package/src/loaders/AnimationLoader.js +2 -0
  211. package/src/loaders/AudioLoader.js +2 -0
  212. package/src/loaders/BufferGeometryLoader.js +2 -0
  213. package/src/loaders/CompressedTextureLoader.js +2 -0
  214. package/src/loaders/CubeTextureLoader.js +2 -0
  215. package/src/loaders/DataTextureLoader.js +2 -0
  216. package/src/loaders/FileLoader.js +2 -0
  217. package/src/loaders/ImageBitmapLoader.js +3 -1
  218. package/src/loaders/ImageLoader.js +1 -0
  219. package/src/loaders/Loader.js +47 -0
  220. package/src/loaders/MaterialLoader.js +2 -0
  221. package/src/loaders/ObjectLoader.js +27 -8
  222. package/src/loaders/TextureLoader.js +5 -3
  223. package/src/loaders/nodes/NodeLoader.js +2 -0
  224. package/src/materials/Material.js +21 -2
  225. package/src/materials/MeshDepthMaterial.js +1 -1
  226. package/src/materials/MeshDistanceMaterial.js +1 -1
  227. package/src/materials/MeshLambertMaterial.js +1 -1
  228. package/src/materials/MeshMatcapMaterial.js +1 -1
  229. package/src/materials/MeshNormalMaterial.js +1 -1
  230. package/src/materials/MeshPhongMaterial.js +1 -1
  231. package/src/materials/MeshPhysicalMaterial.js +90 -11
  232. package/src/materials/MeshStandardMaterial.js +1 -1
  233. package/src/materials/MeshToonMaterial.js +1 -1
  234. package/src/materials/nodes/Line2NodeMaterial.js +32 -10
  235. package/src/materials/nodes/MeshLambertNodeMaterial.js +13 -0
  236. package/src/materials/nodes/MeshPhongNodeMaterial.js +13 -0
  237. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +40 -5
  238. package/src/materials/nodes/MeshToonNodeMaterial.js +13 -0
  239. package/src/materials/nodes/NodeMaterial.js +36 -16
  240. package/src/materials/nodes/NodeMaterialInstance.js +193 -0
  241. package/src/materials/nodes/NodeMaterials.js +1 -0
  242. package/src/materials/nodes/PointsNodeMaterial.js +1 -1
  243. package/src/materials/nodes/SpriteNodeMaterial.js +3 -3
  244. package/src/materials/nodes/manager/NodeMaterialObserver.js +191 -22
  245. package/src/math/Box3.js +2 -2
  246. package/src/math/Color.js +8 -8
  247. package/src/math/ColorManagement.js +2 -21
  248. package/src/math/FrustumArray.js +12 -0
  249. package/src/math/Interpolant.js +1 -1
  250. package/src/math/Line3.js +2 -4
  251. package/src/math/MathUtils.js +33 -46
  252. package/src/math/Matrix2.js +1 -1
  253. package/src/math/Matrix3.js +1 -1
  254. package/src/math/Matrix4.js +1 -1
  255. package/src/math/Triangle.js +2 -1
  256. package/src/math/Vector2.js +1 -1
  257. package/src/math/Vector3.js +1 -1
  258. package/src/math/Vector4.js +1 -1
  259. package/src/nodes/Nodes.js +1 -0
  260. package/src/nodes/TSL.js +2 -0
  261. package/src/nodes/accessors/Arrays.js +1 -1
  262. package/src/nodes/accessors/Batch.js +29 -23
  263. package/src/nodes/accessors/BufferAttributeNode.js +21 -1
  264. package/src/nodes/accessors/BuiltinNode.js +6 -0
  265. package/src/nodes/accessors/Camera.js +100 -93
  266. package/src/nodes/accessors/ClippingNode.js +17 -6
  267. package/src/nodes/accessors/CubeTextureNode.js +12 -24
  268. package/src/nodes/accessors/Instance.js +198 -160
  269. package/src/nodes/accessors/Lights.js +19 -6
  270. package/src/nodes/accessors/MaterialNode.js +33 -4
  271. package/src/nodes/accessors/Morph.js +81 -22
  272. package/src/nodes/accessors/Normal.js +0 -42
  273. package/src/nodes/accessors/Object3DNode.js +6 -0
  274. package/src/nodes/accessors/PointUVNode.js +6 -0
  275. package/src/nodes/accessors/ReferenceAttributeNode.js +279 -0
  276. package/src/nodes/accessors/ReferenceBaseNode.js +6 -0
  277. package/src/nodes/accessors/ReferenceNode.js +6 -0
  278. package/src/nodes/accessors/Skinning.js +57 -52
  279. package/src/nodes/accessors/StorageBufferNode.js +3 -12
  280. package/src/nodes/accessors/TextureBicubic.js +30 -27
  281. package/src/nodes/accessors/TextureNode.js +164 -78
  282. package/src/nodes/accessors/TextureSizeNode.js +6 -0
  283. package/src/nodes/accessors/UniformArrayNode.js +8 -15
  284. package/src/nodes/accessors/VelocityNode.js +13 -8
  285. package/src/nodes/code/CodeNode.js +6 -0
  286. package/src/nodes/code/ExpressionNode.js +6 -0
  287. package/src/nodes/code/FunctionCallNode.js +3 -3
  288. package/src/nodes/code/FunctionNode.js +15 -13
  289. package/src/nodes/core/ArrayNode.js +3 -3
  290. package/src/nodes/core/AssignNode.js +10 -9
  291. package/src/nodes/core/AttributeNode.js +39 -0
  292. package/src/nodes/core/BypassNode.js +6 -0
  293. package/src/nodes/core/ConstNode.js +31 -1
  294. package/src/nodes/core/ContextNode.js +11 -6
  295. package/src/nodes/core/IndexNode.js +6 -0
  296. package/src/nodes/core/InputNode.js +6 -0
  297. package/src/nodes/core/InspectorNode.js +17 -31
  298. package/src/nodes/core/IsolateNode.js +8 -0
  299. package/src/nodes/core/Node.js +367 -67
  300. package/src/nodes/core/NodeBuilder.js +664 -222
  301. package/src/nodes/core/NodeUtils.js +25 -0
  302. package/src/nodes/core/NodeVar.js +10 -1
  303. package/src/nodes/core/OutputStructNode.js +6 -0
  304. package/src/nodes/core/OverrideContextNode.js +38 -37
  305. package/src/nodes/core/PropertyNode.js +14 -0
  306. package/src/nodes/core/StackNode.js +33 -21
  307. package/src/nodes/core/StructNode.js +6 -0
  308. package/src/nodes/core/StructTypeNode.js +6 -0
  309. package/src/nodes/core/SubBuildNode.js +8 -0
  310. package/src/nodes/core/TempNode.js +10 -35
  311. package/src/nodes/core/UniformGroupNode.js +6 -0
  312. package/src/nodes/core/VarNode.js +43 -135
  313. package/src/nodes/core/VaryingNode.js +33 -2
  314. package/src/nodes/display/BlendModes.js +5 -40
  315. package/src/nodes/display/BumpMapNode.js +17 -7
  316. package/src/nodes/display/ColorAdjustment.js +22 -10
  317. package/src/nodes/display/ColorSpaceFunctions.js +2 -14
  318. package/src/nodes/display/ColorSpaceNode.js +3 -3
  319. package/src/nodes/display/FrontFacingNode.js +6 -0
  320. package/src/nodes/display/NormalMapNode.js +3 -3
  321. package/src/nodes/display/PassNode.js +75 -16
  322. package/src/nodes/display/RenderOutputNode.js +22 -5
  323. package/src/nodes/display/ScreenNode.js +6 -0
  324. package/src/nodes/display/ToneMappingFunctions.js +9 -51
  325. package/src/nodes/display/ToneMappingNode.js +3 -3
  326. package/src/nodes/display/ToonOutlinePassNode.js +66 -2
  327. package/src/nodes/display/ViewportDepthNode.js +34 -4
  328. package/src/nodes/functions/BSDF/BRDF_EON.js +65 -0
  329. package/src/nodes/functions/BSDF/BRDF_GGX.js +5 -3
  330. package/src/nodes/functions/BSDF/BRDF_Sheen.js +2 -16
  331. package/src/nodes/functions/BSDF/D_GGX.js +1 -8
  332. package/src/nodes/functions/BSDF/D_GGX_Anisotropic.js +7 -10
  333. package/src/nodes/functions/BSDF/LTC.js +20 -47
  334. package/src/nodes/functions/BSDF/Schlick_to_F0.js +1 -9
  335. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated.js +1 -9
  336. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +10 -13
  337. package/src/nodes/functions/PhysicalLightingModel.js +84 -51
  338. package/src/nodes/functions/VolumetricLightingModel.js +1 -1
  339. package/src/nodes/functions/material/getAlphaHashThreshold.js +3 -9
  340. package/src/nodes/functions/material/getParallaxCorrectNormal.js +10 -11
  341. package/src/nodes/functions/material/getRoughness.js +3 -1
  342. package/src/nodes/geometry/RangeNode.js +52 -69
  343. package/src/nodes/gpgpu/AtomicFunctionNode.js +11 -6
  344. package/src/nodes/gpgpu/BarrierNode.js +6 -0
  345. package/src/nodes/gpgpu/ComputeBuiltinNode.js +6 -0
  346. package/src/nodes/gpgpu/ComputeNode.js +6 -0
  347. package/src/nodes/gpgpu/SubgroupFunctionNode.js +38 -29
  348. package/src/nodes/gpgpu/WorkgroupInfoNode.js +6 -0
  349. package/src/nodes/lighting/AnalyticLightNode.js +7 -14
  350. package/src/nodes/lighting/BasicEnvironmentNode.js +5 -1
  351. package/src/nodes/lighting/EnvironmentNode.js +58 -8
  352. package/src/nodes/lighting/IESSpotLightNode.js +19 -4
  353. package/src/nodes/lighting/LightProbeNode.js +2 -1
  354. package/src/nodes/lighting/LightUtils.js +2 -2
  355. package/src/nodes/lighting/LightingNode.js +6 -0
  356. package/src/nodes/lighting/LightsNode.js +26 -32
  357. package/src/nodes/lighting/PointShadowNode.js +92 -48
  358. package/src/nodes/lighting/ProjectorLightNode.js +1 -1
  359. package/src/nodes/lighting/RectAreaLightNode.js +13 -14
  360. package/src/nodes/lighting/ShadowBaseNode.js +9 -17
  361. package/src/nodes/lighting/ShadowFilterNode.js +26 -3
  362. package/src/nodes/lighting/ShadowNode.js +13 -11
  363. package/src/nodes/materialx/MaterialXColor.js +2 -14
  364. package/src/nodes/materialx/MaterialXColorTransform.js +1 -7
  365. package/src/nodes/materialx/MaterialXNodes.js +8 -11
  366. package/src/nodes/materialx/MaterialXNoise.js +195 -454
  367. package/src/nodes/math/BitcastNode.js +5 -5
  368. package/src/nodes/math/BitcountNode.js +18 -46
  369. package/src/nodes/math/ConditionalNode.js +92 -22
  370. package/src/nodes/math/Hash.js +1 -1
  371. package/src/nodes/math/MathNode.js +86 -64
  372. package/src/nodes/math/MathUtils.js +2 -2
  373. package/src/nodes/math/OperatorNode.js +42 -59
  374. package/src/nodes/math/PackFloatNode.js +9 -9
  375. package/src/nodes/math/Packed4x8IntegerNode.js +20 -52
  376. package/src/nodes/math/TriNoise3D.js +3 -23
  377. package/src/nodes/math/UnpackFloatNode.js +9 -9
  378. package/src/nodes/pmrem/PMREMNode.js +38 -75
  379. package/src/nodes/pmrem/PMREMUtils.js +108 -272
  380. package/src/nodes/procedural/Checker.js +1 -1
  381. package/src/nodes/tsl/TSLCore.js +199 -74
  382. package/src/nodes/utils/ArrayElementNode.js +19 -1
  383. package/src/nodes/utils/CubeMapNode.js +3 -3
  384. package/src/nodes/utils/DebugNode.js +2 -2
  385. package/src/nodes/utils/EventNode.js +6 -0
  386. package/src/nodes/utils/FlipNode.js +3 -3
  387. package/src/nodes/utils/FunctionOverloadingNode.js +7 -1
  388. package/src/nodes/utils/JoinNode.js +3 -3
  389. package/src/nodes/utils/LoopNode.js +14 -9
  390. package/src/nodes/utils/MemberNode.js +18 -0
  391. package/src/nodes/utils/PostProcessingUtils.js +20 -25
  392. package/src/nodes/utils/RTTNode.js +2 -0
  393. package/src/nodes/utils/ReflectorNode.js +24 -0
  394. package/src/nodes/utils/RotateNode.js +3 -3
  395. package/src/nodes/utils/SampleNode.js +6 -0
  396. package/src/nodes/utils/SetNode.js +3 -3
  397. package/src/nodes/utils/SplitNode.js +6 -0
  398. package/src/nodes/utils/UVUtils.js +2 -2
  399. package/src/objects/BatchedMesh.js +146 -15
  400. package/src/objects/InstancedMesh.js +12 -4
  401. package/src/objects/Line.js +20 -0
  402. package/src/objects/Mesh.js +8 -0
  403. package/src/objects/Points.js +20 -0
  404. package/src/objects/Skeleton.js +26 -0
  405. package/src/objects/SkinnedMesh.js +3 -3
  406. package/src/objects/Sprite.js +10 -0
  407. package/src/renderers/WebGLRenderer.js +104 -70
  408. package/src/renderers/common/Animation.js +5 -1
  409. package/src/renderers/common/Attributes.js +67 -57
  410. package/src/renderers/common/Backend.js +78 -3
  411. package/src/renderers/common/BindGroup.js +11 -0
  412. package/src/renderers/common/Binding.js +0 -11
  413. package/src/renderers/common/Bindings.js +116 -10
  414. package/src/renderers/common/Buffer.js +1 -1
  415. package/src/renderers/common/ClippingContext.js +12 -1
  416. package/src/renderers/common/ComputePipeline.js +17 -1
  417. package/src/renderers/common/DirectRenderPipeline.js +7 -3
  418. package/src/renderers/common/Geometries.js +170 -132
  419. package/src/renderers/common/Info.js +1 -1
  420. package/src/renderers/common/InspectorBase.js +5 -5
  421. package/src/renderers/common/Lighting.js +59 -0
  422. package/src/renderers/common/Pipelines.js +26 -12
  423. package/src/renderers/common/ProgrammableStage.js +1 -17
  424. package/src/renderers/common/RenderContext.js +21 -0
  425. package/src/renderers/common/RenderContexts.js +13 -4
  426. package/src/renderers/common/RenderObject.js +111 -35
  427. package/src/renderers/common/RenderObjects.js +37 -19
  428. package/src/renderers/common/Renderer.js +537 -295
  429. package/src/renderers/common/RendererUtils.js +15 -0
  430. package/src/renderers/common/StandardDrawingPipeline.js +343 -0
  431. package/src/renderers/common/Storage3DTexture.js +11 -0
  432. package/src/renderers/common/StorageArrayTexture.js +10 -0
  433. package/src/renderers/common/StorageTexture.js +0 -9
  434. package/src/renderers/common/Textures.js +144 -37
  435. package/src/renderers/common/UniformsGroup.js +19 -0
  436. package/src/renderers/common/XRManager.js +10 -91
  437. package/src/renderers/common/extras/PMREMGenerator.js +298 -576
  438. package/src/renderers/common/nodes/NodeBuilderState.js +7 -5
  439. package/src/renderers/common/nodes/NodeLibrary.js +11 -35
  440. package/src/renderers/common/nodes/NodeManager.js +80 -31
  441. package/src/renderers/common/nodes/NodeSampledTexture.js +14 -0
  442. package/src/renderers/common/nodes/NodeSampler.js +14 -0
  443. package/src/renderers/common/nodes/NodeStorageBuffer.js +1 -1
  444. package/src/renderers/common/nodes/NodeUniformBuffer.js +1 -14
  445. package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +13 -4
  446. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +8 -8
  447. package/src/renderers/shaders/ShaderChunk/lightprobes_pars_fragment.glsl.js +23 -11
  448. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +21 -2
  449. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +1 -1
  450. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +18 -2
  451. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +104 -7
  452. package/src/renderers/shaders/ShaderChunk/morphcolor_vertex.glsl.js +11 -2
  453. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +36 -20
  454. package/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js +5 -0
  455. package/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js +6 -0
  456. package/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js +5 -0
  457. package/src/renderers/shaders/ShaderChunk.js +0 -2
  458. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +4 -18
  459. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +0 -1
  460. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +0 -1
  461. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +8 -1
  462. package/src/renderers/shaders/ShaderLib.js +3 -0
  463. package/src/renderers/shaders/UniformsLib.js +4 -5
  464. package/src/renderers/webgl/WebGLBackground.js +3 -3
  465. package/src/renderers/webgl/WebGLBindingStates.js +4 -2
  466. package/src/renderers/webgl/WebGLCapabilities.js +7 -1
  467. package/src/renderers/webgl/WebGLEnvironments.js +2 -2
  468. package/src/renderers/webgl/WebGLGeometries.js +42 -14
  469. package/src/renderers/webgl/WebGLMaterials.js +15 -2
  470. package/src/renderers/webgl/WebGLOutput.js +37 -1
  471. package/src/renderers/webgl/WebGLProgram.js +13 -54
  472. package/src/renderers/webgl/WebGLPrograms.js +22 -8
  473. package/src/renderers/webgl/WebGLRenderStates.js +11 -8
  474. package/src/renderers/webgl/WebGLShadowMap.js +6 -4
  475. package/src/renderers/webgl/WebGLState.js +10 -6
  476. package/src/renderers/webgl/WebGLTextures.js +129 -77
  477. package/src/renderers/webgl/WebGLUniforms.js +44 -6
  478. package/src/renderers/webgl/WebGLUniformsGroups.js +75 -69
  479. package/src/renderers/webgl-fallback/WebGLBackend.js +206 -278
  480. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +154 -20
  481. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +45 -42
  482. package/src/renderers/webgl-fallback/utils/WebGLState.js +29 -4
  483. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +129 -49
  484. package/src/renderers/webgl-fallback/utils/WebGLVertexArrayUtils.js +346 -0
  485. package/src/renderers/webgpu/WebGPUBackend.js +140 -82
  486. package/src/renderers/webgpu/WebGPURenderer.js +1 -1
  487. package/src/renderers/webgpu/nodes/BasicNodeLibrary.js +10 -10
  488. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +10 -10
  489. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +135 -60
  490. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +128 -55
  491. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +1 -1
  492. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +15 -12
  493. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +55 -19
  494. package/src/renderers/webgpu/utils/WebGPUUtils.js +20 -3
  495. package/src/renderers/webxr/WebXRController.js +3 -3
  496. package/src/renderers/webxr/WebXRManager.js +5 -90
  497. package/src/scenes/Scene.js +4 -4
  498. package/src/textures/CompressedTexture.js +2 -2
  499. package/src/textures/DepthTexture.js +2 -2
  500. package/src/textures/FramebufferTexture.js +11 -0
  501. package/src/textures/Texture.js +29 -1
  502. package/src/textures/TextureSource.js +1 -1
  503. package/src/upe.js +1 -1
  504. package/src/utils.js +4 -4
  505. package/examples/jsm/libs/surfaceNet.js +0 -201
  506. package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +0 -186
@@ -8,7 +8,7 @@ import ParameterNode from './ParameterNode.js';
8
8
  import StructType from './StructType.js';
9
9
  import FunctionNode from '../code/FunctionNode.js';
10
10
  import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
11
- import { getDataFromObject, getTypeFromLength, getTextureType, hashString } from './NodeUtils.js';
11
+ import { getTypeFromLength, getTextureType, isArrayAsParameter, mergeContext } from './NodeUtils.js';
12
12
  import { NodeUpdateType, defaultBuildStages, shaderStages } from './constants.js';
13
13
 
14
14
  import {
@@ -34,10 +34,36 @@ import { warn, error, yieldToMain } from '../../utils.js';
34
34
 
35
35
  let _id = 0;
36
36
 
37
- const _bindingGroupsCache = new WeakMap();
38
37
  const _functionNodeCache = new WeakMap();
38
+ const _layoutDefaultsCache = new WeakMap();
39
39
 
40
- const sharedNodeData = new WeakMap();
40
+ // Inputs of a layout function call. They can be destructured as an array or as an object.
41
+ const _createLayoutInputs = ( layout, values ) => {
42
+
43
+ const inputs = {
44
+ [ Symbol.iterator ]() {
45
+
46
+ let index = 0;
47
+ const values = Object.values( this );
48
+ return {
49
+ next: () => ( {
50
+ value: values[ index ],
51
+ done: index ++ >= values.length
52
+ } )
53
+ };
54
+
55
+ }
56
+ };
57
+
58
+ layout.inputs.forEach( ( input, i ) => {
59
+
60
+ inputs[ input.name ] = values[ i ];
61
+
62
+ } );
63
+
64
+ return inputs;
65
+
66
+ };
41
67
 
42
68
  const typeFromArray = new Map( [
43
69
  [ Int8Array, 'int' ],
@@ -65,6 +91,49 @@ const _toFloat = ( value ) => {
65
91
 
66
92
  };
67
93
 
94
+ const _componentTypeRanks = { bool: 0, uint: 1, int: 2, float: 3 };
95
+
96
+ /**
97
+ * Data of a node in a shader stage. All common properties are declared upfront,
98
+ * so the objects share a single shape.
99
+ *
100
+ * @private
101
+ */
102
+ class NodeData {
103
+
104
+ constructor() {
105
+
106
+ this.properties = undefined;
107
+ this.type = undefined;
108
+ this.typeFromOutput = undefined;
109
+ this.buildStages = undefined;
110
+ this.usageCount = undefined;
111
+ this.readUsageCount = undefined;
112
+ this.writeUsageCount = undefined;
113
+ this.stack = undefined;
114
+ this.stages = undefined;
115
+ this.snippet = undefined;
116
+ this.propertyName = undefined;
117
+ this.generated = undefined;
118
+ this.flowBlock = undefined;
119
+ this.assign = undefined;
120
+ this.forceDeclaration = undefined;
121
+ this.variable = undefined;
122
+ this.cacheVariable = undefined;
123
+ this.uniform = undefined;
124
+ this.subBuilds = undefined;
125
+ this.subBuildsCache = undefined;
126
+
127
+ }
128
+
129
+ }
130
+
131
+ const _componentTypeCache = new Map();
132
+ const _typeLengthCache = new Map();
133
+ const _isVectorCache = new Map();
134
+ const _isMatrixCache = new Map();
135
+ const _isIntegerCache = new Map();
136
+
68
137
  const _checkWriteUsage = ( data ) => {
69
138
 
70
139
  if ( data.writeUsageCount > 0 ) return true;
@@ -87,6 +156,18 @@ const _checkWriteUsage = ( data ) => {
87
156
 
88
157
  };
89
158
 
159
+ const _hasContextOverrides = ( context, baseContext ) => {
160
+
161
+ for ( const key in context ) {
162
+
163
+ if ( key !== 'nodeBlock' && key !== 'nodeLoop' && context[ key ] !== baseContext[ key ] ) return true;
164
+
165
+ }
166
+
167
+ return false;
168
+
169
+ };
170
+
90
171
  /**
91
172
  * Base class for builders which generate a shader program based
92
173
  * on a 3D object and its node material definition.
@@ -254,6 +335,16 @@ class NodeBuilder {
254
335
  */
255
336
  this.hardwareClipping = false;
256
337
 
338
+ /**
339
+ * Whether the build embeds data of the 3D object it is built for, like its buffers,
340
+ * instead of binding the data of the rendered object. Such builds can't be shared
341
+ * with other objects, so the renderer doesn't cache them.
342
+ *
343
+ * @type {boolean}
344
+ * @default false
345
+ */
346
+ this.objectSpecific = false;
347
+
257
348
  /**
258
349
  * The generated vertex shader.
259
350
  *
@@ -504,6 +595,15 @@ class NodeBuilder {
504
595
  */
505
596
  this.fnCall = null;
506
597
 
598
+ /**
599
+ * The block of generated code the builder is in, e.g. a loop body or a conditional branch.
600
+ * Every generated block is a new object linked to its parent, `null` outside of any block.
601
+ *
602
+ * @type {?{parent: ?Object}}
603
+ * @default null
604
+ */
605
+ this.flowBlock = null;
606
+
507
607
  Object.defineProperty( this, 'id', { value: _id ++ } );
508
608
 
509
609
  }
@@ -583,7 +683,7 @@ class NodeBuilder {
583
683
 
584
684
  const renderTarget = this.renderer.getRenderTarget();
585
685
 
586
- if ( renderTarget !== null ) {
686
+ if ( renderTarget !== null && renderTarget.textures[ index ] !== undefined ) {
587
687
 
588
688
  return getTextureType( renderTarget.textures[ index ] );
589
689
 
@@ -632,63 +732,11 @@ class NodeBuilder {
632
732
 
633
733
  //
634
734
 
635
- let bindGroup;
636
-
637
- if ( sharedGroup ) {
638
-
639
- let cacheKeyString = '';
640
-
641
- for ( const binding of bindings ) {
642
-
643
- if ( binding.isNodeUniformsGroup ) {
644
-
645
- binding.uniforms.sort( ( a, b ) => a.nodeUniform.node.id - b.nodeUniform.node.id );
646
-
647
- for ( const uniform of binding.uniforms ) {
648
-
649
- cacheKeyString += uniform.nodeUniform.node.id;
650
-
651
- }
652
-
653
- } else {
654
-
655
- cacheKeyString += binding.nodeUniform.id;
656
-
657
- }
658
-
659
- }
660
-
661
- // TODO: Remove this hack ._currentRenderContext
662
-
663
- const currentContext = this.renderer._currentRenderContext || this.renderer; // use renderer as fallback until we have a compute context
664
-
665
- let bindingGroupsCache = _bindingGroupsCache.get( currentContext );
666
-
667
- if ( bindingGroupsCache === undefined ) {
668
-
669
- bindingGroupsCache = new Map();
670
-
671
- _bindingGroupsCache.set( currentContext, bindingGroupsCache );
672
-
673
- }
674
-
675
- //
676
-
677
- const cacheKey = hashString( cacheKeyString );
678
-
679
- bindGroup = bindingGroupsCache.get( cacheKey );
680
-
681
- if ( bindGroup === undefined ) {
682
-
683
- bindGroup = new BindGroup( groupName, bindings );
735
+ let bindGroup = new BindGroup( groupName, bindings );
684
736
 
685
- bindingGroupsCache.set( cacheKey, bindGroup );
737
+ if ( sharedGroup && this.renderer._bindings !== undefined ) {
686
738
 
687
- }
688
-
689
- } else {
690
-
691
- bindGroup = new BindGroup( groupName, bindings );
739
+ bindGroup = this.renderer._bindings.getSharedBindGroup( bindGroup );
692
740
 
693
741
  }
694
742
 
@@ -1002,6 +1050,23 @@ class NodeBuilder {
1002
1050
 
1003
1051
  }
1004
1052
 
1053
+ /**
1054
+ * Returns the native snippet for a per-component vector select. The default
1055
+ * implementation uses {@link NodeBuilder#getTernary}; renderers can
1056
+ * override this when their ternary operation does not accept vectors.
1057
+ *
1058
+ * @param {string} condSnippet - The per-component boolean (`bvecN`) condition.
1059
+ * @param {string} ifSnippet - The vector expression selected where `condSnippet` is `true`.
1060
+ * @param {string} elseSnippet - The vector expression selected where `condSnippet` is `false`.
1061
+ * @param {string} type - The (vector) type of `ifSnippet`/`elseSnippet`.
1062
+ * @return {string} The resolved method name.
1063
+ */
1064
+ getVectorSelect( condSnippet, ifSnippet, elseSnippet /*, type*/ ) {
1065
+
1066
+ return this.getTernary( condSnippet, ifSnippet, elseSnippet );
1067
+
1068
+ }
1069
+
1005
1070
  /**
1006
1071
  * Returns a node for the given hash, see {@link NodeBuilder#setHashNode}.
1007
1072
  *
@@ -1061,7 +1126,7 @@ class NodeBuilder {
1061
1126
 
1062
1127
  const previousContext = this.getContext();
1063
1128
 
1064
- this.setContext( { ...this.context, ...context } );
1129
+ this.setContext( mergeContext( this.context, context ) );
1065
1130
 
1066
1131
  return previousContext;
1067
1132
 
@@ -1204,6 +1269,75 @@ class NodeBuilder {
1204
1269
 
1205
1270
  }
1206
1271
 
1272
+ /**
1273
+ * Returns a builtin representing the size of a subgroup within the current shader.
1274
+ *
1275
+ * @abstract
1276
+ * @return {string} The subgroup size shader string.
1277
+ */
1278
+ getSubgroupSize() {
1279
+
1280
+ warn( 'Abstract function.' );
1281
+
1282
+ }
1283
+
1284
+ /**
1285
+ * Returns a builtin representing the index of an invocation within its subgroup.
1286
+ *
1287
+ * @abstract
1288
+ * @return {string} The invocation subgroup index shader string.
1289
+ */
1290
+ getInvocationSubgroupIndex() {
1291
+
1292
+ warn( 'Abstract function.' );
1293
+
1294
+ }
1295
+
1296
+ /**
1297
+ * Returns a builtin representing the index of the current invocation's subgroup within its workgroup.
1298
+ *
1299
+ * @abstract
1300
+ * @return {string} The subgroup index shader string.
1301
+ */
1302
+ getSubgroupIndex() {
1303
+
1304
+ warn( 'Abstract function.' );
1305
+
1306
+ }
1307
+
1308
+ /**
1309
+ * Enables subgroups.
1310
+ *
1311
+ * @abstract
1312
+ */
1313
+ enableSubGroups() {
1314
+
1315
+ warn( 'Abstract function.' );
1316
+
1317
+ }
1318
+
1319
+ /**
1320
+ * Enables 16 bit floats.
1321
+ *
1322
+ * @abstract
1323
+ */
1324
+ enableShaderF16() {
1325
+
1326
+ warn( 'Abstract function.' );
1327
+
1328
+ }
1329
+
1330
+ /**
1331
+ * Enables dual source blending.
1332
+ *
1333
+ * @abstract
1334
+ */
1335
+ enableDualSourceBlending() {
1336
+
1337
+ warn( 'Abstract function.' );
1338
+
1339
+ }
1340
+
1207
1341
  /**
1208
1342
  * Whether to flip texture data along its vertical axis or not. WebGL needs
1209
1343
  * this method evaluate to `true`, WebGPU to `false`.
@@ -1425,15 +1559,15 @@ class NodeBuilder {
1425
1559
  if ( type === 'float' || type === 'int' || type === 'uint' ) value = 0;
1426
1560
  else if ( type === 'bool' ) value = false;
1427
1561
  else if ( type === 'color' ) value = new Color();
1428
- else if ( type === 'vec2' || type === 'uvec2' || type === 'ivec2' ) value = new Vector2();
1429
- else if ( type === 'vec3' || type === 'uvec3' || type === 'ivec3' ) value = new Vector3();
1430
- else if ( type === 'vec4' || type === 'uvec4' || type === 'ivec4' ) value = new Vector4();
1562
+ else if ( type === 'vec2' || type === 'uvec2' || type === 'ivec2' || type === 'bvec2' ) value = new Vector2();
1563
+ else if ( type === 'vec3' || type === 'uvec3' || type === 'ivec3' || type === 'bvec3' ) value = new Vector3();
1564
+ else if ( type === 'vec4' || type === 'uvec4' || type === 'ivec4' || type === 'bvec4' ) value = new Vector4();
1431
1565
 
1432
1566
  }
1433
1567
 
1434
1568
  if ( type === 'float' ) return _toFloat( value );
1435
- if ( type === 'int' ) return `${ Math.round( value ) }`;
1436
- if ( type === 'uint' ) return value >= 0 ? `${ Math.round( value ) }u` : '0u';
1569
+ if ( type === 'int' ) return `${ Math.trunc( value ) }`;
1570
+ if ( type === 'uint' ) return value >= 0 ? `${ Math.trunc( value ) }u` : '0u';
1437
1571
  if ( type === 'bool' ) return value ? 'true' : 'false';
1438
1572
  if ( type === 'color' ) return `${ this.getType( 'vec3' ) }( ${ _toFloat( value.r ) }, ${ _toFloat( value.g ) }, ${ _toFloat( value.b ) } )`;
1439
1573
 
@@ -1544,6 +1678,18 @@ class NodeBuilder {
1544
1678
 
1545
1679
  }
1546
1680
 
1681
+ /**
1682
+ * Whether the given type is a scalar type or not.
1683
+ *
1684
+ * @param {string} type - The type to check.
1685
+ * @return {boolean} Whether the given type is a scalar type or not.
1686
+ */
1687
+ isScalar( type ) {
1688
+
1689
+ return type === 'float' || type === 'bool' || type === 'int' || type === 'uint';
1690
+
1691
+ }
1692
+
1547
1693
  /**
1548
1694
  * Returns whether the given name is a reserved keyword of the backend's
1549
1695
  * shading language. Backends override this method to provide their
@@ -1566,7 +1712,9 @@ class NodeBuilder {
1566
1712
  */
1567
1713
  isVector( type ) {
1568
1714
 
1569
- return /vec\d/.test( type );
1715
+ let result = _isVectorCache.get( type );
1716
+ if ( result === undefined ) _isVectorCache.set( type, result = /vec\d/.test( type ) );
1717
+ return result;
1570
1718
 
1571
1719
  }
1572
1720
 
@@ -1578,7 +1726,9 @@ class NodeBuilder {
1578
1726
  */
1579
1727
  isMatrix( type ) {
1580
1728
 
1581
- return /mat\d/.test( type );
1729
+ let result = _isMatrixCache.get( type );
1730
+ if ( result === undefined ) _isMatrixCache.set( type, result = /mat\d/.test( type ) );
1731
+ return result;
1582
1732
 
1583
1733
  }
1584
1734
 
@@ -1654,15 +1804,23 @@ class NodeBuilder {
1654
1804
 
1655
1805
  if ( type === 'float' || type === 'bool' || type === 'int' || type === 'uint' ) return type;
1656
1806
 
1657
- const componentType = /(b|i|u|)(vec|mat)([2-4])/.exec( type );
1807
+ let result = _componentTypeCache.get( type );
1658
1808
 
1659
- if ( componentType === null ) return null;
1809
+ if ( result === undefined ) {
1660
1810
 
1661
- if ( componentType[ 1 ] === 'b' ) return 'bool';
1662
- if ( componentType[ 1 ] === 'i' ) return 'int';
1663
- if ( componentType[ 1 ] === 'u' ) return 'uint';
1811
+ const componentType = /(b|i|u|)(vec|mat)([2-4])/.exec( type );
1664
1812
 
1665
- return 'float';
1813
+ if ( componentType === null ) result = null;
1814
+ else if ( componentType[ 1 ] === 'b' ) result = 'bool';
1815
+ else if ( componentType[ 1 ] === 'i' ) result = 'int';
1816
+ else if ( componentType[ 1 ] === 'u' ) result = 'uint';
1817
+ else result = 'float';
1818
+
1819
+ _componentTypeCache.set( type, result );
1820
+
1821
+ }
1822
+
1823
+ return result;
1666
1824
 
1667
1825
  }
1668
1826
 
@@ -1726,7 +1884,9 @@ class NodeBuilder {
1726
1884
  */
1727
1885
  isInteger( type ) {
1728
1886
 
1729
- return /int|uint|(i|u)vec/.test( type );
1887
+ let result = _isIntegerCache.get( type );
1888
+ if ( result === undefined ) _isIntegerCache.set( type, result = /int|uint|(i|u)vec/.test( type ) );
1889
+ return result;
1730
1890
 
1731
1891
  }
1732
1892
 
@@ -1767,6 +1927,24 @@ class NodeBuilder {
1767
1927
  getTypeLength( type ) {
1768
1928
 
1769
1929
  const vecType = this.getVectorType( type );
1930
+
1931
+ let length = _typeLengthCache.get( vecType );
1932
+
1933
+ if ( length === undefined ) {
1934
+
1935
+ length = this._getTypeLength( vecType );
1936
+
1937
+ _typeLengthCache.set( vecType, length );
1938
+
1939
+ }
1940
+
1941
+ return length;
1942
+
1943
+ }
1944
+
1945
+ _getTypeLength( type ) {
1946
+
1947
+ const vecType = type;
1770
1948
  const vecNum = /vec([2-4])/.exec( vecType );
1771
1949
 
1772
1950
  if ( vecNum !== null ) return Number( vecNum[ 1 ] );
@@ -1806,6 +1984,52 @@ class NodeBuilder {
1806
1984
 
1807
1985
  }
1808
1986
 
1987
+ /**
1988
+ * Returns the common component type of the input nodes. Explicit types are
1989
+ * promoted first, then weak constants adopt that type, being truncated like other
1990
+ * integer constants. Only weak constants out of the integer range promote it.
1991
+ * Inputs consisting only of weak constants default to float.
1992
+ *
1993
+ * @param {...?Node} nodes - The input nodes.
1994
+ * @return {string} The promoted component type.
1995
+ */
1996
+ getPromotedComponentType( ...nodes ) {
1997
+
1998
+ let type = null;
1999
+ let hasWeak = false;
2000
+ let fitsUint = true;
2001
+ let fitsInt = true;
2002
+
2003
+ for ( const node of nodes ) {
2004
+
2005
+ if ( node === null ) continue;
2006
+
2007
+ if ( node.isWeak === true ) {
2008
+
2009
+ const value = Math.trunc( node.value );
2010
+
2011
+ hasWeak = true;
2012
+ fitsUint = fitsUint && value >= 0 && value <= 0xffffffff;
2013
+ fitsInt = fitsInt && value >= - 0x80000000 && value <= 0x7fffffff;
2014
+
2015
+ } else {
2016
+
2017
+ const componentType = this.getComponentType( node.getNodeType( this ) );
2018
+
2019
+ if ( type === null || _componentTypeRanks[ componentType ] > _componentTypeRanks[ type ] ) type = componentType;
2020
+
2021
+ }
2022
+
2023
+ }
2024
+
2025
+ if ( type === null || ( type === 'bool' && hasWeak ) ) return 'float';
2026
+ if ( type === 'uint' && fitsUint === false ) return fitsInt ? 'int' : 'float';
2027
+ if ( type === 'int' && fitsInt === false ) return 'float';
2028
+
2029
+ return type;
2030
+
2031
+ }
2032
+
1809
2033
  /**
1810
2034
  * Returns the integer type pendant for the given type.
1811
2035
  *
@@ -1874,6 +2098,55 @@ class NodeBuilder {
1874
2098
 
1875
2099
  }
1876
2100
 
2101
+ /**
2102
+ * Creates a block that repeats its code, e.g. a loop body, used in the current context.
2103
+ * The block keeps its parent block, the context and its position in the active stack.
2104
+ *
2105
+ * @return {Object} The code block.
2106
+ */
2107
+ createBlock() {
2108
+
2109
+ const stack = this.getActiveStack();
2110
+
2111
+ return {
2112
+ parent: this.context.nodeBlock || null,
2113
+ context: this.context,
2114
+ stack,
2115
+ node: stack !== undefined ? stack._currentNode : undefined
2116
+ };
2117
+
2118
+ }
2119
+
2120
+ /**
2121
+ * Declares a node outside of the stacks of this build, e.g. created outside of a function, before the outermost
2122
+ * block that would repeat it, e.g. a loop body. Blocks set up in another build or with context overrides of the
2123
+ * current one are kept, since the node could have another value in them.
2124
+ *
2125
+ * @param {Node} node - The node to declare.
2126
+ * @return {StackNode|undefined} The stack where the node was declared.
2127
+ */
2128
+ declareBeforeBlock( node ) {
2129
+
2130
+ if ( this.flowBlock !== null ) return;
2131
+
2132
+ let block;
2133
+
2134
+ for ( let nodeBlock = this.context.nodeBlock; nodeBlock; nodeBlock = nodeBlock.parent ) {
2135
+
2136
+ if ( this.activeStacks.includes( nodeBlock.stack ) === false || _hasContextOverrides( this.context, nodeBlock.context ) ) break;
2137
+
2138
+ block = nodeBlock;
2139
+
2140
+ }
2141
+
2142
+ if ( block === undefined || this.activeStacks.some( activeStack => activeStack.nodes.includes( node ) ) ) return;
2143
+
2144
+ block.stack.addToStackBefore( node, block.node );
2145
+
2146
+ return block.stack;
2147
+
2148
+ }
2149
+
1877
2150
  /**
1878
2151
  * Adds a stack node to the internal stack.
1879
2152
  *
@@ -1939,7 +2212,7 @@ class NodeBuilder {
1939
2212
 
1940
2213
  }
1941
2214
 
1942
- if ( nodeData[ shaderStage ] === undefined ) nodeData[ shaderStage ] = {};
2215
+ if ( nodeData[ shaderStage ] === undefined ) nodeData[ shaderStage ] = new NodeData();
1943
2216
 
1944
2217
  //
1945
2218
 
@@ -1954,7 +2227,7 @@ class NodeBuilder {
1954
2227
 
1955
2228
  if ( data.subBuildsCache === undefined ) data.subBuildsCache = {};
1956
2229
 
1957
- data = data.subBuildsCache[ subBuild ] || ( data.subBuildsCache[ subBuild ] = {} );
2230
+ data = data.subBuildsCache[ subBuild ] || ( data.subBuildsCache[ subBuild ] = new NodeData() );
1958
2231
  data.subBuilds = subBuilds;
1959
2232
 
1960
2233
  }
@@ -2124,13 +2397,15 @@ class NodeBuilder {
2124
2397
  * @param {string} [type=node.getNodeType( this )] - The variable's type.
2125
2398
  * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
2126
2399
  * @param {boolean} [readOnly=false] - Whether the variable is read-only or not.
2400
+ * @param {boolean} [local=false] - Whether the variable is declared locally in the flow instead of the variable section.
2401
+ * @param {string} [property='variable'] - The node data property that holds the variable. Allows a node to own more than one variable.
2127
2402
  *
2128
2403
  * @return {NodeVar} The node variable.
2129
2404
  */
2130
- getVarFromNode( node, name = null, type = node.getNodeType( this ), shaderStage = this.shaderStage, readOnly = false ) {
2405
+ getVarFromNode( node, name = null, type = node.getNodeType( this ), shaderStage = this.shaderStage, readOnly = false, local = false, property = 'variable' ) {
2131
2406
 
2132
2407
  const nodeData = this.getDataFromNode( node, shaderStage );
2133
- const subBuildVariable = this.getSubBuildProperty( 'variable', nodeData.subBuilds );
2408
+ const subBuildVariable = this.getSubBuildProperty( property, nodeData.subBuilds );
2134
2409
 
2135
2410
  let nodeVar = nodeData[ subBuildVariable ];
2136
2411
 
@@ -2151,7 +2426,7 @@ class NodeBuilder {
2151
2426
 
2152
2427
  //
2153
2428
 
2154
- if ( subBuildVariable !== 'variable' ) {
2429
+ if ( subBuildVariable !== property ) {
2155
2430
 
2156
2431
  name = this.getSubBuildProperty( name, nodeData.subBuilds );
2157
2432
 
@@ -2161,9 +2436,9 @@ class NodeBuilder {
2161
2436
 
2162
2437
  const count = node.getArrayCount( this );
2163
2438
 
2164
- nodeVar = new NodeVar( name, type, readOnly, count );
2439
+ nodeVar = new NodeVar( name, type, readOnly, count, local );
2165
2440
 
2166
- if ( ! readOnly ) {
2441
+ if ( ! readOnly && ! local ) {
2167
2442
 
2168
2443
  vars.push( nodeVar );
2169
2444
 
@@ -2187,6 +2462,12 @@ class NodeBuilder {
2187
2462
  */
2188
2463
  isDeterministic( node ) {
2189
2464
 
2465
+ if ( node.isVarNode && node.assignable ) {
2466
+
2467
+ node = node.node;
2468
+
2469
+ }
2470
+
2190
2471
  if ( node.isMathNode ) {
2191
2472
 
2192
2473
  return this.isDeterministic( node.aNode ) &&
@@ -2288,16 +2569,16 @@ class NodeBuilder {
2288
2569
  const baseName = node.name;
2289
2570
 
2290
2571
  let name = baseName;
2291
- let property = this.getPropertyName( node );
2572
+ let declarationName = this.getDeclarationName( node );
2292
2573
  let index = 1;
2293
2574
 
2294
2575
  // Automatically renames the property if the name is already in use or reserved.
2295
2576
 
2296
- while ( ( checkKeywords && this.isReservedKeyword( name ) ) || declarations[ property ] !== undefined ) {
2577
+ while ( ( checkKeywords && this.isReservedKeyword( name ) ) || declarations[ declarationName ] !== undefined ) {
2297
2578
 
2298
2579
  name = baseName + '_' + index ++;
2299
2580
  node.name = name;
2300
- property = this.getPropertyName( node );
2581
+ declarationName = this.getDeclarationName( node );
2301
2582
 
2302
2583
  }
2303
2584
 
@@ -2307,7 +2588,20 @@ class NodeBuilder {
2307
2588
 
2308
2589
  }
2309
2590
 
2310
- declarations[ property ] = node;
2591
+ declarations[ declarationName ] = node;
2592
+
2593
+ }
2594
+
2595
+ /**
2596
+ * Returns the identifier the given node declares in the shader. It is used
2597
+ * by {@link NodeBuilder#registerDeclaration} to detect name collisions.
2598
+ *
2599
+ * @param {Object} node - The node.
2600
+ * @return {string} The declaration name.
2601
+ */
2602
+ getDeclarationName( node ) {
2603
+
2604
+ return this.getPropertyName( node );
2311
2605
 
2312
2606
  }
2313
2607
 
@@ -2342,85 +2636,20 @@ class NodeBuilder {
2342
2636
 
2343
2637
  }
2344
2638
 
2345
- /**
2346
- * Adds a code flow based on the code-block hierarchy.
2347
-
2348
- * This is used so that code-blocks like If,Else create their variables locally if the Node
2349
- * is only used inside one of these conditionals in the current shader stage.
2350
- *
2351
- * @param {Node} node - The node to add.
2352
- * @param {Node} nodeBlock - Node-based code-block. Usually 'ConditionalNode'.
2353
- */
2354
- addFlowCodeHierarchy( node, nodeBlock ) {
2355
-
2356
- const { flowCodes, flowCodeBlock } = this.getDataFromNode( node );
2357
-
2358
- let needsFlowCode = true;
2359
- let nodeBlockHierarchy = nodeBlock;
2360
-
2361
- while ( nodeBlockHierarchy ) {
2362
-
2363
- if ( flowCodeBlock.get( nodeBlockHierarchy ) === true ) {
2364
-
2365
- needsFlowCode = false;
2366
- break;
2367
-
2368
- }
2369
-
2370
- nodeBlockHierarchy = this.getDataFromNode( nodeBlockHierarchy ).parentNodeBlock;
2371
-
2372
- }
2373
-
2374
- if ( needsFlowCode ) {
2375
-
2376
- for ( const flowCode of flowCodes ) {
2377
-
2378
- this.addLineFlowCode( flowCode );
2379
-
2380
- }
2381
-
2382
- }
2383
-
2384
- }
2385
-
2386
- /**
2387
- * Add a inline-code to the current flow code-block.
2388
- *
2389
- * @param {Node} node - The node to add.
2390
- * @param {string} code - The code to add.
2391
- * @param {Node} nodeBlock - Current ConditionalNode
2392
- */
2393
- addLineFlowCodeBlock( node, code, nodeBlock ) {
2394
-
2395
- const nodeData = this.getDataFromNode( node );
2396
- const flowCodes = nodeData.flowCodes || ( nodeData.flowCodes = [] );
2397
- const codeBlock = nodeData.flowCodeBlock || ( nodeData.flowCodeBlock = new WeakMap() );
2398
-
2399
- flowCodes.push( code );
2400
- codeBlock.set( nodeBlock, true );
2401
-
2402
- }
2403
-
2404
2639
  /**
2405
2640
  * Add a inline-code to the current flow.
2406
2641
  *
2407
2642
  * @param {string} code - The code to add.
2408
- * @param {?Node} [node= null] - Optional Node, can help the system understand if the Node is part of a code-block.
2643
+ * @param {?Node} [node= null] - The node that generated the code.
2409
2644
  * @return {NodeBuilder} A reference to this node builder.
2410
2645
  */
2411
- addLineFlowCode( code, node = null ) {
2646
+ addLineFlowCode( code /*, node = null */ ) {
2412
2647
 
2413
2648
  if ( code === '' ) return this;
2414
2649
 
2415
- if ( node !== null && this.context.nodeBlock ) {
2416
-
2417
- this.addLineFlowCodeBlock( node, code, this.context.nodeBlock );
2418
-
2419
- }
2420
-
2421
2650
  code = this.tab + code;
2422
2651
 
2423
- if ( ! /;\s*$/.test( code ) ) {
2652
+ if ( code.trimEnd().endsWith( ';' ) === false ) {
2424
2653
 
2425
2654
  code = code + ';\n';
2426
2655
 
@@ -2512,7 +2741,7 @@ class NodeBuilder {
2512
2741
  */
2513
2742
  addInclude( node ) {
2514
2743
 
2515
- if ( this.currentFunctionNode !== null ) {
2744
+ if ( this.currentFunctionNode !== null && this.currentFunctionNode.includes.includes( node ) === false ) {
2516
2745
 
2517
2746
  this.currentFunctionNode.includes.push( node );
2518
2747
 
@@ -2572,37 +2801,229 @@ class NodeBuilder {
2572
2801
 
2573
2802
  const layout = shaderNode.layout;
2574
2803
 
2575
- const inputs = {
2576
- [ Symbol.iterator ]() {
2804
+ const inputs = _createLayoutInputs( layout, layout.inputs.map( input => new ParameterNode( input.type, input.name ) ) );
2805
+
2806
+ //
2807
+
2808
+ shaderNode.layout = null;
2809
+
2810
+ const callNode = shaderNode.call( inputs );
2811
+ const flowData = this.flowStagesNode( callNode, layout.type );
2812
+
2813
+ shaderNode.layout = layout;
2814
+
2815
+ return flowData;
2816
+
2817
+ }
2818
+
2819
+ /**
2820
+ * Returns the inputs of a call to a TSL function with layout. Missing inputs are completed
2821
+ * with the default values of the function parameters, found by running the function once
2822
+ * with all inputs and once without the missing ones, and comparing both node graphs.
2823
+ *
2824
+ * @private
2825
+ * @param {ShaderNodeInternal} shaderNode - The shader node of the function.
2826
+ * @param {?Array} rawInputs - The inputs of the call.
2827
+ * @return {?Array} The inputs of the call, or `null` if the defaults can't be resolved and the function must be expanded inline.
2828
+ */
2829
+ _getLayoutInputs( shaderNode, rawInputs ) {
2830
+
2831
+ const inputs = shaderNode.layout.inputs;
2832
+
2833
+ const firstInput = rawInputs !== null && rawInputs.length > 0 ? rawInputs[ 0 ] : null;
2834
+ const object = firstInput !== null && firstInput !== undefined && isArrayAsParameter( rawInputs ) === false ? firstInput : null;
2835
+ const provided = inputs.map( ( input, i ) => object !== null ? object[ input.name ] !== undefined : rawInputs !== null && rawInputs[ i ] !== undefined );
2836
+
2837
+ if ( provided.every( Boolean ) ) return rawInputs !== null ? rawInputs : [];
2838
+
2839
+ if ( shaderNode.once ) return null;
2840
+
2841
+ // The defaults only depend on which inputs are missing, so they are shared by all builders.
2842
+
2843
+ let cache = _layoutDefaultsCache.get( shaderNode );
2844
+
2845
+ if ( cache === undefined ) {
2846
+
2847
+ cache = new Map();
2848
+ _layoutDefaultsCache.set( shaderNode, cache );
2849
+
2850
+ }
2851
+
2852
+ const key = provided.map( Number ).join( '' );
2853
+
2854
+ let defaults = cache.get( key );
2855
+
2856
+ if ( defaults === undefined ) {
2857
+
2858
+ defaults = this._resolveLayoutDefaults( shaderNode, provided );
2859
+ cache.set( key, defaults );
2860
+
2861
+ }
2862
+
2863
+ if ( defaults === null ) return null;
2864
+
2865
+ if ( object !== null ) {
2866
+
2867
+ const completed = { ...object };
2868
+
2869
+ inputs.forEach( ( input, i ) => {
2870
+
2871
+ if ( provided[ i ] === false ) completed[ input.name ] = defaults[ i ];
2872
+
2873
+ } );
2874
+
2875
+ return [ completed ];
2876
+
2877
+ }
2878
+
2879
+ return provided.map( ( isProvided, i ) => isProvided ? rawInputs[ i ] : defaults[ i ] );
2880
+
2881
+ }
2882
+
2883
+ /**
2884
+ * Resolves the default values of the missing inputs of a TSL function with layout.
2885
+ *
2886
+ * @private
2887
+ * @param {ShaderNodeInternal} shaderNode - The shader node of the function.
2888
+ * @param {Array<boolean>} provided - Whether each input of the layout was provided.
2889
+ * @return {?Array<Node>} The default value of each missing input, or `null` if they could not be resolved.
2890
+ */
2891
+ _resolveLayoutDefaults( shaderNode, provided ) {
2892
+
2893
+ const layout = shaderNode.layout;
2894
+ const parameters = layout.inputs.map( input => new ParameterNode( input.type, input.name ) );
2895
+
2896
+ const fullGraph = this._getLayoutCallGraph( shaderNode, _createLayoutInputs( layout, parameters ) );
2897
+ const partialGraph = this._getLayoutCallGraph( shaderNode, _createLayoutInputs( layout, parameters.map( ( parameter, i ) => provided[ i ] ? parameter : undefined ) ) );
2898
+
2899
+ // Walk both graphs together: where the full graph uses the parameter of a missing input,
2900
+ // the partial graph uses its default value.
2901
+
2902
+ const missing = new Map();
2903
+ parameters.forEach( ( parameter, i ) => {
2904
+
2905
+ if ( provided[ i ] === false ) missing.set( parameter, i );
2906
+
2907
+ } );
2908
+
2909
+ const defaults = [];
2910
+ const visited = new Map();
2911
+
2912
+ const walk = ( a, b ) => {
2913
+
2914
+ if ( a === b ) return true;
2915
+ if ( ! a || ! b || a.isNode !== true || b.isNode !== true ) return false;
2916
+
2917
+ const index = missing.get( a );
2918
+
2919
+ if ( index !== undefined ) {
2920
+
2921
+ if ( defaults[ index ] === undefined ) defaults[ index ] = b;
2922
+
2923
+ return defaults[ index ] === b;
2577
2924
 
2578
- let index = 0;
2579
- const values = Object.values( this );
2580
- return {
2581
- next: () => ( {
2582
- value: values[ index ],
2583
- done: index ++ >= values.length
2584
- } )
2585
- };
2925
+ }
2926
+
2927
+ if ( visited.has( a ) ) return visited.get( a ) === b;
2928
+ if ( a.constructor !== b.constructor ) return false;
2929
+
2930
+ visited.set( a, b );
2931
+
2932
+ const childrenA = [ ...a.getChildren() ];
2933
+ const childrenB = [ ...b.getChildren() ];
2934
+
2935
+ if ( childrenA.length !== childrenB.length ) return false;
2936
+
2937
+ for ( let i = 0; i < childrenA.length; i ++ ) {
2938
+
2939
+ if ( walk( childrenA[ i ], childrenB[ i ] ) === false ) return false;
2586
2940
 
2587
2941
  }
2942
+
2943
+ return true;
2944
+
2588
2945
  };
2589
2946
 
2590
- for ( const input of layout.inputs ) {
2947
+ // The default values are evaluated when the parameters are destructured, before the body,
2948
+ // so the nodes they add to the stack come first. Align the body statements from the end.
2949
+
2950
+ const extra = partialGraph.nodes.length - fullGraph.nodes.length;
2951
+
2952
+ if ( extra < 0 ) return null;
2953
+
2954
+ visited.set( fullGraph, partialGraph );
2955
+
2956
+ if ( walk( fullGraph.outputNode, partialGraph.outputNode ) === false ) return null;
2591
2957
 
2592
- inputs[ input.name ] = new ParameterNode( input.type, input.name );
2958
+ for ( let i = 0; i < fullGraph.nodes.length; i ++ ) {
2959
+
2960
+ if ( walk( fullGraph.nodes[ i ], partialGraph.nodes[ extra + i ] ) === false ) return null;
2593
2961
 
2594
2962
  }
2595
2963
 
2596
- //
2964
+ // Every missing input must have a default that does not depend on other parameters.
2965
+
2966
+ const parameterSet = new Set( parameters );
2967
+
2968
+ for ( const index of missing.values() ) {
2969
+
2970
+ const value = defaults[ index ];
2971
+
2972
+ if ( value === undefined ) return null;
2973
+
2974
+ const stack = [ value ];
2975
+ const seen = new Set();
2976
+
2977
+ while ( stack.length > 0 ) {
2978
+
2979
+ const node = stack.pop();
2980
+
2981
+ if ( parameterSet.has( node ) ) return null;
2982
+ if ( seen.has( node ) ) continue;
2983
+
2984
+ seen.add( node );
2985
+
2986
+ for ( const child of node.getChildren() ) stack.push( child );
2987
+
2988
+ }
2989
+
2990
+ }
2991
+
2992
+ return defaults;
2993
+
2994
+ }
2995
+
2996
+ /**
2997
+ * Runs a TSL function with layout as an inline call and returns the resulting stack.
2998
+ *
2999
+ * @private
3000
+ * @param {ShaderNodeInternal} shaderNode - The shader node of the function.
3001
+ * @param {Object} inputs - The inputs of the call.
3002
+ * @return {StackNode} The stack with the nodes of the call.
3003
+ */
3004
+ _getLayoutCallGraph( shaderNode, inputs ) {
3005
+
3006
+ const layout = shaderNode.layout;
3007
+
3008
+ let graph;
2597
3009
 
2598
3010
  shaderNode.layout = null;
2599
3011
 
2600
- const callNode = shaderNode.call( inputs );
2601
- const flowData = this.flowStagesNode( callNode, layout.type );
3012
+ this.addStack();
2602
3013
 
2603
- shaderNode.layout = layout;
3014
+ try {
2604
3015
 
2605
- return flowData;
3016
+ this.stack.outputNode = shaderNode.call( inputs ).call( this );
3017
+
3018
+ } finally {
3019
+
3020
+ graph = this.removeStack();
3021
+
3022
+ shaderNode.layout = layout;
3023
+
3024
+ }
3025
+
3026
+ return graph;
2606
3027
 
2607
3028
  }
2608
3029
 
@@ -2649,6 +3070,7 @@ class NodeBuilder {
2649
3070
  const previousCache = this.cache;
2650
3071
  const previousBuildStage = this.buildStage;
2651
3072
  const previousStack = this.stack;
3073
+ const previousFlowBlock = this.flowBlock;
2652
3074
 
2653
3075
  const flow = {
2654
3076
  code: ''
@@ -2659,6 +3081,7 @@ class NodeBuilder {
2659
3081
  this.declarations = {};
2660
3082
  this.cache = new NodeCache();
2661
3083
  this.stack = stack();
3084
+ this.flowBlock = null;
2662
3085
 
2663
3086
  for ( const buildStage of defaultBuildStages ) {
2664
3087
 
@@ -2675,6 +3098,7 @@ class NodeBuilder {
2675
3098
  this.declarations = previousDeclarations;
2676
3099
  this.cache = previousCache;
2677
3100
  this.stack = previousStack;
3101
+ this.flowBlock = previousFlowBlock;
2678
3102
 
2679
3103
  this.setBuildStage( previousBuildStage );
2680
3104
 
@@ -2752,12 +3176,14 @@ class NodeBuilder {
2752
3176
  const previousCache = this.cache;
2753
3177
  const previousShaderStage = this.shaderStage;
2754
3178
  const previousContext = this.context;
3179
+ const previousFlowBlock = this.flowBlock;
2755
3180
 
2756
3181
  this.setShaderStage( shaderStage );
2757
3182
 
2758
3183
  const context = { ...this.context };
2759
3184
  delete context.nodeBlock;
2760
3185
 
3186
+ this.flowBlock = null;
2761
3187
  this.cache = this.globalCache;
2762
3188
  this.tab = '\t';
2763
3189
  this.context = context;
@@ -2789,6 +3215,7 @@ class NodeBuilder {
2789
3215
  this.cache = previousCache;
2790
3216
  this.tab = previousTab;
2791
3217
  this.context = previousContext;
3218
+ this.flowBlock = previousFlowBlock;
2792
3219
 
2793
3220
  return result;
2794
3221
 
@@ -2845,6 +3272,49 @@ class NodeBuilder {
2845
3272
 
2846
3273
  }
2847
3274
 
3275
+ /**
3276
+ * Returns a single const variable statement as a shader string for the given variable type and name.
3277
+ *
3278
+ * @param {string} type - The variable's type.
3279
+ * @param {string} name - The variable's name.
3280
+ * @param {?number} [count=null] - The array length.
3281
+ * @return {string} The shader string.
3282
+ */
3283
+ generateConstStatement( type, name, count = null ) {
3284
+
3285
+ return `const ${ this.getVar( type, name, count ) }`;
3286
+
3287
+ }
3288
+
3289
+ /**
3290
+ * Returns a single variable statement as a shader string for the given variable type and name.
3291
+ *
3292
+ * @param {string} type - The variable's type.
3293
+ * @param {string} name - The variable's name.
3294
+ * @param {?number} [count=null] - The array length.
3295
+ * @return {string} The shader string.
3296
+ */
3297
+ generateVarStatement( type, name, count = null ) {
3298
+
3299
+ return this.getVar( type, name, count );
3300
+
3301
+ }
3302
+
3303
+ /**
3304
+ * Returns a runtime read-only variable statement as a shader string.
3305
+ * Backends without a let declaration use a regular variable declaration.
3306
+ *
3307
+ * @param {string} type - The variable's type.
3308
+ * @param {string} name - The variable's name.
3309
+ * @param {?number} [count=null] - The array length.
3310
+ * @return {string} The shader string.
3311
+ */
3312
+ generateLetStatement( type, name, count = null ) {
3313
+
3314
+ return this.generateVarStatement( type, name, count );
3315
+
3316
+ }
3317
+
2848
3318
  /**
2849
3319
  * Returns the variable definitions as a shader string for the given shader stage.
2850
3320
  *
@@ -3127,7 +3597,7 @@ class NodeBuilder {
3127
3597
 
3128
3598
  if ( renderer.contextNode.isContextNode === true ) {
3129
3599
 
3130
- this.context = { ...this.context, ...renderer.contextNode.getFlowContextData() };
3600
+ this.addContext( renderer.contextNode.getFlowContextData() );
3131
3601
 
3132
3602
  } else {
3133
3603
 
@@ -3141,7 +3611,7 @@ class NodeBuilder {
3141
3611
 
3142
3612
  if ( material.contextNode.isContextNode === true ) {
3143
3613
 
3144
- this.context = { ...this.context, ...material.contextNode.getFlowContextData() };
3614
+ this.addContext( material.contextNode.getFlowContextData() );
3145
3615
 
3146
3616
  } else {
3147
3617
 
@@ -3238,9 +3708,10 @@ class NodeBuilder {
3238
3708
  * Async version of build() that yields to main thread between shader stages.
3239
3709
  * Use this in compileAsync() to prevent blocking the main thread.
3240
3710
  *
3711
+ * @param {Function} [yieldFn=yieldToMain] - The function used to yield to the main thread.
3241
3712
  * @return {Promise<NodeBuilder>} A promise that resolves to this node builder.
3242
3713
  */
3243
- async buildAsync() {
3714
+ async buildAsync( yieldFn = yieldToMain ) {
3244
3715
 
3245
3716
  this.prebuild();
3246
3717
 
@@ -3279,7 +3750,7 @@ class NodeBuilder {
3279
3750
  }
3280
3751
 
3281
3752
  // Yield to main thread after each shader stage to prevent blocking
3282
- await yieldToMain();
3753
+ await yieldFn();
3283
3754
 
3284
3755
  }
3285
3756
 
@@ -3297,26 +3768,6 @@ class NodeBuilder {
3297
3768
 
3298
3769
  }
3299
3770
 
3300
- /**
3301
- * Returns shared data object for the given node.
3302
- *
3303
- * @param {Node} node - The node to get shared data from.
3304
- * @return {Object} The shared data.
3305
- */
3306
- getSharedDataFromNode( node ) {
3307
-
3308
- let data = sharedNodeData.get( node );
3309
-
3310
- if ( data === undefined ) {
3311
-
3312
- data = {};
3313
-
3314
- }
3315
-
3316
- return data;
3317
-
3318
- }
3319
-
3320
3771
  /**
3321
3772
  * Returns a uniform representation which is later used for UBO generation and rendering.
3322
3773
  *
@@ -3326,31 +3777,16 @@ class NodeBuilder {
3326
3777
  */
3327
3778
  getNodeUniform( uniformNode, type ) {
3328
3779
 
3329
- const nodeData = this.getSharedDataFromNode( uniformNode );
3330
-
3331
- let node = nodeData.cache;
3332
-
3333
- if ( node === undefined ) {
3334
-
3335
- if ( type === 'float' || type === 'int' || type === 'uint' ) node = new NumberNodeUniform( uniformNode );
3336
- else if ( type === 'vec2' || type === 'ivec2' || type === 'uvec2' ) node = new Vector2NodeUniform( uniformNode );
3337
- else if ( type === 'vec3' || type === 'ivec3' || type === 'uvec3' ) node = new Vector3NodeUniform( uniformNode );
3338
- else if ( type === 'vec4' || type === 'ivec4' || type === 'uvec4' ) node = new Vector4NodeUniform( uniformNode );
3339
- else if ( type === 'color' ) node = new ColorNodeUniform( uniformNode );
3340
- else if ( type === 'mat2' ) node = new Matrix2NodeUniform( uniformNode );
3341
- else if ( type === 'mat3' ) node = new Matrix3NodeUniform( uniformNode );
3342
- else if ( type === 'mat4' ) node = new Matrix4NodeUniform( uniformNode );
3343
- else {
3344
-
3345
- throw new Error( `THREE.NodeBuilder: Uniform "${ type }" not implemented.` );
3346
-
3347
- }
3780
+ if ( type === 'float' || type === 'int' || type === 'uint' ) return new NumberNodeUniform( uniformNode );
3781
+ if ( type === 'vec2' || type === 'ivec2' || type === 'uvec2' ) return new Vector2NodeUniform( uniformNode );
3782
+ if ( type === 'vec3' || type === 'ivec3' || type === 'uvec3' ) return new Vector3NodeUniform( uniformNode );
3783
+ if ( type === 'vec4' || type === 'ivec4' || type === 'uvec4' ) return new Vector4NodeUniform( uniformNode );
3784
+ if ( type === 'color' ) return new ColorNodeUniform( uniformNode );
3785
+ if ( type === 'mat2' ) return new Matrix2NodeUniform( uniformNode );
3786
+ if ( type === 'mat3' ) return new Matrix3NodeUniform( uniformNode );
3787
+ if ( type === 'mat4' ) return new Matrix4NodeUniform( uniformNode );
3348
3788
 
3349
- nodeData.cache = node;
3350
-
3351
- }
3352
-
3353
- return node;
3789
+ throw new Error( `THREE.NodeBuilder: Uniform "${ type }" not implemented.` );
3354
3790
 
3355
3791
  }
3356
3792
 
@@ -3423,13 +3859,19 @@ class NodeBuilder {
3423
3859
 
3424
3860
  if ( toTypeLength === 4 && fromTypeLength > 1 ) { // toType is vec4-like
3425
3861
 
3426
- return `${ this.getType( toType ) }( ${ this.format( snippet, fromType, 'vec3' ) }, 1.0 )`;
3862
+ const componentType = this.getComponentType( toType );
3863
+ const vectorType = this.getTypeFromLength( 3, componentType );
3864
+
3865
+ return `${ this.getType( toType ) }( ${ this.format( snippet, fromType, vectorType ) }, ${ this.generateConst( componentType, componentType === 'bool' ? true : 1 ) } )`;
3427
3866
 
3428
3867
  }
3429
3868
 
3430
3869
  if ( fromTypeLength === 2 ) { // fromType is vec2-like and toType is vec3-like
3431
3870
 
3432
- return `${ this.getType( toType ) }( ${ this.format( snippet, fromType, 'vec2' ) }, 0.0 )`;
3871
+ const componentType = this.getComponentType( toType );
3872
+ const vectorType = this.getTypeFromLength( 2, componentType );
3873
+
3874
+ return `${ this.getType( toType ) }( ${ this.format( snippet, fromType, vectorType ) }, ${ this.generateConst( componentType, componentType === 'bool' ? false : 0 ) } )`;
3433
3875
 
3434
3876
  }
3435
3877
 
@@ -3467,7 +3909,7 @@ class NodeBuilder {
3467
3909
 
3468
3910
  const mrt = this.renderer.getMRT();
3469
3911
 
3470
- return ( mrt && mrt.has( 'velocity' ) ) || ( this.object !== null && getDataFromObject( this.object ).useVelocity === true );
3912
+ return ( mrt !== null && mrt.has( 'velocity' ) );
3471
3913
 
3472
3914
  }
3473
3915