super-three 0.181.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 (693) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +3 -4
  3. package/build/three.cjs +21332 -19201
  4. package/build/three.core.js +20908 -19853
  5. package/build/three.core.min.js +2 -2
  6. package/build/three.module.js +1947 -862
  7. package/build/three.module.min.js +2 -2
  8. package/build/three.tsl.js +37 -16
  9. package/build/three.tsl.min.js +2 -2
  10. package/build/three.webgpu.js +33628 -25197
  11. package/build/three.webgpu.min.js +2 -2
  12. package/build/three.webgpu.nodes.js +33394 -25000
  13. package/build/three.webgpu.nodes.min.js +2 -2
  14. package/examples/jsm/Addons.js +14 -3
  15. package/examples/jsm/animation/CCDIKSolver.js +7 -3
  16. package/examples/jsm/controls/ArcballControls.js +13 -6
  17. package/examples/jsm/controls/DragControls.js +2 -2
  18. package/examples/jsm/controls/FirstPersonControls.js +127 -86
  19. package/examples/jsm/controls/FlyControls.js +4 -0
  20. package/examples/jsm/controls/MapControls.js +55 -1
  21. package/examples/jsm/controls/OrbitControls.js +111 -8
  22. package/examples/jsm/controls/TrackballControls.js +8 -8
  23. package/examples/jsm/controls/TransformControls.js +102 -17
  24. package/examples/jsm/csm/CSM.js +2 -1
  25. package/examples/jsm/csm/CSMFrustum.js +31 -6
  26. package/examples/jsm/csm/CSMShadowNode.js +10 -3
  27. package/examples/jsm/effects/AnaglyphEffect.js +102 -7
  28. package/examples/jsm/effects/AsciiEffect.js +14 -1
  29. package/examples/jsm/environments/ColorEnvironment.js +59 -0
  30. package/examples/jsm/environments/RoomEnvironment.js +3 -0
  31. package/examples/jsm/exporters/DRACOExporter.js +27 -6
  32. package/examples/jsm/exporters/EXRExporter.js +1 -1
  33. package/examples/jsm/exporters/GLTFExporter.js +266 -21
  34. package/examples/jsm/exporters/PLYExporter.js +286 -73
  35. package/examples/jsm/exporters/USDZExporter.js +353 -99
  36. package/examples/jsm/generators/CityGenerator.js +346 -0
  37. package/examples/jsm/generators/ForestGenerator.js +347 -0
  38. package/examples/jsm/generators/TerrainGenerator.js +504 -0
  39. package/examples/jsm/generators/TreeGenerator.js +377 -0
  40. package/examples/jsm/generators/city/SidewalkGenerator.js +253 -0
  41. package/examples/jsm/generators/city/SkyscraperGenerator.js +1357 -0
  42. package/examples/jsm/geometries/DecalGeometry.js +1 -1
  43. package/examples/jsm/geometries/LoftGeometry.js +355 -0
  44. package/examples/jsm/geometries/TextGeometry.js +18 -0
  45. package/examples/jsm/helpers/AnimationPathHelper.js +302 -0
  46. package/examples/jsm/helpers/LightProbeGridHelper.js +221 -0
  47. package/examples/jsm/helpers/LightProbeHelper.js +5 -4
  48. package/examples/jsm/helpers/LightProbeHelperGPU.js +1 -1
  49. package/examples/jsm/helpers/TextureHelperGPU.js +1 -1
  50. package/examples/jsm/helpers/ViewHelper.js +83 -14
  51. package/examples/jsm/inspector/Extension.js +13 -0
  52. package/examples/jsm/inspector/Inspector.js +244 -91
  53. package/examples/jsm/inspector/RendererInspector.js +165 -39
  54. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js +916 -0
  55. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphLoader.js +281 -0
  56. package/examples/jsm/inspector/tabs/Console.js +241 -25
  57. package/examples/jsm/inspector/tabs/Memory.js +136 -0
  58. package/examples/jsm/inspector/tabs/Parameters.js +115 -7
  59. package/examples/jsm/inspector/tabs/Performance.js +24 -9
  60. package/examples/jsm/inspector/tabs/Settings.js +306 -0
  61. package/examples/jsm/inspector/tabs/Timeline.js +1696 -0
  62. package/examples/jsm/inspector/tabs/Viewer.js +723 -9
  63. package/examples/jsm/inspector/ui/Graph.js +162 -25
  64. package/examples/jsm/inspector/ui/Item.js +92 -13
  65. package/examples/jsm/inspector/ui/List.js +2 -2
  66. package/examples/jsm/inspector/ui/Profiler.js +1991 -44
  67. package/examples/jsm/inspector/ui/Style.js +1943 -543
  68. package/examples/jsm/inspector/ui/Tab.js +226 -5
  69. package/examples/jsm/inspector/ui/Values.js +126 -8
  70. package/examples/jsm/inspector/ui/utils.js +143 -10
  71. package/examples/jsm/interaction/InteractionManager.js +226 -0
  72. package/examples/jsm/libs/basis/README.md +0 -1
  73. package/examples/jsm/libs/demuxer_mp4.js +3 -3
  74. package/examples/jsm/libs/draco/README.md +0 -1
  75. package/examples/jsm/libs/meshopt_clusterizer.module.js +421 -0
  76. package/examples/jsm/libs/meshopt_decoder.module.js +9 -8
  77. package/examples/jsm/libs/meshopt_simplifier.module.js +627 -0
  78. package/examples/jsm/libs/mikktspace.module.js +34 -9
  79. package/examples/jsm/lighting/ClusteredLighting.js +55 -0
  80. package/examples/jsm/lighting/DynamicLighting.js +82 -0
  81. package/examples/jsm/lighting/LightProbeGrid.js +681 -0
  82. package/examples/jsm/lines/LineMaterial.js +45 -16
  83. package/examples/jsm/lines/LineSegments2.js +8 -0
  84. package/examples/jsm/lines/webgpu/LineSegments2.js +8 -0
  85. package/examples/jsm/loaders/3DMLoader.js +6 -5
  86. package/examples/jsm/loaders/3MFLoader.js +2 -2
  87. package/examples/jsm/loaders/AMFLoader.js +2 -2
  88. package/examples/jsm/loaders/ColladaLoader.js +24 -4026
  89. package/examples/jsm/loaders/DRACOLoader.js +51 -18
  90. package/examples/jsm/loaders/EXRLoader.js +701 -90
  91. package/examples/jsm/loaders/FBXLoader.js +235 -37
  92. package/examples/jsm/loaders/GCodeLoader.js +34 -8
  93. package/examples/jsm/loaders/GLTFLoader.js +146 -178
  94. package/examples/jsm/loaders/HDRLoader.js +7 -30
  95. package/examples/jsm/loaders/KMZLoader.js +5 -5
  96. package/examples/jsm/loaders/KTX2Loader.js +58 -17
  97. package/examples/jsm/loaders/LDrawLoader.js +49 -58
  98. package/examples/jsm/loaders/LUT3dlLoader.js +2 -2
  99. package/examples/jsm/loaders/LUTCubeLoader.js +2 -2
  100. package/examples/jsm/loaders/LWOLoader.js +11 -39
  101. package/examples/jsm/loaders/LottieLoader.js +1 -1
  102. package/examples/jsm/loaders/MaterialXLoader.js +31 -9
  103. package/examples/jsm/loaders/NRRDLoader.js +5 -5
  104. package/examples/jsm/loaders/PCDLoader.js +11 -9
  105. package/examples/jsm/loaders/PLYLoader.js +218 -55
  106. package/examples/jsm/loaders/SVGLoader.js +549 -497
  107. package/examples/jsm/loaders/TDSLoader.js +0 -2
  108. package/examples/jsm/loaders/TGALoader.js +0 -2
  109. package/examples/jsm/loaders/TTFLoader.js +1 -1
  110. package/examples/jsm/loaders/USDLoader.js +127 -43
  111. package/examples/jsm/loaders/UltraHDRLoader.js +285 -160
  112. package/examples/jsm/loaders/VOXLoader.js +660 -117
  113. package/examples/jsm/loaders/VRMLLoader.js +80 -3
  114. package/examples/jsm/loaders/VTKLoader.js +42 -25
  115. package/examples/jsm/loaders/collada/ColladaComposer.js +3044 -0
  116. package/examples/jsm/loaders/collada/ColladaParser.js +1977 -0
  117. package/examples/jsm/loaders/usd/USDAParser.js +504 -344
  118. package/examples/jsm/loaders/usd/USDCParser.js +1867 -6
  119. package/examples/jsm/loaders/usd/USDComposer.js +4627 -0
  120. package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +2 -2
  121. package/examples/jsm/materials/WoodNodeMaterial.js +11 -11
  122. package/examples/jsm/math/Octree.js +131 -1
  123. package/examples/jsm/misc/GPUComputationRenderer.js +2 -0
  124. package/examples/jsm/misc/RollerCoaster.js +42 -4
  125. package/examples/jsm/misc/TileCreasedNormalsPlugin.js +270 -0
  126. package/examples/jsm/misc/Volume.js +2 -3
  127. package/examples/jsm/misc/VolumeSlice.js +0 -1
  128. package/examples/jsm/modifiers/TessellateModifier.js +1 -1
  129. package/examples/jsm/objects/GroundedSkybox.js +1 -1
  130. package/examples/jsm/objects/LensflareMesh.js +1 -1
  131. package/examples/jsm/objects/Reflector.js +72 -25
  132. package/examples/jsm/objects/Sky.js +90 -6
  133. package/examples/jsm/objects/SkyMesh.js +150 -16
  134. package/examples/jsm/objects/Water.js +4 -3
  135. package/examples/jsm/objects/Water2.js +5 -3
  136. package/examples/jsm/objects/Water2Mesh.js +1 -1
  137. package/examples/jsm/objects/WaterMesh.js +5 -7
  138. package/examples/jsm/physics/AmmoPhysics.js +27 -15
  139. package/examples/jsm/physics/JoltPhysics.js +10 -6
  140. package/examples/jsm/physics/RapierPhysics.js +36 -7
  141. package/examples/jsm/postprocessing/EffectComposer.js +7 -5
  142. package/examples/jsm/postprocessing/OutputPass.js +9 -0
  143. package/examples/jsm/postprocessing/RenderPass.js +10 -0
  144. package/examples/jsm/postprocessing/RenderTransitionPass.js +1 -1
  145. package/examples/jsm/postprocessing/UnrealBloomPass.js +48 -18
  146. package/examples/jsm/renderers/CSS3DRenderer.js +1 -1
  147. package/examples/jsm/renderers/Projector.js +246 -28
  148. package/examples/jsm/renderers/SVGRenderer.js +174 -60
  149. package/examples/jsm/shaders/GTAOShader.js +19 -6
  150. package/examples/jsm/shaders/HalftoneShader.js +12 -1
  151. package/examples/jsm/shaders/PoissonDenoiseShader.js +6 -2
  152. package/examples/jsm/shaders/SAOShader.js +17 -4
  153. package/examples/jsm/shaders/SSAOShader.js +11 -1
  154. package/examples/jsm/shaders/SSRShader.js +6 -5
  155. package/examples/jsm/shaders/UnpackDepthRGBAShader.js +2 -4
  156. package/examples/jsm/shaders/VignetteShader.js +1 -1
  157. package/examples/jsm/shaders/VolumeShader.js +31 -44
  158. package/examples/jsm/transpiler/AST.js +44 -0
  159. package/examples/jsm/transpiler/GLSLDecoder.js +65 -8
  160. package/examples/jsm/transpiler/Linker.js +1 -1
  161. package/examples/jsm/transpiler/ShaderToyDecoder.js +2 -0
  162. package/examples/jsm/transpiler/TSLEncoder.js +46 -3
  163. package/examples/jsm/transpiler/TranspilerUtils.js +3 -3
  164. package/examples/jsm/transpiler/WGSLEncoder.js +27 -0
  165. package/examples/jsm/tsl/WebGLNodesHandler.js +605 -0
  166. package/examples/jsm/tsl/display/AfterImageNode.js +11 -1
  167. package/examples/jsm/tsl/display/AnaglyphPassNode.js +458 -16
  168. package/examples/jsm/tsl/display/BilateralBlurNode.js +374 -0
  169. package/examples/jsm/tsl/display/BloomNode.js +75 -25
  170. package/examples/jsm/tsl/display/CRT.js +150 -0
  171. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +3 -36
  172. package/examples/jsm/tsl/display/DenoiseNode.js +1 -1
  173. package/examples/jsm/tsl/display/DepthOfFieldNode.js +3 -3
  174. package/examples/jsm/tsl/display/DotScreenNode.js +1 -1
  175. package/examples/jsm/tsl/display/FSR1Node.js +477 -0
  176. package/examples/jsm/tsl/display/FXAANode.js +13 -14
  177. package/examples/jsm/tsl/display/GTAONode.js +40 -17
  178. package/examples/jsm/tsl/display/GaussianBlurNode.js +21 -2
  179. package/examples/jsm/tsl/display/GodraysNode.js +615 -0
  180. package/examples/jsm/tsl/display/ImportanceSampledEnvironment.js +560 -0
  181. package/examples/jsm/tsl/display/LensflareNode.js +1 -1
  182. package/examples/jsm/tsl/display/Lut3DNode.js +1 -1
  183. package/examples/jsm/tsl/display/OutlineNode.js +69 -19
  184. package/examples/jsm/tsl/display/ParallaxBarrierPassNode.js +2 -2
  185. package/examples/jsm/tsl/display/PixelationPassNode.js +9 -8
  186. package/examples/jsm/tsl/display/RGBShiftNode.js +2 -2
  187. package/examples/jsm/tsl/display/RecurrentDenoiseNode.js +912 -0
  188. package/examples/jsm/tsl/display/RetroPassNode.js +263 -0
  189. package/examples/jsm/tsl/display/SMAANode.js +2 -2
  190. package/examples/jsm/tsl/display/SSAAPassNode.js +15 -27
  191. package/examples/jsm/tsl/display/SSGINode.js +96 -62
  192. package/examples/jsm/tsl/display/SSRNode.js +831 -134
  193. package/examples/jsm/tsl/display/SSSNode.js +8 -6
  194. package/examples/jsm/tsl/display/Shape.js +29 -0
  195. package/examples/jsm/tsl/display/SharpenNode.js +283 -0
  196. package/examples/jsm/tsl/display/SobelOperatorNode.js +2 -2
  197. package/examples/jsm/tsl/display/StereoCompositePassNode.js +8 -1
  198. package/examples/jsm/tsl/display/StereoPassNode.js +1 -2
  199. package/examples/jsm/tsl/display/TAAUNode.js +835 -0
  200. package/examples/jsm/tsl/display/TRAANode.js +315 -126
  201. package/examples/jsm/tsl/display/TemporalReprojectNode.js +1023 -0
  202. package/examples/jsm/tsl/display/TransitionNode.js +1 -1
  203. package/examples/jsm/tsl/display/depthAwareBlend.js +80 -0
  204. package/examples/jsm/tsl/display/radialBlur.js +68 -0
  205. package/examples/jsm/tsl/lighting/ClusteredLightsNode.js +622 -0
  206. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +300 -0
  207. package/examples/jsm/tsl/lighting/data/AmbientLightDataNode.js +61 -0
  208. package/examples/jsm/tsl/lighting/data/DirectionalLightDataNode.js +111 -0
  209. package/examples/jsm/tsl/lighting/data/HemisphereLightDataNode.js +99 -0
  210. package/examples/jsm/tsl/lighting/data/PointLightDataNode.js +134 -0
  211. package/examples/jsm/tsl/lighting/data/SpotLightDataNode.js +161 -0
  212. package/examples/jsm/tsl/math/Bayer.js +53 -3
  213. package/examples/jsm/tsl/math/curlNoise.js +107 -0
  214. package/examples/jsm/tsl/shadows/TileShadowNode.js +1 -1
  215. package/examples/jsm/tsl/shadows/TileShadowNodeHelper.js +3 -3
  216. package/examples/jsm/tsl/utils/GroundedSkybox.js +62 -0
  217. package/examples/jsm/tsl/utils/RNoise.js +51 -0
  218. package/examples/jsm/tsl/utils/SpecularHelpers.js +325 -0
  219. package/examples/jsm/utils/BufferGeometryUtils.js +128 -62
  220. package/examples/jsm/utils/ColorUtils.js +76 -0
  221. package/examples/jsm/utils/GeometryCompressionUtils.js +1 -1
  222. package/examples/jsm/utils/LDrawUtils.js +1 -1
  223. package/examples/jsm/utils/SceneOptimizer.js +1 -1
  224. package/examples/jsm/utils/ShadowMapViewer.js +24 -10
  225. package/examples/jsm/utils/ShadowMapViewerGPU.js +1 -1
  226. package/examples/jsm/utils/SkeletonUtils.js +14 -8
  227. package/examples/jsm/utils/WebGPUTextureUtils.js +1 -1
  228. package/examples/jsm/webxr/ARButton.js +1 -1
  229. package/examples/jsm/webxr/WebGLXRFallback.js +89 -0
  230. package/examples/jsm/webxr/XRControllerModelFactory.js +2 -2
  231. package/examples/jsm/webxr/XRHandMeshModel.js +36 -10
  232. package/examples/jsm/webxr/XRHandModelFactory.js +2 -1
  233. package/package.json +28 -34
  234. package/src/Three.Core.js +3 -1
  235. package/src/Three.TSL.js +35 -14
  236. package/src/Three.WebGPU.Nodes.js +5 -0
  237. package/src/Three.WebGPU.js +13 -0
  238. package/src/Three.js +1 -0
  239. package/src/animation/AnimationAction.js +18 -4
  240. package/src/animation/AnimationClip.js +0 -139
  241. package/src/animation/AnimationMixer.js +6 -0
  242. package/src/animation/AnimationUtils.js +1 -12
  243. package/src/animation/KeyframeTrack.js +47 -8
  244. package/src/animation/PropertyBinding.js +2 -2
  245. package/src/animation/PropertyMixer.js +4 -4
  246. package/src/animation/tracks/BooleanKeyframeTrack.js +1 -1
  247. package/src/animation/tracks/ColorKeyframeTrack.js +1 -1
  248. package/src/animation/tracks/NumberKeyframeTrack.js +1 -1
  249. package/src/animation/tracks/QuaternionKeyframeTrack.js +1 -1
  250. package/src/animation/tracks/StringKeyframeTrack.js +1 -1
  251. package/src/animation/tracks/VectorKeyframeTrack.js +1 -1
  252. package/src/audio/Audio.js +1 -1
  253. package/src/audio/AudioContext.js +2 -2
  254. package/src/audio/AudioListener.js +5 -3
  255. package/src/cameras/Camera.js +34 -4
  256. package/src/cameras/CubeCamera.js +20 -0
  257. package/src/cameras/StereoCamera.js +5 -2
  258. package/src/constants.js +90 -5
  259. package/src/core/BufferAttribute.js +13 -1
  260. package/src/core/BufferGeometry.js +43 -9
  261. package/src/core/Clock.js +7 -0
  262. package/src/core/Object3D.js +69 -11
  263. package/src/core/Raycaster.js +3 -3
  264. package/src/core/RenderTarget.js +19 -6
  265. package/src/extras/PMREMGenerator.js +13 -22
  266. package/src/extras/TextureUtils.js +6 -2
  267. package/src/extras/core/ShapePath.js +149 -160
  268. package/src/extras/curves/CatmullRomCurve3.js +3 -2
  269. package/src/geometries/ExtrudeGeometry.js +2 -2
  270. package/src/geometries/PolyhedronGeometry.js +1 -1
  271. package/src/geometries/SphereGeometry.js +8 -3
  272. package/src/geometries/TorusGeometry.js +8 -3
  273. package/src/helpers/CameraHelper.js +3 -0
  274. package/src/helpers/DirectionalLightHelper.js +6 -1
  275. package/src/helpers/HemisphereLightHelper.js +5 -0
  276. package/src/helpers/PointLightHelper.js +3 -25
  277. package/src/helpers/SpotLightHelper.js +4 -1
  278. package/src/lights/DirectionalLight.js +13 -0
  279. package/src/lights/HemisphereLight.js +10 -0
  280. package/src/lights/Light.js +1 -11
  281. package/src/lights/LightProbe.js +0 -15
  282. package/src/lights/LightShadow.js +15 -6
  283. package/src/lights/PointLight.js +15 -0
  284. package/src/lights/PointLightShadow.js +0 -86
  285. package/src/lights/SpotLight.js +22 -1
  286. package/src/lights/webgpu/IESSpotLight.js +2 -1
  287. package/src/loaders/AudioLoader.js +11 -1
  288. package/src/loaders/Cache.js +28 -0
  289. package/src/loaders/DataTextureLoader.js +75 -42
  290. package/src/loaders/FileLoader.js +2 -3
  291. package/src/loaders/ImageBitmapLoader.js +12 -9
  292. package/src/loaders/Loader.js +6 -0
  293. package/src/loaders/LoadingManager.js +5 -0
  294. package/src/loaders/MaterialLoader.js +37 -266
  295. package/src/loaders/ObjectLoader.js +48 -6
  296. package/src/loaders/nodes/NodeLoader.js +2 -2
  297. package/src/loaders/nodes/NodeObjectLoader.js +18 -0
  298. package/src/materials/LineBasicMaterial.js +4 -0
  299. package/src/materials/Material.js +198 -1
  300. package/src/materials/MeshBasicMaterial.js +24 -0
  301. package/src/materials/MeshDepthMaterial.js +10 -0
  302. package/src/materials/MeshDistanceMaterial.js +10 -0
  303. package/src/materials/MeshLambertMaterial.js +49 -1
  304. package/src/materials/MeshMatcapMaterial.js +25 -1
  305. package/src/materials/MeshNormalMaterial.js +9 -1
  306. package/src/materials/MeshPhongMaterial.js +49 -1
  307. package/src/materials/MeshPhysicalMaterial.js +38 -0
  308. package/src/materials/MeshStandardMaterial.js +42 -1
  309. package/src/materials/MeshToonMaterial.js +35 -2
  310. package/src/materials/PointsMaterial.js +7 -0
  311. package/src/materials/ShaderMaterial.js +106 -1
  312. package/src/materials/SpriteMaterial.js +7 -0
  313. package/src/materials/nodes/Line2NodeMaterial.js +380 -297
  314. package/src/materials/nodes/MeshBasicNodeMaterial.js +2 -2
  315. package/src/materials/nodes/MeshNormalNodeMaterial.js +2 -2
  316. package/src/materials/nodes/MeshPhongNodeMaterial.js +0 -9
  317. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +3 -30
  318. package/src/materials/nodes/MeshSSSNodeMaterial.js +0 -13
  319. package/src/materials/nodes/MeshStandardNodeMaterial.js +5 -15
  320. package/src/materials/nodes/NodeMaterial.js +153 -89
  321. package/src/materials/nodes/SpriteNodeMaterial.js +0 -10
  322. package/src/materials/nodes/manager/NodeMaterialObserver.js +234 -100
  323. package/src/math/Box3.js +5 -0
  324. package/src/math/FrustumArray.js +103 -133
  325. package/src/math/Interpolant.js +1 -1
  326. package/src/math/Line3.js +6 -5
  327. package/src/math/MathUtils.js +12 -12
  328. package/src/math/Matrix2.js +13 -9
  329. package/src/math/Matrix3.js +24 -9
  330. package/src/math/Matrix4.js +112 -74
  331. package/src/math/Plane.js +4 -3
  332. package/src/math/Quaternion.js +3 -29
  333. package/src/math/Sphere.js +1 -1
  334. package/src/math/Triangle.js +1 -1
  335. package/src/math/Vector2.js +13 -9
  336. package/src/math/Vector3.js +17 -15
  337. package/src/math/Vector4.js +15 -11
  338. package/src/math/interpolants/BezierInterpolant.js +106 -0
  339. package/src/nodes/Nodes.js +86 -71
  340. package/src/nodes/TSL.js +15 -13
  341. package/src/nodes/accessors/Arrays.js +5 -5
  342. package/src/nodes/accessors/Batch.js +108 -0
  343. package/src/nodes/accessors/Bitangent.js +7 -7
  344. package/src/nodes/accessors/BufferAttributeNode.js +120 -17
  345. package/src/nodes/accessors/BufferNode.js +29 -2
  346. package/src/nodes/accessors/Camera.js +149 -28
  347. package/src/nodes/accessors/ClippingNode.js +5 -5
  348. package/src/nodes/accessors/CubeTextureNode.js +27 -2
  349. package/src/nodes/accessors/Instance.js +264 -0
  350. package/src/nodes/accessors/MaterialNode.js +27 -3
  351. package/src/nodes/accessors/MaterialProperties.js +6 -8
  352. package/src/nodes/accessors/MaterialReferenceNode.js +1 -2
  353. package/src/nodes/accessors/ModelNode.js +1 -1
  354. package/src/nodes/accessors/{MorphNode.js → Morph.js} +99 -112
  355. package/src/nodes/accessors/Normal.js +24 -24
  356. package/src/nodes/accessors/Object3DNode.js +1 -1
  357. package/src/nodes/accessors/Position.js +39 -3
  358. package/src/nodes/accessors/ReferenceBaseNode.js +6 -6
  359. package/src/nodes/accessors/ReferenceNode.js +9 -8
  360. package/src/nodes/accessors/ReflectVector.js +3 -3
  361. package/src/nodes/accessors/RendererReferenceNode.js +1 -2
  362. package/src/nodes/accessors/SceneProperties.js +47 -0
  363. package/src/nodes/accessors/Skinning.js +263 -0
  364. package/src/nodes/accessors/StorageBufferNode.js +16 -27
  365. package/src/nodes/accessors/StorageTexture3DNode.js +100 -0
  366. package/src/nodes/accessors/StorageTextureNode.js +74 -11
  367. package/src/nodes/accessors/Tangent.js +8 -18
  368. package/src/nodes/accessors/Texture3DNode.js +32 -35
  369. package/src/nodes/accessors/TextureNode.js +124 -25
  370. package/src/nodes/accessors/UniformArrayNode.js +6 -4
  371. package/src/nodes/accessors/UserDataNode.js +1 -2
  372. package/src/nodes/accessors/VertexColorNode.js +1 -2
  373. package/src/nodes/code/FunctionCallNode.js +1 -1
  374. package/src/nodes/code/FunctionNode.js +4 -19
  375. package/src/nodes/core/ArrayNode.js +21 -2
  376. package/src/nodes/core/AssignNode.js +3 -3
  377. package/src/nodes/core/AttributeNode.js +3 -3
  378. package/src/nodes/core/BypassNode.js +1 -1
  379. package/src/nodes/core/ContextNode.js +104 -5
  380. package/src/nodes/core/IndexNode.js +2 -1
  381. package/src/nodes/core/InputNode.js +1 -1
  382. package/src/nodes/core/InspectorNode.js +1 -1
  383. package/src/nodes/core/IsolateNode.js +1 -1
  384. package/src/nodes/core/MRTNode.js +55 -4
  385. package/src/nodes/core/Node.js +151 -17
  386. package/src/nodes/core/NodeBuilder.js +479 -101
  387. package/src/nodes/core/NodeError.js +28 -0
  388. package/src/nodes/core/NodeFrame.js +12 -4
  389. package/src/nodes/core/NodeUtils.js +20 -18
  390. package/src/nodes/core/OutputStructNode.js +13 -11
  391. package/src/nodes/core/OverrideContextNode.js +153 -0
  392. package/src/nodes/core/ParameterNode.js +4 -4
  393. package/src/nodes/core/PropertyNode.js +66 -4
  394. package/src/nodes/core/StackNode.js +91 -20
  395. package/src/nodes/core/StackTrace.js +139 -0
  396. package/src/nodes/core/StructNode.js +20 -8
  397. package/src/nodes/core/StructTypeNode.js +17 -23
  398. package/src/nodes/core/SubBuildNode.js +2 -2
  399. package/src/nodes/core/UniformGroupNode.js +36 -6
  400. package/src/nodes/core/UniformNode.js +21 -5
  401. package/src/nodes/core/VarNode.js +56 -23
  402. package/src/nodes/core/VaryingNode.js +14 -21
  403. package/src/nodes/display/BlendModes.js +1 -105
  404. package/src/nodes/display/BumpMapNode.js +6 -1
  405. package/src/nodes/display/ColorAdjustment.js +27 -9
  406. package/src/nodes/display/ColorSpaceNode.js +3 -3
  407. package/src/nodes/display/FrontFacingNode.js +38 -9
  408. package/src/nodes/display/NormalMapNode.js +41 -6
  409. package/src/nodes/display/PassNode.js +157 -56
  410. package/src/nodes/display/PremultiplyAlphaFunctions.js +39 -0
  411. package/src/nodes/display/RenderOutputNode.js +19 -10
  412. package/src/nodes/display/ScreenNode.js +4 -2
  413. package/src/nodes/display/ToneMappingNode.js +1 -1
  414. package/src/nodes/display/ToonOutlinePassNode.js +2 -2
  415. package/src/nodes/display/ViewportDepthNode.js +52 -4
  416. package/src/nodes/display/ViewportDepthTextureNode.js +11 -15
  417. package/src/nodes/display/ViewportTextureNode.js +39 -11
  418. package/src/nodes/fog/Fog.js +18 -35
  419. package/src/nodes/functions/BSDF/BRDF_GGX_Multiscatter.js +3 -3
  420. package/src/nodes/functions/BSDF/DFGLUT.js +56 -0
  421. package/src/nodes/functions/BSDF/EnvironmentBRDF.js +2 -2
  422. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +2 -2
  423. package/src/nodes/functions/PhysicalLightingModel.js +126 -45
  424. package/src/nodes/functions/VolumetricLightingModel.js +40 -7
  425. package/src/nodes/geometry/RangeNode.js +5 -3
  426. package/src/nodes/gpgpu/AtomicFunctionNode.js +1 -1
  427. package/src/nodes/gpgpu/BarrierNode.js +9 -0
  428. package/src/nodes/gpgpu/ComputeBuiltinNode.js +2 -3
  429. package/src/nodes/gpgpu/ComputeNode.js +74 -48
  430. package/src/nodes/gpgpu/SubgroupFunctionNode.js +2 -2
  431. package/src/nodes/gpgpu/WorkgroupInfoNode.js +5 -5
  432. package/src/nodes/lighting/AnalyticLightNode.js +53 -0
  433. package/src/nodes/lighting/EnvironmentNode.js +30 -5
  434. package/src/nodes/lighting/IESSpotLightNode.js +40 -2
  435. package/src/nodes/lighting/LightingContextNode.js +10 -2
  436. package/src/nodes/lighting/LightsNode.js +97 -65
  437. package/src/nodes/lighting/PointShadowNode.js +166 -148
  438. package/src/nodes/lighting/ShadowFilterNode.js +74 -117
  439. package/src/nodes/lighting/ShadowNode.js +149 -51
  440. package/src/nodes/materialx/lib/mx_noise.js +2 -2
  441. package/src/nodes/math/BitcastNode.js +1 -1
  442. package/src/nodes/math/BitcountNode.js +433 -0
  443. package/src/nodes/math/ConditionalNode.js +6 -6
  444. package/src/nodes/math/MathNode.js +115 -52
  445. package/src/nodes/math/OperatorNode.js +24 -23
  446. package/src/nodes/math/PackFloatNode.js +98 -0
  447. package/src/nodes/math/UnpackFloatNode.js +96 -0
  448. package/src/nodes/parsers/GLSLNodeFunction.js +1 -1
  449. package/src/nodes/pmrem/PMREMNode.js +34 -3
  450. package/src/nodes/pmrem/PMREMUtils.js +9 -15
  451. package/src/nodes/tsl/TSLBase.js +1 -1
  452. package/src/nodes/tsl/TSLCore.js +99 -33
  453. package/src/nodes/utils/ArrayElementNode.js +14 -1
  454. package/src/nodes/utils/ConvertNode.js +1 -1
  455. package/src/nodes/utils/DebugNode.js +12 -12
  456. package/src/nodes/utils/EquirectUV.js +30 -5
  457. package/src/nodes/utils/EventNode.js +31 -2
  458. package/src/nodes/utils/FlipNode.js +1 -1
  459. package/src/nodes/utils/FunctionOverloadingNode.js +2 -2
  460. package/src/nodes/utils/JoinNode.js +3 -3
  461. package/src/nodes/utils/LoopNode.js +1 -1
  462. package/src/nodes/utils/MemberNode.js +2 -2
  463. package/src/nodes/utils/Packing.js +48 -5
  464. package/src/nodes/utils/PostProcessingUtils.js +33 -1
  465. package/src/nodes/utils/RTTNode.js +41 -25
  466. package/src/nodes/utils/ReflectorNode.js +4 -4
  467. package/src/nodes/utils/Remap.js +48 -0
  468. package/src/nodes/utils/RotateNode.js +1 -1
  469. package/src/nodes/utils/SampleNode.js +1 -1
  470. package/src/nodes/utils/SetNode.js +1 -1
  471. package/src/nodes/utils/SplitNode.js +1 -1
  472. package/src/nodes/utils/SpriteSheetUV.js +35 -0
  473. package/src/nodes/utils/StorageArrayElementNode.js +1 -1
  474. package/src/nodes/utils/UVUtils.js +28 -0
  475. package/src/objects/BatchedMesh.js +66 -30
  476. package/src/objects/InstancedMesh.js +19 -3
  477. package/src/objects/Line.js +1 -1
  478. package/src/objects/Mesh.js +1 -1
  479. package/src/objects/Points.js +1 -1
  480. package/src/objects/SkinnedMesh.js +26 -9
  481. package/src/renderers/WebGLRenderer.js +344 -156
  482. package/src/renderers/common/Animation.js +3 -3
  483. package/src/renderers/common/Attributes.js +15 -1
  484. package/src/renderers/common/Backend.js +78 -13
  485. package/src/renderers/common/Background.js +26 -13
  486. package/src/renderers/common/BindGroup.js +1 -16
  487. package/src/renderers/common/Binding.js +11 -0
  488. package/src/renderers/common/Bindings.js +141 -57
  489. package/src/renderers/common/BlendMode.js +143 -0
  490. package/src/renderers/common/Buffer.js +49 -0
  491. package/src/renderers/common/BundleGroup.js +1 -1
  492. package/src/renderers/common/ChainMap.js +30 -6
  493. package/src/renderers/common/ClippingContext.js +10 -2
  494. package/src/renderers/common/ComputePipeline.js +1 -1
  495. package/src/renderers/common/CubeRenderTarget.js +51 -7
  496. package/src/renderers/common/Geometries.js +29 -3
  497. package/src/renderers/common/Info.js +374 -4
  498. package/src/renderers/common/InspectorBase.js +6 -1
  499. package/src/renderers/common/Lighting.js +51 -19
  500. package/src/renderers/common/Pipelines.js +40 -7
  501. package/src/renderers/common/PostProcessing.js +8 -206
  502. package/src/renderers/common/ReadbackBuffer.js +78 -0
  503. package/src/renderers/common/RenderBundle.js +3 -1
  504. package/src/renderers/common/RenderBundles.js +7 -3
  505. package/src/renderers/common/RenderContext.js +16 -0
  506. package/src/renderers/common/RenderContexts.js +33 -49
  507. package/src/renderers/common/RenderList.js +41 -4
  508. package/src/renderers/common/RenderLists.js +2 -1
  509. package/src/renderers/common/RenderObject.js +88 -16
  510. package/src/renderers/common/RenderObjectPipeline.js +40 -0
  511. package/src/renderers/common/RenderObjects.js +21 -5
  512. package/src/renderers/common/RenderPipeline.js +232 -17
  513. package/src/renderers/common/Renderer.js +700 -163
  514. package/src/renderers/common/Sampler.js +16 -48
  515. package/src/renderers/common/StorageBuffer.js +13 -1
  516. package/src/renderers/common/Textures.js +121 -9
  517. package/src/renderers/common/TimestampQueryPool.js +6 -4
  518. package/src/renderers/common/Uniform.js +8 -0
  519. package/src/renderers/common/UniformsGroup.js +84 -1
  520. package/src/renderers/common/XRManager.js +377 -51
  521. package/src/renderers/common/extras/PMREMGenerator.js +40 -61
  522. package/src/renderers/common/nodes/NodeBuilderState.js +10 -2
  523. package/src/renderers/common/nodes/NodeLibrary.js +4 -4
  524. package/src/renderers/common/nodes/{Nodes.js → NodeManager.js} +298 -106
  525. package/src/renderers/common/nodes/NodeStorageBuffer.js +13 -2
  526. package/src/renderers/common/nodes/NodeUniformBuffer.js +65 -0
  527. package/src/renderers/shaders/DFGLUTData.js +19 -34
  528. package/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js +2 -2
  529. package/src/renderers/shaders/ShaderChunk/color_fragment.glsl.js +1 -5
  530. package/src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl.js +1 -5
  531. package/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js +1 -5
  532. package/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js +8 -10
  533. package/src/renderers/shaders/ShaderChunk/common.glsl.js +13 -4
  534. package/src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js +0 -6
  535. package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +0 -1
  536. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +9 -13
  537. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +2 -2
  538. package/src/renderers/shaders/ShaderChunk/envmap_vertex.glsl.js +1 -1
  539. package/src/renderers/shaders/ShaderChunk/lightprobes_pars_fragment.glsl.js +80 -0
  540. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +13 -2
  541. package/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js +6 -0
  542. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +6 -2
  543. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +3 -1
  544. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +8 -4
  545. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +112 -53
  546. package/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js +2 -2
  547. package/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js +7 -0
  548. package/src/renderers/shaders/ShaderChunk/normal_vertex.glsl.js +6 -0
  549. package/src/renderers/shaders/ShaderChunk/packing.glsl.js +20 -4
  550. package/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl.js +0 -1
  551. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +225 -186
  552. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +12 -2
  553. package/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js +1 -1
  554. package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +2 -2
  555. package/src/renderers/shaders/ShaderChunk.js +5 -3
  556. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +1 -2
  557. package/src/renderers/shaders/ShaderLib/depth.glsl.js +3 -0
  558. package/src/renderers/shaders/ShaderLib/{distanceRGBA.glsl.js → distance.glsl.js} +2 -3
  559. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +2 -1
  560. package/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +1 -2
  561. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +2 -1
  562. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +4 -9
  563. package/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +0 -1
  564. package/src/renderers/shaders/ShaderLib/shadow.glsl.js +1 -1
  565. package/src/renderers/shaders/ShaderLib/vsm.glsl.js +4 -6
  566. package/src/renderers/shaders/ShaderLib.js +7 -6
  567. package/src/renderers/shaders/UniformsLib.js +7 -5
  568. package/src/renderers/shaders/UniformsUtils.js +27 -5
  569. package/src/renderers/webgl/WebGLAnimation.js +2 -1
  570. package/src/renderers/webgl/WebGLBackground.js +15 -15
  571. package/src/renderers/webgl/WebGLBindingStates.js +99 -27
  572. package/src/renderers/webgl/WebGLBufferRenderer.js +0 -32
  573. package/src/renderers/webgl/WebGLCapabilities.js +9 -4
  574. package/src/renderers/webgl/WebGLEnvironments.js +228 -0
  575. package/src/renderers/webgl/WebGLGeometries.js +10 -7
  576. package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +0 -32
  577. package/src/renderers/webgl/WebGLLights.js +18 -1
  578. package/src/renderers/webgl/WebGLMaterials.js +24 -13
  579. package/src/renderers/webgl/WebGLObjects.js +3 -1
  580. package/src/renderers/webgl/WebGLOutput.js +271 -0
  581. package/src/renderers/webgl/WebGLProgram.js +54 -113
  582. package/src/renderers/webgl/WebGLPrograms.js +74 -55
  583. package/src/renderers/webgl/WebGLRenderLists.js +24 -1
  584. package/src/renderers/webgl/WebGLRenderStates.js +13 -2
  585. package/src/renderers/webgl/WebGLShaderCache.js +5 -11
  586. package/src/renderers/webgl/WebGLShadowMap.js +188 -24
  587. package/src/renderers/webgl/WebGLState.js +75 -37
  588. package/src/renderers/webgl/WebGLTextures.js +230 -56
  589. package/src/renderers/webgl/WebGLUniforms.js +40 -3
  590. package/src/renderers/webgl/WebGLUniformsGroups.js +82 -35
  591. package/src/renderers/webgl/WebGLUtils.js +6 -2
  592. package/src/renderers/webgl-fallback/WebGLBackend.js +322 -92
  593. package/src/renderers/webgl-fallback/WebGLBufferRenderer.js +0 -41
  594. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +295 -66
  595. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +53 -19
  596. package/src/renderers/webgl-fallback/utils/WebGLCapabilities.js +25 -0
  597. package/src/renderers/webgl-fallback/utils/WebGLState.js +223 -6
  598. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +118 -73
  599. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +10 -10
  600. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +9 -3
  601. package/src/renderers/webgpu/WebGPUBackend.js +733 -302
  602. package/src/renderers/webgpu/WebGPURenderer.js +2 -1
  603. package/src/renderers/webgpu/descriptors/GPUBindGroupDescriptor.js +48 -0
  604. package/src/renderers/webgpu/descriptors/GPUBufferDescriptor.js +57 -0
  605. package/src/renderers/webgpu/descriptors/GPUCommandEncoderDescriptor.js +30 -0
  606. package/src/renderers/webgpu/descriptors/GPUComputePassDescriptor.js +38 -0
  607. package/src/renderers/webgpu/descriptors/GPUComputePipelineDescriptor.js +48 -0
  608. package/src/renderers/webgpu/descriptors/GPUCopyExternalImageDestInfo.js +47 -0
  609. package/src/renderers/webgpu/descriptors/GPUCopyExternalImageSourceInfo.js +50 -0
  610. package/src/renderers/webgpu/descriptors/GPUExtent3D.js +51 -0
  611. package/src/renderers/webgpu/descriptors/GPUPipelineLayoutDescriptor.js +39 -0
  612. package/src/renderers/webgpu/descriptors/GPUQuerySetDescriptor.js +47 -0
  613. package/src/renderers/webgpu/descriptors/GPURenderBundleEncoderDescriptor.js +74 -0
  614. package/src/renderers/webgpu/descriptors/GPURenderPassColorAttachment.js +72 -0
  615. package/src/renderers/webgpu/descriptors/GPURenderPassDepthStencilAttachment.js +99 -0
  616. package/src/renderers/webgpu/descriptors/GPURenderPassDescriptor.js +72 -0
  617. package/src/renderers/webgpu/descriptors/GPURenderPassTimestampWrites.js +49 -0
  618. package/src/renderers/webgpu/descriptors/GPURenderPipelineDescriptor.js +130 -0
  619. package/src/renderers/webgpu/descriptors/GPUSamplerDescriptor.js +119 -0
  620. package/src/renderers/webgpu/descriptors/GPUShaderModuleDescriptor.js +46 -0
  621. package/src/renderers/webgpu/descriptors/GPUTexelCopyBufferInfo.js +57 -0
  622. package/src/renderers/webgpu/descriptors/GPUTexelCopyBufferLayout.js +48 -0
  623. package/src/renderers/webgpu/descriptors/GPUTexelCopyTextureInfo.js +61 -0
  624. package/src/renderers/webgpu/descriptors/GPUTextureDescriptor.js +99 -0
  625. package/src/renderers/webgpu/descriptors/GPUTextureViewDescriptor.js +108 -0
  626. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +0 -1
  627. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +526 -93
  628. package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +1 -1
  629. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +194 -61
  630. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +395 -234
  631. package/src/renderers/webgpu/utils/WebGPUCapabilities.js +48 -0
  632. package/src/renderers/webgpu/utils/WebGPUConstants.js +10 -0
  633. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +224 -91
  634. package/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js +228 -213
  635. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +428 -175
  636. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +40 -25
  637. package/src/renderers/webgpu/utils/WebGPUUtils.js +70 -13
  638. package/src/renderers/webxr/WebXRController.js +12 -0
  639. package/src/renderers/webxr/WebXRManager.js +4 -2
  640. package/src/textures/CubeDepthTexture.js +76 -0
  641. package/src/textures/DepthTexture.js +1 -1
  642. package/src/textures/ExternalTexture.js +0 -3
  643. package/src/textures/HTMLTexture.js +74 -0
  644. package/src/textures/Source.js +2 -2
  645. package/src/textures/Texture.js +16 -5
  646. package/src/utils.js +280 -3
  647. package/examples/fonts/LICENSE +0 -13
  648. package/examples/fonts/MPLUSRounded1c/MPLUSRounded1c-Regular.typeface.json.zip +0 -0
  649. package/examples/fonts/MPLUSRounded1c/OFL.txt +0 -91
  650. package/examples/fonts/README.md +0 -11
  651. package/examples/fonts/droid/NOTICE +0 -190
  652. package/examples/fonts/droid/README.txt +0 -18
  653. package/examples/fonts/droid/droid_sans_bold.typeface.json +0 -1
  654. package/examples/fonts/droid/droid_sans_mono_regular.typeface.json +0 -1
  655. package/examples/fonts/droid/droid_sans_regular.typeface.json +0 -1
  656. package/examples/fonts/droid/droid_serif_bold.typeface.json +0 -1
  657. package/examples/fonts/droid/droid_serif_regular.typeface.json +0 -1
  658. package/examples/fonts/gentilis_bold.typeface.json +0 -1
  659. package/examples/fonts/gentilis_regular.typeface.json +0 -1
  660. package/examples/fonts/helvetiker_bold.typeface.json +0 -1
  661. package/examples/fonts/helvetiker_regular.typeface.json +0 -1
  662. package/examples/fonts/optimer_bold.typeface.json +0 -1
  663. package/examples/fonts/optimer_regular.typeface.json +0 -1
  664. package/examples/fonts/ttf/README.md +0 -9
  665. package/examples/fonts/ttf/kenpixel.ttf +0 -0
  666. package/examples/jsm/libs/ammo.wasm.js +0 -822
  667. package/examples/jsm/libs/ammo.wasm.wasm +0 -0
  668. package/examples/jsm/libs/draco/draco_encoder.js +0 -33
  669. package/examples/jsm/libs/draco/gltf/draco_encoder.js +0 -33
  670. package/examples/jsm/libs/lottie_canvas.module.js +0 -14849
  671. package/examples/jsm/libs/opentype.module.js +0 -14506
  672. package/examples/jsm/libs/rhino3dm/rhino3dm.js +0 -21
  673. package/examples/jsm/libs/rhino3dm/rhino3dm.module.js +0 -16
  674. package/examples/jsm/libs/rhino3dm/rhino3dm.wasm +0 -0
  675. package/examples/jsm/lighting/TiledLighting.js +0 -42
  676. package/examples/jsm/materials/MeshGouraudMaterial.js +0 -434
  677. package/examples/jsm/materials/MeshPostProcessingMaterial.js +0 -167
  678. package/examples/jsm/shaders/GodRaysShader.js +0 -333
  679. package/examples/jsm/tsl/display/AnamorphicNode.js +0 -282
  680. package/examples/jsm/tsl/lighting/TiledLightsNode.js +0 -442
  681. package/src/nodes/accessors/BatchNode.js +0 -163
  682. package/src/nodes/accessors/InstanceNode.js +0 -244
  683. package/src/nodes/accessors/InstancedMeshNode.js +0 -50
  684. package/src/nodes/accessors/SceneNode.js +0 -145
  685. package/src/nodes/accessors/SkinningNode.js +0 -327
  686. package/src/nodes/code/ScriptableNode.js +0 -726
  687. package/src/nodes/code/ScriptableValueNode.js +0 -253
  688. package/src/nodes/display/PosterizeNode.js +0 -65
  689. package/src/nodes/functions/BSDF/DFGApprox.js +0 -71
  690. package/src/nodes/utils/RemapNode.js +0 -125
  691. package/src/nodes/utils/SpriteSheetUVNode.js +0 -90
  692. package/src/renderers/webgl/WebGLCubeMaps.js +0 -99
  693. package/src/renderers/webgl/WebGLCubeUVMaps.js +0 -134
@@ -1,11 +1,30 @@
1
- import { HalfFloatType, RenderTarget, Vector2, RendererUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType, LinearFilter, LinearMipmapLinearFilter } from 'three/webgpu';
2
- import { texture, reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, sqrt, mul, div, cross, float, Continue, Break, Loop, int, max, abs, sub, If, dot, reflect, normalize, screenCoordinate, nodeObject, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, vec3, vec4 } from 'three/tsl';
1
+ import { Break, Continue, Fn, If, Loop, abs, bool, cross, distance, div, dot, float, getScreenPosition, getViewPosition, int, logarithmicDepthToViewZ, luminance, max, min, mix, mul, nodeObject, normalize, orthographicDepthToViewZ, passTexture, perspectiveDepthToViewZ, reference, reflect, sub, texture, trunc, uniform, uv, vec2, vec3, vec4, viewZToPerspectiveDepth } from 'three/tsl';
2
+ import { HalfFloatType, LinearFilter, LinearMipmapLinearFilter, Matrix4, NodeMaterial, NodeUpdateType, QuadMesh, RenderTarget, RendererUtils, TempNode, Vector2, Vector3 } from 'three/webgpu';
3
+ import { bindAnalyticNoise } from '../utils/RNoise.js';
4
+ import { ENV_RAY_LENGTH, getSpecularDominantFactor, ggxReflectionSample } from '../utils/SpecularHelpers.js';
3
5
  import { boxBlur } from './boxBlur.js';
6
+ import ImportanceSampledEnvironment from './ImportanceSampledEnvironment.js';
4
7
 
5
8
  const _quadMesh = /*@__PURE__*/ new QuadMesh();
6
9
  const _size = /*@__PURE__*/ new Vector2();
7
10
  let _rendererState;
8
11
 
12
+ // Maximum ray-march step count; `quality` (0..1) scales it to a fixed per-ray count.
13
+ const MAX_STEPS = 64;
14
+
15
+ /**
16
+ * @typedef {Object} SSRNodeOptions
17
+ * @property {boolean} [stochastic=false] - When `false`, traces a single mirror reflection and softens roughness with a blur pass (first-generation SSR). When `true`, varies the reflection direction per pixel with stochastic GGX rays (second-generation SSR); higher quality on rough/glossy surfaces but noisier, so it expects a temporal/spatial denoiser downstream.
18
+ * @property {Node<float>} [metalnessNode=null] - Per-pixel metalness. Drives GGX reflection sampling and, with `reflectNonMetals=false`, the non-metal early-out.
19
+ * @property {Node<float>} [roughnessNode=null] - Per-pixel roughness. Drives GGX sampling and the blur mip selection.
20
+ * @property {boolean} [reflectNonMetals=false] - Only used when `stochastic=false`. When `false`, non-metallic surfaces are discarded for a noticeable performance gain; set `true` to also reflect dielectrics (e.g. marble, polished wood, plastic).
21
+ * @property {Texture} [environmentNode=null] - Equirectangular HDR environment map with CPU-side `image.data` (e.g. from RGBELoader). Not compatible with PMREM / `scene.environment` cubemaps.
22
+ * @property {boolean} [envImportanceSampling=false] - When `true`, precomputes env-luminance CDF tables and uses MIS for environment misses. Build-time only.
23
+ * @property {Node} [diffuseNode=null] - Scene diffuse / base color. Defaults to `vec3(1)` in the shader when omitted.
24
+ * @property {boolean} [binaryRefine=false] - Sub-step binary-search refinement of detected hits. Compile-time constant (baked into the shader at construction).
25
+ * @property {Camera} [camera=null] - Camera the scene is rendered with. Inferred from the color pass when omitted.
26
+ */
27
+
9
28
  /**
10
29
  * Post processing node for computing screen space reflections (SSR).
11
30
  *
@@ -28,14 +47,42 @@ class SSRNode extends TempNode {
28
47
  * @param {Node<vec4>} colorNode - The node that represents the beauty pass.
29
48
  * @param {Node<float>} depthNode - A node that represents the beauty pass's depth.
30
49
  * @param {Node<vec3>} normalNode - A node that represents the beauty pass's normals.
31
- * @param {Node<float>} metalnessNode - A node that represents the beauty pass's metalness.
32
- * @param {?Node<float>} [roughnessNode=null] - A node that represents the beauty pass's roughness.
33
- * @param {?Camera} [camera=null] - The camera the scene is rendered with.
50
+ * @param {SSRNodeOptions} [options] - Optional inputs for material and environment data.
34
51
  */
35
- constructor( colorNode, depthNode, normalNode, metalnessNode, roughnessNode = null, camera = null ) {
52
+ constructor( colorNode, depthNode, normalNode, options = {} ) {
36
53
 
37
54
  super( 'vec4' );
38
55
 
56
+ const {
57
+ stochastic = false,
58
+ metalnessNode = null,
59
+ roughnessNode = null,
60
+ reflectNonMetals = false,
61
+ environmentNode = null,
62
+ envImportanceSampling = false,
63
+ diffuseNode = null,
64
+ binaryRefine = false
65
+ } = options;
66
+
67
+ let camera = options.camera ?? null;
68
+
69
+ /**
70
+ * When `true`, the reflection direction is varied per pixel with stochastic GGX rays
71
+ * (second-generation SSR). When `false`, a single mirror reflection is traced and
72
+ * roughness is softened with a blur pass (first-generation SSR).
73
+ *
74
+ * @type {boolean}
75
+ */
76
+ this.stochastic = stochastic;
77
+
78
+ /**
79
+ * When `true`, env-luminance CDF tables are built and MIS is used for environment misses.
80
+ * Fixed at construction time.
81
+ *
82
+ * @type {boolean}
83
+ */
84
+ this.envImportanceSampling = envImportanceSampling;
85
+
39
86
  /**
40
87
  * The node that represents the beauty pass.
41
88
  *
@@ -43,6 +90,14 @@ class SSRNode extends TempNode {
43
90
  */
44
91
  this.colorNode = colorNode;
45
92
 
93
+ /**
94
+ * A node that represents the scene's diffuse color (typically the MRT `diffuseColor` attachment).
95
+ * When `null`, the shader uses `vec3(1)`.
96
+ *
97
+ * @type {?Node<vec4>}
98
+ */
99
+ this.diffuseNode = diffuseNode !== null ? nodeObject( diffuseNode ) : null;
100
+
46
101
  /**
47
102
  * A node that represents the beauty pass's depth.
48
103
  *
@@ -58,23 +113,32 @@ class SSRNode extends TempNode {
58
113
  this.normalNode = normalNode;
59
114
 
60
115
  /**
61
- * A node that represents the beauty pass's metalness.
116
+ * Per-pixel metalness, used to drive the GGX reflection sampling and the non-metal
117
+ * early-out. When `null`, the shader treats surfaces as non-metallic.
62
118
  *
63
- * @type {Node<float>}
119
+ * @type {?Node<float>}
64
120
  */
65
121
  this.metalnessNode = metalnessNode;
66
122
 
67
123
  /**
68
- * Whether the SSR reflections should be blurred or not. Blurring is a costly
69
- * operation so turn it off if you encounter performance issues on certain
70
- * devices.
124
+ * Per-pixel roughness, used to drive the GGX reflection sampling and the blur mip
125
+ * selection. When `null`, the shader treats surfaces as fully smooth.
71
126
  *
72
- * @private
73
- * @type {Node<float>}
74
- * @default false
127
+ * @type {?Node<float>}
75
128
  */
76
129
  this.roughnessNode = roughnessNode;
77
130
 
131
+ /**
132
+ * Only used when {@link SSRNode#stochastic} is `false`. When `false`, non-metallic
133
+ * surfaces are discarded for a noticeable performance gain; set `true` to also
134
+ * reflect dielectrics. Baked into the shader as a compile-time constant; assigning a
135
+ * new value recompiles the SSR material.
136
+ *
137
+ * @type {boolean}
138
+ * @default false
139
+ */
140
+ this._reflectNonMetals = reflectNonMetals;
141
+
78
142
  /**
79
143
  * The resolution scale. Valid values are in the range
80
144
  * `[0,1]`. `1` means best quality but also results in
@@ -111,11 +175,45 @@ class SSRNode extends TempNode {
111
175
  this.thickness = uniform( 0.1 );
112
176
 
113
177
  /**
114
- * Controls how the SSR reflections are blended with the beauty pass.
178
+ * A multiplier for the overall reflection intensity. `1` leaves the
179
+ * reflections unchanged, lower values dim them and higher values boost them.
180
+ *
181
+ * @type {UniformNode<float>}
182
+ * @default 1
183
+ */
184
+ this.intensity = uniform( 1 );
185
+
186
+ /**
187
+ * Screen-edge fade width, in UV units. As a screen-space hit approaches a screen
188
+ * border, the reflection is faded over this distance — either toward the environment
189
+ * reflection ({@link SSRNode#screenEdgeFadeBlack} `false`) or to zero intensity
190
+ * (`true`). `0` disables it.
191
+ *
192
+ * @type {UniformNode<float>}
193
+ * @default 0.2
194
+ */
195
+ this.screenEdgeFade = uniform( 0.2 );
196
+
197
+ /**
198
+ * When `true`, SSR fades to zero near screen borders instead of blending toward
199
+ * the environment map. Hits are faded by the reflection sample UV; misses are
200
+ * faded by the surface pixel UV.
201
+ *
202
+ * Baked into the shader as a compile-time constant so the unused fade branch is
203
+ * eliminated; assigning a new value recompiles the SSR material.
204
+ *
205
+ * @type {boolean}
206
+ * @default false
207
+ */
208
+ this._screenEdgeFadeBlack = false;
209
+
210
+ /**
211
+ * Absolute env luminance cap. HDR env samples above this are scaled down (hue preserved).
115
212
  *
116
213
  * @type {UniformNode<float>}
214
+ * @default 10
117
215
  */
118
- this.opacity = uniform( 1 );
216
+ this.maxLuminance = uniform( 10 );
119
217
 
120
218
  /**
121
219
  * This parameter controls how detailed the raymarching process works.
@@ -130,12 +228,72 @@ class SSRNode extends TempNode {
130
228
  */
131
229
  this.quality = uniform( 0.5 );
132
230
 
231
+ /**
232
+ * Mirror bias for the stochastic GGX sampling. Concentrates the reflected rays toward
233
+ * the lobe's narrow (near-mirror) core, trading a small amount of bias for less noise.
234
+ * `0` samples the full VNDF lobe; values toward `1` tighten the cone. Range `[0,1]`.
235
+ *
236
+ * @type {UniformNode<float>}
237
+ * @default 0.5
238
+ */
239
+ this.mirrorBias = uniform( 0.5 );
240
+
133
241
  /**
134
242
  * The quality of the blur. Must be an integer in the range `[1,3]`.
135
243
  *
136
- * @type {UniformNode<int>}
244
+ * Baked into the blur shader as a compile-time constant so the `(size*2+1)²`
245
+ * sample loop unrolls; assigning a new value recompiles the blur material.
246
+ *
247
+ * @type {number}
248
+ * @default 2
249
+ */
250
+ this._blurQuality = 2;
251
+
252
+ /**
253
+ * Enables sub-step binary-search refinement of a detected hit. When on, a coarse
254
+ * crossing is bisected toward the exact intersection (sharper hits, less step
255
+ * aliasing) at the cost of extra depth samples. Baked into the shader as a
256
+ * compile-time constant; assigning a new value rebuilds the SSR material.
257
+ *
258
+ * @type {boolean}
259
+ * @default false
137
260
  */
138
- this.blurQuality = uniform( 2 );
261
+ this._binaryRefine = binaryRefine;
262
+
263
+ /**
264
+ * Non-linear step distribution exponent. `1` = uniform steps; `> 1` concentrates
265
+ * samples near the ray origin — where most short-range reflections are missed — and
266
+ * spaces them out toward maxDistance, as `s = (i / steps) ^ stepExponent`.
267
+ *
268
+ * Baked into the shader as a compile-time constant so `pow()` folds to a few
269
+ * multiplies; assigning a new value recompiles the SSR material. Only used by the
270
+ * stochastic reflection path.
271
+ *
272
+ * @type {number}
273
+ * @default 2
274
+ */
275
+ this._stepExponent = 2;
276
+
277
+ /**
278
+ * HDR environment map for screen-space misses.
279
+ *
280
+ * @type {?Texture}
281
+ */
282
+ this.environmentNode = environmentNode;
283
+
284
+ /**
285
+ * A node that represents the history texture for multi-bounce reflections.
286
+ *
287
+ * @type {?Texture}
288
+ */
289
+ this.historyTexture = null;
290
+
291
+ /**
292
+ * A node that represents the velocity texture for reprojection.
293
+ *
294
+ * @type {?Node<vec2>}
295
+ */
296
+ this.velocityTexture = null;
139
297
 
140
298
  //
141
299
 
@@ -147,7 +305,7 @@ class SSRNode extends TempNode {
147
305
 
148
306
  } else {
149
307
 
150
- throw new Error( 'THREE.TSL: No camera found. ssr() requires a camera.' );
308
+ throw new Error( 'THREE.SSRNode: No camera found. ssr() requires a camera.' );
151
309
 
152
310
  }
153
311
 
@@ -200,21 +358,38 @@ class SSRNode extends TempNode {
200
358
  */
201
359
  this._cameraFar = reference( 'far', 'float', camera );
202
360
 
361
+ this._cameraWorldMatrix = uniform( new Matrix4().copy( camera.matrixWorld ) );
362
+ this._cameraWorldPosition = uniform( new Vector3().copy( camera.position ) );
363
+
364
+ this._cameraViewMatrix = uniform( new Matrix4().copy( camera.matrixWorld ) );
365
+ this._cameraViewMatrixInverse = uniform( new Matrix4().copy( camera.matrixWorldInverse ) );
366
+
203
367
  /**
204
- * Whether the scene's camera is perspective or orthographic.
368
+ * The resolution of the pass.
205
369
  *
206
370
  * @private
207
- * @type {UniformNode<bool>}
371
+ * @type {UniformNode<vec2>}
208
372
  */
209
- this._isPerspectiveCamera = uniform( camera.isPerspectiveCamera );
373
+ this._resolution = uniform( new Vector2() );
374
+
375
+ this._noiseIndex = uniform( 0 );
210
376
 
211
377
  /**
212
- * The resolution of the pass.
378
+ * CDF-backed environment sampler. Created when {@link setEnvMap} is called.
213
379
  *
214
380
  * @private
215
- * @type {UniformNode<vec2>}
381
+ * @type {?ImportanceSampledEnvironment}
216
382
  */
217
- this._resolution = uniform( new Vector2() );
383
+ this._importanceEnvironment = null;
384
+
385
+ /**
386
+ * Intensity multiplier applied to environment-map reflections on screen-space
387
+ * misses and at screen edges. Defaults to π to match the former hardcoded multiplier.
388
+ *
389
+ * @type {UniformNode<float>}
390
+ * @default Math.PI
391
+ */
392
+ this.environmentIntensity = uniform( Math.PI );
218
393
 
219
394
  /**
220
395
  * The render target the SSR is rendered into.
@@ -244,6 +419,16 @@ class SSRNode extends TempNode {
244
419
  this._ssrMaterial = new NodeMaterial();
245
420
  this._ssrMaterial.name = 'SSRNode.SSR';
246
421
 
422
+ /**
423
+ * The SSR fragment `Fn` and its shared context, captured in {@link SSRNode#setup}.
424
+ * Re-invoking the `Fn` produces a fresh node graph, which is how the baked
425
+ * compile-time constants are re-applied when they change (see {@link SSRNode#_buildSSRMaterial}).
426
+ *
427
+ * @private
428
+ */
429
+ this._ssrFn = null;
430
+ this._sharedContext = null;
431
+
247
432
  /**
248
433
  * The blur material.
249
434
  *
@@ -272,10 +457,11 @@ class SSRNode extends TempNode {
272
457
 
273
458
  let blurredTextureNode = null;
274
459
 
275
- if ( this.roughnessNode !== null ) {
460
+ if ( this.stochastic === false && this.roughnessNode !== null ) {
276
461
 
277
462
  const mips = this._blurRenderTarget.texture.mipmaps.length - 1;
278
- const lod = float( this.roughnessNode ).mul( mips ).clamp( 0, mips );
463
+ const r = this.roughnessNode;
464
+ const lod = r.mul( r ).mul( mips ).clamp( 0, mips );
279
465
 
280
466
  blurredTextureNode = passTexture( this, this._blurRenderTarget.texture ).level( lod );
281
467
 
@@ -289,6 +475,159 @@ class SSRNode extends TempNode {
289
475
  */
290
476
  this._blurredTextureNode = blurredTextureNode;
291
477
 
478
+ if ( environmentNode !== null && environmentNode.isTexture === true ) {
479
+
480
+ this.setEnvMap( environmentNode );
481
+
482
+ }
483
+
484
+ }
485
+
486
+ /**
487
+ * Non-linear step distribution exponent (compile-time constant). See the backing
488
+ * field for details. Assigning a new value recompiles the SSR material.
489
+ *
490
+ * @type {number}
491
+ */
492
+ get stepExponent() {
493
+
494
+ return this._stepExponent;
495
+
496
+ }
497
+
498
+ set stepExponent( value ) {
499
+
500
+ if ( value !== this._stepExponent ) {
501
+
502
+ this._stepExponent = value;
503
+ this._buildSSRMaterial();
504
+
505
+ }
506
+
507
+ }
508
+
509
+ /**
510
+ * Blur kernel size (compile-time constant). Assigning a new value recompiles the
511
+ * blur material.
512
+ *
513
+ * @type {number}
514
+ */
515
+ get blurQuality() {
516
+
517
+ return this._blurQuality;
518
+
519
+ }
520
+
521
+ set blurQuality( value ) {
522
+
523
+ if ( value !== this._blurQuality ) {
524
+
525
+ this._blurQuality = value;
526
+
527
+ // The size is baked into the boxBlur node tree, so rebuild it (recompiles the material).
528
+ if ( this.stochastic === false ) this._buildBlurMaterial();
529
+
530
+ }
531
+
532
+ }
533
+
534
+ /**
535
+ * Builds (or rebuilds) the blur material's node graph, baking the current
536
+ * {@link SSRNode#blurQuality} as the kernel size so the sample loop unrolls.
537
+ *
538
+ * @private
539
+ */
540
+ _buildBlurMaterial() {
541
+
542
+ this._blurMaterial.fragmentNode = boxBlur( texture( this._ssrRenderTarget.texture ), { size: this._blurQuality, separation: this._blurSpread } );
543
+ this._blurMaterial.needsUpdate = true;
544
+
545
+ }
546
+
547
+ /**
548
+ * Whether SSR fades to black near screen borders (compile-time constant). Assigning
549
+ * a new value recompiles the SSR material.
550
+ *
551
+ * @type {boolean}
552
+ */
553
+ get screenEdgeFadeBlack() {
554
+
555
+ return this._screenEdgeFadeBlack;
556
+
557
+ }
558
+
559
+ set screenEdgeFadeBlack( value ) {
560
+
561
+ if ( value !== this._screenEdgeFadeBlack ) {
562
+
563
+ this._screenEdgeFadeBlack = value;
564
+ this._buildSSRMaterial();
565
+
566
+ }
567
+
568
+ }
569
+
570
+ /**
571
+ * Whether sub-step binary-search hit refinement is enabled (compile-time constant).
572
+ * Assigning a new value rebuilds the SSR material.
573
+ *
574
+ * @type {boolean}
575
+ */
576
+ get binaryRefine() {
577
+
578
+ return this._binaryRefine;
579
+
580
+ }
581
+
582
+ set binaryRefine( value ) {
583
+
584
+ if ( value !== this._binaryRefine ) {
585
+
586
+ this._binaryRefine = value;
587
+ this._buildSSRMaterial();
588
+
589
+ }
590
+
591
+ }
592
+
593
+ /**
594
+ * Whether dielectrics are reflected in the non-stochastic path (compile-time constant).
595
+ * Assigning a new value rebuilds the SSR material.
596
+ *
597
+ * @type {boolean}
598
+ */
599
+ get reflectNonMetals() {
600
+
601
+ return this._reflectNonMetals;
602
+
603
+ }
604
+
605
+ set reflectNonMetals( value ) {
606
+
607
+ if ( value !== this._reflectNonMetals ) {
608
+
609
+ this._reflectNonMetals = value;
610
+ this._buildSSRMaterial();
611
+
612
+ }
613
+
614
+ }
615
+
616
+ /**
617
+ * Rebuilds the SSR material's node graph by re-invoking the fragment `Fn`, which
618
+ * re-bakes the compile-time constants ({@link SSRNode#binaryRefine},
619
+ * {@link SSRNode#stepExponent}, {@link SSRNode#screenEdgeFadeBlack}) at their current
620
+ * values. A no-op until {@link SSRNode#setup} has captured the `Fn`.
621
+ *
622
+ * @private
623
+ */
624
+ _buildSSRMaterial() {
625
+
626
+ if ( this._ssrFn === null ) return;
627
+
628
+ this._ssrMaterial.fragmentNode = this._ssrFn().context( this._sharedContext );
629
+ this._ssrMaterial.needsUpdate = true;
630
+
292
631
  }
293
632
 
294
633
  /**
@@ -298,7 +637,7 @@ class SSRNode extends TempNode {
298
637
  */
299
638
  getTextureNode() {
300
639
 
301
- return this.roughnessNode !== null ? this._blurredTextureNode : this._textureNode;
640
+ return ( this.stochastic === false && this.roughnessNode !== null ) ? this._blurredTextureNode : this._textureNode;
302
641
 
303
642
  }
304
643
 
@@ -319,6 +658,81 @@ class SSRNode extends TempNode {
319
658
 
320
659
  }
321
660
 
661
+ /**
662
+ * Wires the feedback inputs for multi-bounce reflections: the previous frame's
663
+ * denoised result (`history`) and the velocity buffer used to reproject it
664
+ * (`velocity`). `history` accepts the producing node (e.g. a
665
+ * {@link RecurrentDenoiseNode}) — its output render target is used — or a raw
666
+ * texture. Pass `null` for both to disable multi-bounce.
667
+ *
668
+ * @param {Texture} history
669
+ * @param {Node<vec2>} velocity
670
+ */
671
+ setHistory( history, velocity ) {
672
+
673
+ this.historyTexture = ( history && typeof history.getRenderTarget === 'function' )
674
+ ? history.getRenderTarget().texture
675
+ : history;
676
+ this.velocityTexture = velocity;
677
+
678
+ }
679
+
680
+ /**
681
+ * Sets the environment map for importance-sampled env lighting when
682
+ * screen-space rays miss. Call this whenever the scene's env map changes.
683
+ *
684
+ * Uses {@link ImportanceSampledEnvironment} (CDF + MIS adapted from
685
+ * [three-gpu-pathtracer](https://github.com/gkjohnson/three-gpu-pathtracer)).
686
+ *
687
+ * @param {Texture|null} hdr - The equirectangular HDR environment map, or null to disable.
688
+ * @see {@link https://github.com/gkjohnson/three-gpu-pathtracer}
689
+ */
690
+ setEnvMap( hdr ) {
691
+
692
+ if ( hdr === null ) {
693
+
694
+ if ( this._importanceEnvironment !== null ) {
695
+
696
+ this._importanceEnvironment.clear();
697
+ this._importanceEnvironment = null;
698
+
699
+ }
700
+
701
+ this._buildSSRMaterial();
702
+ return;
703
+
704
+ }
705
+
706
+ if ( hdr.image === undefined || hdr.image.data === undefined ) {
707
+
708
+ console.warn( 'SSRNode: `environmentNode` / `setEnvMap()` expects an equirectangular HDR texture with CPU-side image data (e.g. RGBELoader). PMREM cubemaps and `scene.environment` are not supported.' );
709
+ return;
710
+
711
+ }
712
+
713
+ if ( this._importanceEnvironment === null ) {
714
+
715
+ this._importanceEnvironment = new ImportanceSampledEnvironment( this.envImportanceSampling );
716
+
717
+ }
718
+
719
+ this._importanceEnvironment.updateFrom( hdr );
720
+ this._buildSSRMaterial();
721
+
722
+ }
723
+
724
+ /**
725
+ * Intensity multiplier for the importance-sampled env contribution.
726
+ * Only available after {@link setEnvMap} has been called.
727
+ *
728
+ * @type {?UniformNode<float>}
729
+ */
730
+ get envMapIntensity() {
731
+
732
+ return this._importanceEnvironment !== null ? this._importanceEnvironment.intensity : null;
733
+
734
+ }
735
+
322
736
  /**
323
737
  * This method is used to render the effect once per frame.
324
738
  *
@@ -328,6 +742,9 @@ class SSRNode extends TempNode {
328
742
 
329
743
  const { renderer } = frame;
330
744
 
745
+ this._cameraWorldMatrix.value.copy( this.camera.matrixWorld );
746
+ this._cameraWorldPosition.value.copy( this.camera.position );
747
+
331
748
  _rendererState = RendererUtils.resetRendererState( renderer, _rendererState );
332
749
 
333
750
  const ssrRenderTarget = this._ssrRenderTarget;
@@ -339,6 +756,9 @@ class SSRNode extends TempNode {
339
756
 
340
757
  this.setSize( size.width, size.height );
341
758
 
759
+ // Advance the noise index once per frame (matches SSGI / Denoise).
760
+ this._noiseIndex.value = ( this._noiseIndex.value + 1 ) % 0x7fffffff;
761
+
342
762
  // clear
343
763
 
344
764
  renderer.setMRT( null );
@@ -352,7 +772,7 @@ class SSRNode extends TempNode {
352
772
 
353
773
  // blur (optional)
354
774
 
355
- if ( this.roughnessNode !== null ) {
775
+ if ( this.stochastic === false && this.roughnessNode !== null ) {
356
776
 
357
777
  // blur mips but leave the base mip unblurred
358
778
 
@@ -385,7 +805,7 @@ class SSRNode extends TempNode {
385
805
 
386
806
  const uvNode = uv();
387
807
 
388
- const pointToLineDistance = Fn( ( [ point, linePointA, linePointB ] )=> {
808
+ const pointToLineDistance = Fn( ( [ point, linePointA, linePointB ] ) => {
389
809
 
390
810
  // https://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
391
811
 
@@ -393,16 +813,15 @@ class SSRNode extends TempNode {
393
813
 
394
814
  } );
395
815
 
396
- const pointPlaneDistance = Fn( ( [ point, planePoint, planeNormal ] )=> {
816
+ const pointPlaneDistance = Fn( ( [ point, planePoint, planeNormal ] ) => {
397
817
 
398
818
  // https://mathworld.wolfram.com/Point-PlaneDistance.html
399
819
  // https://en.wikipedia.org/wiki/Plane_(geometry)
400
820
  // http://paulbourke.net/geometry/pointlineplane/
401
821
 
822
+ // planeNormal is already normalized, so the denominator is 1.
402
823
  const d = mul( planeNormal.x, planePoint.x ).add( mul( planeNormal.y, planePoint.y ) ).add( mul( planeNormal.z, planePoint.z ) ).negate().toVar();
403
-
404
- const denominator = sqrt( mul( planeNormal.x, planeNormal.x, ).add( mul( planeNormal.y, planeNormal.y ) ).add( mul( planeNormal.z, planeNormal.z ) ) ).toVar();
405
- const distance = div( mul( planeNormal.x, point.x ).add( mul( planeNormal.y, point.y ) ).add( mul( planeNormal.z, point.z ) ).add( d ), denominator );
824
+ const distance = mul( planeNormal.x, point.x ).add( mul( planeNormal.y, point.y ) ).add( mul( planeNormal.z, point.z ) ).add( d );
406
825
  return distance;
407
826
 
408
827
  } );
@@ -441,176 +860,438 @@ class SSRNode extends TempNode {
441
860
 
442
861
  };
443
862
 
863
+ const sampleMarchNoise = this.stochastic === true ? bindAnalyticNoise( this._resolution, 47 ) : null;
864
+
865
+ const computeScreenBorderFactor = Fn( ( [ uvCoord, borderWidth ] ) => {
866
+
867
+ const border = borderWidth.max( 1e-4 );
868
+
869
+ // Distance to the nearest screen edge — uniform falloff at corners.
870
+ const edgeDist = min(
871
+ min( uvCoord.x, float( 1 ).sub( uvCoord.x ) ),
872
+ min( uvCoord.y, float( 1 ).sub( uvCoord.y ) )
873
+ );
874
+
875
+ // Two smoothsteps for a softer ease-in-out than a single ramp.
876
+ const t = edgeDist.smoothstep( 0, border );
877
+
878
+ return t.smoothstep( 0, 1 ).pow( 0.125 );
879
+
880
+ } ).setLayout( {
881
+ name: 'computeScreenBorderFactor',
882
+ type: 'float',
883
+ inputs: [
884
+ { name: 'uvCoord', type: 'vec2' },
885
+ { name: 'borderWidth', type: 'float' }
886
+ ]
887
+ } );
888
+
444
889
  const ssr = Fn( () => {
445
890
 
446
- const metalness = float( this.metalnessNode );
891
+ const noise = this.stochastic === true ? sampleMarchNoise( uvNode, this._noiseIndex ) : null;
892
+ const uvPos = uvNode.toVar();
893
+
894
+ const depth = sampleDepth( uvPos ).toVar();
447
895
 
448
- // fragments with no metalness do not reflect their environment
449
- metalness.equal( 0.0 ).discard();
896
+ // Skip background pixels (cleared far-plane depth); the target is cleared each frame.
897
+ depth.greaterThanEqual( 1.0 ).discard();
450
898
 
451
- // compute some standard FX entities
452
- const depth = sampleDepth( uvNode ).toVar();
453
- const viewPosition = getViewPosition( uvNode, depth, this._cameraProjectionMatrixInverse ).toVar();
899
+ const viewPosition = getViewPosition( uvPos, depth, this._cameraProjectionMatrixInverse ).toVar();
900
+ const worldPosition = this._cameraWorldMatrix.mul( vec4( viewPosition, 1.0 ) ).xyz.toVar();
454
901
  const viewNormal = this.normalNode.rgb.normalize().toVar();
455
902
 
456
- // compute the direction from the position in view space to the camera
457
903
  const viewIncidentDir = ( ( this.camera.isPerspectiveCamera ) ? normalize( viewPosition ) : vec3( 0, 0, - 1 ) ).toVar();
458
904
 
459
- // compute the direction in which the light is reflected on the surface
460
- const viewReflectDir = reflect( viewIncidentDir, viewNormal ).toVar();
905
+ // The node system samples the metalness/roughness textures at the current uv,
906
+ // so no explicit sample() is needed here.
907
+ const metalness = float( this.metalnessNode );
908
+
909
+ if ( this.stochastic === false && this._reflectNonMetals === false ) {
910
+
911
+ metalness.lessThanEqual( 0.0 ).discard();
912
+
913
+ }
914
+
915
+ const roughness = float( this.roughnessNode );
916
+ const glossiness = min( roughness.div( 0.25 ), 1 ).oneMinus();
917
+ // Only the fade-to-black miss path reads this, and that path is baked out otherwise.
918
+ const surfaceBorderFactor = this.screenEdgeFadeBlack ? computeScreenBorderFactor( uvPos, this.screenEdgeFade ) : null;
919
+ const hitBorderWidth = this.screenEdgeFade.mul( glossiness );
920
+
921
+ const V = viewIncidentDir.negate().normalize().toVar();
922
+
923
+ let viewReflectDir, finalSampleWeight, specDominantFactor;
924
+ const albedo = vec3( 1 ).toVar();
925
+ let sampleEnvReflection = null;
926
+
927
+ if ( this.stochastic === false ) {
928
+
929
+ viewReflectDir = reflect( viewIncidentDir, viewNormal ).normalize().toVar();
930
+ finalSampleWeight = vec3( metalness );
931
+ specDominantFactor = float( 1 );
932
+
933
+ } else {
934
+
935
+ const Xi = noise.toVar();
936
+ // Mirror-bias: pull `Xi.y` toward the cap top to tighten the GGX lobe and cut mid-roughness
937
+ // noise. Unbiased — bounded VNDF keeps brdf·cos/pdf ~constant (EA, "Stochastic SSR").
938
+ Xi.y.assign( mix( Xi.y, 0.0, this.mirrorBias.mul( Xi.w.sqrt() ) ) );
939
+
940
+ albedo.assign( ( this.diffuseNode !== null ? this.diffuseNode.sample( uvPos ).rgb : vec3( 1 ) ) );
941
+ const ggxSample = ggxReflectionSample( viewNormal, V, roughness, metalness, albedo, Xi ).toVar();
942
+
943
+ // Sometimes the GGX sample is facing away from the surface, so we need to re-sample.
944
+ If( ggxSample.get( 'reflectDir' ).dot( viewNormal ).lessThan( 0 ), () => {
945
+
946
+ ggxSample.assign( ggxReflectionSample( viewNormal, V, roughness, metalness, albedo, Xi.add( Xi.mul( 7 ) ).fract() ) );
947
+
948
+ } );
949
+
950
+ viewReflectDir = ggxSample.get( 'reflectDir' ).toVar();
951
+ finalSampleWeight = ggxSample.get( 'sampleWeight' ).toVar();
952
+ specDominantFactor = getSpecularDominantFactor( ggxSample.get( 'NdotV' ), roughness ).toVar();
953
+
954
+ sampleEnvReflection = () => {
955
+
956
+ const envColor = vec3( 0 ).toVar();
957
+
958
+ if ( this.envImportanceSampling ) {
959
+
960
+ const Xi2 = bindAnalyticNoise( this._resolution, 59 )( uvPos, this._noiseIndex );
961
+
962
+ envColor.assign( this._importanceEnvironment.sampleEnvironmentMIS( {
963
+ cameraWorldMatrix: this._cameraWorldMatrix,
964
+ viewReflectDir,
965
+ N: viewNormal,
966
+ V,
967
+ alpha: ggxSample.get( 'alpha' ),
968
+ f0: ggxSample.get( 'f0' ),
969
+ Xi2
970
+ } ) );
971
+
972
+ } else {
973
+
974
+ envColor.assign( this._importanceEnvironment.sampleEnvironmentBRDF( {
975
+ cameraWorldMatrix: this._cameraWorldMatrix,
976
+ viewReflectDir,
977
+ N: viewNormal,
978
+ V,
979
+ alpha: ggxSample.get( 'alpha' ),
980
+ f0: ggxSample.get( 'f0' )
981
+ } ) );
982
+
983
+ }
984
+
985
+ return envColor;
986
+
987
+ };
988
+
989
+ }
990
+
991
+ // Multi-bounce: fold in the previous frame's reflection at the hit point, reprojected by its
992
+ // own motion. The (1 - history.a) decay damps the feedback. No-op until both textures are set.
993
+ const reprojectHitPointHistory = ( uvHit, color ) => {
994
+
995
+ if ( ! ( this.historyTexture && this.velocityTexture ) ) return color;
996
+
997
+ const velocity = this.velocityTexture.sample( uvHit ).xy;
998
+ const historyUV = uvHit.sub( velocity );
999
+ const historyBounce = texture( this.historyTexture, historyUV ).toVar();
1000
+ const sampleDecay = historyBounce.a.oneMinus();
1001
+
1002
+ return color.add( historyBounce.rgb.mul( sampleDecay ) );
1003
+
1004
+ };
1005
+
1006
+ // Fades a screen-space hit near the screen borders, using the hit sample UV (where the
1007
+ // screen-space data was read). `screenEdgeFadeBlack` is baked, so the two modes branch in
1008
+ // JS: fade the reflection to black, or blend it toward the environment reflection.
1009
+ const applyHitEdgeFade = ( reflectColor, uvS, hitBorderWidth ) => {
1010
+
1011
+ if ( this.screenEdgeFadeBlack ) {
1012
+
1013
+ const hitBorderFactor = computeScreenBorderFactor( uvS, this.screenEdgeFade );
1014
+ reflectColor.rgb.mulAssign( hitBorderFactor );
1015
+
1016
+ } else {
1017
+
1018
+ const hitBorderFactor = computeScreenBorderFactor( uvS, hitBorderWidth );
1019
+
1020
+ If( hitBorderFactor.lessThan( 1 ), () => {
1021
+
1022
+ reflectColor.rgb.assign( mix( sampleEnvReflection().mul( this.environmentIntensity ), reflectColor.rgb, hitBorderFactor ) );
1023
+
1024
+ } );
1025
+
1026
+ }
1027
+
1028
+ };
461
1029
 
462
- // adapt maximum distance to the local geometry (see https://www.mathsisfun.com/algebra/vectors-dot-product.html)
463
1030
  const maxReflectRayLen = this.maxDistance.div( dot( viewIncidentDir.negate(), viewNormal ) ).toVar();
464
1031
 
465
- // compute the maximum point of the reflection ray in view space
466
1032
  const d1viewPosition = viewPosition.add( viewReflectDir.mul( maxReflectRayLen ) ).toVar();
467
1033
 
468
- // check if d1viewPosition lies behind the camera near plane
469
- If( this._isPerspectiveCamera.and( d1viewPosition.z.greaterThan( this._cameraNear.negate() ) ), () => {
1034
+ // Camera type is fixed at build time, so guard the near-plane clamp with a JS branch
1035
+ // rather than a runtime uniform (the orthographic case compiles it out entirely).
1036
+ if ( this.camera.isPerspectiveCamera ) {
470
1037
 
471
- // if so, ensure d1viewPosition is clamped on the near plane.
472
- // this prevents artifacts during the ray marching process
473
- const t = sub( this._cameraNear.negate(), viewPosition.z ).div( viewReflectDir.z );
474
- d1viewPosition.assign( viewPosition.add( viewReflectDir.mul( t ) ) );
1038
+ If( d1viewPosition.z.greaterThan( this._cameraNear.negate() ), () => {
475
1039
 
476
- } );
1040
+ const t = sub( this._cameraNear.negate(), viewPosition.z ).div( viewReflectDir.z );
1041
+ d1viewPosition.assign( viewPosition.add( viewReflectDir.mul( t ) ) );
477
1042
 
478
- // d0 and d1 are the start and maximum points of the reflection ray in screen space
479
- const d0 = screenCoordinate.xy.toVar();
480
- const d1 = getScreenPosition( d1viewPosition, this._cameraProjectionMatrix ).mul( this._resolution ).toVar();
1043
+ } );
481
1044
 
482
- // below variables are used to control the raymarching process
1045
+ }
483
1046
 
484
- // total length of the ray
485
- const totalLen = d1.sub( d0 ).length().toVar();
1047
+ const d0 = uvPos.mul( this._resolution ).xy.toVar();
1048
+ const d1 = getScreenPosition( d1viewPosition, this._cameraProjectionMatrix ).mul( this._resolution ).toVar();
486
1049
 
487
- // offset in x and y direction
488
1050
  const xLen = d1.x.sub( d0.x ).toVar();
489
1051
  const yLen = d1.y.sub( d0.y ).toVar();
490
1052
 
491
- // determine the larger delta
492
- // The larger difference will help to determine how much to travel in the X and Y direction each iteration and
493
- // how many iterations are needed to travel the entire ray
494
- const totalStep = int( max( abs( xLen ), abs( yLen ) ).mul( this.quality.clamp() ) ).toConst();
1053
+ // dominant-axis ray length in texels (used for the per-step floor below)
1054
+ const rayLen = max( xLen.abs(), yLen.abs() ).max( 1 ).toVar();
1055
+
1056
+ // Blur traces a single mirror ray, so spend steps in proportion to the ray's screen-space
1057
+ // length (cheap for the short rays that dominate). Scatter needs a fixed, bounded count for
1058
+ // coherent stochastic sampling; each step then spans the whole ray as rayVec / totalStep.
1059
+ const totalStep = int( this.stochastic === false
1060
+ ? trunc( max( abs( xLen ), abs( yLen ) ).mul( this.quality.clamp() ) ).max( int( 1 ) ).toConst()
1061
+ : this.quality.clamp().mul( MAX_STEPS ).max( float( 1 ) ) ).toConst();
495
1062
 
496
- // step sizes in the x and y directions
497
1063
  const xSpan = xLen.div( totalStep ).toVar();
498
1064
  const ySpan = yLen.div( totalStep ).toVar();
499
1065
 
500
- const output = vec4( 0 ).toVar();
501
-
502
- // the actual ray marching loop
503
- // starting from d0, the code gradually travels along the ray and looks for an intersection with the geometry.
504
- // it does not exceed d1 (the maximum ray extend)
505
- Loop( totalStep, ( { i } ) => {
1066
+ const stepVec = vec2( xSpan, ySpan ).toVar();
1067
+ const invResolution = vec2( float( 1 ), float( 1 ) ).div( this._resolution ).toVar();
1068
+ const uvPixelStepX = vec2( invResolution.x, float( 0 ) ).toVar();
506
1069
 
507
- // advance on the ray by computing a new position in screen coordinates
508
- const xy = vec2( d0.x.add( xSpan.mul( float( i ) ) ), d0.y.add( ySpan.mul( float( i ) ) ) ).toVar();
1070
+ const output = vec4( 0 ).toVar();
1071
+ const hit = float( 0 ).toVar();
1072
+
1073
+ // Reflected-ray view-space Z at ray parameter s ∈ [0,1] (linear in 1/z for perspective),
1074
+ // hoisted so the march and refinement evaluate it identically.
1075
+ const recipVPZ = float( 1 ).div( viewPosition.z ).toConst();
1076
+ const recipD1VPZ = float( 1 ).div( d1viewPosition.z ).toConst();
1077
+
1078
+ // Camera type is known at build time, so branch at compile time rather than via a runtime select.
1079
+ const reflectRayZAt = this.camera.isPerspectiveCamera
1080
+ ? ( sVal ) => float( 1 ).div( recipVPZ.add( sVal.mul( recipD1VPZ.sub( recipVPZ ) ) ) )
1081
+ : ( sVal ) => viewPosition.z.add( sVal.mul( d1viewPosition.z.sub( viewPosition.z ) ) );
1082
+
1083
+ // Screen-space position along the ray for a given s ∈ [0,1].
1084
+ const screenPosAt = ( sVal ) => d0.add( stepVec.mul( sVal.mul( totalStep ) ) );
1085
+
1086
+ // Ray parameter s ∈ [0,1] for step `idx`. Blur marches uniformly (matching the original loop:
1087
+ // one ~texel step per iteration). Scatter uses an exponential remap `(idx/steps)^stepExponent`
1088
+ // that concentrates samples near the origin, floored to ≥1 texel/step; `jitter` dissolves banding.
1089
+ const sampleFraction = this.stochastic === false
1090
+ ? ( idx ) => idx.div( totalStep )
1091
+ : ( idx ) => max(
1092
+ idx.add( noise.z.sub( 0.5 ) ).div( totalStep ).pow( this.stepExponent ),
1093
+ idx.div( rayLen )
1094
+ );
1095
+
1096
+ // Carry the hit out of the loop so refinement runs after the march, not nested inside it (a
1097
+ // loop-inside-a-loop tripped shader-compiler bugs on some drivers). hitSLo/hitSHi bracket s.
1098
+ const foundHit = bool( false ).toVar();
1099
+ const hitSLo = float( 0 ).toVar();
1100
+ const hitSHi = float( 0 ).toVar();
1101
+ // Carry the coarse hit's UV/depth to skip a redundant fetch when refinement is off.
1102
+ const hitUvS = vec2( 0 ).toVar();
1103
+ const hitD = float( 0 ).toVar();
1104
+
1105
+ // March from d0 toward d1, looking for an intersection with the depth buffer.
1106
+ Loop( { start: int( 1 ), end: totalStep }, ( { i } ) => {
1107
+
1108
+ // Exponentially-distributed ray parameter, shared by the sample position and ray depth.
1109
+ const s = sampleFraction( float( i ) ).toVar();
1110
+
1111
+ const xy = screenPosAt( s ).toVar();
509
1112
 
510
- // stop processing if the new position lies outside of the screen
511
1113
  If( xy.x.lessThan( 0 ).or( xy.x.greaterThan( this._resolution.x ) ).or( xy.y.lessThan( 0 ) ).or( xy.y.greaterThan( this._resolution.y ) ), () => {
512
1114
 
513
1115
  Break();
514
1116
 
515
1117
  } );
516
1118
 
517
- // compute new uv, depth and viewZ for the next fragment
518
- const uvNode = xy.div( this._resolution );
519
- const d = sampleDepth( uvNode ).toVar();
1119
+ const uvS = xy.mul( invResolution ).toVar();
1120
+ const d = sampleDepth( uvS ).toVar();
520
1121
  const vZ = getViewZ( d ).toVar();
521
1122
 
522
- const viewReflectRayZ = float( 0 ).toVar();
1123
+ const viewReflectRayZ = reflectRayZAt( s ).toVar();
1124
+
1125
+ If( viewReflectRayZ.lessThanEqual( vZ ), () => {
1126
+
1127
+ // Depth crossing: ray went behind the depth buffer. Gate by thickness before stopping
1128
+ // so an occluder gap doesn't end the march prematurely.
1129
+ const vP = getViewPosition( uvS, d, this._cameraProjectionMatrixInverse ).toVar();
1130
+ const away = pointToLineDistance( vP, viewPosition, d1viewPosition ).toVar();
1131
+
1132
+ const uvNeighbor = uvS.add( uvPixelStepX ).toVar();
1133
+ const vPNeighbor = getViewPosition( uvNeighbor, d, this._cameraProjectionMatrixInverse ).toVar();
1134
+ const minThickness = vPNeighbor.x.sub( vP.x ).mul( 3 ).toVar();
1135
+ const tk = max( minThickness, this.thickness ).toVar();
1136
+
1137
+ If( away.lessThanEqual( tk ), () => {
1138
+
1139
+ const vN = this.normalNode.sample( uvS ).rgb.normalize().toVar();
1140
+
1141
+ // the reflected ray is pointing towards the same side as the fragment's normal (current ray position),
1142
+ // which means it wouldn't reflect off the surface. The loop continues to the next step for the next ray sample.
1143
+ if ( this.stochastic === false ) {
1144
+
1145
+ If( dot( viewReflectDir, vN ).greaterThanEqual( 0 ), () => {
1146
+
1147
+ Continue();
1148
+
1149
+ } );
1150
+
1151
+ // this distance represents the depth of the intersection point between the reflected ray and the scene.
1152
+ const distance = pointPlaneDistance( vP, viewPosition, viewNormal ).toVar();
1153
+
1154
+ // Distance exceeding limit: The reflection is potentially too far away and
1155
+ // might not contribute significantly to the final color
1156
+ If( distance.greaterThan( this.maxDistance ), () => {
1157
+
1158
+ Break();
1159
+
1160
+ } );
1161
+
1162
+ }
1163
+
1164
+ foundHit.assign( true );
1165
+ hitUvS.assign( uvS );
1166
+ hitD.assign( d );
523
1167
 
524
- // normalized distance between the current position xy and the starting point d0
525
- const s = xy.sub( d0 ).length().div( totalLen );
1168
+ if ( this.binaryRefine ) {
526
1169
 
527
- // depending on the camera type, we now compute the z-coordinate of the reflected ray at the current step in view space
528
- If( this._isPerspectiveCamera, () => {
1170
+ hitSLo.assign( sampleFraction( float( i ).sub( 1 ) ) );
1171
+ hitSHi.assign( s );
529
1172
 
530
- const recipVPZ = float( 1 ).div( viewPosition.z ).toVar();
531
- viewReflectRayZ.assign( float( 1 ).div( recipVPZ.add( s.mul( float( 1 ).div( d1viewPosition.z ).sub( recipVPZ ) ) ) ) );
1173
+ }
1174
+
1175
+ Break();
532
1176
 
533
- } ).Else( () => {
534
1177
 
535
- viewReflectRayZ.assign( viewPosition.z.add( s.mul( d1viewPosition.z.sub( viewPosition.z ) ) ) );
1178
+ } );
536
1179
 
537
1180
  } );
538
1181
 
539
- // if viewReflectRayZ is less or equal than the real z-coordinate at this place, it potentially intersects the geometry
540
- If( viewReflectRayZ.lessThanEqual( vZ ), () => {
1182
+ } );
541
1183
 
542
- // compute the distance of the new location to the ray in view space
543
- // to clarify vP is the fragment's view position which is not an exact point on the ray
544
- const vP = getViewPosition( uvNode, d, this._cameraProjectionMatrixInverse ).toVar();
545
- const away = pointToLineDistance( vP, viewPosition, d1viewPosition ).toVar();
1184
+ If( foundHit, () => {
546
1185
 
547
- // compute the minimum thickness between the current fragment and its neighbor in the x-direction.
548
- const xyNeighbor = vec2( xy.x.add( 1 ), xy.y ).toVar(); // move one pixel
549
- const uvNeighbor = xyNeighbor.div( this._resolution );
550
- const vPNeighbor = getViewPosition( uvNeighbor, d, this._cameraProjectionMatrixInverse ).toVar();
551
- const minThickness = vPNeighbor.x.sub( vP.x ).toVar();
552
- minThickness.mulAssign( 3 ); // expand a bit to avoid errors
1186
+ // Bisect the bracketed crossing toward the exact intersection. Run after the march, not
1187
+ // nested (a loop-inside-a-loop tripped shader-compiler bugs on some drivers).
1188
+ if ( this.binaryRefine ) {
553
1189
 
554
- const tk = max( minThickness, this.thickness ).toVar();
1190
+ Loop( { start: int( 0 ), end: int( 8 ), type: 'int', condition: '<' }, () => {
1191
+
1192
+ const sMid = hitSLo.add( hitSHi ).mul( 0.5 ).toVar();
1193
+ const sceneZMid = getViewZ( sampleDepth( screenPosAt( sMid ).mul( invResolution ) ) );
555
1194
 
556
- If( away.lessThanEqual( tk ), () => { // hit
1195
+ If( reflectRayZAt( sMid ).lessThanEqual( sceneZMid ), () => {
557
1196
 
558
- const vN = this.normalNode.sample( uvNode ).rgb.normalize().toVar();
1197
+ hitSHi.assign( sMid );
559
1198
 
560
- If( dot( viewReflectDir, vN ).greaterThanEqual( 0 ), () => {
1199
+ } ).Else( () => {
561
1200
 
562
- // the reflected ray is pointing towards the same side as the fragment's normal (current ray position),
563
- // which means it wouldn't reflect off the surface. The loop continues to the next step for the next ray sample.
564
- Continue();
1201
+ hitSLo.assign( sMid );
565
1202
 
566
1203
  } );
567
1204
 
568
- // this distance represents the depth of the intersection point between the reflected ray and the scene.
569
- const distance = pointPlaneDistance( vP, viewPosition, viewNormal ).toVar();
1205
+ } );
570
1206
 
571
- If( distance.greaterThan( this.maxDistance ), () => {
1207
+ // Refinement moved the crossing, so re-fetch UV/depth at the refined `s`.
1208
+ hitUvS.assign( screenPosAt( hitSHi ).mul( invResolution ) );
1209
+ hitD.assign( sampleDepth( hitUvS ) );
572
1210
 
573
- // Distance exceeding limit: The reflection is potentially too far away and
574
- // might not contribute significantly to the final color
575
- Break();
1211
+ }
576
1212
 
577
- } );
1213
+ // Shade the hit, reusing the depth fetched during the march (or refinement).
1214
+ const uvS = hitUvS;
1215
+ const vP = getViewPosition( uvS, hitD, this._cameraProjectionMatrixInverse ).toVar();
578
1216
 
579
- const op = this.opacity.mul( metalness ).toVar();
1217
+ // In blur mode the ratio² falloff re-grows past maxDistance, so over-range hits fall back
1218
+ // to env. The scatter path bounds reach via ray length, so every hit shades.
1219
+ const distancePointPlane = this.stochastic === false ? pointPlaneDistance( vP, viewPosition, viewNormal ).toVar() : float( 0 );
1220
+ const withinRange = distancePointPlane.lessThanEqual( this.maxDistance );
580
1221
 
581
- // distance attenuation (the reflection should fade out the farther it is away from the surface)
582
- const ratio = float( 1 ).sub( distance.div( this.maxDistance ) ).toVar();
583
- const attenuation = ratio.mul( ratio );
584
- op.mulAssign( attenuation );
1222
+ If( withinRange, () => {
585
1223
 
586
- // fresnel (reflect more light on surfaces that are viewed at grazing angles)
587
- const fresnelCoe = div( dot( viewIncidentDir, viewReflectDir ).add( 1 ), 2 );
588
- op.mulAssign( fresnelCoe );
1224
+ const hitWorldPosition = this._cameraWorldMatrix.mul( vec4( vP, 1.0 ) ).xyz.toVar();
1225
+ const worldDistance = distance( worldPosition, hitWorldPosition ).mul( specDominantFactor ).toVar();
589
1226
 
590
- // output
591
- const reflectColor = this.colorNode.sample( uvNode );
592
- output.assign( vec4( reflectColor.rgb, op ) );
593
- Break();
1227
+ const reflectColor = this.colorNode.sample( uvS ).toVar();
594
1228
 
595
- } );
1229
+ // Multi-bounce: add the reprojected previous-frame reflection at the hit point.
1230
+ reflectColor.rgb.assign( reprojectHitPointHistory( uvS, reflectColor.rgb ) );
1231
+
1232
+ if ( this.stochastic === true ) applyHitEdgeFade( reflectColor, uvS, hitBorderWidth );
1233
+
1234
+ // The scatter (GGX) path bakes distance/grazing response into finalSampleWeight.
1235
+ // The mirror/blur path is a plain reflection, so reapply upstream's squared
1236
+ // distance attenuation and grazing Fresnel here to match its falloff.
1237
+ let weightedColor = reflectColor.rgb.mul( finalSampleWeight );
1238
+
1239
+ if ( this.stochastic === false ) {
1240
+
1241
+ const ratio = float( 1 ).sub( distancePointPlane.div( this.maxDistance ) ).toVar();
1242
+ const attenuation = ratio.mul( ratio ).toVar();
1243
+ const fresnelCoe = div( dot( viewIncidentDir, viewReflectDir ).add( 1 ), 2 ).toVar();
1244
+ weightedColor = weightedColor.mul( attenuation.mul( fresnelCoe ) );
1245
+
1246
+ }
1247
+
1248
+ hit.assign( 1 );
1249
+ output.assign( vec4( weightedColor, worldDistance ) );
596
1250
 
597
1251
  } );
598
1252
 
599
1253
  } );
600
1254
 
601
- return output;
1255
+ // Screen-space ray missed: environment fallback (MIS when CDF env is set up).
1256
+ If( hit.equal( 0 ), () => {
1257
+
1258
+ if ( this.stochastic === true ) {
1259
+
1260
+ output.assign( vec4( sampleEnvReflection().mul( this.environmentIntensity ), float( ENV_RAY_LENGTH ) ) );
1261
+
1262
+ // Misses fade by the surface pixel UV (where the reflection is being shaded).
1263
+ if ( this.screenEdgeFadeBlack ) {
1264
+
1265
+ output.rgb.mulAssign( surfaceBorderFactor );
1266
+
1267
+ }
1268
+
1269
+ }
1270
+
1271
+ } );
1272
+
1273
+ const lum = luminance( output.rgb ).max( 1e-4 ).toVar();
1274
+ output.rgb.mulAssign( this.maxLuminance.div( lum ).min( 1 ) );
1275
+
1276
+ // scale the reflection color by the user-controlled intensity
1277
+ output.rgb.mulAssign( this.intensity );
1278
+
1279
+ return output.max( 0 );
602
1280
 
603
1281
  } );
604
1282
 
605
- this._ssrMaterial.fragmentNode = ssr().context( builder.getSharedContext() );
606
- this._ssrMaterial.needsUpdate = true;
607
1283
 
608
- // below materials are used for blurring
1284
+ this._ssrFn = ssr;
1285
+ this._sharedContext = builder.getSharedContext();
1286
+ this._buildSSRMaterial();
609
1287
 
610
1288
  const reflectionBuffer = texture( this._ssrRenderTarget.texture );
611
1289
 
612
- this._blurMaterial.fragmentNode = boxBlur( reflectionBuffer, { size: this.blurQuality, separation: this._blurSpread } );
613
- this._blurMaterial.needsUpdate = true;
1290
+ if ( this.stochastic === false ) {
1291
+
1292
+ this._buildBlurMaterial();
1293
+
1294
+ }
614
1295
 
615
1296
  this._copyMaterial.fragmentNode = reflectionBuffer;
616
1297
  this._copyMaterial.needsUpdate = true;
@@ -621,6 +1302,12 @@ class SSRNode extends TempNode {
621
1302
 
622
1303
  }
623
1304
 
1305
+ getRenderTarget() {
1306
+
1307
+ return this._ssrRenderTarget;
1308
+
1309
+ }
1310
+
624
1311
  /**
625
1312
  * Frees internal resources. This method should be called
626
1313
  * when the effect is no longer required.
@@ -634,6 +1321,13 @@ class SSRNode extends TempNode {
634
1321
  this._blurMaterial.dispose();
635
1322
  this._copyMaterial.dispose();
636
1323
 
1324
+ if ( this._importanceEnvironment !== null ) {
1325
+
1326
+ this._importanceEnvironment.dispose();
1327
+ this._importanceEnvironment = null;
1328
+
1329
+ }
1330
+
637
1331
  }
638
1332
 
639
1333
  }
@@ -648,9 +1342,12 @@ export default SSRNode;
648
1342
  * @param {Node<vec4>} colorNode - The node that represents the beauty pass.
649
1343
  * @param {Node<float>} depthNode - A node that represents the beauty pass's depth.
650
1344
  * @param {Node<vec3>} normalNode - A node that represents the beauty pass's normals.
651
- * @param {Node<float>} metalnessNode - A node that represents the beauty pass's metalness.
652
- * @param {?Node<float>} [roughnessNode=null] - A node that represents the beauty pass's roughness.
653
- * @param {?Camera} [camera=null] - The camera the scene is rendered with.
1345
+ * @param {SSRNodeOptions} [options] - Optional inputs for material and environment data.
654
1346
  * @returns {SSRNode}
655
1347
  */
656
- export const ssr = ( colorNode, depthNode, normalNode, metalnessNode, roughnessNode = null, camera = null ) => nodeObject( new SSRNode( nodeObject( colorNode ), nodeObject( depthNode ), nodeObject( normalNode ), nodeObject( metalnessNode ), nodeObject( roughnessNode ), camera ) );
1348
+ export const ssr = ( colorNode, depthNode, normalNode, options = {} ) => nodeObject( new SSRNode(
1349
+ nodeObject( colorNode ),
1350
+ nodeObject( depthNode ),
1351
+ nodeObject( normalNode ),
1352
+ options
1353
+ ) );