@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
@@ -1,10 +1,8 @@
1
1
  import {
2
2
  Texture,
3
- RepeatWrapping,
4
- ClampToEdgeWrapping,
5
- MirroredRepeatWrapping,
6
3
  ImageLoader,
7
4
  ImageBitmapLoader,
5
+ LoaderUtils,
8
6
  Matrix3,
9
7
  Matrix4,
10
8
  MeshBasicNodeMaterial,
@@ -13,6 +11,7 @@ import {
13
11
 
14
12
  import {
15
13
  float,
14
+ texture,
16
15
  int,
17
16
  bool,
18
17
  sub,
@@ -26,6 +25,14 @@ import {
26
25
  element,
27
26
  mx_transform_uv,
28
27
  mx_srgb_texture_to_lin_rec709,
28
+ positionLocal,
29
+ positionWorld,
30
+ normalLocal,
31
+ normalWorld,
32
+ tangentLocal,
33
+ tangentWorld,
34
+ bitangentLocal,
35
+ bitangentWorld,
29
36
  } from 'three/tsl';
30
37
 
31
38
  import { MaterialXLogCodes } from './MaterialXLog.js';
@@ -33,8 +40,9 @@ import { createMaterialXCompileRegistry, compileNodeFromRegistry } from './compi
33
40
  import { parseMaterialXNodeTree, parseMaterialXText } from './parse/MaterialXParser.js';
34
41
  import { getSurfaceMapper } from './MaterialXSurfaceMappings.js';
35
42
  import { MtlXLibrary } from './MaterialXNodeLibrary.js';
43
+ import { resolveNodeDef } from './MaterialXNodeDefs.js';
36
44
  import { mxHextileCoord, mxHextileComputeBlendWeights } from './MaterialXHextile.js';
37
- import { toBooleanNode } from './MaterialXUtils.js';
45
+ import { resolveTextureAddressMode, TEXTURE_ADDRESS_MODE_WRAPPING, toBooleanNode } from './MaterialXUtils.js';
38
46
 
39
47
  const colorSpaceLib = {
40
48
  mx_srgb_texture_to_lin_rec709,
@@ -45,12 +53,6 @@ const IDENTITY_MAT3_VALUES = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
45
53
  const IDENTITY_MAT4_VALUES = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ];
46
54
  const MATRIX_INVERSE_EPSILON = 1e-8;
47
55
  const COMPILE_REGISTRY = createMaterialXCompileRegistry();
48
- const TEXTURE_ADDRESS_MODE_WRAPPING = {
49
- constant: ClampToEdgeWrapping,
50
- clamp: ClampToEdgeWrapping,
51
- periodic: RepeatWrapping,
52
- mirror: MirroredRepeatWrapping,
53
- };
54
56
  const NODE_CLASS_BY_TYPE = {
55
57
  integer: int,
56
58
  float,
@@ -63,6 +65,84 @@ const NODE_CLASS_BY_TYPE = {
63
65
  matrix33: mat3,
64
66
  matrix44: mat4,
65
67
  };
68
+ // Geometric properties a nodedef input can default to via `defaultgeomprop`.
69
+ const GEOMPROP_NODES = {
70
+ Pobject: positionLocal,
71
+ Pworld: positionWorld,
72
+ Nobject: normalLocal,
73
+ Nworld: normalWorld,
74
+ Tobject: tangentLocal,
75
+ Tworld: tangentWorld,
76
+ Bobject: bitangentLocal,
77
+ Bworld: bitangentWorld,
78
+ Vworld: MtlXLibrary.viewdirection.nodeFunc( 'world' ),
79
+ };
80
+
81
+ function parseValueVector( value ) {
82
+
83
+ const vector = [];
84
+ for ( const val of value.split( /[,|\s]/ ) ) {
85
+
86
+ if ( val !== '' ) vector.push( Number( val.trim() ) );
87
+
88
+ }
89
+
90
+ return vector;
91
+
92
+ }
93
+
94
+ function createMatrixNode( size, vector ) {
95
+
96
+ const expectedLength = size * size;
97
+ if ( vector.length !== expectedLength ) return null;
98
+
99
+ // MaterialX matrix values are serialized in column-major order.
100
+ // Reorder to row-major before constructing TSL matrix nodes so
101
+ // transformmatrix semantics match MaterialXJS and MaterialXView.
102
+ const reordered = [];
103
+ for ( let row = 0; row < size; row += 1 ) {
104
+
105
+ for ( let column = 0; column < size; column += 1 ) {
106
+
107
+ reordered.push( vector[ column * size + row ] );
108
+
109
+ }
110
+
111
+ }
112
+
113
+ return size === 3 ? mat3( ...reordered ) : mat4( ...reordered );
114
+
115
+ }
116
+
117
+ // Empty strings are valid string defaults, but an empty filename means "no texture".
118
+ function hasDefaultValue( input ) {
119
+
120
+ if ( input.value === undefined ) return false;
121
+ return input.value !== '' || input.type === 'string';
122
+
123
+ }
124
+
125
+ // string values stay strings so the compiler can read e.g. space names
126
+ function createValueNode( type, value ) {
127
+
128
+ const trimmed = value.trim();
129
+
130
+ if ( type === 'boolean' ) {
131
+
132
+ const normalized = trimmed.toLowerCase();
133
+ return bool( normalized === 'true' || normalized === '1' );
134
+
135
+ }
136
+
137
+ if ( type === 'matrix33' ) return createMatrixNode( 3, parseValueVector( trimmed ) ) || mat3( ...IDENTITY_MAT3_VALUES );
138
+ if ( type === 'matrix44' ) return createMatrixNode( 4, parseValueVector( trimmed ) ) || mat4( ...IDENTITY_MAT4_VALUES );
139
+ if ( type === 'string' || type === 'filename' ) return trimmed;
140
+
141
+ const nodeClass = NODE_CLASS_BY_TYPE[ type ];
142
+ return nodeClass ? nodeClass( ...parseValueVector( trimmed ) ) : float( 0 );
143
+
144
+ }
145
+
66
146
  const OUTPUT_CHANNELS = {
67
147
  outx: 0,
68
148
  outr: 0,
@@ -111,15 +191,6 @@ function isSvgUri( uri ) {
111
191
 
112
192
  }
113
193
 
114
- function normalizeTextureAddressMode( value ) {
115
-
116
- if ( value === null || value === undefined || value === '' ) return 'periodic';
117
-
118
- const mode = value.trim().toLowerCase();
119
- return mode in TEXTURE_ADDRESS_MODE_WRAPPING ? mode : null;
120
-
121
- }
122
-
123
194
  function invertConstantMatrixValues( values, size ) {
124
195
 
125
196
  if ( ! Array.isArray( values ) || values.length !== size * size ) return null;
@@ -170,6 +241,7 @@ class MaterialXNode {
170
241
  this.parent = null;
171
242
  this.node = null;
172
243
  this.children = [];
244
+ this._nodeDef = undefined;
173
245
 
174
246
  }
175
247
 
@@ -273,6 +345,19 @@ class MaterialXNode {
273
345
 
274
346
  return this.referencePath !== null;
275
347
 
348
+ }
349
+
350
+ getReferencedNode() {
351
+
352
+ if ( this.nodeGraph !== null ) {
353
+
354
+ const graph = this.materialX.getMaterialXNode( this.nodeGraph );
355
+ return graph ? this.output !== null ? graph.getChildByName( this.output ) || null : graph.children.find( ( child ) => child.element === 'output' ) || null : null;
356
+
357
+ }
358
+
359
+ return this.hasReference ? this.materialX.getMaterialXNode( this.referencePath ) || null : null;
360
+
276
361
  }
277
362
  get isConst() {
278
363
 
@@ -280,9 +365,65 @@ class MaterialXNode {
280
365
 
281
366
  }
282
367
 
368
+ /**
369
+ * The stdlib or document nodedef this node instance resolves to, or `null` when the category is unknown.
370
+ *
371
+ * @type {?Object}
372
+ */
373
+ get nodeDef() {
374
+
375
+ if ( this._nodeDef === undefined ) this._nodeDef = resolveNodeDef( this );
376
+ return this._nodeDef;
377
+
378
+ }
379
+
380
+ hasDeclaredOutput( name ) {
381
+
382
+ return this.nodeDef !== null && name in this.nodeDef.outputs;
383
+
384
+ }
385
+
386
+ // The declared type of a nodedef input, or `null` when the nodedef does not declare it.
387
+ getNodeDefInputType( name ) {
388
+
389
+ const input = this.nodeDef ? this.nodeDef.inputs[ name ] : undefined;
390
+ return input ? input.type : null;
391
+
392
+ }
393
+
394
+ // `undefined` when the nodedef declares no default (e.g. filenames)
395
+ getDefaultInputNode( name ) {
396
+
397
+ const input = this.nodeDef ? this.nodeDef.inputs[ name ] : undefined;
398
+ if ( ! input ) return undefined;
399
+
400
+ if ( input.defaultgeomprop ) return this.materialX.compileContext.getGeomPropNode( input.defaultgeomprop );
401
+ if ( ! hasDefaultValue( input ) ) return undefined;
402
+
403
+ return createValueNode( input.type, input.value );
404
+
405
+ }
406
+
407
+ // geometric defaults are left out so surface mappers can tell an authored normal from the default
408
+ getDefaultInputNodes() {
409
+
410
+ const nodes = {};
411
+ if ( this.nodeDef === null ) return nodes;
412
+
413
+ for ( const [ name, input ] of Object.entries( this.nodeDef.inputs ) ) {
414
+
415
+ if ( input.defaultgeomprop || ! hasDefaultValue( input ) ) continue;
416
+ nodes[ name ] = createValueNode( input.type, input.value );
417
+
418
+ }
419
+
420
+ return nodes;
421
+
422
+ }
423
+
283
424
  getColorSpaceNode() {
284
425
 
285
- const csSource = this.getAttribute( 'colorspace' );
426
+ const csSource = this.getValueInput().getAttribute( 'colorspace' ) || this.getAttribute( 'colorspace' );
286
427
  const csTarget = this.getRoot().getAttribute( 'colorspace' );
287
428
  if ( ! csSource || ! csTarget ) return null;
288
429
  const nodeName = `mx_${csSource}_to_${csTarget}`;
@@ -290,10 +431,23 @@ class MaterialXNode {
290
431
 
291
432
  }
292
433
 
434
+ logUnsupportedNode() {
435
+
436
+ this.materialX.log.add(
437
+ MaterialXLogCodes.UNSUPPORTED_NODE,
438
+ `Unsupported MaterialX node category "${this.element}" on "${this.name}".`,
439
+ this.name,
440
+ );
441
+
442
+ }
443
+
293
444
  getTextureAddressMode( inputName ) {
294
445
 
295
- const rawMode = this.getInputValueByName( inputName );
296
- const mode = normalizeTextureAddressMode( rawMode );
446
+ // e.g. tiledimage, which samples with the image node's default addressing.
447
+ if ( this.declaresInput( inputName ) === false ) return 'periodic';
448
+
449
+ const rawMode = this.getNodeByName( inputName );
450
+ const mode = resolveTextureAddressMode( rawMode );
297
451
  if ( mode ) return mode;
298
452
 
299
453
  this.materialX.log.add(
@@ -314,10 +468,22 @@ class MaterialXNode {
314
468
 
315
469
  }
316
470
 
471
+ // Follow an interfacename binding to its source input.
472
+ getValueInput() {
473
+
474
+ if ( this.interfaceName === null ) return this;
475
+ const boundInput = this.materialX.getInterfaceInput( this );
476
+ return boundInput !== null ? boundInput : this;
477
+
478
+ }
479
+
317
480
  getTexture() {
318
481
 
319
- const filePrefix = this.getRecursiveAttribute( 'fileprefix' ) || '';
320
- const sourceURI = filePrefix + this.value;
482
+ const valueInput = this.getValueInput();
483
+ if ( valueInput.getValue() === '' ) return null;
484
+
485
+ const filePrefix = valueInput.getRecursiveAttribute( 'fileprefix' ) || '';
486
+ const sourceURI = filePrefix + valueInput.value;
321
487
  const resolvedURI = this.materialX.resolveTextureURI( sourceURI );
322
488
  const svgTexture = isSvgUri( resolvedURI );
323
489
  const textureSourceNode = this.parent && typeof this.parent.getTextureAddressModes === 'function' ? this.parent : this;
@@ -331,29 +497,66 @@ class MaterialXNode {
331
497
  }
332
498
 
333
499
  let loader = svgTexture ? this.materialX.imageLoader : this.materialX.textureLoader;
500
+ let textureURL = resolvedURI;
334
501
  if ( resolvedURI && ! svgTexture ) {
335
502
 
336
503
  const handler = this.materialX.manager.getHandler( resolvedURI );
337
- if ( handler !== null ) loader = handler;
504
+ if ( handler !== null ) {
505
+
506
+ // The built-in loaders carry the document path; handlers do not.
507
+ loader = handler;
508
+ textureURL = LoaderUtils.resolveURL( resolvedURI, this.materialX.path );
509
+
510
+ }
338
511
 
339
512
  }
340
513
 
341
- const textureNode = new Texture();
342
- textureNode.wrapS = TEXTURE_ADDRESS_MODE_WRAPPING[ addressModes.u ];
343
- textureNode.wrapT = TEXTURE_ADDRESS_MODE_WRAPPING[ addressModes.v ];
344
- textureNode.flipY = false;
514
+ const textureNode = texture( new Texture() );
515
+ textureNode.value.wrapS = TEXTURE_ADDRESS_MODE_WRAPPING[ addressModes.u ];
516
+ textureNode.value.wrapT = TEXTURE_ADDRESS_MODE_WRAPPING[ addressModes.v ];
517
+ textureNode.value.flipY = false;
345
518
  this.materialX.textureCache.set( textureCacheKey, textureNode );
346
519
 
347
- loader.load( resolvedURI, ( imageData ) => {
520
+ const nodeName = this.name;
521
+ const materialX = this.materialX;
522
+
523
+ materialX.pendingResources.push( new Promise( ( resolveLoad ) => {
524
+
525
+ loader.load( textureURL, ( imageData ) => {
348
526
 
349
- textureNode.image = imageData;
350
- textureNode.needsUpdate = true;
527
+ if ( imageData.isTexture ) {
351
528
 
352
- }, undefined, () => {
529
+ // Clone so the wrapping and orientation set below don't modify the handler's texture.
530
+ textureNode.value = imageData.clone();
531
+ textureNode.value.wrapS = TEXTURE_ADDRESS_MODE_WRAPPING[ addressModes.u ];
532
+ textureNode.value.wrapT = TEXTURE_ADDRESS_MODE_WRAPPING[ addressModes.v ];
353
533
 
354
- throw new Error( `Failed to load texture "${resolvedURI}".` );
534
+ // MaterialXLoader keeps textures top-first. Loaders such as EXRLoader store rows
535
+ // bottom-first (flipY = false), so invert the loader's orientation to match.
536
+ // flipY has no meaning for compressed textures.
537
+ if ( imageData.isCompressedTexture !== true ) textureNode.value.flipY = ! imageData.flipY;
355
538
 
356
- } );
539
+ } else {
540
+
541
+ textureNode.value.image = imageData;
542
+
543
+ }
544
+
545
+ textureNode.value.needsUpdate = true;
546
+ resolveLoad();
547
+
548
+ }, undefined, () => {
549
+
550
+ materialX.log.add(
551
+ MaterialXLogCodes.TEXTURE_LOAD_FAILED,
552
+ `Failed to load texture "${resolvedURI}".`,
553
+ nodeName,
554
+ );
555
+ resolveLoad();
556
+
557
+ } );
558
+
559
+ } ) );
357
560
 
358
561
  return textureNode;
359
562
 
@@ -373,12 +576,17 @@ class MaterialXNode {
373
576
 
374
577
  getNode( out = null ) {
375
578
 
376
- if ( this.node !== null && out === null ) return this.node;
579
+ // A named output must not replace the cached default output.
580
+ const cacheDefaultOutput = out === null;
581
+ const cachedNode = this.materialX.getCachedNode( this );
582
+ if ( cachedNode !== null && cacheDefaultOutput ) return cachedNode;
377
583
 
378
584
  let node;
585
+ let implemented = false;
379
586
 
380
587
 
381
- if ( ( this.element === 'separate2' || this.element === 'separate3' || this.element === 'separate4' ) && out ) {
588
+ // A connection that names no output reads the first one, as in MaterialX.
589
+ if ( this.element === 'separate2' || this.element === 'separate3' || this.element === 'separate4' ) {
382
590
 
383
591
  const inNode = this.getNodeByName( 'in' );
384
592
  return element( inNode, getOutputChannel( out ) );
@@ -386,33 +594,12 @@ class MaterialXNode {
386
594
  }
387
595
 
388
596
  const type = this.type;
389
- const channelRequested = this.element !== 'input' && this.element !== 'gltf_colorimage' && isChannelOutput( out );
597
+ // Channel suffixes (outr, outy, ...) extract a component unless the nodedef declares an output of that name.
598
+ const channelRequested = this.element !== 'input' && isChannelOutput( out ) && this.hasDeclaredOutput( out ) === false;
390
599
 
391
600
  if ( this.isConst ) {
392
601
 
393
- if ( type === 'boolean' ) {
394
-
395
- const normalized = this.getValue().trim().toLowerCase();
396
- node = bool( normalized === 'true' || normalized === '1' );
397
-
398
- } else if ( type === 'matrix33' ) {
399
-
400
- node = this.getMatrix( 3 ) || mat3( 1, 0, 0, 0, 1, 0, 0, 0, 1 );
401
-
402
- } else if ( type === 'matrix44' ) {
403
-
404
- node = this.getMatrix( 4 ) || mat4( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 );
405
-
406
- } else if ( type === 'string' ) {
407
-
408
- node = this.getValue();
409
-
410
- } else {
411
-
412
- const nodeClass = this.getClassFromType( type );
413
- node = nodeClass ? nodeClass( ...this.getVector() ) : float( 0 );
414
-
415
- }
602
+ node = createValueNode( type, this.getValue() );
416
603
 
417
604
  } else if ( this.hasReference ) {
418
605
 
@@ -426,9 +613,14 @@ class MaterialXNode {
426
613
 
427
614
  }
428
615
 
429
- const referenceNode = this.materialX.getMaterialXNode( this.referencePath );
616
+ const interfaceNode = this.interfaceName !== null ? this.materialX.getInterfaceNode( this ) : null;
617
+ const referenceNode = interfaceNode === null ? this.materialX.getMaterialXNode( this.referencePath ) : null;
618
+
619
+ if ( interfaceNode !== null ) {
430
620
 
431
- if ( referenceNode ) {
621
+ node = interfaceNode;
622
+
623
+ } else if ( referenceNode ) {
432
624
 
433
625
  node = referenceNode.getNode( requestedOutput );
434
626
 
@@ -443,31 +635,22 @@ class MaterialXNode {
443
635
 
444
636
  }
445
637
 
446
- } else if ( this.element === 'input' && this.name === 'texcoord' && this.type === 'vector2' ) {
447
-
448
- let index = 0;
449
- const defaultGeomProp = this.getAttribute( 'defaultgeomprop' );
450
- if ( defaultGeomProp && /^UV(\d+)$/.test( defaultGeomProp ) ) {
638
+ } else if ( this.element === 'input' && this.getAttribute( 'defaultgeomprop' ) !== null ) {
451
639
 
452
- index = parseInt( defaultGeomProp.match( /^UV(\d+)$/ )[ 1 ], 10 );
453
-
454
- }
455
-
456
- node = this.materialX.compileContext.mxToBottomLeftUvSpace( uv( index ) );
640
+ // An unconnected interface input takes its value from its declared geometric property.
641
+ node = this.materialX.compileContext.getGeomPropNode( this.getAttribute( 'defaultgeomprop' ) );
457
642
 
458
643
  } else {
459
644
 
460
- node = compileNodeFromRegistry( this, out, this.materialX.compileContext );
645
+ const resolvedNode = this.materialX.nodeResolver !== null ? this.materialX.nodeResolver( this, out ) : null;
646
+ implemented = ( resolvedNode === null || resolvedNode === undefined ) && this.materialX.getScope( this ) !== null;
647
+ node = resolvedNode !== null && resolvedNode !== undefined ? resolvedNode : implemented ? this.materialX.compileImplementation( this, channelRequested ? null : out ) : compileNodeFromRegistry( this, out, this.materialX.compileContext );
461
648
 
462
649
  }
463
650
 
464
651
  if ( node === null || node === undefined ) {
465
652
 
466
- this.materialX.log.add(
467
- MaterialXLogCodes.UNSUPPORTED_NODE,
468
- `Unsupported MaterialX node category "${this.element}" on "${this.name}".`,
469
- this.name,
470
- );
653
+ this.logUnsupportedNode();
471
654
  node = float( 0 );
472
655
 
473
656
  }
@@ -515,7 +698,7 @@ class MaterialXNode {
515
698
 
516
699
  }
517
700
 
518
- this.node = node;
701
+ if ( cacheDefaultOutput ) this.materialX.setCachedNode( this, node );
519
702
  return node;
520
703
 
521
704
  }
@@ -544,17 +727,43 @@ class MaterialXNode {
544
727
 
545
728
  }
546
729
 
547
- getNodeByName( name ) {
730
+ getInputTypes() {
548
731
 
549
- const child = this.getChildByName( name );
550
- return child ? child.getNode( child.output ) : undefined;
732
+ const types = {};
733
+ for ( const input of this.children ) {
734
+
735
+ types[ input.name ] = input.type;
736
+
737
+ }
738
+
739
+ return types;
740
+
741
+ }
742
+
743
+ // nodes without a nodedef (e.g. from a host node resolver) accept any input
744
+ declaresInput( name ) {
745
+
746
+ return this.getChildByName( name ) !== undefined || this.nodeDef === null || name in this.nodeDef.inputs;
551
747
 
552
748
  }
553
749
 
554
- getInputValueByName( name ) {
750
+ getNodeByName( name ) {
555
751
 
556
752
  const child = this.getChildByName( name );
557
- return child ? child.value : null;
753
+ if ( child ) return child.getNode( child.output );
754
+
755
+ if ( this.declaresInput( name ) === false ) {
756
+
757
+ this.materialX.log.add(
758
+ MaterialXLogCodes.UNKNOWN_INPUT,
759
+ `"${this.element}" reads input "${name}", which nodedef "${this.nodeDef.name}" does not declare. Using fallback 0.`,
760
+ this.name,
761
+ );
762
+ return float( 0 );
763
+
764
+ }
765
+
766
+ return this.getDefaultInputNode( name );
558
767
 
559
768
  }
560
769
 
@@ -580,37 +789,7 @@ class MaterialXNode {
580
789
 
581
790
  getVector() {
582
791
 
583
- const vector = [];
584
- for ( const val of this.getValue().split( /[,|\s]/ ) ) {
585
-
586
- if ( val !== '' ) vector.push( Number( val.trim() ) );
587
-
588
- }
589
-
590
- return vector;
591
-
592
- }
593
-
594
- getMatrix( size ) {
595
-
596
- const vector = this.getVector();
597
- const expectedLength = size * size;
598
- if ( vector.length !== expectedLength ) return null;
599
- // MaterialX matrix values are serialized in column-major order.
600
- // Reorder to row-major before constructing TSL matrix nodes so
601
- // transformmatrix semantics match MaterialXJS and MaterialXView.
602
- const reordered = [];
603
- for ( let row = 0; row < size; row += 1 ) {
604
-
605
- for ( let column = 0; column < size; column += 1 ) {
606
-
607
- reordered.push( vector[ column * size + row ] );
608
-
609
- }
610
-
611
- }
612
-
613
- return size === 3 ? mat3( ...reordered ) : mat4( ...reordered );
792
+ return parseValueVector( this.getValue() );
614
793
 
615
794
  }
616
795
 
@@ -640,26 +819,33 @@ class MaterialXNode {
640
819
 
641
820
  }
642
821
 
643
- setMaterial( material ) {
822
+ setMaterial( material, out = null ) {
823
+
824
+ if ( this.element === 'input' || this.element === 'output' ) {
825
+
826
+ const shader = this.getReferencedNode();
827
+ if ( shader !== null ) shader.setMaterial( material, this.nodeGraph !== null ? null : this.output || out );
828
+ return;
829
+
830
+ }
831
+
832
+ if ( this.materialX.setImplementationMaterial( this, material, out ) ) return;
644
833
 
645
834
  const mapper = getSurfaceMapper( this.element );
646
835
  if ( mapper ) {
647
836
 
648
- mapper.apply( material, this.getNodes(), this.materialX.log, this.name );
837
+ const authored = this.getNodes();
838
+ mapper.apply( material, { ...this.getDefaultInputNodes(), ...authored }, this.materialX.log, this.name, authored, this.getInputTypes() );
649
839
 
650
840
  } else {
651
841
 
652
- this.materialX.log.add(
653
- MaterialXLogCodes.UNSUPPORTED_NODE,
654
- `Unsupported MaterialX node category "${this.element}" on "${this.name}".`,
655
- this.name,
656
- );
842
+ this.logUnsupportedNode();
657
843
 
658
844
  }
659
845
 
660
846
  }
661
847
 
662
- toBasicMaterial() {
848
+ toNodeGraphMaterial() {
663
849
 
664
850
  const material = new MeshBasicNodeMaterial();
665
851
  material.name = this.name;
@@ -681,29 +867,49 @@ class MaterialXNode {
681
867
 
682
868
  resolveSurfaceShaderNode( nodeX ) {
683
869
 
684
- if ( nodeX.hasReference ) {
685
-
686
- return this.materialX.getMaterialXNode( nodeX.referencePath ) || null;
870
+ const visited = new Set();
871
+ let shader = nodeX || null;
872
+ let out = null;
687
873
 
688
- }
874
+ while ( shader !== null && ( shader.element === 'input' || shader.element === 'output' ) ) {
689
875
 
690
- if ( nodeX.nodeName ) {
691
-
692
- return this.materialX.getMaterialXNode( nodeX.nodeName ) || null;
876
+ if ( visited.has( shader ) ) return null;
877
+ visited.add( shader );
878
+ out = shader.nodeGraph !== null ? null : shader.output;
879
+ shader = shader.getReferencedNode();
693
880
 
694
881
  }
695
882
 
696
- return null;
883
+ return shader !== null ? this.materialX.resolveImplementationShader( shader, out ) : null;
697
884
 
698
885
  }
699
886
 
700
- toPhysicalMaterial() {
887
+ toSurfaceMaterial() {
701
888
 
702
- const material = new MeshPhysicalNodeMaterial();
889
+ const surfaceShader = this.resolveSurfaceShaderNode( this.getChildByName( 'surfaceshader' ) );
890
+ const material = surfaceShader?.nodeDef?.name === 'ND_surface_unlit' ? new MeshBasicNodeMaterial() : new MeshPhysicalNodeMaterial();
703
891
  material.name = this.name;
704
892
 
705
893
  for ( const nodeX of this.children ) {
706
894
 
895
+ if ( nodeX.name === 'backsurfaceshader' ) {
896
+
897
+ // MaterialX supports separate back-surface shaders. Their use in practice
898
+ // is unclear; translating them per face is left for future work.
899
+ if ( nodeX.hasReference || nodeX.nodeGraph !== null ) {
900
+
901
+ this.materialX.log.add(
902
+ MaterialXLogCodes.IGNORED_SURFACE_INPUT,
903
+ 'surfacematerial input "backsurfaceshader" is currently ignored in MaterialX translation.',
904
+ this.name,
905
+ );
906
+
907
+ }
908
+
909
+ continue;
910
+
911
+ }
912
+
707
913
  const shaderProperties = this.resolveSurfaceShaderNode( nodeX );
708
914
  if ( shaderProperties === null ) {
709
915
 
@@ -716,7 +922,7 @@ class MaterialXNode {
716
922
 
717
923
  }
718
924
 
719
- shaderProperties.setMaterial( material );
925
+ nodeX.setMaterial( material );
720
926
 
721
927
  }
722
928
 
@@ -747,7 +953,7 @@ class MaterialXNode {
747
953
 
748
954
  for ( const nodeX of selectedSurfaceMaterials ) {
749
955
 
750
- const material = nodeX.toPhysicalMaterial();
956
+ const material = nodeX.toSurfaceMaterial();
751
957
  materials[ material.name ] = material;
752
958
 
753
959
  }
@@ -756,9 +962,10 @@ class MaterialXNode {
756
962
 
757
963
  for ( const nodeX of this.children ) {
758
964
 
759
- if ( nodeX.element === 'nodegraph' ) {
965
+ // Only standalone nodegraphs should create preview materials.
966
+ if ( nodeX.element === 'nodegraph' && nodeX.getAttribute( 'nodedef' ) === null && this.materialX.implementationGraphNodes.has( nodeX ) === false ) {
760
967
 
761
- const material = nodeX.toBasicMaterial();
968
+ const material = nodeX.toNodeGraphMaterial();
762
969
  materials[ material.name ] = material;
763
970
 
764
971
  }
@@ -797,12 +1004,28 @@ class MaterialXDocument {
797
1004
  this.textureLoader.setOptions( { imageOrientation: 'none' } );
798
1005
  this.textureLoader.setPath( path );
799
1006
  this.textureCache = new Map();
1007
+ this.pendingResources = [];
1008
+ this.nodeResolver = null;
1009
+ this.documentNodeDefs = null;
1010
+
1011
+ this.implementationGraphs = new Map();
1012
+ this.implementationGraphNodes = new Set();
1013
+ this.scope = null;
1014
+ this.rootScopes = new Map();
800
1015
  const bottomLeftUvSpaceHelpers = getBottomLeftUvSpaceHelpers( this.uvSpace );
801
1016
 
802
1017
  this.compileContext = {
803
1018
  compileRegistry: COMPILE_REGISTRY,
804
1019
  nodeLibrary: MtlXLibrary,
805
1020
  ...bottomLeftUvSpaceHelpers,
1021
+ getTexcoordNode: ( index = 0 ) => bottomLeftUvSpaceHelpers.mxToBottomLeftUvSpace( uv( index ) ),
1022
+ getGeomPropNode: ( name ) => {
1023
+
1024
+ const uvMatch = /^UV(\d+)$/.exec( name );
1025
+ if ( uvMatch ) return bottomLeftUvSpaceHelpers.mxToBottomLeftUvSpace( uv( parseInt( uvMatch[ 1 ], 10 ) ) );
1026
+ return GEOMPROP_NODES[ name ];
1027
+
1028
+ },
806
1029
  mxTransformUv: mx_transform_uv,
807
1030
  mxHextileCoord,
808
1031
  mxHextileComputeBlendWeights,
@@ -826,6 +1049,207 @@ class MaterialXDocument {
826
1049
 
827
1050
  }
828
1051
 
1052
+ indexImplementations( rootNode ) {
1053
+
1054
+ for ( const nodeX of rootNode.children ) {
1055
+
1056
+ const nodeDefName = nodeX.getAttribute( 'nodedef' );
1057
+ const graphName = nodeX.element === 'implementation' ? nodeX.getAttribute( 'nodegraph' ) : null;
1058
+ const graph = nodeX.element === 'nodegraph' && nodeDefName !== null ? nodeX : graphName !== null ? this.getMaterialXNode( graphName ) : undefined;
1059
+ if ( graph === undefined ) continue;
1060
+
1061
+ this.implementationGraphNodes.add( graph );
1062
+ if ( this.implementationGraphs.has( nodeDefName ) === false ) this.implementationGraphs.set( nodeDefName, graph );
1063
+
1064
+ }
1065
+
1066
+ }
1067
+
1068
+ // Each custom node instance needs its own inputs and cached TSL nodes.
1069
+ getScope( materialXNode ) {
1070
+
1071
+ const nodeDef = materialXNode.nodeDef;
1072
+ const graph = nodeDef !== null ? this.implementationGraphs.get( nodeDef.name ) : undefined;
1073
+ if ( graph === undefined ) return null;
1074
+
1075
+ for ( let parent = this.scope; parent !== null; parent = parent.parent ) {
1076
+
1077
+ if ( parent.graph === graph ) {
1078
+
1079
+ this.log.add(
1080
+ MaterialXLogCodes.INVALID_VALUE,
1081
+ `The nodegraph of "${ materialXNode.element }" uses the node it implements.`,
1082
+ materialXNode.name,
1083
+ );
1084
+ return null;
1085
+
1086
+ }
1087
+
1088
+ }
1089
+
1090
+ const scopes = this.scope !== null ? this.scope.childScopes : this.rootScopes;
1091
+ let scope = scopes.get( materialXNode );
1092
+
1093
+ if ( scope === undefined ) {
1094
+
1095
+ scope = { instance: materialXNode, nodeDef, graph, parent: this.scope, nodes: new Map(), childScopes: new Map() };
1096
+ scopes.set( materialXNode, scope );
1097
+
1098
+ }
1099
+
1100
+ return scope;
1101
+
1102
+ }
1103
+
1104
+ withScope( scope, callback ) {
1105
+
1106
+ const previous = this.scope;
1107
+ this.scope = scope;
1108
+
1109
+ try {
1110
+
1111
+ return callback();
1112
+
1113
+ } finally {
1114
+
1115
+ this.scope = previous;
1116
+
1117
+ }
1118
+
1119
+ }
1120
+
1121
+ isInScope( materialXNode ) {
1122
+
1123
+ if ( this.scope === null ) return false;
1124
+
1125
+ for ( let parent = materialXNode.parent; parent !== null; parent = parent.parent ) {
1126
+
1127
+ if ( parent === this.scope.graph ) return true;
1128
+
1129
+ }
1130
+
1131
+ return false;
1132
+
1133
+ }
1134
+
1135
+ getCachedNode( materialXNode ) {
1136
+
1137
+ if ( this.isInScope( materialXNode ) ) return this.scope.nodes.get( materialXNode ) ?? null;
1138
+ return materialXNode.node;
1139
+
1140
+ }
1141
+
1142
+ setCachedNode( materialXNode, node ) {
1143
+
1144
+ if ( this.isInScope( materialXNode ) ) this.scope.nodes.set( materialXNode, node );
1145
+ else materialXNode.node = node;
1146
+
1147
+ }
1148
+
1149
+ getGraphOutput( scope, out ) {
1150
+
1151
+ // An omitted selector uses the first output declared by the nodedef.
1152
+ const name = out === null ? Object.keys( scope.nodeDef.outputs )[ 0 ] : out;
1153
+ return scope.graph.children.find( ( child ) => child.element === 'output' && child.name === name ) || null;
1154
+
1155
+ }
1156
+
1157
+ compileImplementation( materialXNode, out ) {
1158
+
1159
+ const scope = this.getScope( materialXNode );
1160
+ if ( scope === null ) return null;
1161
+
1162
+ const output = this.getGraphOutput( scope, out );
1163
+ if ( output === null ) {
1164
+
1165
+ this.log.add(
1166
+ MaterialXLogCodes.MISSING_REFERENCE,
1167
+ `Missing output "${ out || 'out' }" in the nodegraph of "${ materialXNode.name }".`,
1168
+ materialXNode.name,
1169
+ );
1170
+ return float( 0 );
1171
+
1172
+ }
1173
+
1174
+ // Use the output selector stored on the graph output.
1175
+ return this.withScope( scope, () => output.getNode() );
1176
+
1177
+ }
1178
+
1179
+ setImplementationMaterial( materialXNode, material, out ) {
1180
+
1181
+ const scope = this.getScope( materialXNode );
1182
+ if ( scope === null ) return false;
1183
+
1184
+ const output = this.getGraphOutput( scope, out );
1185
+ const shaderNode = output !== null && output.hasReference ? this.getMaterialXNode( output.referencePath ) : undefined;
1186
+ if ( shaderNode === undefined ) {
1187
+
1188
+ this.log.add(
1189
+ MaterialXLogCodes.MISSING_REFERENCE,
1190
+ `Missing shader output "${ out || 'out' }" in the nodegraph of "${ materialXNode.name }".`,
1191
+ materialXNode.name,
1192
+ );
1193
+ return true;
1194
+
1195
+ }
1196
+
1197
+ this.withScope( scope, () => shaderNode.setMaterial( material, output.output ) );
1198
+ return true;
1199
+
1200
+ }
1201
+
1202
+ resolveImplementationShader( materialXNode, out ) {
1203
+
1204
+ const scope = this.getScope( materialXNode );
1205
+ if ( scope === null ) return materialXNode;
1206
+
1207
+ const output = this.getGraphOutput( scope, out );
1208
+ return this.withScope( scope, () => materialXNode.resolveSurfaceShaderNode( output ) );
1209
+
1210
+ }
1211
+
1212
+ // Resolve interfacename to the node instance's input.
1213
+ // If that input is omitted, use the nodedef default.
1214
+ getInterfaceInput( materialXNode ) {
1215
+
1216
+ // Regular nodegraphs bind to their own inputs.
1217
+ if ( ! this.isInScope( materialXNode ) ) {
1218
+
1219
+ const graphInput = this.getMaterialXNode( materialXNode.referencePath );
1220
+ return graphInput !== undefined && graphInput !== materialXNode ? graphInput : null;
1221
+
1222
+ }
1223
+
1224
+ const scope = this.scope;
1225
+ const name = materialXNode.interfaceName;
1226
+ const input = scope.instance.getChildByName( name );
1227
+ if ( input !== undefined ) return this.withScope( scope.parent, () => input.getValueInput() );
1228
+ const declaration = this.getMaterialXNode( scope.nodeDef.name );
1229
+ return declaration ? declaration.getChildByName( name ) ?? null : null;
1230
+
1231
+ }
1232
+
1233
+ getInterfaceNode( materialXNode ) {
1234
+
1235
+ if ( ! this.isInScope( materialXNode ) ) return null;
1236
+
1237
+ const scope = this.scope;
1238
+ const name = materialXNode.interfaceName;
1239
+ const input = scope.instance.getChildByName( name );
1240
+ // Evaluate the instance input in the parent scope to resolve nested interface bindings.
1241
+ if ( input !== undefined ) return this.withScope( scope.parent, () => input.getNode( input.output ) );
1242
+
1243
+ return this.withScope( null, () => scope.instance.getDefaultInputNode( name ) ?? null );
1244
+
1245
+ }
1246
+
1247
+ waitForResources() {
1248
+
1249
+ return Promise.all( this.pendingResources ).then( () => undefined );
1250
+
1251
+ }
1252
+
829
1253
  addMaterialXNode( materialXNode ) {
830
1254
 
831
1255
  this.nodesXLib.set( materialXNode.nodePath, materialXNode );
@@ -838,6 +1262,49 @@ class MaterialXDocument {
838
1262
 
839
1263
  }
840
1264
 
1265
+ // Convert document nodedefs to the format used by the stdlib registry.
1266
+ getDocumentNodeDefs() {
1267
+
1268
+ if ( this.documentNodeDefs !== null ) return this.documentNodeDefs;
1269
+
1270
+ this.documentNodeDefs = {};
1271
+
1272
+ for ( const nodeX of this.nodesXLib.values() ) {
1273
+
1274
+ if ( nodeX.element !== 'nodedef' ) continue;
1275
+
1276
+ const nodedef = { node: nodeX.getAttribute( 'node' ), inputs: {}, outputs: {} };
1277
+ const version = nodeX.getAttribute( 'version' );
1278
+ if ( version ) nodedef.version = version;
1279
+ if ( nodeX.getAttribute( 'isdefaultversion' ) === 'true' ) nodedef.isdefaultversion = true;
1280
+ if ( nodeX.type && nodeX.type !== 'multioutput' ) nodedef.outputs.out = nodeX.type;
1281
+
1282
+ for ( const child of nodeX.children ) {
1283
+
1284
+ if ( child.element === 'output' ) {
1285
+
1286
+ nodedef.outputs[ child.name ] = child.type;
1287
+
1288
+ } else if ( child.element === 'input' ) {
1289
+
1290
+ const input = { type: child.type };
1291
+ if ( child.value !== null ) input.value = child.value;
1292
+ const geomprop = child.getAttribute( 'defaultgeomprop' );
1293
+ if ( geomprop ) input.defaultgeomprop = geomprop;
1294
+ nodedef.inputs[ child.name ] = input;
1295
+
1296
+ }
1297
+
1298
+ }
1299
+
1300
+ this.documentNodeDefs[ nodeX.name ] = nodedef;
1301
+
1302
+ }
1303
+
1304
+ return this.documentNodeDefs;
1305
+
1306
+ }
1307
+
841
1308
  parseNode( nodeXML, nodePath = '' ) {
842
1309
 
843
1310
  return parseMaterialXNodeTree(
@@ -851,12 +1318,17 @@ class MaterialXDocument {
851
1318
 
852
1319
  parse( text, materialName = null, options = {} ) {
853
1320
 
1321
+ this.nodeResolver = options.nodeResolver || null;
1322
+ this.documentNodeDefs = null;
1323
+
854
1324
  const rootNode = parseMaterialXText(
855
1325
  text,
856
1326
  ( childNodeXML, childNodePath ) => new MaterialXNode( this, childNodeXML, childNodePath ),
857
1327
  ( materialXNode ) => this.addMaterialXNode( materialXNode ),
858
1328
  );
859
1329
 
1330
+ this.indexImplementations( rootNode );
1331
+
860
1332
  if ( options.interfaceValidator ) {
861
1333
 
862
1334
  options.interfaceValidator( rootNode, this.log );