super-three 0.184.0 → 0.185.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. package/build/three.cjs +1260 -927
  2. package/build/three.core.js +1104 -829
  3. package/build/three.core.min.js +1 -1
  4. package/build/three.module.js +156 -98
  5. package/build/three.module.min.js +1 -1
  6. package/build/three.tsl.js +11 -4
  7. package/build/three.tsl.min.js +1 -1
  8. package/build/three.webgpu.js +7538 -3367
  9. package/build/three.webgpu.min.js +1 -1
  10. package/build/three.webgpu.nodes.js +7538 -3366
  11. package/build/three.webgpu.nodes.min.js +1 -1
  12. package/examples/jsm/Addons.js +3 -0
  13. package/examples/jsm/controls/ArcballControls.js +6 -2
  14. package/examples/jsm/controls/FirstPersonControls.js +79 -42
  15. package/examples/jsm/controls/TransformControls.js +68 -15
  16. package/examples/jsm/csm/CSMFrustum.js +31 -6
  17. package/examples/jsm/csm/CSMShadowNode.js +4 -1
  18. package/examples/jsm/effects/AsciiEffect.js +14 -1
  19. package/examples/jsm/exporters/DRACOExporter.js +27 -6
  20. package/examples/jsm/exporters/GLTFExporter.js +114 -12
  21. package/examples/jsm/exporters/PLYExporter.js +286 -73
  22. package/examples/jsm/exporters/USDZExporter.js +347 -112
  23. package/examples/jsm/generators/CityGenerator.js +346 -0
  24. package/examples/jsm/generators/ForestGenerator.js +347 -0
  25. package/examples/jsm/generators/TerrainGenerator.js +504 -0
  26. package/examples/jsm/generators/TreeGenerator.js +377 -0
  27. package/examples/jsm/generators/city/SidewalkGenerator.js +253 -0
  28. package/examples/jsm/generators/city/SkyscraperGenerator.js +1357 -0
  29. package/examples/jsm/geometries/LoftGeometry.js +355 -0
  30. package/examples/jsm/helpers/LightProbeGridHelper.js +1 -1
  31. package/examples/jsm/helpers/LightProbeHelper.js +5 -4
  32. package/examples/jsm/helpers/ViewHelper.js +16 -6
  33. package/examples/jsm/inspector/Inspector.js +53 -15
  34. package/examples/jsm/inspector/RendererInspector.js +152 -36
  35. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js +1 -1
  36. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphLoader.js +1 -1
  37. package/examples/jsm/inspector/tabs/Console.js +200 -18
  38. package/examples/jsm/inspector/tabs/Memory.js +8 -0
  39. package/examples/jsm/inspector/tabs/Parameters.js +64 -4
  40. package/examples/jsm/inspector/tabs/Performance.js +21 -6
  41. package/examples/jsm/inspector/tabs/Settings.js +51 -9
  42. package/examples/jsm/inspector/tabs/Timeline.js +178 -93
  43. package/examples/jsm/inspector/tabs/Viewer.js +628 -16
  44. package/examples/jsm/inspector/ui/Graph.js +162 -25
  45. package/examples/jsm/inspector/ui/Item.js +92 -13
  46. package/examples/jsm/inspector/ui/List.js +1 -1
  47. package/examples/jsm/inspector/ui/Profiler.js +90 -45
  48. package/examples/jsm/inspector/ui/Style.js +1788 -1401
  49. package/examples/jsm/inspector/ui/Tab.js +5 -3
  50. package/examples/jsm/inspector/ui/Values.js +71 -6
  51. package/examples/jsm/inspector/ui/utils.js +130 -10
  52. package/examples/jsm/libs/basis/README.md +0 -1
  53. package/examples/jsm/libs/demuxer_mp4.js +3 -3
  54. package/examples/jsm/libs/draco/README.md +0 -1
  55. package/examples/jsm/libs/meshopt_clusterizer.module.js +421 -0
  56. package/examples/jsm/libs/meshopt_simplifier.module.js +627 -0
  57. package/examples/jsm/libs/mikktspace.module.js +34 -9
  58. package/examples/jsm/lighting/ClusteredLighting.js +55 -0
  59. package/examples/jsm/lighting/LightProbeGrid.js +106 -76
  60. package/examples/jsm/lines/LineMaterial.js +38 -15
  61. package/examples/jsm/lines/LineSegments2.js +8 -0
  62. package/examples/jsm/lines/webgpu/LineSegments2.js +8 -0
  63. package/examples/jsm/loaders/3DMLoader.js +1 -1
  64. package/examples/jsm/loaders/DRACOLoader.js +46 -13
  65. package/examples/jsm/loaders/EXRLoader.js +27 -55
  66. package/examples/jsm/loaders/HDRLoader.js +6 -28
  67. package/examples/jsm/loaders/KTX2Loader.js +31 -12
  68. package/examples/jsm/loaders/LDrawLoader.js +8 -8
  69. package/examples/jsm/loaders/LUT3dlLoader.js +2 -2
  70. package/examples/jsm/loaders/LUTCubeLoader.js +2 -2
  71. package/examples/jsm/loaders/LWOLoader.js +4 -0
  72. package/examples/jsm/loaders/LottieLoader.js +1 -1
  73. package/examples/jsm/loaders/MaterialXLoader.js +31 -9
  74. package/examples/jsm/loaders/NRRDLoader.js +3 -3
  75. package/examples/jsm/loaders/PCDLoader.js +7 -7
  76. package/examples/jsm/loaders/PLYLoader.js +218 -55
  77. package/examples/jsm/loaders/SVGLoader.js +547 -495
  78. package/examples/jsm/loaders/TTFLoader.js +1 -1
  79. package/examples/jsm/loaders/USDLoader.js +33 -9
  80. package/examples/jsm/loaders/VRMLLoader.js +1 -1
  81. package/examples/jsm/loaders/usd/USDAParser.js +93 -20
  82. package/examples/jsm/loaders/usd/USDCParser.js +1 -1
  83. package/examples/jsm/loaders/usd/USDComposer.js +52 -19
  84. package/examples/jsm/misc/TileCreasedNormalsPlugin.js +270 -0
  85. package/examples/jsm/misc/Volume.js +2 -2
  86. package/examples/jsm/objects/GroundedSkybox.js +1 -1
  87. package/examples/jsm/objects/Reflector.js +2 -3
  88. package/examples/jsm/objects/Water2Mesh.js +1 -1
  89. package/examples/jsm/physics/AmmoPhysics.js +15 -8
  90. package/examples/jsm/physics/RapierPhysics.js +27 -2
  91. package/examples/jsm/shaders/VolumeShader.js +31 -44
  92. package/examples/jsm/transpiler/GLSLDecoder.js +6 -6
  93. package/examples/jsm/transpiler/Linker.js +1 -1
  94. package/examples/jsm/tsl/display/BloomNode.js +59 -19
  95. package/examples/jsm/tsl/display/DepthOfFieldNode.js +2 -2
  96. package/examples/jsm/tsl/display/FXAANode.js +11 -12
  97. package/examples/jsm/tsl/display/GTAONode.js +34 -13
  98. package/examples/jsm/tsl/display/GodraysNode.js +1 -1
  99. package/examples/jsm/tsl/display/ImportanceSampledEnvironment.js +560 -0
  100. package/examples/jsm/tsl/display/PixelationPassNode.js +2 -2
  101. package/examples/jsm/tsl/display/RecurrentDenoiseNode.js +912 -0
  102. package/examples/jsm/tsl/display/SSAAPassNode.js +13 -25
  103. package/examples/jsm/tsl/display/SSGINode.js +89 -39
  104. package/examples/jsm/tsl/display/SSRNode.js +829 -132
  105. package/examples/jsm/tsl/display/SSSNode.js +2 -2
  106. package/examples/jsm/tsl/display/TemporalReprojectNode.js +1023 -0
  107. package/examples/jsm/tsl/lighting/ClusteredLightsNode.js +622 -0
  108. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +1 -1
  109. package/examples/jsm/tsl/math/curlNoise.js +107 -0
  110. package/examples/jsm/tsl/shadows/TileShadowNode.js +1 -1
  111. package/examples/jsm/tsl/shadows/TileShadowNodeHelper.js +3 -3
  112. package/examples/jsm/tsl/utils/GroundedSkybox.js +62 -0
  113. package/examples/jsm/tsl/utils/RNoise.js +51 -0
  114. package/examples/jsm/tsl/utils/SpecularHelpers.js +325 -0
  115. package/examples/jsm/utils/BufferGeometryUtils.js +126 -59
  116. package/examples/jsm/utils/GeometryCompressionUtils.js +1 -1
  117. package/examples/jsm/utils/SceneOptimizer.js +1 -1
  118. package/examples/jsm/webxr/ARButton.js +1 -1
  119. package/examples/jsm/webxr/WebGLXRFallback.js +89 -0
  120. package/examples/jsm/webxr/XRControllerModelFactory.js +2 -2
  121. package/package.json +7 -7
  122. package/src/Three.TSL.js +10 -3
  123. package/src/Three.WebGPU.js +4 -0
  124. package/src/animation/AnimationAction.js +15 -11
  125. package/src/animation/AnimationClip.js +0 -139
  126. package/src/animation/KeyframeTrack.js +2 -2
  127. package/src/animation/PropertyBinding.js +2 -2
  128. package/src/cameras/Camera.js +2 -2
  129. package/src/cameras/StereoCamera.js +5 -2
  130. package/src/constants.js +1 -1
  131. package/src/core/BufferGeometry.js +29 -7
  132. package/src/core/Object3D.js +17 -7
  133. package/src/core/Raycaster.js +1 -1
  134. package/src/core/RenderTarget.js +15 -2
  135. package/src/extras/PMREMGenerator.js +6 -4
  136. package/src/extras/TextureUtils.js +1 -1
  137. package/src/extras/core/ShapePath.js +149 -160
  138. package/src/geometries/SphereGeometry.js +8 -3
  139. package/src/helpers/DirectionalLightHelper.js +2 -0
  140. package/src/helpers/HemisphereLightHelper.js +2 -0
  141. package/src/helpers/PointLightHelper.js +2 -0
  142. package/src/helpers/SpotLightHelper.js +1 -1
  143. package/src/loaders/DataTextureLoader.js +69 -38
  144. package/src/loaders/LoadingManager.js +5 -0
  145. package/src/loaders/MaterialLoader.js +36 -266
  146. package/src/loaders/ObjectLoader.js +3 -1
  147. package/src/materials/LineBasicMaterial.js +4 -0
  148. package/src/materials/Material.js +196 -1
  149. package/src/materials/MeshBasicMaterial.js +24 -0
  150. package/src/materials/MeshDepthMaterial.js +10 -0
  151. package/src/materials/MeshDistanceMaterial.js +10 -0
  152. package/src/materials/MeshLambertMaterial.js +40 -1
  153. package/src/materials/MeshMatcapMaterial.js +25 -1
  154. package/src/materials/MeshNormalMaterial.js +9 -1
  155. package/src/materials/MeshPhongMaterial.js +40 -1
  156. package/src/materials/MeshPhysicalMaterial.js +38 -0
  157. package/src/materials/MeshStandardMaterial.js +42 -1
  158. package/src/materials/MeshToonMaterial.js +34 -1
  159. package/src/materials/PointsMaterial.js +7 -0
  160. package/src/materials/ShaderMaterial.js +86 -0
  161. package/src/materials/SpriteMaterial.js +7 -0
  162. package/src/materials/nodes/Line2NodeMaterial.js +378 -322
  163. package/src/materials/nodes/MeshBasicNodeMaterial.js +2 -2
  164. package/src/materials/nodes/MeshNormalNodeMaterial.js +2 -2
  165. package/src/materials/nodes/MeshPhongNodeMaterial.js +0 -9
  166. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +0 -30
  167. package/src/materials/nodes/MeshSSSNodeMaterial.js +0 -13
  168. package/src/materials/nodes/MeshStandardNodeMaterial.js +0 -11
  169. package/src/materials/nodes/NodeMaterial.js +115 -71
  170. package/src/materials/nodes/SpriteNodeMaterial.js +0 -10
  171. package/src/materials/nodes/manager/NodeMaterialObserver.js +49 -20
  172. package/src/math/Box3.js +5 -0
  173. package/src/math/FrustumArray.js +103 -133
  174. package/src/math/Interpolant.js +1 -1
  175. package/src/math/MathUtils.js +2 -2
  176. package/src/math/Matrix3.js +11 -0
  177. package/src/math/Matrix4.js +28 -3
  178. package/src/math/Vector2.js +2 -2
  179. package/src/math/Vector3.js +2 -2
  180. package/src/math/Vector4.js +2 -2
  181. package/src/math/interpolants/BezierInterpolant.js +4 -6
  182. package/src/nodes/Nodes.js +2 -5
  183. package/src/nodes/TSL.js +8 -6
  184. package/src/nodes/accessors/Arrays.js +4 -4
  185. package/src/nodes/accessors/Batch.js +108 -0
  186. package/src/nodes/accessors/Bitangent.js +2 -2
  187. package/src/nodes/accessors/BufferAttributeNode.js +13 -2
  188. package/src/nodes/accessors/Camera.js +7 -7
  189. package/src/nodes/accessors/ClippingNode.js +1 -1
  190. package/src/nodes/accessors/Instance.js +264 -0
  191. package/src/nodes/accessors/MaterialNode.js +18 -2
  192. package/src/nodes/accessors/MaterialProperties.js +4 -3
  193. package/src/nodes/accessors/{MorphNode.js → Morph.js} +99 -112
  194. package/src/nodes/accessors/Normal.js +13 -13
  195. package/src/nodes/accessors/Position.js +5 -1
  196. package/src/nodes/accessors/ReferenceNode.js +1 -0
  197. package/src/nodes/accessors/ReflectVector.js +3 -3
  198. package/src/nodes/accessors/SceneProperties.js +1 -1
  199. package/src/nodes/accessors/Skinning.js +263 -0
  200. package/src/nodes/accessors/StorageBufferNode.js +2 -2
  201. package/src/nodes/accessors/StorageTexture3DNode.js +100 -0
  202. package/src/nodes/accessors/StorageTextureNode.js +39 -7
  203. package/src/nodes/accessors/Tangent.js +4 -4
  204. package/src/nodes/accessors/TextureNode.js +60 -5
  205. package/src/nodes/code/FunctionNode.js +2 -16
  206. package/src/nodes/core/MRTNode.js +7 -2
  207. package/src/nodes/core/Node.js +39 -2
  208. package/src/nodes/core/NodeBuilder.js +201 -41
  209. package/src/nodes/core/NodeUtils.js +13 -13
  210. package/src/nodes/core/OutputStructNode.js +1 -1
  211. package/src/nodes/core/OverrideContextNode.js +153 -0
  212. package/src/nodes/core/PropertyNode.js +51 -5
  213. package/src/nodes/core/StackNode.js +56 -34
  214. package/src/nodes/core/StructNode.js +4 -6
  215. package/src/nodes/core/StructTypeNode.js +6 -6
  216. package/src/nodes/core/VarNode.js +8 -0
  217. package/src/nodes/core/VaryingNode.js +12 -2
  218. package/src/nodes/display/BlendModes.js +1 -41
  219. package/src/nodes/display/BumpMapNode.js +6 -1
  220. package/src/nodes/display/ColorAdjustment.js +10 -9
  221. package/src/nodes/display/FrontFacingNode.js +38 -9
  222. package/src/nodes/display/NormalMapNode.js +2 -2
  223. package/src/nodes/display/PassNode.js +35 -43
  224. package/src/nodes/display/PremultiplyAlphaFunctions.js +39 -0
  225. package/src/nodes/display/RenderOutputNode.js +12 -3
  226. package/src/nodes/functions/VolumetricLightingModel.js +40 -7
  227. package/src/nodes/gpgpu/WorkgroupInfoNode.js +1 -1
  228. package/src/nodes/lighting/EnvironmentNode.js +2 -2
  229. package/src/nodes/lighting/IESSpotLightNode.js +40 -2
  230. package/src/nodes/lighting/LightingContextNode.js +10 -2
  231. package/src/nodes/lighting/LightsNode.js +90 -37
  232. package/src/nodes/lighting/PointShadowNode.js +6 -1
  233. package/src/nodes/lighting/ShadowFilterNode.js +21 -52
  234. package/src/nodes/lighting/ShadowNode.js +34 -14
  235. package/src/nodes/materialx/lib/mx_noise.js +2 -2
  236. package/src/nodes/math/ConditionalNode.js +3 -3
  237. package/src/nodes/math/MathNode.js +39 -11
  238. package/src/nodes/math/OperatorNode.js +23 -23
  239. package/src/nodes/parsers/GLSLNodeFunction.js +1 -1
  240. package/src/nodes/pmrem/PMREMNode.js +33 -2
  241. package/src/nodes/tsl/TSLCore.js +63 -18
  242. package/src/nodes/utils/EquirectUV.js +30 -5
  243. package/src/nodes/utils/FunctionOverloadingNode.js +1 -1
  244. package/src/nodes/utils/Packing.js +35 -4
  245. package/src/nodes/utils/RTTNode.js +40 -24
  246. package/src/nodes/utils/ReflectorNode.js +1 -0
  247. package/src/nodes/utils/StorageArrayElementNode.js +1 -1
  248. package/src/objects/BatchedMesh.js +22 -14
  249. package/src/objects/InstancedMesh.js +0 -11
  250. package/src/objects/Skeleton.js +0 -9
  251. package/src/renderers/WebGLRenderer.js +19 -15
  252. package/src/renderers/common/Backend.js +49 -5
  253. package/src/renderers/common/Bindings.js +114 -45
  254. package/src/renderers/common/Buffer.js +9 -0
  255. package/src/renderers/common/ClippingContext.js +10 -2
  256. package/src/renderers/common/Info.js +63 -22
  257. package/src/renderers/common/Lighting.js +53 -5
  258. package/src/renderers/common/RenderList.js +41 -4
  259. package/src/renderers/common/RenderObject.js +73 -13
  260. package/src/renderers/common/Renderer.js +281 -108
  261. package/src/renderers/common/Sampler.js +16 -48
  262. package/src/renderers/common/Textures.js +32 -5
  263. package/src/renderers/common/TimestampQueryPool.js +1 -1
  264. package/src/renderers/common/UniformsGroup.js +31 -9
  265. package/src/renderers/common/XRManager.js +340 -22
  266. package/src/renderers/common/extras/PMREMGenerator.js +15 -38
  267. package/src/renderers/common/nodes/NodeBuilderState.js +9 -1
  268. package/src/renderers/common/nodes/NodeLibrary.js +4 -4
  269. package/src/renderers/common/nodes/NodeManager.js +63 -14
  270. package/src/renderers/common/nodes/NodeUniformBuffer.js +13 -0
  271. package/src/renderers/shaders/ShaderChunk/common.glsl.js +13 -4
  272. package/src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js +0 -6
  273. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +1 -1
  274. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +2 -2
  275. package/src/renderers/shaders/ShaderChunk/envmap_vertex.glsl.js +1 -1
  276. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +1 -1
  277. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +1 -1
  278. package/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js +2 -2
  279. package/src/renderers/shaders/ShaderChunk/normal_vertex.glsl.js +6 -0
  280. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +1 -1
  281. package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +1 -1
  282. package/src/renderers/shaders/ShaderLib/distance.glsl.js +1 -1
  283. package/src/renderers/webgl/WebGLOutput.js +2 -1
  284. package/src/renderers/webgl/WebGLProgram.js +5 -4
  285. package/src/renderers/webgl/WebGLPrograms.js +12 -5
  286. package/src/renderers/webgl/WebGLRenderLists.js +9 -1
  287. package/src/renderers/webgl/WebGLShaderCache.js +5 -11
  288. package/src/renderers/webgl/WebGLTextures.js +20 -7
  289. package/src/renderers/webgl/WebGLUniformsGroups.js +66 -38
  290. package/src/renderers/webgl-fallback/WebGLBackend.js +84 -25
  291. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +138 -8
  292. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +1 -1
  293. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +52 -22
  294. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +4 -2
  295. package/src/renderers/webgpu/WebGPUBackend.js +480 -169
  296. package/src/renderers/webgpu/descriptors/GPUBindGroupDescriptor.js +48 -0
  297. package/src/renderers/webgpu/descriptors/GPUBufferDescriptor.js +57 -0
  298. package/src/renderers/webgpu/descriptors/GPUCommandEncoderDescriptor.js +30 -0
  299. package/src/renderers/webgpu/descriptors/GPUComputePassDescriptor.js +38 -0
  300. package/src/renderers/webgpu/descriptors/GPUComputePipelineDescriptor.js +48 -0
  301. package/src/renderers/webgpu/descriptors/GPUCopyExternalImageDestInfo.js +47 -0
  302. package/src/renderers/webgpu/descriptors/GPUCopyExternalImageSourceInfo.js +50 -0
  303. package/src/renderers/webgpu/descriptors/GPUExtent3D.js +51 -0
  304. package/src/renderers/webgpu/descriptors/GPUPipelineLayoutDescriptor.js +39 -0
  305. package/src/renderers/webgpu/descriptors/GPUQuerySetDescriptor.js +47 -0
  306. package/src/renderers/webgpu/descriptors/GPURenderBundleEncoderDescriptor.js +74 -0
  307. package/src/renderers/webgpu/descriptors/GPURenderPassColorAttachment.js +72 -0
  308. package/src/renderers/webgpu/descriptors/GPURenderPassDepthStencilAttachment.js +99 -0
  309. package/src/renderers/webgpu/descriptors/GPURenderPassDescriptor.js +72 -0
  310. package/src/renderers/webgpu/descriptors/GPURenderPassTimestampWrites.js +49 -0
  311. package/src/renderers/webgpu/descriptors/GPURenderPipelineDescriptor.js +130 -0
  312. package/src/renderers/webgpu/descriptors/GPUSamplerDescriptor.js +119 -0
  313. package/src/renderers/webgpu/descriptors/GPUShaderModuleDescriptor.js +46 -0
  314. package/src/renderers/webgpu/descriptors/GPUTexelCopyBufferInfo.js +57 -0
  315. package/src/renderers/webgpu/descriptors/GPUTexelCopyBufferLayout.js +48 -0
  316. package/src/renderers/webgpu/descriptors/GPUTexelCopyTextureInfo.js +61 -0
  317. package/src/renderers/webgpu/descriptors/GPUTextureDescriptor.js +99 -0
  318. package/src/renderers/webgpu/descriptors/GPUTextureViewDescriptor.js +108 -0
  319. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +0 -1
  320. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +164 -7
  321. package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +1 -1
  322. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +98 -38
  323. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +72 -68
  324. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +164 -69
  325. package/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js +158 -95
  326. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +297 -141
  327. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +33 -18
  328. package/src/renderers/webgpu/utils/WebGPUUtils.js +38 -3
  329. package/src/textures/DepthTexture.js +1 -1
  330. package/src/textures/ExternalTexture.js +0 -3
  331. package/examples/fonts/LICENSE +0 -13
  332. package/examples/fonts/MPLUSRounded1c/MPLUSRounded1c-Regular.typeface.json.zip +0 -0
  333. package/examples/fonts/MPLUSRounded1c/OFL.txt +0 -91
  334. package/examples/fonts/README.md +0 -11
  335. package/examples/fonts/droid/NOTICE +0 -190
  336. package/examples/fonts/droid/README.txt +0 -18
  337. package/examples/fonts/droid/droid_sans_bold.typeface.json +0 -1
  338. package/examples/fonts/droid/droid_sans_mono_regular.typeface.json +0 -1
  339. package/examples/fonts/droid/droid_sans_regular.typeface.json +0 -1
  340. package/examples/fonts/droid/droid_serif_bold.typeface.json +0 -1
  341. package/examples/fonts/droid/droid_serif_regular.typeface.json +0 -1
  342. package/examples/fonts/gentilis_bold.typeface.json +0 -1
  343. package/examples/fonts/gentilis_regular.typeface.json +0 -1
  344. package/examples/fonts/helvetiker_bold.typeface.json +0 -1
  345. package/examples/fonts/helvetiker_regular.typeface.json +0 -1
  346. package/examples/fonts/optimer_bold.typeface.json +0 -1
  347. package/examples/fonts/optimer_regular.typeface.json +0 -1
  348. package/examples/fonts/ttf/README.md +0 -9
  349. package/examples/fonts/ttf/kenpixel.ttf +0 -0
  350. package/examples/jsm/inspector/extensions/extensions.json +0 -6
  351. package/examples/jsm/libs/ammo.wasm.js +0 -822
  352. package/examples/jsm/libs/ammo.wasm.wasm +0 -0
  353. package/examples/jsm/libs/draco/draco_encoder.js +0 -33
  354. package/examples/jsm/libs/draco/gltf/draco_encoder.js +0 -33
  355. package/examples/jsm/libs/lottie_canvas.module.js +0 -14849
  356. package/examples/jsm/libs/opentype.module.js +0 -14506
  357. package/examples/jsm/libs/rhino3dm/rhino3dm.js +0 -21
  358. package/examples/jsm/libs/rhino3dm/rhino3dm.module.js +0 -16
  359. package/examples/jsm/libs/rhino3dm/rhino3dm.wasm +0 -0
  360. package/examples/jsm/lighting/TiledLighting.js +0 -42
  361. package/examples/jsm/tsl/display/AnamorphicNode.js +0 -293
  362. package/examples/jsm/tsl/lighting/TiledLightsNode.js +0 -442
  363. package/src/nodes/accessors/BatchNode.js +0 -163
  364. package/src/nodes/accessors/InstanceNode.js +0 -349
  365. package/src/nodes/accessors/InstancedMeshNode.js +0 -50
  366. package/src/nodes/accessors/SkinningNode.js +0 -328
@@ -0,0 +1,1023 @@
1
+ import { EPSILON, Fn, If, abs, convertToTexture, dFdx, dFdy, dot, exp, float, floor, fwidth, getViewPosition, ivec2, luminance, max, min, mix, nodeObject, normalize, passTexture, screenCoordinate, select, smoothstep, sqrt, struct, texture, textureLoad, uniform, unpackRGBToNormal, uv, vec2, vec3, vec4, velocity } from 'three/tsl';
2
+ import { DepthTexture, HalfFloatType, Matrix4, NodeMaterial, NodeUpdateType, QuadMesh, RenderTarget, RendererUtils, TempNode, Vector2, Vector3 } from 'three/webgpu';
3
+ import { ENV_RAY_LENGTH, ENV_RAY_LENGTH_THRESHOLD } from '../utils/SpecularHelpers.js';
4
+
5
+ // Reprojection helpers
6
+
7
+ /**
8
+ * Maps a resolve (screen) texel to the corresponding beauty-input texel when resolutions differ.
9
+ *
10
+ * @tsl
11
+ */
12
+ const beautyTexelFromScreen = Fn( ( [ screenTexel, beautySize, resolveSize ] ) => {
13
+
14
+ return ivec2( floor( vec2( screenTexel ).mul( beautySize ).div( resolveSize ) ) );
15
+
16
+ } ).setLayout( {
17
+ name: 'beautyTexelFromScreen',
18
+ type: 'ivec2',
19
+ inputs: [
20
+ { name: 'screenTexel', type: 'ivec2' },
21
+ { name: 'beautySize', type: 'vec2' },
22
+ { name: 'resolveSize', type: 'vec2' }
23
+ ]
24
+ } );
25
+
26
+ /**
27
+ * Projects a world-space position into previous-frame UV coordinates.
28
+ *
29
+ * @tsl
30
+ */
31
+ const projectWorldToUV = Fn( ( [ worldPos, previousViewMatrix, previousProjectionMatrix ] ) => {
32
+
33
+ const resultUV = vec2( - 1 ).toVar();
34
+ const viewSpace = previousViewMatrix.mul( vec4( worldPos, 1.0 ) );
35
+ const clipSpace = previousProjectionMatrix.mul( viewSpace ).toVar();
36
+ const clipW = clipSpace.w.toVar();
37
+
38
+ If( abs( clipW ).greaterThan( float( 1e-5 ) ), () => {
39
+
40
+ const ndc = clipSpace.xyz.div( clipW );
41
+ resultUV.assign( ndc.xy.mul( 0.5 ).add( 0.5 ) );
42
+ resultUV.y.assign( resultUV.y.oneMinus() );
43
+
44
+ } );
45
+
46
+ return resultUV;
47
+
48
+ } ).setLayout( {
49
+ name: 'projectWorldToUV',
50
+ type: 'vec2',
51
+ inputs: [
52
+ { name: 'worldPos', type: 'vec3' },
53
+ { name: 'previousViewMatrix', type: 'mat4' },
54
+ { name: 'previousProjectionMatrix', type: 'mat4' }
55
+ ]
56
+ } );
57
+
58
+ // YCoCg variance clipping
59
+
60
+ /**
61
+ * @param {Node<vec3>} c
62
+ * @returns {Node<vec3>}
63
+ */
64
+ const rgbToYCoCg = ( c ) => vec3(
65
+ dot( c, vec3( 0.25, 0.5, 0.25 ) ),
66
+ dot( c, vec3( 0.5, 0.0, - 0.5 ) ),
67
+ dot( c, vec3( - 0.25, 0.5, - 0.25 ) )
68
+ );
69
+
70
+ /**
71
+ * @param {Node<vec3>} c
72
+ * @returns {Node<vec3>}
73
+ */
74
+ const ycocgToRGB = ( c ) => vec3(
75
+ c.x.add( c.y ).sub( c.z ),
76
+ c.x.add( c.z ),
77
+ c.x.sub( c.y ).sub( c.z )
78
+ );
79
+
80
+ const VARIANCE_CLIP_LUMA_SCALE = 10;
81
+
82
+ /**
83
+ * Inverse-luminance compression for HDR variance clipping (Karis-style).
84
+ * Bright samples contribute less to neighbourhood moments so sun pixels do not
85
+ * inflate the YCoCg AABB and cause aggressive clipping flicker.
86
+ *
87
+ * @param {Node<vec3>} rgb
88
+ * @param {Node<float>} flickerSuppression
89
+ * @returns {Node<vec3>}
90
+ */
91
+ const dampenForVarianceClip = ( rgb, flickerSuppression ) => {
92
+
93
+ const scale = luminance( rgb ).mul( flickerSuppression ).mul( VARIANCE_CLIP_LUMA_SCALE ).add( 1 );
94
+ return rgb.div( scale );
95
+
96
+ };
97
+
98
+ /**
99
+ * Clips the history sample to the neighbourhood AABB by projecting it toward the box centre.
100
+ * Reference: https://github.com/playdeadgames/temporal
101
+ *
102
+ * @tsl
103
+ */
104
+ const clipToAABB = Fn( ( [ history, boxMin, boxMax ] ) => {
105
+
106
+ const pClip = boxMax.add( boxMin ).mul( 0.5 );
107
+ const eClip = boxMax.sub( boxMin ).mul( 0.5 ).add( 1e-7 );
108
+ const vClip = history.sub( pClip );
109
+ const vUnit = vClip.div( eClip );
110
+ const absUnit = vUnit.abs();
111
+ const maxUnit = max( absUnit.x, absUnit.y, absUnit.z );
112
+
113
+ return maxUnit.greaterThan( 1 ).select( pClip.add( vClip.div( maxUnit ) ), history );
114
+
115
+ } ).setLayout( {
116
+ name: 'clipToAABB',
117
+ type: 'vec3',
118
+ inputs: [
119
+ { name: 'history', type: 'vec3' },
120
+ { name: 'boxMin', type: 'vec3' },
121
+ { name: 'boxMax', type: 'vec3' }
122
+ ]
123
+ } );
124
+
125
+ const neighborhoodStruct = struct( {
126
+ mean: 'vec3',
127
+ stdColor: 'vec3',
128
+ rayLength: 'float',
129
+ envProbability: 'float',
130
+ stdDevRayLength: 'float'
131
+ } );
132
+
133
+ /**
134
+ * Single 3×3 neighbourhood pass over the beauty buffer. One textureLoad per tap feeds both the
135
+ * YCoCg variance-clipping box (colour) and the SSR ray-length statistics (alpha), which previously
136
+ * required two separate 3×3 fetches of the same texture.
137
+ *
138
+ * Sampling is done on the beauty-texel grid (`beautyTexel + offset`), so the taps are distinct
139
+ * source texels even when the beauty buffer is lower resolution than the resolve pass (upscaling).
140
+ *
141
+ * @tsl
142
+ */
143
+ const collectNeighborhood = Fn( ( [ beautyTexture, beautyTexel, inputColor, flickerSuppression ] ) => {
144
+
145
+ const offsets = [
146
+ [ - 1, - 1 ],
147
+ [ - 1, 1 ],
148
+ [ 1, - 1 ],
149
+ [ 1, 1 ],
150
+ [ 1, 0 ],
151
+ [ 0, - 1 ],
152
+ [ 0, 1 ],
153
+ [ - 1, 0 ],
154
+ ];
155
+
156
+ // Colour moments (YCoCg) — centre reuses the already-fetched inputColor.
157
+ const center = rgbToYCoCg( dampenForVarianceClip( inputColor.rgb, flickerSuppression ) );
158
+ const moment1 = center.toVar();
159
+ const moment2 = center.pow2().toVar();
160
+
161
+ // Ray-length statistics (Welford) over screen-space hits only.
162
+ const rayLengthSum = float( 0 ).toVar();
163
+ const rayLengthCount = float( 0 ).toVar();
164
+ const meanRayLength = float( 0 ).toVar();
165
+ const m2RayLength = float( 0 ).toVar();
166
+
167
+ const accumulateRayLength = ( alpha ) => {
168
+
169
+ If( alpha.lessThan( ENV_RAY_LENGTH_THRESHOLD ), () => {
170
+
171
+ rayLengthSum.addAssign( alpha );
172
+ rayLengthCount.addAssign( 1 );
173
+
174
+ const delta = alpha.sub( meanRayLength ).toVar();
175
+ meanRayLength.addAssign( delta.div( rayLengthCount ) );
176
+ m2RayLength.addAssign( delta.mul( alpha.sub( meanRayLength ) ) );
177
+
178
+ } );
179
+
180
+ };
181
+
182
+ accumulateRayLength( inputColor.a );
183
+
184
+ for ( const [ x, y ] of offsets ) {
185
+
186
+ const neighbor = textureLoad( beautyTexture, beautyTexel.add( ivec2( x, y ) ) ).max( 0 ).toVar();
187
+
188
+ const c = rgbToYCoCg( dampenForVarianceClip( neighbor.rgb, flickerSuppression ) );
189
+ moment1.addAssign( c );
190
+ moment2.addAssign( c.pow2() );
191
+
192
+ accumulateRayLength( neighbor.a );
193
+
194
+ }
195
+
196
+ const N = float( offsets.length + 1 );
197
+ const mean = moment1.div( N );
198
+ const stdColor = moment2.div( N ).sub( mean.pow2() ).max( 0 ).sqrt();
199
+
200
+ // Continuous environment probability: fraction of the 3×3 neighbourhood that missed in screen space
201
+ // and fell back to env (0 = all hits, 1 = all env), for smooth reflection/environment transitions.
202
+ const envProbability = rayLengthCount.div( float( 9 ) ).oneMinus();
203
+ const rayLength = rayLengthCount.lessThan( 0.5 ).select( float( ENV_RAY_LENGTH ), rayLengthSum.div( max( rayLengthCount, float( 1e-4 ) ) ) );
204
+ const stdDevRayLength = sqrt( m2RayLength.div( max( rayLengthCount, float( 1.0 ) ) ) ).max( 1e-3 );
205
+
206
+ return neighborhoodStruct( mean, stdColor, rayLength, envProbability, stdDevRayLength );
207
+
208
+ } );
209
+
210
+ /**
211
+ * Variance clipping in YCoCg space (Salvi, GDC 2016). Uses the colour moments gathered by
212
+ * {@link collectNeighborhood}; `gamma` widens the AABB and is kept out of the gather so the
213
+ * neighbourhood pass stays independent of the per-pixel motion factor.
214
+ *
215
+ * @tsl
216
+ */
217
+ const applyVarianceClipping = Fn( ( [ historyColor, mean, stdColor, gamma, flickerSuppression ] ) => {
218
+
219
+ const stddev = stdColor.mul( gamma );
220
+ const boxMin = mean.sub( stddev );
221
+ const boxMax = mean.add( stddev );
222
+
223
+ const historyRGB = historyColor.rgb.toVar();
224
+ const historyScale = luminance( historyRGB ).mul( flickerSuppression ).mul( VARIANCE_CLIP_LUMA_SCALE ).add( 1 );
225
+ const clipped = clipToAABB( rgbToYCoCg( historyRGB.div( historyScale ) ), boxMin, boxMax );
226
+
227
+ return ycocgToRGB( clipped ).mul( historyScale );
228
+
229
+ } );
230
+
231
+ // History sampling
232
+
233
+ const bilinearTapStruct = struct( { color: 'vec4', weight: 'float', confidence: 'float' } );
234
+ const historyResultStruct = struct( { color: 'vec4', tapConfidence: 'float', minConfidence: 'float' } );
235
+
236
+ /**
237
+ * Single bilinear history tap with plane-distance and normal confidence.
238
+ *
239
+ * @tsl
240
+ */
241
+ const sampleBilinearTap = Fn( ( [
242
+ historyTexture,
243
+ previousDepthNode,
244
+ previousNormalNode,
245
+ resolution,
246
+ previousProjectionMatrixInverse,
247
+ previousCameraWorldMatrix,
248
+ previousCameraViewMatrix,
249
+ tapCoord,
250
+ bilinearWeight,
251
+ worldPosition,
252
+ worldNormal
253
+ ] ) => {
254
+
255
+ const color = textureLoad( historyTexture, tapCoord ).max( 0 );
256
+ const reprojDepth = textureLoad( previousDepthNode, tapCoord ).r;
257
+ const reprojViewPos = getViewPosition( vec2( tapCoord ).add( 0.5 ).div( resolution ), reprojDepth, previousProjectionMatrixInverse );
258
+ const reprojWorldPos = previousCameraWorldMatrix.mul( vec4( reprojViewPos, 1.0 ) ).xyz;
259
+ const reprojWorldNorm = unpackRGBToNormal( textureLoad( previousNormalNode, tapCoord ).rgb ).transformDirection( previousCameraViewMatrix );
260
+
261
+ const planeDiff = abs( dot( reprojWorldPos.sub( worldPosition ), worldNormal ) ).toVar();
262
+ planeDiff.divAssign( abs( reprojViewPos.z ) );
263
+ const normalConfidence = smoothstep( 0.95, 0.999, reprojWorldNorm.dot( worldNormal ) );
264
+ const confidence = smoothstep( 0, 0.01, planeDiff ).oneMinus().mul( normalConfidence );
265
+ const weight = bilinearWeight.mul( confidence );
266
+
267
+ return bilinearTapStruct( color.mul( weight ), weight, confidence );
268
+
269
+ } );
270
+
271
+ /**
272
+ * @param {Object} ctx - Shared {@link sampleBilinearTap} inputs plus `reprojICoord`.
273
+ * @param {Node<ivec2>} tapOffset
274
+ * @param {Node<float>} bilinearWeight
275
+ */
276
+ function bilinearHistoryTap( ctx, tapOffset, bilinearWeight ) {
277
+
278
+ return sampleBilinearTap(
279
+ ctx.historyTexture,
280
+ ctx.previousDepthNode,
281
+ ctx.previousNormalNode,
282
+ ctx.resolution,
283
+ ctx.previousProjectionMatrixInverse,
284
+ ctx.previousCameraWorldMatrix,
285
+ ctx.previousCameraViewMatrix,
286
+ ctx.reprojICoord.add( tapOffset ),
287
+ bilinearWeight,
288
+ ctx.worldPosition,
289
+ ctx.worldNormal
290
+ );
291
+
292
+ }
293
+
294
+ /**
295
+ * Geometrically-weighted 4-tap bilinear history sample.
296
+ *
297
+ * @tsl
298
+ */
299
+ const sampleHistory4Tap = Fn( ( [
300
+ historyTexture,
301
+ previousDepthNode,
302
+ previousNormalNode,
303
+ resolution,
304
+ previousProjectionMatrixInverse,
305
+ previousCameraWorldMatrix,
306
+ previousCameraViewMatrix,
307
+ reprojUV,
308
+ worldPosition,
309
+ worldNormal,
310
+ inputColor
311
+ ] ) => {
312
+
313
+ const reprojPixelCoord = reprojUV.mul( resolution ).sub( 0.5 ).toVar();
314
+ const reprojICoord = ivec2( floor( reprojPixelCoord ) );
315
+ const fCoord = reprojPixelCoord.fract();
316
+
317
+ const fx = fCoord.x;
318
+ const fy = fCoord.y;
319
+ const f00 = float( 1 ).sub( fx ).mul( float( 1 ).sub( fy ) );
320
+ const f10 = fx.mul( float( 1 ).sub( fy ) );
321
+ const f01 = float( 1 ).sub( fx ).mul( fy );
322
+ const f11 = fx.mul( fy );
323
+
324
+ const tapCtx = {
325
+ historyTexture,
326
+ previousDepthNode,
327
+ previousNormalNode,
328
+ resolution,
329
+ previousProjectionMatrixInverse,
330
+ previousCameraWorldMatrix,
331
+ previousCameraViewMatrix,
332
+ reprojICoord,
333
+ worldPosition,
334
+ worldNormal
335
+ };
336
+
337
+ const tap00 = bilinearHistoryTap( tapCtx, ivec2( 0, 0 ), f00 );
338
+ const tap10 = bilinearHistoryTap( tapCtx, ivec2( 1, 0 ), f10 );
339
+ const tap01 = bilinearHistoryTap( tapCtx, ivec2( 0, 1 ), f01 );
340
+ const tap11 = bilinearHistoryTap( tapCtx, ivec2( 1, 1 ), f11 );
341
+
342
+ const colorSum = tap00.get( 'color' ).add( tap10.get( 'color' ) ).add( tap01.get( 'color' ) ).add( tap11.get( 'color' ) );
343
+ const weightSum = tap00.get( 'weight' ).add( tap10.get( 'weight' ) ).add( tap01.get( 'weight' ) ).add( tap11.get( 'weight' ) );
344
+ const maxConf = max( max( tap00.get( 'confidence' ), tap10.get( 'confidence' ) ), max( tap01.get( 'confidence' ), tap11.get( 'confidence' ) ) );
345
+ const minConf = min( min( tap00.get( 'confidence' ), tap10.get( 'confidence' ) ), min( tap01.get( 'confidence' ), tap11.get( 'confidence' ) ) );
346
+
347
+ return historyResultStruct(
348
+ select( weightSum.greaterThan( 0.01 ), colorSum.div( weightSum ), vec4( inputColor.rgb, float( 1 ) ) ),
349
+ maxConf,
350
+ minConf
351
+ );
352
+
353
+ } );
354
+
355
+ // Diffuse reprojection
356
+
357
+ /**
358
+ * Reprojection-stretch confidence — detects history magnification (surface stretching).
359
+ *
360
+ * Differentiates the per-pixel history UV with hardware screen-space derivatives to form the
361
+ * reprojection Jacobian `J = ∂(historyPixel)/∂(screenPixel)`, then returns its **minimum
362
+ * singular value**, clamped to `[0,1]`.
363
+ *
364
+ * `σ_min < 1` means the most-stretched axis magnifies history — a few history pixels are smeared
365
+ * over many current pixels (e.g. a surface seen at grazing in the previous frame, face-on now), so
366
+ * history is undersampled and its confidence should be reduced. `σ_min ≥ 1` (history minified) is
367
+ * safe and clamps to 1. Using the minimum singular value rather than the Jacobian determinant
368
+ * catches anisotropic 1-D stretch that an area-only measure would smear out.
369
+ *
370
+ * Works for any reprojection (surface-velocity or parallax hit-point) since it differentiates the
371
+ * final history UV, so the same factor applies to both the diffuse and specular paths.
372
+ *
373
+ * @tsl
374
+ */
375
+ const reprojectionStretchConfidence = Fn( ( [ historyUV, resolution ] ) => {
376
+
377
+ // Jacobian columns in pixels: how the history sample position moves per screen pixel.
378
+ const jx = dFdx( historyUV ).mul( resolution ).toVar();
379
+ const jy = dFdy( historyUV ).mul( resolution ).toVar();
380
+
381
+ // Singular values of the 2×2 J are sqrt( eigenvalues of JᵀJ ), with
382
+ // trace( JᵀJ ) = ‖J‖²_F and det( JᵀJ ) = det( J )².
383
+ const det = jx.x.mul( jy.y ).sub( jx.y.mul( jy.x ) );
384
+ const fro2 = dot( jx, jx ).add( dot( jy, jy ) );
385
+ const disc = fro2.mul( fro2 ).mul( 0.25 ).sub( det.mul( det ) ).max( 0 ).sqrt();
386
+ const sigMin = fro2.mul( 0.5 ).sub( disc ).max( 0 ).sqrt();
387
+
388
+ return sigMin.saturate();
389
+
390
+ } );
391
+
392
+ // Specular reprojection
393
+
394
+ /**
395
+ * Parallax-corrected hit-point reprojection into previous-frame UVs.
396
+ *
397
+ * @tsl
398
+ */
399
+ const reprojectHitPoint = Fn( ( [
400
+ rayOrig,
401
+ rayLength,
402
+ cameraWorldPosition,
403
+ previousViewMatrix,
404
+ previousProjectionMatrix
405
+ ] ) => {
406
+
407
+ const cameraRay = normalize( rayOrig.sub( cameraWorldPosition ) ).toVar();
408
+ const parallaxHitPoint = rayOrig.add( cameraRay.mul( rayLength ) );
409
+
410
+ return projectWorldToUV( parallaxHitPoint, previousViewMatrix, previousProjectionMatrix );
411
+
412
+ } );
413
+
414
+ /**
415
+ * Converts screen-space velocity (NDC derivative) to a UV reprojection offset.
416
+ *
417
+ * @tsl
418
+ */
419
+ const velocityToUVOffset = Fn( ( [ velocity ] ) => {
420
+
421
+ return velocity.mul( vec2( 0.5, - 0.5 ) );
422
+
423
+ } ).setLayout( {
424
+ name: 'velocityToUVOffset',
425
+ type: 'vec2',
426
+ inputs: [ { name: 'velocity', type: 'vec2' } ]
427
+ } );
428
+
429
+ /**
430
+ * Current and previous-frame camera matrices for temporal reprojection passes.
431
+ *
432
+ * @param {Camera} camera
433
+ */
434
+ function bindTemporalCameraUniforms( camera ) {
435
+
436
+ const worldMatrix = uniform( new Matrix4().copy( camera.matrixWorld ) );
437
+ const viewMatrix = uniform( new Matrix4().copy( camera.matrixWorldInverse ) );
438
+ const projectionMatrix = uniform( new Matrix4().copy( camera.projectionMatrix ) );
439
+ const projectionMatrixInverse = uniform( new Matrix4().copy( camera.projectionMatrixInverse ) );
440
+ const worldPosition = uniform( new Vector3().copy( camera.position ) );
441
+
442
+ const previousWorldMatrix = uniform( new Matrix4().copy( camera.matrixWorld ) );
443
+ const previousViewMatrix = uniform( new Matrix4().copy( camera.matrixWorldInverse ) );
444
+ const previousProjectionMatrix = uniform( new Matrix4().copy( camera.projectionMatrix ) );
445
+ const previousProjectionMatrixInverse = uniform( new Matrix4().copy( camera.projectionMatrixInverse ) );
446
+
447
+ /**
448
+ * @param {Camera} cam
449
+ */
450
+ function updateFromCamera( cam ) {
451
+
452
+ previousWorldMatrix.value.copy( worldMatrix.value );
453
+ previousViewMatrix.value.copy( viewMatrix.value );
454
+ previousProjectionMatrix.value.copy( projectionMatrix.value );
455
+ previousProjectionMatrixInverse.value.copy( projectionMatrixInverse.value );
456
+
457
+ worldMatrix.value.copy( cam.matrixWorld );
458
+ viewMatrix.value.copy( cam.matrixWorldInverse );
459
+ projectionMatrix.value.copy( cam.projectionMatrix );
460
+ projectionMatrixInverse.value.copy( cam.projectionMatrixInverse );
461
+ worldPosition.value.copy( cam.position );
462
+
463
+ }
464
+
465
+ return {
466
+ worldMatrix,
467
+ viewMatrix,
468
+ projectionMatrix,
469
+ projectionMatrixInverse,
470
+ worldPosition,
471
+ previousWorldMatrix,
472
+ previousViewMatrix,
473
+ previousProjectionMatrix,
474
+ previousProjectionMatrixInverse,
475
+ updateFromCamera
476
+ };
477
+
478
+ }
479
+
480
+ const _quadMesh = /*@__PURE__*/ new QuadMesh();
481
+ const _size = /*@__PURE__*/ new Vector2();
482
+
483
+ let _rendererState;
484
+
485
+ const DEFAULT_MAX_VELOCITY_LENGTH = 128;
486
+ const VARIANCE_GAMMA_MIN = 0.5;
487
+ const VARIANCE_GAMMA_MAX = 1;
488
+
489
+ /**
490
+ * @typedef {'diffuse' | 'specular'} TemporalReprojectMode
491
+ */
492
+
493
+ /**
494
+ * @typedef {Object} TemporalReprojectNodeOptions
495
+ * @property {TemporalReprojectMode} [mode='diffuse'] - `diffuse` for SSGI/scene colour; `specular` for SSR reflections.
496
+ * @property {boolean} [hitPointReprojection] - Parallax hit-point reprojection (specular mode only). Defaults to `true` in specular mode.
497
+ * @property {boolean} [accumulate=false] - When `true`, history is stored in this pass (classic temporal resolve). When `false`,
498
+ * use {@link TemporalReprojectNode#setHistoryTexture} to read history from another pass (e.g. denoise output).
499
+ */
500
+
501
+ /**
502
+ * Temporal reprojection pass for denoising screen-space effects (SSGI, SSR, etc.).
503
+ *
504
+ * Both modes share geometrically-weighted 4-tap bilinear history sampling and YCoCg variance clipping.
505
+ * Surface velocity reprojection is always sampled first. Specular mode then blends in
506
+ * hit-point parallax history on top of that surface result.
507
+ * Diffuse mode applies velocity-field divergence to detect surface stretching.
508
+ *
509
+ * Unlike jitter-based TAA/TAAU, this node does not apply camera sub-pixel jitter — it only
510
+ * reprojects and accumulates history using motion vectors.
511
+ *
512
+ * References:
513
+ * - {@link https://alextardif.com/TAA.html}
514
+ * - {@link https://www.elopezr.com/temporal-aa-and-the-quest-for-the-holy-trail/}
515
+ *
516
+ * @augments TempNode
517
+ * @three_import import { temporalReproject } from 'three/addons/tsl/display/TemporalReprojectNode.js';
518
+ */
519
+ class TemporalReprojectNode extends TempNode {
520
+
521
+ static get type() {
522
+
523
+ return 'TemporalReprojectNode';
524
+
525
+ }
526
+
527
+ /**
528
+ * @param {TextureNode} beautyNode
529
+ * @param {TextureNode} depthNode
530
+ * @param {TextureNode} normalNode
531
+ * @param {TextureNode} velocityNode
532
+ * @param {Camera} camera
533
+ * @param {TemporalReprojectNodeOptions} [options]
534
+ */
535
+ constructor( beautyNode, depthNode, normalNode, velocityNode, camera, options = {} ) {
536
+
537
+ super( 'vec4' );
538
+
539
+ const {
540
+ mode = 'diffuse',
541
+ hitPointReprojection = mode === 'specular',
542
+ accumulate = false
543
+ } = options;
544
+
545
+ if ( mode !== 'specular' && mode !== 'diffuse' ) {
546
+
547
+ throw new Error( 'TemporalReprojectNode: `mode` must be `diffuse` or `specular`.' );
548
+
549
+ }
550
+
551
+ this.isTemporalReprojectNode = true;
552
+ this.updateBeforeType = NodeUpdateType.FRAME;
553
+
554
+ this.beautyNode = beautyNode;
555
+ this.depthNode = depthNode;
556
+ this.normalNode = normalNode;
557
+ this.velocityNode = velocityNode;
558
+ this.camera = camera;
559
+
560
+ /**
561
+ * @type {TemporalReprojectMode}
562
+ */
563
+ this.mode = mode;
564
+
565
+ /**
566
+ * When `true`, resolve output is copied into the internal history buffer each frame.
567
+ * When `false`, history is supplied externally via {@link TemporalReprojectNode#setHistoryTexture}.
568
+ *
569
+ * @type {boolean}
570
+ */
571
+ this.accumulate = accumulate;
572
+
573
+ this.maxVelocityLength = DEFAULT_MAX_VELOCITY_LENGTH;
574
+
575
+ this._resolution = uniform( new Vector2() );
576
+
577
+ this._cameraUniforms = bindTemporalCameraUniforms( camera );
578
+
579
+ this.maxFrames = uniform( 32 );
580
+ this.hitPointReprojection = uniform( hitPointReprojection, 'bool' );
581
+ this.clampIntensity = uniform( 1 );
582
+ this.flickerSuppression = uniform( 1 );
583
+
584
+ this._historyRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false, type: HalfFloatType, depthTexture: new DepthTexture() } );
585
+ this._historyRenderTarget.texture.name = 'TemporalReprojectNode.history';
586
+ this._historyTextureNode = texture( this._historyRenderTarget.texture );
587
+
588
+ this._resolveRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false, type: HalfFloatType } );
589
+ this._resolveRenderTarget.texture.name = 'TemporalReprojectNode.resolve';
590
+
591
+ this._resolveMaterial = new NodeMaterial();
592
+ this._resolveMaterial.name = 'TemporalReproject.resolve';
593
+
594
+ this._seedMaterial = new NodeMaterial();
595
+ this._seedMaterial.name = 'TemporalReproject.seed';
596
+
597
+ this._textureNode = passTexture( this, this._resolveRenderTarget.texture );
598
+
599
+ this._originalProjectionMatrix = new Matrix4();
600
+
601
+ this._placeholderPreviousDepthTexture = new DepthTexture( 1, 1 );
602
+ this._previousDepthNode = texture( this._placeholderPreviousDepthTexture );
603
+ this._previousNormalTexture = normalNode.value.clone();
604
+ this._previousNormalNode = texture( this._previousNormalTexture );
605
+
606
+ this._needsPostProcessingSync = false;
607
+ this._externalHistoryTexture = null;
608
+
609
+ this._syncHistoryTextureBinding();
610
+
611
+ }
612
+
613
+ getTextureNode() {
614
+
615
+ return this._textureNode;
616
+
617
+ }
618
+
619
+ setSize( width, height ) {
620
+
621
+ if ( width === null || height === null ) return;
622
+
623
+ this._historyRenderTarget.setSize( width, height );
624
+ this._resolveRenderTarget.setSize( width, height );
625
+
626
+ this._resolution.value.set( width, height );
627
+
628
+ }
629
+
630
+ setViewOffset() {
631
+
632
+ this.camera.updateProjectionMatrix();
633
+ this._originalProjectionMatrix.copy( this.camera.projectionMatrix );
634
+ velocity.setProjectionMatrix( this._originalProjectionMatrix );
635
+
636
+ }
637
+
638
+ clearViewOffset() {
639
+
640
+ velocity.setProjectionMatrix( null );
641
+
642
+ }
643
+
644
+ updateBefore( frame ) {
645
+
646
+ const { renderer } = frame;
647
+
648
+ this._cameraUniforms.updateFromCamera( this.camera );
649
+
650
+ const drawingBufferSize = renderer.getDrawingBufferSize( _size );
651
+ const width = drawingBufferSize.width;
652
+ const height = drawingBufferSize.height;
653
+
654
+ if ( this._needsPostProcessingSync === true ) {
655
+
656
+ this.setViewOffset();
657
+ this._needsPostProcessingSync = false;
658
+
659
+ }
660
+
661
+ _rendererState = RendererUtils.resetRendererState( renderer, _rendererState );
662
+
663
+ const needsRestart = this._historyRenderTarget.width !== width || this._historyRenderTarget.height !== height;
664
+ this.setSize( width, height );
665
+
666
+ let historySwappedForRestart = false;
667
+
668
+ if ( needsRestart === true ) {
669
+
670
+ renderer.initRenderTarget( this._historyRenderTarget );
671
+ renderer.initRenderTarget( this._resolveRenderTarget );
672
+
673
+ this._previousNormalTexture.dispose();
674
+ this._previousNormalTexture = this.normalNode.value.clone();
675
+ this._previousNormalNode.value = this._previousNormalTexture;
676
+
677
+ // External history (e.g. denoise feedback) is stale at the old resolution — use
678
+ // freshly seeded internal history for this frame instead.
679
+ if ( this.accumulate === false && this._externalHistoryTexture !== null ) {
680
+
681
+ this._historyTextureNode.value = this._historyRenderTarget.texture;
682
+ historySwappedForRestart = true;
683
+
684
+ }
685
+
686
+ renderer.setRenderTarget( this._historyRenderTarget );
687
+ _quadMesh.material = this._seedMaterial;
688
+ _quadMesh.name = 'TemporalReproject.seed';
689
+ _quadMesh.render( renderer );
690
+ renderer.setRenderTarget( null );
691
+
692
+ }
693
+
694
+ renderer.setRenderTarget( this._resolveRenderTarget );
695
+
696
+ _quadMesh.material = this._resolveMaterial;
697
+ _quadMesh.name = 'TemporalReproject';
698
+ _quadMesh.render( renderer );
699
+ renderer.setRenderTarget( null );
700
+
701
+ if ( historySwappedForRestart === true ) {
702
+
703
+ this._syncHistoryTextureBinding();
704
+
705
+ } else if ( this.accumulate === true ) {
706
+
707
+ renderer.copyTextureToTexture( this._resolveRenderTarget.texture, this._historyRenderTarget.texture );
708
+
709
+ }
710
+
711
+ const currentDepth = this.depthNode.value;
712
+ const srcW = currentDepth.image !== null && currentDepth.image !== undefined ? currentDepth.image.width : 0;
713
+ const srcH = currentDepth.image !== null && currentDepth.image !== undefined ? currentDepth.image.height : 0;
714
+
715
+ if ( srcW > 0 && srcH > 0 ) {
716
+
717
+ renderer.copyTextureToTexture( currentDepth, this._historyRenderTarget.depthTexture );
718
+ renderer.copyTextureToTexture( this.normalNode.value, this._previousNormalTexture );
719
+
720
+ this._previousDepthNode.value = this._historyRenderTarget.depthTexture;
721
+
722
+ }
723
+
724
+ RendererUtils.restoreRendererState( renderer, _rendererState );
725
+
726
+ }
727
+
728
+ setup( builder ) {
729
+
730
+ const renderPipeline = builder.context.renderPipeline;
731
+
732
+ if ( renderPipeline ) {
733
+
734
+ this._needsPostProcessingSync = true;
735
+
736
+ renderPipeline.context.onBeforeRenderPipeline = () => {
737
+
738
+ this.setViewOffset();
739
+
740
+ };
741
+
742
+ renderPipeline.context.onAfterRenderPipeline = () => {
743
+
744
+ this.clearViewOffset();
745
+
746
+ };
747
+
748
+ }
749
+
750
+ this._resolveMaterial.fragmentNode = this._buildResolve( builder );
751
+ this._resolveMaterial.needsUpdate = true;
752
+
753
+ this._buildSeed( builder );
754
+
755
+ return this._textureNode;
756
+
757
+ }
758
+
759
+ _buildSeed( builder ) {
760
+
761
+ const seed = Fn( () => {
762
+
763
+ const screenTexel = ivec2( floor( screenCoordinate.xy.sub( 0.5 ) ) );
764
+ const beautySize = this.beautyNode.size();
765
+ const beautyTexel = beautyTexelFromScreen( screenTexel, beautySize, this._resolution );
766
+
767
+ return textureLoad( this.beautyNode, beautyTexel ).max( 0 );
768
+
769
+ } );
770
+
771
+ this._seedMaterial.fragmentNode = seed().context( builder.getSharedContext() );
772
+ this._seedMaterial.needsUpdate = true;
773
+
774
+ }
775
+
776
+ _buildResolve( builder ) {
777
+
778
+ const isSpecular = this.mode === 'specular';
779
+ const cameraUniforms = this._cameraUniforms;
780
+
781
+ const resolve = Fn( () => {
782
+
783
+ const uvNode = uv();
784
+
785
+ const screenTexel = ivec2( floor( screenCoordinate.xy.sub( 0.5 ) ) );
786
+ const depth = textureLoad( this.depthNode, screenTexel ).r.toVar();
787
+ depth.greaterThanEqual( 1.0 ).discard();
788
+
789
+ const beautySize = this.beautyNode.size();
790
+ const beautyTexel = beautyTexelFromScreen( screenTexel, beautySize, this._resolution );
791
+
792
+ const inputColor = textureLoad( this.beautyNode, beautyTexel ).max( 0 ).toVar();
793
+ const viewNormal = unpackRGBToNormal( textureLoad( this.normalNode, screenTexel ).rgb ).toVar();
794
+
795
+ // Shared 3×3 beauty fetch: feeds both the variance-clip box and the SSR ray-length stats.
796
+ const neighborhood = collectNeighborhood( this.beautyNode, beautyTexel, inputColor, this.flickerSuppression );
797
+ const worldNormal = viewNormal.transformDirection( cameraUniforms.viewMatrix ).toVar();
798
+
799
+ const viewPosition = getViewPosition( uvNode, depth, cameraUniforms.projectionMatrixInverse ).toVar();
800
+ const worldPosition = cameraUniforms.worldMatrix.mul( vec4( viewPosition, 1.0 ) ).xyz.toVar();
801
+
802
+ const sampleHistory = ( reprojUV ) => sampleHistory4Tap(
803
+ this._historyTextureNode,
804
+ this._previousDepthNode,
805
+ this._previousNormalNode,
806
+ this._resolution,
807
+ cameraUniforms.previousProjectionMatrixInverse,
808
+ cameraUniforms.previousWorldMatrix,
809
+ cameraUniforms.previousViewMatrix,
810
+ reprojUV,
811
+ worldPosition,
812
+ worldNormal,
813
+ inputColor.rgb
814
+ );
815
+
816
+ // Surface-velocity reprojection — the base history for both modes. `historyUV` is
817
+ // reused below for the stretch guard, so it is computed once here.
818
+ const velocityOff = velocityToUVOffset( textureLoad( this.velocityNode, screenTexel ).xy ).toVar();
819
+ const motionFactor = velocityOff.mul( this._resolution ).length().div( float( this.maxVelocityLength ) ).saturate();
820
+
821
+ const historyUV = uvNode.sub( velocityOff ).toVar();
822
+ const surf = sampleHistory( historyUV );
823
+
824
+ const historyColor = surf.get( 'color' ).toVar();
825
+ const totalConfidence = float( 1 ).toVar();
826
+ const historyTrust = float( 0 ).toVar();
827
+
828
+ // Specular: blend parallax hit-point history on top of the surface result. Returns the resolved
829
+ // color (rgb from the blend, alpha from the surface tap), its confidence, and the hit-vs-surface trust.
830
+ const resolveSpecularHistory = () => {
831
+
832
+ const surfValid = historyUV.x.greaterThanEqual( 0 ).and( historyUV.x.lessThanEqual( 1 ) )
833
+ .and( historyUV.y.greaterThanEqual( 0 ) ).and( historyUV.y.lessThanEqual( 1 ) );
834
+
835
+ const historyUV_hit = reprojectHitPoint(
836
+ worldPosition,
837
+ neighborhood.get( 'rayLength' ),
838
+ cameraUniforms.worldPosition,
839
+ cameraUniforms.previousViewMatrix,
840
+ cameraUniforms.previousProjectionMatrix
841
+ ).toVar();
842
+
843
+ const hitValid = historyUV_hit.x.greaterThanEqual( 0 ).and( historyUV_hit.x.lessThanEqual( 1 ) )
844
+ .and( historyUV_hit.y.greaterThanEqual( 0 ) ).and( historyUV_hit.y.lessThanEqual( 1 ) )
845
+ .and( this.hitPointReprojection );
846
+
847
+ const hit = sampleHistory( historyUV_hit );
848
+
849
+ const hcHit = hit.get( 'color' ).rgb.max( 0 );
850
+ const hcSurf = surf.get( 'color' ).rgb.max( 0 );
851
+
852
+ const confHit = hitValid.select( hit.get( 'tapConfidence' ), float( 0 ) );
853
+ const confSurf = surfValid.select( surf.get( 'tapConfidence' ), float( 0 ) );
854
+ const minConfHit = hit.get( 'minConfidence' );
855
+
856
+ const reflectionEdgeFactor = neighborhood.get( 'stdDevRayLength' );
857
+ reflectionEdgeFactor.assign( reflectionEdgeFactor.mul( motionFactor.mul( 100 ).min( 1 ) ).mul( 3.5 ).min( 1 ).oneMinus() );
858
+
859
+ const curvatureFactor = fwidth( worldNormal.xyz ).length().mul( 50 ).clamp();
860
+
861
+ const envProbability = neighborhood.get( 'envProbability' );
862
+
863
+ const wHitRaw = minConfHit
864
+ .mul( reflectionEdgeFactor )
865
+ .mul( curvatureFactor.oneMinus() )
866
+ .mul( confHit ).toConst();
867
+
868
+ const wHit = wHitRaw.mul( envProbability.pow2().oneMinus() );
869
+ const wSurf = wHit.oneMinus().mul( confSurf );
870
+ const wSum = max( wHit.add( wSurf ), float( EPSILON ) );
871
+
872
+ const color = vec4(
873
+ hcHit.mul( wHit ).add( hcSurf.mul( wSurf ) ).div( wSum ),
874
+ surf.get( 'color' ).a
875
+ ).toVar();
876
+ const confidence = confHit.mul( wHit ).add( confSurf.mul( wSurf ) ).div( wSum );
877
+
878
+ // Near-black blend means neither tap was usable — fall back to the current frame.
879
+ If( color.rgb.length().lessThan( EPSILON ), () => {
880
+
881
+ color.assign( vec4( inputColor.rgb, 1 ) );
882
+
883
+ } );
884
+
885
+ return { color, confidence, trust: wHitRaw }; // without env probability
886
+
887
+ };
888
+
889
+ if ( isSpecular ) {
890
+
891
+ const spec = resolveSpecularHistory();
892
+ historyColor.assign( spec.color );
893
+ totalConfidence.assign( spec.confidence );
894
+ historyTrust.assign( spec.trust );
895
+
896
+ }
897
+
898
+ const a = historyColor.a.max( EPSILON );
899
+
900
+ // Universal stretch guard: reduce confidence where a "small area" is projected over a "large area".
901
+ const stretchConfidence = reprojectionStretchConfidence( historyUV, this._resolution );
902
+ totalConfidence.mulAssign( stretchConfidence.pow( 2 ) );
903
+
904
+ const varianceGamma = mix( float( VARIANCE_GAMMA_MIN ), float( VARIANCE_GAMMA_MAX ), motionFactor.oneMinus().pow2() );
905
+
906
+ const clippedRGB = applyVarianceClipping(
907
+ historyColor,
908
+ neighborhood.get( 'mean' ),
909
+ neighborhood.get( 'stdColor' ),
910
+ varianceGamma,
911
+ this.flickerSuppression
912
+ ).toVar();
913
+
914
+ const clampIntensity = this.clampIntensity.mul( max( motionFactor.mul( 10 ).min( 1 ), 0.25 ) ).mul(
915
+ float( 1 ).add( stretchConfidence.oneMinus().add( historyTrust.oneMinus() ).clamp() )
916
+ );
917
+ const originalHistoryColor = vec3( historyColor.rgb );
918
+ historyColor.rgb.assign( mix( historyColor.rgb, clippedRGB, clampIntensity ) );
919
+
920
+ totalConfidence.mulAssign( exp( originalHistoryColor.sub( clippedRGB ).length().mul( clampIntensity ).mul( 30 ).negate() ) );
921
+ totalConfidence.mulAssign( mix( float( 1 ), historyTrust.mul( 0.05 ).add( 0.95 ), motionFactor.mul( 100 ).clamp() ) );
922
+
923
+ If( totalConfidence.lessThan( EPSILON ), () => {
924
+
925
+ historyColor.assign( vec4( inputColor.rgb, 1 ) );
926
+
927
+ } );
928
+
929
+ const currentFrameCount = float( 1 ).div( a ).mul( totalConfidence ).add( 1 ).min( this.maxFrames ).toVar();
930
+
931
+ if ( isSpecular ) {
932
+
933
+ // A black current sample means no reflection was found this frame (a miss, not dark).
934
+ // Since no valid sample was found, decrement the frame count (as the next accumulating pass will increase it).
935
+ If( inputColor.rgb.length().lessThan( EPSILON ), () => {
936
+
937
+ currentFrameCount.assign( currentFrameCount.sub( 1 ).max( 1 ) );
938
+
939
+ } );
940
+
941
+ }
942
+
943
+ return vec4( historyColor.rgb, float( 1 ).div( currentFrameCount ) );
944
+
945
+ } );
946
+
947
+ return resolve().context( builder.getSharedContext() );
948
+
949
+ }
950
+
951
+ _syncHistoryTextureBinding() {
952
+
953
+ if ( this.accumulate === true || this._externalHistoryTexture === null ) {
954
+
955
+ this._historyTextureNode.value = this._historyRenderTarget.texture;
956
+
957
+ } else {
958
+
959
+ this._historyTextureNode.value = this._externalHistoryTexture;
960
+
961
+ }
962
+
963
+ }
964
+
965
+ /**
966
+ * Supplies an external history source (e.g. a {@link RecurrentDenoiseNode} or its
967
+ * texture). Only used when {@link TemporalReprojectNode#accumulate} is `false`.
968
+ *
969
+ * @param {?(Object|Texture)} source
970
+ */
971
+ setHistoryTexture( source ) {
972
+
973
+ this._externalHistoryTexture = ( source && typeof source.getRenderTarget === 'function' )
974
+ ? source.getRenderTarget().texture
975
+ : source;
976
+ this._syncHistoryTextureBinding();
977
+
978
+ }
979
+
980
+ dispose() {
981
+
982
+ this._previousNormalTexture.dispose();
983
+
984
+ if ( this._previousDepthNode.value !== this._historyRenderTarget.depthTexture ) {
985
+
986
+ this._previousDepthNode.value.dispose();
987
+
988
+ }
989
+
990
+ if ( this._placeholderPreviousDepthTexture !== this._historyRenderTarget.depthTexture ) {
991
+
992
+ this._placeholderPreviousDepthTexture.dispose();
993
+
994
+ }
995
+
996
+ this._historyRenderTarget.dispose();
997
+ this._resolveRenderTarget.dispose();
998
+ this._resolveMaterial.dispose();
999
+ this._seedMaterial.dispose();
1000
+
1001
+ }
1002
+
1003
+ }
1004
+
1005
+ export default TemporalReprojectNode;
1006
+
1007
+ /**
1008
+ * @param {TextureNode} beautyNode
1009
+ * @param {TextureNode} depthNode
1010
+ * @param {TextureNode} normalNode
1011
+ * @param {TextureNode} velocityNode
1012
+ * @param {Camera} camera
1013
+ * @param {TemporalReprojectNodeOptions} [options]
1014
+ * @returns {TemporalReprojectNode}
1015
+ */
1016
+ export const temporalReproject = ( beautyNode, depthNode, normalNode, velocityNode, camera, options = {} ) => nodeObject( new TemporalReprojectNode(
1017
+ convertToTexture( beautyNode ),
1018
+ nodeObject( depthNode ),
1019
+ nodeObject( normalNode ),
1020
+ nodeObject( velocityNode ),
1021
+ camera,
1022
+ options
1023
+ ) );