super-three 0.184.0 → 0.185.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. package/build/three.cjs +1260 -927
  2. package/build/three.core.js +1104 -829
  3. package/build/three.core.min.js +1 -1
  4. package/build/three.module.js +156 -98
  5. package/build/three.module.min.js +1 -1
  6. package/build/three.tsl.js +11 -4
  7. package/build/three.tsl.min.js +1 -1
  8. package/build/three.webgpu.js +7538 -3367
  9. package/build/three.webgpu.min.js +1 -1
  10. package/build/three.webgpu.nodes.js +7538 -3366
  11. package/build/three.webgpu.nodes.min.js +1 -1
  12. package/examples/jsm/Addons.js +3 -0
  13. package/examples/jsm/controls/ArcballControls.js +6 -2
  14. package/examples/jsm/controls/FirstPersonControls.js +79 -42
  15. package/examples/jsm/controls/TransformControls.js +68 -15
  16. package/examples/jsm/csm/CSMFrustum.js +31 -6
  17. package/examples/jsm/csm/CSMShadowNode.js +4 -1
  18. package/examples/jsm/effects/AsciiEffect.js +14 -1
  19. package/examples/jsm/exporters/DRACOExporter.js +27 -6
  20. package/examples/jsm/exporters/GLTFExporter.js +114 -12
  21. package/examples/jsm/exporters/PLYExporter.js +286 -73
  22. package/examples/jsm/exporters/USDZExporter.js +347 -112
  23. package/examples/jsm/generators/CityGenerator.js +346 -0
  24. package/examples/jsm/generators/ForestGenerator.js +347 -0
  25. package/examples/jsm/generators/TerrainGenerator.js +504 -0
  26. package/examples/jsm/generators/TreeGenerator.js +377 -0
  27. package/examples/jsm/generators/city/SidewalkGenerator.js +253 -0
  28. package/examples/jsm/generators/city/SkyscraperGenerator.js +1357 -0
  29. package/examples/jsm/geometries/LoftGeometry.js +355 -0
  30. package/examples/jsm/helpers/LightProbeGridHelper.js +1 -1
  31. package/examples/jsm/helpers/LightProbeHelper.js +5 -4
  32. package/examples/jsm/helpers/ViewHelper.js +16 -6
  33. package/examples/jsm/inspector/Inspector.js +53 -15
  34. package/examples/jsm/inspector/RendererInspector.js +152 -36
  35. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js +1 -1
  36. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphLoader.js +1 -1
  37. package/examples/jsm/inspector/tabs/Console.js +200 -18
  38. package/examples/jsm/inspector/tabs/Memory.js +8 -0
  39. package/examples/jsm/inspector/tabs/Parameters.js +64 -4
  40. package/examples/jsm/inspector/tabs/Performance.js +21 -6
  41. package/examples/jsm/inspector/tabs/Settings.js +51 -9
  42. package/examples/jsm/inspector/tabs/Timeline.js +178 -93
  43. package/examples/jsm/inspector/tabs/Viewer.js +628 -16
  44. package/examples/jsm/inspector/ui/Graph.js +162 -25
  45. package/examples/jsm/inspector/ui/Item.js +92 -13
  46. package/examples/jsm/inspector/ui/List.js +1 -1
  47. package/examples/jsm/inspector/ui/Profiler.js +90 -45
  48. package/examples/jsm/inspector/ui/Style.js +1788 -1401
  49. package/examples/jsm/inspector/ui/Tab.js +5 -3
  50. package/examples/jsm/inspector/ui/Values.js +71 -6
  51. package/examples/jsm/inspector/ui/utils.js +130 -10
  52. package/examples/jsm/libs/basis/README.md +0 -1
  53. package/examples/jsm/libs/demuxer_mp4.js +3 -3
  54. package/examples/jsm/libs/draco/README.md +0 -1
  55. package/examples/jsm/libs/meshopt_clusterizer.module.js +421 -0
  56. package/examples/jsm/libs/meshopt_simplifier.module.js +627 -0
  57. package/examples/jsm/libs/mikktspace.module.js +34 -9
  58. package/examples/jsm/lighting/ClusteredLighting.js +55 -0
  59. package/examples/jsm/lighting/LightProbeGrid.js +106 -76
  60. package/examples/jsm/lines/LineMaterial.js +38 -15
  61. package/examples/jsm/lines/LineSegments2.js +8 -0
  62. package/examples/jsm/lines/webgpu/LineSegments2.js +8 -0
  63. package/examples/jsm/loaders/3DMLoader.js +1 -1
  64. package/examples/jsm/loaders/DRACOLoader.js +46 -13
  65. package/examples/jsm/loaders/EXRLoader.js +27 -55
  66. package/examples/jsm/loaders/HDRLoader.js +6 -28
  67. package/examples/jsm/loaders/KTX2Loader.js +31 -12
  68. package/examples/jsm/loaders/LDrawLoader.js +8 -8
  69. package/examples/jsm/loaders/LUT3dlLoader.js +2 -2
  70. package/examples/jsm/loaders/LUTCubeLoader.js +2 -2
  71. package/examples/jsm/loaders/LWOLoader.js +4 -0
  72. package/examples/jsm/loaders/LottieLoader.js +1 -1
  73. package/examples/jsm/loaders/MaterialXLoader.js +31 -9
  74. package/examples/jsm/loaders/NRRDLoader.js +3 -3
  75. package/examples/jsm/loaders/PCDLoader.js +7 -7
  76. package/examples/jsm/loaders/PLYLoader.js +218 -55
  77. package/examples/jsm/loaders/SVGLoader.js +547 -495
  78. package/examples/jsm/loaders/TTFLoader.js +1 -1
  79. package/examples/jsm/loaders/USDLoader.js +33 -9
  80. package/examples/jsm/loaders/VRMLLoader.js +1 -1
  81. package/examples/jsm/loaders/usd/USDAParser.js +93 -20
  82. package/examples/jsm/loaders/usd/USDCParser.js +1 -1
  83. package/examples/jsm/loaders/usd/USDComposer.js +52 -19
  84. package/examples/jsm/misc/TileCreasedNormalsPlugin.js +270 -0
  85. package/examples/jsm/misc/Volume.js +2 -2
  86. package/examples/jsm/objects/GroundedSkybox.js +1 -1
  87. package/examples/jsm/objects/Reflector.js +2 -3
  88. package/examples/jsm/objects/Water2Mesh.js +1 -1
  89. package/examples/jsm/physics/AmmoPhysics.js +15 -8
  90. package/examples/jsm/physics/RapierPhysics.js +27 -2
  91. package/examples/jsm/shaders/VolumeShader.js +31 -44
  92. package/examples/jsm/transpiler/GLSLDecoder.js +6 -6
  93. package/examples/jsm/transpiler/Linker.js +1 -1
  94. package/examples/jsm/tsl/display/BloomNode.js +59 -19
  95. package/examples/jsm/tsl/display/DepthOfFieldNode.js +2 -2
  96. package/examples/jsm/tsl/display/FXAANode.js +11 -12
  97. package/examples/jsm/tsl/display/GTAONode.js +34 -13
  98. package/examples/jsm/tsl/display/GodraysNode.js +1 -1
  99. package/examples/jsm/tsl/display/ImportanceSampledEnvironment.js +560 -0
  100. package/examples/jsm/tsl/display/PixelationPassNode.js +2 -2
  101. package/examples/jsm/tsl/display/RecurrentDenoiseNode.js +912 -0
  102. package/examples/jsm/tsl/display/SSAAPassNode.js +13 -25
  103. package/examples/jsm/tsl/display/SSGINode.js +89 -39
  104. package/examples/jsm/tsl/display/SSRNode.js +829 -132
  105. package/examples/jsm/tsl/display/SSSNode.js +2 -2
  106. package/examples/jsm/tsl/display/TemporalReprojectNode.js +1023 -0
  107. package/examples/jsm/tsl/lighting/ClusteredLightsNode.js +622 -0
  108. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +1 -1
  109. package/examples/jsm/tsl/math/curlNoise.js +107 -0
  110. package/examples/jsm/tsl/shadows/TileShadowNode.js +1 -1
  111. package/examples/jsm/tsl/shadows/TileShadowNodeHelper.js +3 -3
  112. package/examples/jsm/tsl/utils/GroundedSkybox.js +62 -0
  113. package/examples/jsm/tsl/utils/RNoise.js +51 -0
  114. package/examples/jsm/tsl/utils/SpecularHelpers.js +325 -0
  115. package/examples/jsm/utils/BufferGeometryUtils.js +126 -59
  116. package/examples/jsm/utils/GeometryCompressionUtils.js +1 -1
  117. package/examples/jsm/utils/SceneOptimizer.js +1 -1
  118. package/examples/jsm/webxr/ARButton.js +1 -1
  119. package/examples/jsm/webxr/WebGLXRFallback.js +89 -0
  120. package/examples/jsm/webxr/XRControllerModelFactory.js +2 -2
  121. package/package.json +7 -7
  122. package/src/Three.TSL.js +10 -3
  123. package/src/Three.WebGPU.js +4 -0
  124. package/src/animation/AnimationAction.js +15 -11
  125. package/src/animation/AnimationClip.js +0 -139
  126. package/src/animation/KeyframeTrack.js +2 -2
  127. package/src/animation/PropertyBinding.js +2 -2
  128. package/src/cameras/Camera.js +2 -2
  129. package/src/cameras/StereoCamera.js +5 -2
  130. package/src/constants.js +1 -1
  131. package/src/core/BufferGeometry.js +29 -7
  132. package/src/core/Object3D.js +17 -7
  133. package/src/core/Raycaster.js +1 -1
  134. package/src/core/RenderTarget.js +15 -2
  135. package/src/extras/PMREMGenerator.js +6 -4
  136. package/src/extras/TextureUtils.js +1 -1
  137. package/src/extras/core/ShapePath.js +149 -160
  138. package/src/geometries/SphereGeometry.js +8 -3
  139. package/src/helpers/DirectionalLightHelper.js +2 -0
  140. package/src/helpers/HemisphereLightHelper.js +2 -0
  141. package/src/helpers/PointLightHelper.js +2 -0
  142. package/src/helpers/SpotLightHelper.js +1 -1
  143. package/src/loaders/DataTextureLoader.js +69 -38
  144. package/src/loaders/LoadingManager.js +5 -0
  145. package/src/loaders/MaterialLoader.js +36 -266
  146. package/src/loaders/ObjectLoader.js +3 -1
  147. package/src/materials/LineBasicMaterial.js +4 -0
  148. package/src/materials/Material.js +196 -1
  149. package/src/materials/MeshBasicMaterial.js +24 -0
  150. package/src/materials/MeshDepthMaterial.js +10 -0
  151. package/src/materials/MeshDistanceMaterial.js +10 -0
  152. package/src/materials/MeshLambertMaterial.js +40 -1
  153. package/src/materials/MeshMatcapMaterial.js +25 -1
  154. package/src/materials/MeshNormalMaterial.js +9 -1
  155. package/src/materials/MeshPhongMaterial.js +40 -1
  156. package/src/materials/MeshPhysicalMaterial.js +38 -0
  157. package/src/materials/MeshStandardMaterial.js +42 -1
  158. package/src/materials/MeshToonMaterial.js +34 -1
  159. package/src/materials/PointsMaterial.js +7 -0
  160. package/src/materials/ShaderMaterial.js +86 -0
  161. package/src/materials/SpriteMaterial.js +7 -0
  162. package/src/materials/nodes/Line2NodeMaterial.js +378 -322
  163. package/src/materials/nodes/MeshBasicNodeMaterial.js +2 -2
  164. package/src/materials/nodes/MeshNormalNodeMaterial.js +2 -2
  165. package/src/materials/nodes/MeshPhongNodeMaterial.js +0 -9
  166. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +0 -30
  167. package/src/materials/nodes/MeshSSSNodeMaterial.js +0 -13
  168. package/src/materials/nodes/MeshStandardNodeMaterial.js +0 -11
  169. package/src/materials/nodes/NodeMaterial.js +115 -71
  170. package/src/materials/nodes/SpriteNodeMaterial.js +0 -10
  171. package/src/materials/nodes/manager/NodeMaterialObserver.js +49 -20
  172. package/src/math/Box3.js +5 -0
  173. package/src/math/FrustumArray.js +103 -133
  174. package/src/math/Interpolant.js +1 -1
  175. package/src/math/MathUtils.js +2 -2
  176. package/src/math/Matrix3.js +11 -0
  177. package/src/math/Matrix4.js +28 -3
  178. package/src/math/Vector2.js +2 -2
  179. package/src/math/Vector3.js +2 -2
  180. package/src/math/Vector4.js +2 -2
  181. package/src/math/interpolants/BezierInterpolant.js +4 -6
  182. package/src/nodes/Nodes.js +2 -5
  183. package/src/nodes/TSL.js +8 -6
  184. package/src/nodes/accessors/Arrays.js +4 -4
  185. package/src/nodes/accessors/Batch.js +108 -0
  186. package/src/nodes/accessors/Bitangent.js +2 -2
  187. package/src/nodes/accessors/BufferAttributeNode.js +13 -2
  188. package/src/nodes/accessors/Camera.js +7 -7
  189. package/src/nodes/accessors/ClippingNode.js +1 -1
  190. package/src/nodes/accessors/Instance.js +264 -0
  191. package/src/nodes/accessors/MaterialNode.js +18 -2
  192. package/src/nodes/accessors/MaterialProperties.js +4 -3
  193. package/src/nodes/accessors/{MorphNode.js → Morph.js} +99 -112
  194. package/src/nodes/accessors/Normal.js +13 -13
  195. package/src/nodes/accessors/Position.js +5 -1
  196. package/src/nodes/accessors/ReferenceNode.js +1 -0
  197. package/src/nodes/accessors/ReflectVector.js +3 -3
  198. package/src/nodes/accessors/SceneProperties.js +1 -1
  199. package/src/nodes/accessors/Skinning.js +263 -0
  200. package/src/nodes/accessors/StorageBufferNode.js +2 -2
  201. package/src/nodes/accessors/StorageTexture3DNode.js +100 -0
  202. package/src/nodes/accessors/StorageTextureNode.js +39 -7
  203. package/src/nodes/accessors/Tangent.js +4 -4
  204. package/src/nodes/accessors/TextureNode.js +60 -5
  205. package/src/nodes/code/FunctionNode.js +2 -16
  206. package/src/nodes/core/MRTNode.js +7 -2
  207. package/src/nodes/core/Node.js +39 -2
  208. package/src/nodes/core/NodeBuilder.js +201 -41
  209. package/src/nodes/core/NodeUtils.js +13 -13
  210. package/src/nodes/core/OutputStructNode.js +1 -1
  211. package/src/nodes/core/OverrideContextNode.js +153 -0
  212. package/src/nodes/core/PropertyNode.js +51 -5
  213. package/src/nodes/core/StackNode.js +56 -34
  214. package/src/nodes/core/StructNode.js +4 -6
  215. package/src/nodes/core/StructTypeNode.js +6 -6
  216. package/src/nodes/core/VarNode.js +8 -0
  217. package/src/nodes/core/VaryingNode.js +12 -2
  218. package/src/nodes/display/BlendModes.js +1 -41
  219. package/src/nodes/display/BumpMapNode.js +6 -1
  220. package/src/nodes/display/ColorAdjustment.js +10 -9
  221. package/src/nodes/display/FrontFacingNode.js +38 -9
  222. package/src/nodes/display/NormalMapNode.js +2 -2
  223. package/src/nodes/display/PassNode.js +35 -43
  224. package/src/nodes/display/PremultiplyAlphaFunctions.js +39 -0
  225. package/src/nodes/display/RenderOutputNode.js +12 -3
  226. package/src/nodes/functions/VolumetricLightingModel.js +40 -7
  227. package/src/nodes/gpgpu/WorkgroupInfoNode.js +1 -1
  228. package/src/nodes/lighting/EnvironmentNode.js +2 -2
  229. package/src/nodes/lighting/IESSpotLightNode.js +40 -2
  230. package/src/nodes/lighting/LightingContextNode.js +10 -2
  231. package/src/nodes/lighting/LightsNode.js +90 -37
  232. package/src/nodes/lighting/PointShadowNode.js +6 -1
  233. package/src/nodes/lighting/ShadowFilterNode.js +21 -52
  234. package/src/nodes/lighting/ShadowNode.js +34 -14
  235. package/src/nodes/materialx/lib/mx_noise.js +2 -2
  236. package/src/nodes/math/ConditionalNode.js +3 -3
  237. package/src/nodes/math/MathNode.js +39 -11
  238. package/src/nodes/math/OperatorNode.js +23 -23
  239. package/src/nodes/parsers/GLSLNodeFunction.js +1 -1
  240. package/src/nodes/pmrem/PMREMNode.js +33 -2
  241. package/src/nodes/tsl/TSLCore.js +63 -18
  242. package/src/nodes/utils/EquirectUV.js +30 -5
  243. package/src/nodes/utils/FunctionOverloadingNode.js +1 -1
  244. package/src/nodes/utils/Packing.js +35 -4
  245. package/src/nodes/utils/RTTNode.js +40 -24
  246. package/src/nodes/utils/ReflectorNode.js +1 -0
  247. package/src/nodes/utils/StorageArrayElementNode.js +1 -1
  248. package/src/objects/BatchedMesh.js +22 -14
  249. package/src/objects/InstancedMesh.js +0 -11
  250. package/src/objects/Skeleton.js +0 -9
  251. package/src/renderers/WebGLRenderer.js +19 -15
  252. package/src/renderers/common/Backend.js +49 -5
  253. package/src/renderers/common/Bindings.js +114 -45
  254. package/src/renderers/common/Buffer.js +9 -0
  255. package/src/renderers/common/ClippingContext.js +10 -2
  256. package/src/renderers/common/Info.js +63 -22
  257. package/src/renderers/common/Lighting.js +53 -5
  258. package/src/renderers/common/RenderList.js +41 -4
  259. package/src/renderers/common/RenderObject.js +73 -13
  260. package/src/renderers/common/Renderer.js +281 -108
  261. package/src/renderers/common/Sampler.js +16 -48
  262. package/src/renderers/common/Textures.js +32 -5
  263. package/src/renderers/common/TimestampQueryPool.js +1 -1
  264. package/src/renderers/common/UniformsGroup.js +31 -9
  265. package/src/renderers/common/XRManager.js +340 -22
  266. package/src/renderers/common/extras/PMREMGenerator.js +15 -38
  267. package/src/renderers/common/nodes/NodeBuilderState.js +9 -1
  268. package/src/renderers/common/nodes/NodeLibrary.js +4 -4
  269. package/src/renderers/common/nodes/NodeManager.js +63 -14
  270. package/src/renderers/common/nodes/NodeUniformBuffer.js +13 -0
  271. package/src/renderers/shaders/ShaderChunk/common.glsl.js +13 -4
  272. package/src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js +0 -6
  273. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +1 -1
  274. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +2 -2
  275. package/src/renderers/shaders/ShaderChunk/envmap_vertex.glsl.js +1 -1
  276. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +1 -1
  277. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +1 -1
  278. package/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js +2 -2
  279. package/src/renderers/shaders/ShaderChunk/normal_vertex.glsl.js +6 -0
  280. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +1 -1
  281. package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +1 -1
  282. package/src/renderers/shaders/ShaderLib/distance.glsl.js +1 -1
  283. package/src/renderers/webgl/WebGLOutput.js +2 -1
  284. package/src/renderers/webgl/WebGLProgram.js +5 -4
  285. package/src/renderers/webgl/WebGLPrograms.js +12 -5
  286. package/src/renderers/webgl/WebGLRenderLists.js +9 -1
  287. package/src/renderers/webgl/WebGLShaderCache.js +5 -11
  288. package/src/renderers/webgl/WebGLTextures.js +20 -7
  289. package/src/renderers/webgl/WebGLUniformsGroups.js +66 -38
  290. package/src/renderers/webgl-fallback/WebGLBackend.js +84 -25
  291. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +138 -8
  292. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +1 -1
  293. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +52 -22
  294. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +4 -2
  295. package/src/renderers/webgpu/WebGPUBackend.js +480 -169
  296. package/src/renderers/webgpu/descriptors/GPUBindGroupDescriptor.js +48 -0
  297. package/src/renderers/webgpu/descriptors/GPUBufferDescriptor.js +57 -0
  298. package/src/renderers/webgpu/descriptors/GPUCommandEncoderDescriptor.js +30 -0
  299. package/src/renderers/webgpu/descriptors/GPUComputePassDescriptor.js +38 -0
  300. package/src/renderers/webgpu/descriptors/GPUComputePipelineDescriptor.js +48 -0
  301. package/src/renderers/webgpu/descriptors/GPUCopyExternalImageDestInfo.js +47 -0
  302. package/src/renderers/webgpu/descriptors/GPUCopyExternalImageSourceInfo.js +50 -0
  303. package/src/renderers/webgpu/descriptors/GPUExtent3D.js +51 -0
  304. package/src/renderers/webgpu/descriptors/GPUPipelineLayoutDescriptor.js +39 -0
  305. package/src/renderers/webgpu/descriptors/GPUQuerySetDescriptor.js +47 -0
  306. package/src/renderers/webgpu/descriptors/GPURenderBundleEncoderDescriptor.js +74 -0
  307. package/src/renderers/webgpu/descriptors/GPURenderPassColorAttachment.js +72 -0
  308. package/src/renderers/webgpu/descriptors/GPURenderPassDepthStencilAttachment.js +99 -0
  309. package/src/renderers/webgpu/descriptors/GPURenderPassDescriptor.js +72 -0
  310. package/src/renderers/webgpu/descriptors/GPURenderPassTimestampWrites.js +49 -0
  311. package/src/renderers/webgpu/descriptors/GPURenderPipelineDescriptor.js +130 -0
  312. package/src/renderers/webgpu/descriptors/GPUSamplerDescriptor.js +119 -0
  313. package/src/renderers/webgpu/descriptors/GPUShaderModuleDescriptor.js +46 -0
  314. package/src/renderers/webgpu/descriptors/GPUTexelCopyBufferInfo.js +57 -0
  315. package/src/renderers/webgpu/descriptors/GPUTexelCopyBufferLayout.js +48 -0
  316. package/src/renderers/webgpu/descriptors/GPUTexelCopyTextureInfo.js +61 -0
  317. package/src/renderers/webgpu/descriptors/GPUTextureDescriptor.js +99 -0
  318. package/src/renderers/webgpu/descriptors/GPUTextureViewDescriptor.js +108 -0
  319. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +0 -1
  320. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +164 -7
  321. package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +1 -1
  322. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +98 -38
  323. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +72 -68
  324. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +164 -69
  325. package/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js +158 -95
  326. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +297 -141
  327. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +33 -18
  328. package/src/renderers/webgpu/utils/WebGPUUtils.js +38 -3
  329. package/src/textures/DepthTexture.js +1 -1
  330. package/src/textures/ExternalTexture.js +0 -3
  331. package/examples/fonts/LICENSE +0 -13
  332. package/examples/fonts/MPLUSRounded1c/MPLUSRounded1c-Regular.typeface.json.zip +0 -0
  333. package/examples/fonts/MPLUSRounded1c/OFL.txt +0 -91
  334. package/examples/fonts/README.md +0 -11
  335. package/examples/fonts/droid/NOTICE +0 -190
  336. package/examples/fonts/droid/README.txt +0 -18
  337. package/examples/fonts/droid/droid_sans_bold.typeface.json +0 -1
  338. package/examples/fonts/droid/droid_sans_mono_regular.typeface.json +0 -1
  339. package/examples/fonts/droid/droid_sans_regular.typeface.json +0 -1
  340. package/examples/fonts/droid/droid_serif_bold.typeface.json +0 -1
  341. package/examples/fonts/droid/droid_serif_regular.typeface.json +0 -1
  342. package/examples/fonts/gentilis_bold.typeface.json +0 -1
  343. package/examples/fonts/gentilis_regular.typeface.json +0 -1
  344. package/examples/fonts/helvetiker_bold.typeface.json +0 -1
  345. package/examples/fonts/helvetiker_regular.typeface.json +0 -1
  346. package/examples/fonts/optimer_bold.typeface.json +0 -1
  347. package/examples/fonts/optimer_regular.typeface.json +0 -1
  348. package/examples/fonts/ttf/README.md +0 -9
  349. package/examples/fonts/ttf/kenpixel.ttf +0 -0
  350. package/examples/jsm/inspector/extensions/extensions.json +0 -6
  351. package/examples/jsm/libs/ammo.wasm.js +0 -822
  352. package/examples/jsm/libs/ammo.wasm.wasm +0 -0
  353. package/examples/jsm/libs/draco/draco_encoder.js +0 -33
  354. package/examples/jsm/libs/draco/gltf/draco_encoder.js +0 -33
  355. package/examples/jsm/libs/lottie_canvas.module.js +0 -14849
  356. package/examples/jsm/libs/opentype.module.js +0 -14506
  357. package/examples/jsm/libs/rhino3dm/rhino3dm.js +0 -21
  358. package/examples/jsm/libs/rhino3dm/rhino3dm.module.js +0 -16
  359. package/examples/jsm/libs/rhino3dm/rhino3dm.wasm +0 -0
  360. package/examples/jsm/lighting/TiledLighting.js +0 -42
  361. package/examples/jsm/tsl/display/AnamorphicNode.js +0 -293
  362. package/examples/jsm/tsl/lighting/TiledLightsNode.js +0 -442
  363. package/src/nodes/accessors/BatchNode.js +0 -163
  364. package/src/nodes/accessors/InstanceNode.js +0 -349
  365. package/src/nodes/accessors/InstancedMeshNode.js +0 -50
  366. package/src/nodes/accessors/SkinningNode.js +0 -328
@@ -0,0 +1,107 @@
1
+ import { mod, Fn, vec2, div, vec4, dot, floor, step, sub, min, max, mul, abs, vec3, inverseSqrt, add, float } from 'three/tsl';
2
+
3
+ /**
4
+ * Permutation polynomial for noise generation.
5
+ *
6
+ * @tsl
7
+ * @function
8
+ * @param {Node<vec4>} x - Input vector.
9
+ * @return {Node<vec4>} Permuted vector.
10
+ */
11
+ export const permute = /*@__PURE__*/ Fn( ( [ x ] ) => {
12
+
13
+ return mod( x.mul( x ).mul( 34. ).add( x ), 289. );
14
+
15
+ }, { x: 'vec4', return: 'vec4' } );
16
+
17
+ /**
18
+ * 3D Simplex noise implementation in TSL.
19
+ *
20
+ * @tsl
21
+ * @function
22
+ * @param {Node<vec3>} v - Input coordinate vector.
23
+ * @return {Node<float>} Simplex noise value.
24
+ */
25
+ export const snoise = /*@__PURE__*/ Fn( ( [ v ] ) => {
26
+
27
+ const C = div( 1., vec2( 6, 3 ) );
28
+ const D = vec4( 0, .5, 1, 2 );
29
+ const i = floor( v.add( dot( v, C.yyy ) ) );
30
+ const x0 = v.sub( i ).add( dot( i, C.xxx ) );
31
+ const g = step( x0.yzx, x0.xyz );
32
+ const l = sub( 1., g );
33
+ const i1 = min( g.xyz, l.zxy );
34
+ const i2 = max( g.xyz, l.zxy );
35
+ const x1 = x0.sub( i1 ).add( C.x );
36
+ const x2 = x0.sub( i2 ).add( C.y );
37
+ const x3 = x0.sub( D.yyy );
38
+ i.assign( mod( i, 289. ) );
39
+ const p = permute( permute( permute( i.z.add( vec4( 0., i1.z, i2.z, 1. ) ) ).add( i.y ).add( vec4( 0., i1.y, i2.y, 1. ) ) ).add( i.x ).add( vec4( 0., i1.x, i2.x, 1. ) ) );
40
+ const ns = mul( .142857142857, D.wyz ).sub( D.xzx );
41
+ const j = p.sub( mul( 49., floor( p.mul( ns.z ).mul( ns.z ) ) ) );
42
+ const x_ = floor( j.mul( ns.z ) );
43
+ const x = x_.mul( ns.x ).add( ns.yyyy );
44
+ const y = floor( j.sub( mul( 7., x_ ) ) ).mul( ns.x ).add( ns.yyyy );
45
+ const h = sub( 1., abs( x ) ).sub( abs( y ) );
46
+ const b0 = vec4( x.xy, y.xy );
47
+ const b1 = vec4( x.zw, y.zw );
48
+ const sh = step( h, vec4( 0 ) ).negate();
49
+ const a0 = b0.xzyw.add( floor( b0 ).mul( 2. ).add( 1. ).xzyw.mul( sh.xxyy ) );
50
+ const a1 = b1.xzyw.add( floor( b1 ).mul( 2. ).add( 1. ).xzyw.mul( sh.zzww ) );
51
+ const p0 = vec3( a0.xy, h.x );
52
+ const p1 = vec3( a0.zw, h.y );
53
+ const p2 = vec3( a1.xy, h.z );
54
+ const p3 = vec3( a1.zw, h.w );
55
+ const norm = inverseSqrt( vec4( dot( p0, p0 ), dot( p1, p1 ), dot( p2, p2 ), dot( p3, p3 ) ) );
56
+ p0.mulAssign( norm.x );
57
+ p1.mulAssign( norm.y );
58
+ p2.mulAssign( norm.z );
59
+ p3.mulAssign( norm.w );
60
+ const m = max( sub( .6, vec4( dot( x0, x0 ), dot( x1, x1 ), dot( x2, x2 ), dot( x3, x3 ) ) ), 0. );
61
+
62
+ return add( .5, mul( 12., dot( m.mul( m ).mul( m ), vec4( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ), dot( p3, x3 ) ) ) ) );
63
+
64
+ }, { v: 'vec3', return: 'float' } );
65
+
66
+ /**
67
+ * 3D Simplex noise vector. Returns a vec3 containing three independent noise samples.
68
+ *
69
+ * @tsl
70
+ * @function
71
+ * @param {Node<vec3>} x - Input coordinate vector.
72
+ * @return {Node<vec3>} Vector of three noise values.
73
+ */
74
+ export const snoiseVec3 = /*@__PURE__*/ Fn( ( [ x ] ) => {
75
+
76
+ return vec3( snoise( vec3( x ).mul( 2. ).sub( 1. ) ), snoise( vec3( x.y.sub( 19.1 ), x.z.add( 33.4 ), x.x.add( 47.2 ) ) ).mul( 2. ).sub( 1. ), snoise( vec3( x.z.add( 74.2 ), x.x.sub( 124.5 ), x.y.add( 99.4 ) ).mul( 2. ).sub( 1. ) ) );
77
+
78
+ }, { x: 'vec3', return: 'vec3' } );
79
+
80
+ /**
81
+ * 3D Curl noise in TSL. Generates a divergence-free vector field from simplex noise.
82
+ *
83
+ * @tsl
84
+ * @function
85
+ * @param {Node<vec3>} p - Input coordinate vector.
86
+ * @return {Node<vec3>} Curl noise vector.
87
+ */
88
+ export const curlNoise = /*@__PURE__*/ Fn( ( [ p ] ) => {
89
+
90
+ const e = float( .1 );
91
+ const dx = vec3( e, 0.0, 0.0 );
92
+ const dy = vec3( 0.0, e, 0.0 );
93
+ const dz = vec3( 0.0, 0.0, e );
94
+ const p_x0 = snoiseVec3( p.sub( dx ) );
95
+ const p_x1 = snoiseVec3( p.add( dx ) );
96
+ const p_y0 = snoiseVec3( p.sub( dy ) );
97
+ const p_y1 = snoiseVec3( p.add( dy ) );
98
+ const p_z0 = snoiseVec3( p.sub( dz ) );
99
+ const p_z1 = snoiseVec3( p.add( dz ) );
100
+ const x = p_y1.z.sub( p_y0.z ).sub( p_z1.y ).add( p_z0.y );
101
+ const y = p_z1.x.sub( p_z0.x ).sub( p_x1.z ).add( p_x0.z );
102
+ const z = p_x1.y.sub( p_x0.y ).sub( p_y1.x ).add( p_y0.x );
103
+ const divisor = div( 1.0, mul( 2.0, e ) );
104
+
105
+ return vec3( x, y, z ).mul( divisor );
106
+
107
+ }, { p: 'vec3', return: 'vec3' } );
@@ -162,7 +162,7 @@ class TileShadowNode extends ShadowBaseNode {
162
162
  const depthTexture = new DepthTexture( shadowWidth, shadowHeight, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, tileCount );
163
163
  depthTexture.compareFunction = LessCompare;
164
164
  depthTexture.name = 'ShadowDepthArrayTexture';
165
- const shadowMap = builder.createRenderTarget( shadowWidth, shadowHeight, { format: RedFormat, depth: tileCount } );
165
+ const shadowMap = builder.createRenderTarget( shadowWidth, shadowHeight, { format: RedFormat, depth: tileCount, useArrayDepthTexture: true } );
166
166
  shadowMap.depthTexture = depthTexture;
167
167
  shadowMap.texture.name = 'ShadowTexture';
168
168
  this.shadowMap = shadowMap;
@@ -1,5 +1,5 @@
1
1
  import { Group, NodeMaterial, Mesh, PlaneGeometry, DoubleSide, CameraHelper } from 'three/webgpu';
2
- import { Fn, vec4, vec3, texture, uv, positionLocal, vec2, float, screenSize } from 'three/tsl';
2
+ import { Fn, vec4, vec3, texture, uv, positionLocal, vec2, float, int, screenSize } from 'three/tsl';
3
3
 
4
4
  /**
5
5
  * Helper class to manage and display debug visuals for TileShadowNode.
@@ -18,7 +18,7 @@ class TileShadowNodeHelper extends Group {
18
18
 
19
19
  if ( ! tileShadowNode ) {
20
20
 
21
- throw new Error( 'TileShadowNode instance is required for TileShadowNodeHelper.' );
21
+ throw new Error( 'THREE.TileShadowNode instance is required for TileShadowNodeHelper.' );
22
22
 
23
23
  }
24
24
 
@@ -109,7 +109,7 @@ class TileShadowNodeHelper extends Group {
109
109
 
110
110
  const sampledDepth = texture( this.tileShadowNode.shadowMap.depthTexture )
111
111
  .sample( uv().flipY() )
112
- .depth( float( i ) ) // Sample correct layer
112
+ .depth( int( i ) ) // Sample correct layer
113
113
  .compare( 0.9 ); // Example comparison value
114
114
 
115
115
  // Simple tint based on index for visual distinction
@@ -0,0 +1,62 @@
1
+ import { Fn, If, vec3, float, min, cameraPosition, positionWorld } from 'three/tsl';
2
+
3
+ /**
4
+ * @module GroundedSkybox
5
+ * @three_import import { getGroundProjectedNormal } from 'three/addons/tsl/utils/GroundedSkybox.js';
6
+ */
7
+
8
+ /**
9
+ * Projects the world position onto a sphere whose bottom is clipped by a ground disk,
10
+ * then returns a vector usable for sampling an environment cube map.
11
+ *
12
+ * @tsl
13
+ * @function
14
+ * @param {Node<float>} radiusNode - The radius of the projection sphere. Must be large enough to ensure the scene's camera stays inside.
15
+ * @param {Node<float>} heightNode - The height is how far the camera that took the photo was above the ground. A larger value will magnify the downward part of the image.
16
+ * @return {Node<vec3>} A direction vector for sampling the environment cube map.
17
+ */
18
+ export const getGroundProjectedNormal = Fn( ( [ radiusNode, heightNode ] ) => {
19
+
20
+ const p = positionWorld.sub( cameraPosition ).normalize().toConst();
21
+ const camPos = cameraPosition.toVar();
22
+ camPos.y.subAssign( heightNode );
23
+
24
+ // sphereIntersect( camPos, p, vec3( 0 ), radius )
25
+ const b = camPos.dot( p ).toConst();
26
+ const c = camPos.dot( camPos ).sub( radiusNode.mul( radiusNode ) ).toConst();
27
+ const h = b.mul( b ).sub( c ).toConst();
28
+
29
+ const intersection = h.greaterThanEqual( 0 ).select( h.sqrt().sub( b ), - 1 );
30
+
31
+ const projected = vec3( 0, 1, 0 ).toVar();
32
+
33
+ If( intersection.greaterThan( 0 ), () => {
34
+
35
+ // diskIntersectWithBackFaceCulling( camPos, p, diskCenter, n, radius )
36
+ const diskCenter = vec3( 0, heightNode.negate(), 0 ).toConst();
37
+ const n = vec3( 0, 1, 0 ).toConst();
38
+ const d = p.dot( n ).toConst();
39
+
40
+ const intersection2 = float( 1e6 ).toVar();
41
+
42
+ If( d.lessThanEqual( 0 ), () => {
43
+
44
+ const o = camPos.sub( diskCenter ).toConst();
45
+ const t = n.dot( o ).negate().div( d ).toConst();
46
+ const q = o.add( p.mul( t ) ).toConst();
47
+
48
+ If( q.dot( q ).lessThan( radiusNode.mul( radiusNode ) ), () => {
49
+
50
+ intersection2.assign( t );
51
+
52
+ } );
53
+
54
+ } );
55
+
56
+ projected.assign( camPos.add( p.mul( min( intersection, intersection2 ) ) ).div( radiusNode ) );
57
+
58
+ } );
59
+
60
+ return projected;
61
+
62
+ } );
@@ -0,0 +1,51 @@
1
+ import { float, Fn, fract, int, vec2, vec4 } from 'three/tsl';
2
+
3
+ /**
4
+ * Returns a TSL function that samples texture-free analytic R² noise.
5
+ * Index 0 uses continuous screen pixels; other indices tile-shift with an R²
6
+ * sequence into a 64×64 period. Values are four independent R² dimensions
7
+ * hashed from the sample coordinates.
8
+ *
9
+ * @param {UniformNode<Vector2>} resolution
10
+ * @param {number} [seed=0] - Added to the coordinate hash so each pass gets an independent R² phase.
11
+ */
12
+ export function bindAnalyticNoise( resolution, seed = 0 ) {
13
+
14
+ const seedOffset = int( seed );
15
+
16
+ const r4 = ( coords ) => {
17
+
18
+ const P = 1.32471795724474602596;
19
+
20
+ const t = coords.x.mul( 1 / P ).add( coords.y.mul( 1 / P ** 2 ) ).add( float( seed ) );
21
+
22
+ return vec4(
23
+ fract( t.mul( P ).mul( 1 / P ) ),
24
+ fract( t.mul( P * 2 ).mul( 1 / P ** 2 ) ),
25
+ fract( t.mul( P * 3 ).mul( 0.4198754210 ) ), // this is not 1 / P ** 3, however this magic constant gives better noise
26
+ fract( t.mul( P * 4 ).mul( 1 / P ** 3 ) )
27
+ );
28
+
29
+ };
30
+
31
+ return Fn( ( [ uvCoord, sampleIndex ] ) => {
32
+
33
+ const index = int( sampleIndex ).add( seedOffset );
34
+ const noise = vec4().toVar();
35
+
36
+ const tileSize = float( 32 );
37
+
38
+ const screenPixel = uvCoord.mul( resolution ).floor();
39
+ const offset = fract( vec2(
40
+ float( index ).mul( 0.7548776662 ),
41
+ float( index ).mul( 0.5698402910 )
42
+ ) ).mul( tileSize ).floor();
43
+ const coords = screenPixel.add( offset ).mod( tileSize );
44
+
45
+ noise.assign( r4( coords ) );
46
+
47
+ return noise;
48
+
49
+ } );
50
+
51
+ }
@@ -0,0 +1,325 @@
1
+ import { Fn, If, PI, clamp, cos, cross, dot, equirectUV, float, log, max, mix, normalize, pow, reflect, sin, sqrt, struct, vec3 } from 'three/tsl';
2
+
3
+ /**
4
+ * Specular / microfacet BRDF helpers: VNDF sampling, GTR distribution, Smith geometry,
5
+ * Fresnel, reflection importance sampling, parallax-corrected ray-length terms, and
6
+ * equirectangular environment sampling / MIS helpers.
7
+ * Pure TSL functions of their inputs (no scene/camera state).
8
+ */
9
+
10
+ /**
11
+ * Sentinel ray length the SSR pass writes for environment misses (no screen-space hit), set far above
12
+ * any real hit distance so a single magnitude test separates misses from hits and survives `.max( 0 )`.
13
+ *
14
+ * @type {number}
15
+ */
16
+ export const ENV_RAY_LENGTH = 1e4;
17
+
18
+ /**
19
+ * Classification threshold for {@link ENV_RAY_LENGTH}: above this is an env miss, below a real hit.
20
+ * An order of magnitude under the sentinel, robust to fp16 storage and bilinear blending at borders.
21
+ *
22
+ * @type {number}
23
+ */
24
+ export const ENV_RAY_LENGTH_THRESHOLD = 1e3;
25
+
26
+ // Bounded-VNDF sampler (Eto & Tokuyoshi 2023; spherical-cap form, Dupuy & Benyoub 2023)
27
+ const SampleGGXVNDF = Fn( ( [ V, ax, ay, r1, r2 ] ) => {
28
+
29
+ // Warp the view direction to the hemisphere ("standard") configuration.
30
+ const wiStd = normalize( vec3( ax.mul( V.x ), ay.mul( V.y ), V.z ) ).toVar();
31
+
32
+ // Isotropic bound on the spherical cap (Eto & Tokuyoshi eq. 5). alpha ∈ [0,1] here,
33
+ // so the sign term in `s` is always +1 and is dropped.
34
+ const a = ax.min( ay ).toVar();
35
+ const s = float( 1.0 ).add( V.xy.length() ).toVar();
36
+ const a2 = a.mul( a ).toVar();
37
+ const s2 = s.mul( s ).toVar();
38
+ const k = a2.oneMinus().mul( s2 ).div( s2.add( a2.mul( V.z ).mul( V.z ) ) ).toVar();
39
+
40
+ // Tighten the cap with the bound (upper hemisphere; N·V ≥ 0 in our usage).
41
+ const b = wiStd.z.mul( k ).toVar();
42
+
43
+ // Sample the (bounded) spherical cap.
44
+ const phi = float( 6.283185307179586 ).mul( r1 ).toVar(); // 2*pi
45
+ const z = r2.oneMinus().mul( float( 1.0 ).add( b ) ).sub( b ).toVar();
46
+ const sinTheta = sqrt( max( float( 0.0 ), float( 1.0 ).sub( z.mul( z ) ) ) ).toVar();
47
+ const c = vec3( sinTheta.mul( cos( phi ) ), sinTheta.mul( sin( phi ) ), z ).toVar();
48
+
49
+ // Microfacet normal in the standard config, then warp back to the ellipsoid (unstretch).
50
+ const wmStd = c.add( wiStd ).toVar();
51
+ const Ne = normalize( vec3(
52
+ ax.mul( wmStd.x ),
53
+ ay.mul( wmStd.y ),
54
+ max( float( 0.0 ), wmStd.z )
55
+ ) ).toVar();
56
+
57
+ return Ne;
58
+
59
+ }, {
60
+ name: 'SampleGGXVNDF',
61
+ type: 'vec3',
62
+ inputs: [
63
+ { name: 'V', type: 'vec3' },
64
+ { name: 'ax', type: 'float' },
65
+ { name: 'ay', type: 'float' },
66
+ { name: 'r1', type: 'float' },
67
+ { name: 'r2', type: 'float' },
68
+ ]
69
+ } );
70
+
71
+ // Generalized Trowbridge-Reitz (GTR). For GGX set k=2.
72
+ // D_GTR(roughness, NoH, k) where roughness = α (not α²).
73
+ export const D_GTR = Fn( ( [ roughness, NoH, k ] ) => {
74
+
75
+ // see: Filament - Normal distribution function (specular D) - 4.4.1
76
+ const a2 = roughness.mul( roughness ).toVar(); // α²
77
+ const NoH2 = NoH.mul( NoH ).toVar();
78
+ const base = NoH2.mul( a2.sub( float( 1.0 ) ) ).add( float( 1.0 ) ).toVar();
79
+ // a² / (π * base^k)
80
+ return a2.div( PI.mul( pow( base, k ) ) ).toVar(); // float
81
+
82
+ } );
83
+
84
+ // Smith G1 (Heitz): expects alpha (not squared); it squares internally
85
+ export const SmithG = Fn( ( [ NDotX, alpha ] ) => {
86
+
87
+ // see: Filament - Geometric shadowing (specular G) - 4.4.2
88
+
89
+ const a2 = alpha.mul( alpha ).toVar(); // α²
90
+ const NDotX2 = NDotX.mul( NDotX ).toVar(); // (N·X)²
91
+ return float( 2.0 ).mul( NDotX ).div(
92
+ NDotX.add( sqrt(
93
+ a2.add( a2.oneMinus().mul( NDotX2 ) )
94
+ ) )
95
+ );
96
+
97
+ } );
98
+
99
+ // Geometry term G = G1(N·L, α_G) * G1(N·V, α_G) (α_G is NOT squared here)
100
+ export const GeometryTerm = Fn( ( [ NoL, NoV, alphaG ] ) => {
101
+
102
+ const G1v = SmithG( NoV, alphaG ).toVar();
103
+ const G1l = SmithG( NoL, alphaG ).toVar();
104
+ return G1v.mul( G1l ).toVar();
105
+
106
+ } );
107
+
108
+ // Bounded VNDF direction PDF (reflection mapping), matching SampleGGXVNDF above.
109
+ // p(L) = D_GTR(roughness, NoH, 2) / ( 2 * (k * N·V + t) ) (Eto & Tokuyoshi eq. 8)
110
+ // with the isotropic cap bound k and t = ‖(α·V.xy, V.z)‖. Here 'roughness' is α, not α².
111
+ const GGXVNDFPdf = Fn( ( [ NoH, NoV, roughness ] ) => {
112
+
113
+ const D = D_GTR( roughness, NoH, float( 2.0 ) ).toVar();
114
+ const a2 = roughness.mul( roughness ).toVar();
115
+ const sinV2 = max( float( 0.0 ), float( 1.0 ).sub( NoV.mul( NoV ) ) ).toVar(); // ‖V.xy‖²
116
+ const s = float( 1.0 ).add( sqrt( sinV2 ) ).toVar();
117
+ const s2 = s.mul( s ).toVar();
118
+ const k = float( 1.0 ).sub( a2 ).mul( s2 ).div( s2.add( a2.mul( NoV ).mul( NoV ) ) ).toVar();
119
+ const t = sqrt( a2.mul( sinV2 ).add( NoV.mul( NoV ) ) ).toVar();
120
+ return D.div( max( float( 1e-6 ), float( 2.0 ).mul( k.mul( NoV ).add( t ) ) ) ).toVar();
121
+
122
+ } );
123
+
124
+ /**
125
+ * Fresnel reflectance for the Schlick approximation.
126
+ */
127
+ export const F_Schlick = Fn( ( [ f0, theta ] ) => {
128
+
129
+ const oneMinus = float( 1.0 ).sub( theta ).toVar();
130
+ const oneMinus2 = oneMinus.mul( oneMinus ).toVar();
131
+ const oneMinus5 = oneMinus2.mul( oneMinus2 ).mul( oneMinus ).toVar();
132
+ return f0.add( vec3( 1.0 ).sub( f0 ).mul( oneMinus5 ) ).toVar(); // vec3
133
+
134
+ } );
135
+
136
+ /**
137
+ * Specular dominant factor for parallax-corrected ray length.
138
+ * From REBLUR: A Hierarchical Recurrent Denoiser (NRD).
139
+ */
140
+ export const getSpecularDominantFactor = Fn( ( [ NoV, roughness ] ) => {
141
+
142
+ const a = float( 0.298475 ).mul(
143
+ log( float( 39.4115 ).sub( float( 39.0029 ).mul( roughness ) ) )
144
+ );
145
+ const f = float( 1.0 ).sub( NoV ).pow( 10.8649 )
146
+ .mul( float( 1.0 ).sub( a ) )
147
+ .add( a );
148
+ return clamp( f );
149
+
150
+ } ).setLayout( {
151
+ name: 'getSpecularDominantFactor',
152
+ type: 'float',
153
+ inputs: [
154
+ { name: 'NoV', type: 'float' },
155
+ { name: 'roughness', type: 'float' }
156
+ ]
157
+ } );
158
+
159
+ /**
160
+ * Everything a single GGX reflection sample produces. `reflectDir` and `sampleWeight`
161
+ * drive the SSR ray-march and compositing; `pdf`, `NdotV`, `alpha` and `f0` are the GGX
162
+ * terms the env-miss MIS fallback needs so the caller never re-derives microfacet math.
163
+ */
164
+ const ggxReflectionStruct = struct( {
165
+ reflectDir: 'vec3', // view-space reflected ray direction
166
+ sampleWeight: 'vec3', // chromatic weight (incl. Fresnel tint) to multiply gathered radiance by
167
+ pdf: 'float', // VNDF direction pdf (for MIS against the env CDF)
168
+ NdotV: 'float',
169
+ alpha: 'float', // GGX alpha (roughness²), clamped
170
+ f0: 'vec3' // Fresnel reflectance at normal incidence
171
+ } );
172
+
173
+ /**
174
+ * Importance-samples the GGX/VNDF specular lobe for one pixel and returns the reflected
175
+ * ray direction plus the Monte-Carlo weight to apply to the gathered radiance, along with
176
+ * the GGX terms the SSR env-miss MIS fallback needs.
177
+ *
178
+ * @param {Node<vec3>} N - View-space shading normal (normalized).
179
+ * @param {Node<vec3>} V - View-space surface→camera direction (normalized).
180
+ * @param {Node<float>} roughness - Perceptual roughness in `[0,1]`.
181
+ * @param {Node<float>} metalness - Metalness in `[0,1]`.
182
+ * @param {Node<vec3>} albedo - Surface base color; tints the metal Fresnel reflectance (`f0`).
183
+ * @param {Node<vec4>} Xi - Per-pixel random numbers; only `.xy` are used.
184
+ * @return {ggxReflectionStruct}
185
+ */
186
+ export const ggxReflectionSample = Fn( ( [ N, V, roughness, metalness, albedo, Xi ] ) => {
187
+
188
+ // GGX alpha (use r^2, clamp to avoid degenerate)
189
+ const a = roughness.mul( roughness ).max( 0.001 ).toVar();
190
+ const ax = a.toVar();
191
+ const ay = a.toVar();
192
+
193
+ // TBN from view-space normal
194
+ const up = vec3( 0, 0, 1 );
195
+ let T = cross( up, N ).toVar();
196
+ T = T.normalize().toVar();
197
+ If( T.length().lessThan( 1e-3 ), () => {
198
+
199
+ T.assign( cross( vec3( 0, 1, 0 ), N ).normalize() );
200
+
201
+ } );
202
+ const B = cross( N, T ).normalize().toVar();
203
+
204
+ // transform V to LOCAL frame (N = +Z)
205
+ const Vlocal = vec3( dot( T, V ), dot( B, V ), dot( N, V ) ).toVar();
206
+
207
+ // VNDF sample **in local frame**
208
+ const Hlocal = SampleGGXVNDF( Vlocal, ax, ay, Xi.x, Xi.y ).toVar();
209
+ If( Hlocal.z.lessThan( 0 ), () => {
210
+
211
+ Hlocal.assign( Hlocal.negate() );
212
+
213
+ } );
214
+
215
+ // transform H back to VIEW space
216
+ const h = normalize( T.mul( Hlocal.x ).add( B.mul( Hlocal.y ) ).add( N.mul( Hlocal.z ) ) ).toVar();
217
+
218
+ // reflect with V (surface->camera) and H
219
+ const viewReflectDir = reflect( V.negate(), h ).normalize().toVar();
220
+
221
+ // BRDF/PDF evaluation for the sampled direction
222
+ // V: surface -> camera, L: reflected direction, N: normal, H: half-vector
223
+ const L = viewReflectDir.toVar();
224
+ const H = normalize( V.add( L ) ).toVar(); // ~h; recomputed for robustness
225
+
226
+ const NdotV = max( float( 0.0 ), dot( N, V ) ).toVar();
227
+ const NdotL = max( float( 0.0 ), dot( N, L ) ).toVar();
228
+ const NdotH = max( float( 0.0 ), dot( N, H ) ).toVar();
229
+ const VdotH = max( float( 0.0 ), dot( V, H ) ).toVar();
230
+
231
+ const f0 = mix( vec3( 0.04 ), albedo, metalness ).toVar();
232
+ // Chromatic Fresnel reflectance: for metals f0 = albedo, so the reflection is tinted and desaturates
233
+ // toward white at grazing angles. Kept as vec3 so colored metals reflect with the correct chroma.
234
+ const fresnelWeight = F_Schlick( f0, VdotH ).toVar(); // vec3
235
+
236
+ // Bounded-VNDF direction pdf — still needed for the env-miss MIS path.
237
+ const pdf = GGXVNDFPdf( NdotH, NdotV, ax ).toVar();
238
+
239
+ // Numerically stable importance weight: brdf·NdotL/pdf ≡ fresnel·G2·(k·NdotV + t)/(2·NdotV), which
240
+ // cancels the GGX D analytically. Evaluating D explicitly is catastrophic at low roughness
241
+ // (D → 3e5 at α = 0.001 wrecks f32 precision); the cancelled form stays stable down to a mirror.
242
+ // (k·NdotV + t) is the bounded-cap normalization; k shrinks the cap to drop below-horizon samples.
243
+ const a2 = ax.mul( ax ).toVar();
244
+ const sinV2 = NdotV.mul( NdotV ).oneMinus().max( 0.0 ).toVar(); // ‖V.xy‖²
245
+ const sB = float( 1.0 ).add( sqrt( sinV2 ) ).toVar();
246
+ const s2B = sB.mul( sB ).toVar();
247
+ const kB = a2.oneMinus().mul( s2B ).div( s2B.add( a2.mul( NdotV ).mul( NdotV ) ) ).toVar();
248
+ const tB = sqrt( a2.mul( sinV2 ).add( NdotV.mul( NdotV ) ) ).toVar();
249
+ const glossyWeight = fresnelWeight
250
+ .mul( GeometryTerm( NdotL, NdotV, ax ) )
251
+ .mul( kB.mul( NdotV ).add( tB ) )
252
+ .div( float( 2.0 ).mul( NdotV ).max( 1e-4 ) ).toVar();
253
+
254
+ return ggxReflectionStruct( viewReflectDir, glossyWeight, pdf, NdotV, ax, f0 );
255
+
256
+ } );
257
+
258
+ // Equirectangular environment sampling
259
+
260
+ /**
261
+ * Equirectangular direction / UV / PDF helpers and MIS weighting shared by environment sampling code.
262
+ * Env-miss MIS integration lives in {@link ImportanceSampledEnvironment}.
263
+ *
264
+ * Equirectangular parameterization helpers used with CDF importance sampling are adapted from
265
+ * [three-gpu-pathtracer](https://github.com/gkjohnson/three-gpu-pathtracer).
266
+ *
267
+ * @see {@link https://github.com/gkjohnson/three-gpu-pathtracer}
268
+ */
269
+
270
+ // uv -> direction (equirectangular)
271
+ export const equirectUvToDir = Fn( ( [ uvIn ] ) => {
272
+
273
+ const phi = uvIn.x.mul( Math.PI * 2 ).sub( Math.PI );
274
+ const lat = uvIn.y.sub( 0.5 ).mul( Math.PI );
275
+ const cosLat = cos( lat );
276
+ return normalize( vec3(
277
+ cosLat.mul( cos( phi ) ),
278
+ sin( lat ),
279
+ cosLat.mul( sin( phi ) )
280
+ ) );
281
+
282
+ } ).setLayout( {
283
+ name: 'equirectUvToDir',
284
+ type: 'vec3',
285
+ inputs: [ { name: 'uv', type: 'vec2' } ]
286
+ } );
287
+
288
+ // Solid-angle PDF of a direction under equirectangular parameterization.
289
+ export const equirectDirPdf = Fn( ( [ direction ] ) => {
290
+
291
+ const uvDir = equirectUV( direction );
292
+ const sinTheta = sin( uvDir.y.mul( Math.PI ) );
293
+ return sinTheta.abs().lessThan( float( 1e-6 ) ).select(
294
+ float( 0 ),
295
+ float( 1 ).div( float( 2 * Math.PI * Math.PI ).mul( sinTheta ) )
296
+ );
297
+
298
+ } ).setLayout( {
299
+ name: 'equirectDirPdf',
300
+ type: 'float',
301
+ inputs: [ { name: 'direction', type: 'vec3' } ]
302
+ } );
303
+
304
+ /**
305
+ * MIS power heuristic with β = 2: `pdfA² / (pdfA² + pdfB²)`.
306
+ * Weights the contribution of the strategy that produced `pdfA` against the other strategy.
307
+ *
308
+ * @see Eric Veach, *Optimally Combining Sampling Techniques for Monte Carlo Rendering*
309
+ * @tsl
310
+ */
311
+ export const misPowerHeuristic = Fn( ( [ pdfA, pdfB ] ) => {
312
+
313
+ const pdfASq = pdfA.mul( pdfA );
314
+ const pdfBSq = pdfB.mul( pdfB );
315
+ return pdfASq.div( pdfASq.add( pdfBSq ) );
316
+
317
+ } ).setLayout( {
318
+ name: 'misPowerHeuristic',
319
+ type: 'float',
320
+ inputs: [
321
+ { name: 'pdfA', type: 'float' },
322
+ { name: 'pdfB', type: 'float' }
323
+ ]
324
+ } );
325
+