@plastic-software/three 0.180.0 → 0.181.2

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 (357) hide show
  1. package/build/three.cjs +944 -487
  2. package/build/three.core.js +506 -327
  3. package/build/three.core.min.js +1 -1
  4. package/build/three.module.js +436 -164
  5. package/build/three.module.min.js +1 -1
  6. package/build/three.tsl.js +8 -2
  7. package/build/three.tsl.min.js +1 -1
  8. package/build/three.webgpu.js +3753 -1177
  9. package/build/three.webgpu.min.js +1 -1
  10. package/build/three.webgpu.nodes.js +3752 -1176
  11. package/build/three.webgpu.nodes.min.js +1 -1
  12. package/examples/fonts/MPLUSRounded1c/MPLUSRounded1c-Regular.typeface.json.zip +0 -0
  13. package/examples/fonts/MPLUSRounded1c/OFL.txt +91 -0
  14. package/examples/jsm/animation/CCDIKSolver.js +1 -1
  15. package/examples/jsm/controls/ArcballControls.js +1 -1
  16. package/examples/jsm/controls/DragControls.js +1 -1
  17. package/examples/jsm/controls/FirstPersonControls.js +1 -1
  18. package/examples/jsm/controls/FlyControls.js +1 -1
  19. package/examples/jsm/controls/OrbitControls.js +2 -2
  20. package/examples/jsm/controls/PointerLockControls.js +2 -2
  21. package/examples/jsm/controls/TrackballControls.js +1 -1
  22. package/examples/jsm/controls/TransformControls.js +1 -1
  23. package/examples/jsm/effects/AsciiEffect.js +8 -8
  24. package/examples/jsm/exporters/DRACOExporter.js +2 -2
  25. package/examples/jsm/exporters/EXRExporter.js +1 -1
  26. package/examples/jsm/exporters/GLTFExporter.js +3 -3
  27. package/examples/jsm/exporters/USDZExporter.js +9 -2
  28. package/examples/jsm/geometries/DecalGeometry.js +2 -2
  29. package/examples/jsm/geometries/ParametricGeometry.js +1 -1
  30. package/examples/jsm/geometries/TeapotGeometry.js +2 -2
  31. package/examples/jsm/geometries/TextGeometry.js +3 -2
  32. package/examples/jsm/gpgpu/BitonicSort.js +715 -0
  33. package/examples/jsm/helpers/ViewHelper.js +43 -5
  34. package/examples/jsm/inspector/Inspector.js +427 -0
  35. package/examples/jsm/inspector/RendererInspector.js +415 -0
  36. package/examples/jsm/inspector/tabs/Console.js +204 -0
  37. package/examples/jsm/inspector/tabs/Parameters.js +332 -0
  38. package/examples/jsm/inspector/tabs/Performance.js +268 -0
  39. package/examples/jsm/inspector/tabs/Viewer.js +166 -0
  40. package/examples/jsm/inspector/ui/Graph.js +95 -0
  41. package/examples/jsm/inspector/ui/Item.js +170 -0
  42. package/examples/jsm/inspector/ui/List.js +75 -0
  43. package/examples/jsm/inspector/ui/Profiler.js +170 -0
  44. package/examples/jsm/inspector/ui/Style.js +654 -0
  45. package/examples/jsm/inspector/ui/Tab.js +46 -0
  46. package/examples/jsm/inspector/ui/Values.js +423 -0
  47. package/examples/jsm/inspector/ui/utils.js +56 -0
  48. package/examples/jsm/interactive/HTMLMesh.js +6 -10
  49. package/examples/jsm/interactive/InteractiveGroup.js +1 -1
  50. package/examples/jsm/interactive/SelectionBox.js +30 -0
  51. package/examples/jsm/lights/RectAreaLightTexturesLib.js +1 -1
  52. package/examples/jsm/loaders/3MFLoader.js +1 -1
  53. package/examples/jsm/loaders/ColladaLoader.js +2 -2
  54. package/examples/jsm/loaders/DDSLoader.js +1 -1
  55. package/examples/jsm/loaders/DRACOLoader.js +73 -22
  56. package/examples/jsm/loaders/FBXLoader.js +2 -2
  57. package/examples/jsm/loaders/FontLoader.js +23 -5
  58. package/examples/jsm/loaders/GLTFLoader.js +5 -3
  59. package/examples/jsm/loaders/KTX2Loader.js +28 -21
  60. package/examples/jsm/loaders/KTXLoader.js +2 -2
  61. package/examples/jsm/loaders/LDrawLoader.js +1 -1
  62. package/examples/jsm/loaders/LUT3dlLoader.js +2 -2
  63. package/examples/jsm/loaders/LUTCubeLoader.js +1 -1
  64. package/examples/jsm/loaders/LWOLoader.js +2 -2
  65. package/examples/jsm/loaders/MaterialXLoader.js +22 -5
  66. package/examples/jsm/loaders/OBJLoader.js +1 -1
  67. package/examples/jsm/loaders/PDBLoader.js +1 -1
  68. package/examples/jsm/loaders/SVGLoader.js +2 -2
  69. package/examples/jsm/loaders/UltraHDRLoader.js +1 -1
  70. package/examples/jsm/math/ConvexHull.js +1 -1
  71. package/examples/jsm/math/ImprovedNoise.js +1 -1
  72. package/examples/jsm/math/SimplexNoise.js +1 -1
  73. package/examples/jsm/misc/ProgressiveLightMap.js +9 -3
  74. package/examples/jsm/misc/ProgressiveLightMapGPU.js +7 -1
  75. package/examples/jsm/misc/TubePainter.js +383 -40
  76. package/examples/jsm/modifiers/SimplifyModifier.js +1 -1
  77. package/examples/jsm/objects/ReflectorForSSRPass.js +1 -0
  78. package/examples/jsm/objects/Sky.js +1 -1
  79. package/examples/jsm/objects/SkyMesh.js +1 -1
  80. package/examples/jsm/objects/Water.js +3 -3
  81. package/examples/jsm/objects/WaterMesh.js +6 -6
  82. package/examples/jsm/postprocessing/GlitchPass.js +2 -2
  83. package/examples/jsm/postprocessing/UnrealBloomPass.js +8 -6
  84. package/examples/jsm/renderers/CSS2DRenderer.js +16 -5
  85. package/examples/jsm/renderers/CSS3DRenderer.js +7 -6
  86. package/examples/jsm/renderers/SVGRenderer.js +1 -1
  87. package/examples/jsm/shaders/ACESFilmicToneMappingShader.js +1 -1
  88. package/examples/jsm/shaders/AfterimageShader.js +1 -1
  89. package/examples/jsm/shaders/BleachBypassShader.js +1 -1
  90. package/examples/jsm/shaders/BokehShader.js +1 -1
  91. package/examples/jsm/shaders/BokehShader2.js +1 -1
  92. package/examples/jsm/shaders/DotScreenShader.js +1 -1
  93. package/examples/jsm/shaders/FocusShader.js +1 -1
  94. package/examples/jsm/shaders/GTAOShader.js +2 -2
  95. package/examples/jsm/shaders/GodRaysShader.js +1 -1
  96. package/examples/jsm/shaders/KaleidoShader.js +1 -1
  97. package/examples/jsm/shaders/PoissonDenoiseShader.js +2 -2
  98. package/examples/jsm/shaders/SSRShader.js +1 -1
  99. package/examples/jsm/shaders/SepiaShader.js +1 -1
  100. package/examples/jsm/shaders/SubsurfaceScatteringShader.js +1 -1
  101. package/examples/jsm/shaders/TriangleBlurShader.js +1 -1
  102. package/examples/jsm/shaders/VignetteShader.js +1 -1
  103. package/examples/jsm/transpiler/TSLEncoder.js +7 -0
  104. package/examples/jsm/tsl/display/AfterImageNode.js +26 -24
  105. package/examples/jsm/tsl/display/AnamorphicNode.js +2 -1
  106. package/examples/jsm/tsl/display/BloomNode.js +4 -0
  107. package/examples/jsm/tsl/display/DenoiseNode.js +2 -0
  108. package/examples/jsm/tsl/display/DepthOfFieldNode.js +7 -0
  109. package/examples/jsm/tsl/display/GTAONode.js +45 -5
  110. package/examples/jsm/tsl/display/GaussianBlurNode.js +5 -3
  111. package/examples/jsm/tsl/display/OutlineNode.js +11 -0
  112. package/examples/jsm/tsl/display/SSGINode.js +654 -0
  113. package/examples/jsm/tsl/display/SSRNode.js +2 -0
  114. package/examples/jsm/tsl/display/SSSNode.js +488 -0
  115. package/examples/jsm/tsl/display/TRAANode.js +123 -6
  116. package/examples/jsm/tsl/display/boxBlur.js +1 -0
  117. package/examples/jsm/tsl/display/hashBlur.js +1 -0
  118. package/examples/jsm/tsl/lighting/TiledLightsNode.js +21 -1
  119. package/examples/jsm/webxr/XRControllerModelFactory.js +1 -1
  120. package/examples/jsm/webxr/XRHandModelFactory.js +2 -6
  121. package/package.json +5 -10
  122. package/src/Three.Core.js +3 -2
  123. package/src/Three.TSL.js +7 -1
  124. package/src/Three.WebGPU.Nodes.js +2 -0
  125. package/src/Three.WebGPU.js +2 -0
  126. package/src/animation/AnimationClip.js +3 -2
  127. package/src/animation/AnimationMixer.js +3 -3
  128. package/src/animation/AnimationObjectGroup.js +2 -1
  129. package/src/animation/KeyframeTrack.js +7 -6
  130. package/src/animation/PropertyBinding.js +12 -11
  131. package/src/audio/Audio.js +10 -9
  132. package/src/audio/PositionalAudio.js +1 -1
  133. package/src/cameras/OrthographicCamera.js +1 -1
  134. package/src/cameras/PerspectiveCamera.js +1 -1
  135. package/src/cameras/StereoCamera.js +2 -2
  136. package/src/constants.js +1 -1
  137. package/src/core/BufferGeometry.js +8 -8
  138. package/src/core/EventDispatcher.js +1 -1
  139. package/src/core/InterleavedBuffer.js +1 -1
  140. package/src/core/InterleavedBufferAttribute.js +3 -2
  141. package/src/core/Object3D.js +3 -2
  142. package/src/core/Raycaster.js +2 -1
  143. package/src/core/RenderTarget.js +10 -1
  144. package/src/extras/Controls.js +5 -4
  145. package/src/extras/DataUtils.js +2 -1
  146. package/src/extras/Earcut.js +6 -0
  147. package/src/extras/ImageUtils.js +2 -2
  148. package/src/extras/PMREMGenerator.js +268 -55
  149. package/src/extras/core/Curve.js +2 -1
  150. package/src/extras/core/Interpolations.js +7 -1
  151. package/src/extras/core/ShapePath.js +4 -4
  152. package/src/extras/lib/earcut.js +7 -7
  153. package/src/geometries/BoxGeometry.js +1 -0
  154. package/src/geometries/CapsuleGeometry.js +1 -0
  155. package/src/geometries/CircleGeometry.js +1 -0
  156. package/src/geometries/ConeGeometry.js +1 -0
  157. package/src/geometries/CylinderGeometry.js +1 -0
  158. package/src/geometries/DodecahedronGeometry.js +1 -0
  159. package/src/geometries/ExtrudeGeometry.js +8 -6
  160. package/src/geometries/IcosahedronGeometry.js +1 -0
  161. package/src/geometries/LatheGeometry.js +1 -0
  162. package/src/geometries/OctahedronGeometry.js +1 -0
  163. package/src/geometries/PlaneGeometry.js +1 -0
  164. package/src/geometries/RingGeometry.js +1 -0
  165. package/src/geometries/ShapeGeometry.js +1 -0
  166. package/src/geometries/SphereGeometry.js +1 -0
  167. package/src/geometries/TetrahedronGeometry.js +1 -0
  168. package/src/geometries/TorusGeometry.js +1 -0
  169. package/src/geometries/TorusKnotGeometry.js +1 -0
  170. package/src/geometries/TubeGeometry.js +1 -0
  171. package/src/helpers/CameraHelper.js +1 -1
  172. package/src/loaders/AnimationLoader.js +2 -1
  173. package/src/loaders/AudioLoader.js +2 -1
  174. package/src/loaders/BufferGeometryLoader.js +2 -2
  175. package/src/loaders/Cache.js +2 -2
  176. package/src/loaders/DataTextureLoader.js +1 -1
  177. package/src/loaders/FileLoader.js +3 -2
  178. package/src/loaders/ImageBitmapLoader.js +5 -4
  179. package/src/loaders/ImageLoader.js +1 -1
  180. package/src/loaders/Loader.js +3 -3
  181. package/src/loaders/LoadingManager.js +25 -3
  182. package/src/loaders/MaterialLoader.js +3 -2
  183. package/src/loaders/ObjectLoader.js +13 -13
  184. package/src/loaders/TextureLoader.js +1 -1
  185. package/src/loaders/nodes/NodeLoader.js +3 -2
  186. package/src/materials/Material.js +4 -3
  187. package/src/materials/MeshBasicMaterial.js +1 -0
  188. package/src/materials/MeshDepthMaterial.js +1 -0
  189. package/src/materials/MeshLambertMaterial.js +2 -1
  190. package/src/materials/MeshMatcapMaterial.js +22 -0
  191. package/src/materials/MeshNormalMaterial.js +1 -0
  192. package/src/materials/MeshPhongMaterial.js +2 -1
  193. package/src/materials/MeshPhysicalMaterial.js +2 -1
  194. package/src/materials/MeshStandardMaterial.js +8 -7
  195. package/src/materials/MeshToonMaterial.js +1 -0
  196. package/src/materials/PointsMaterial.js +1 -1
  197. package/src/materials/ShaderMaterial.js +2 -2
  198. package/src/materials/nodes/Line2NodeMaterial.js +2 -2
  199. package/src/materials/nodes/MeshSSSNodeMaterial.js +1 -1
  200. package/src/materials/nodes/NodeMaterial.js +62 -22
  201. package/src/materials/nodes/manager/NodeMaterialObserver.js +2 -1
  202. package/src/math/Color.js +6 -5
  203. package/src/math/ColorManagement.js +2 -2
  204. package/src/math/Cylindrical.js +1 -1
  205. package/src/math/Euler.js +2 -1
  206. package/src/math/MathUtils.js +13 -11
  207. package/src/math/Matrix2.js +1 -1
  208. package/src/math/Matrix3.js +2 -2
  209. package/src/math/Matrix4.js +7 -7
  210. package/src/math/Plane.js +1 -1
  211. package/src/math/Quaternion.js +68 -66
  212. package/src/math/Spherical.js +1 -1
  213. package/src/nodes/Nodes.js +1 -1
  214. package/src/nodes/TSL.js +1 -1
  215. package/src/nodes/accessors/CubeTextureNode.js +3 -2
  216. package/src/nodes/accessors/InstanceNode.js +22 -4
  217. package/src/nodes/accessors/Lights.js +10 -0
  218. package/src/nodes/accessors/Normal.js +5 -4
  219. package/src/nodes/accessors/Position.js +18 -2
  220. package/src/nodes/accessors/ReferenceNode.js +2 -1
  221. package/src/nodes/accessors/SceneNode.js +2 -1
  222. package/src/nodes/accessors/StorageBufferNode.js +2 -1
  223. package/src/nodes/accessors/StorageTextureNode.js +22 -0
  224. package/src/nodes/accessors/Texture3DNode.js +1 -1
  225. package/src/nodes/accessors/TextureNode.js +61 -27
  226. package/src/nodes/code/FunctionCallNode.js +5 -4
  227. package/src/nodes/core/ArrayNode.js +1 -0
  228. package/src/nodes/core/AttributeNode.js +2 -1
  229. package/src/nodes/core/ContextNode.js +5 -10
  230. package/src/nodes/core/IndexNode.js +2 -2
  231. package/src/nodes/core/InputNode.js +2 -1
  232. package/src/nodes/core/InspectorNode.js +128 -0
  233. package/src/nodes/core/{CacheNode.js → IsolateNode.js} +40 -7
  234. package/src/nodes/core/Node.js +137 -12
  235. package/src/nodes/core/NodeBuilder.js +135 -21
  236. package/src/nodes/core/NodeFrame.js +20 -20
  237. package/src/nodes/core/NodeFunction.js +2 -1
  238. package/src/nodes/core/NodeParser.js +2 -1
  239. package/src/nodes/core/NodeUtils.js +17 -90
  240. package/src/nodes/core/ParameterNode.js +31 -0
  241. package/src/nodes/core/PropertyNode.js +7 -0
  242. package/src/nodes/core/StackNode.js +16 -14
  243. package/src/nodes/core/UniformNode.js +2 -1
  244. package/src/nodes/core/VarNode.js +70 -12
  245. package/src/nodes/core/VaryingNode.js +3 -2
  246. package/src/nodes/display/BlendModes.js +5 -4
  247. package/src/nodes/display/BumpMapNode.js +1 -1
  248. package/src/nodes/display/ColorAdjustment.js +1 -1
  249. package/src/nodes/display/NormalMapNode.js +2 -1
  250. package/src/nodes/display/PassNode.js +51 -10
  251. package/src/nodes/display/RenderOutputNode.js +28 -2
  252. package/src/nodes/display/ScreenNode.js +2 -1
  253. package/src/nodes/display/ToneMappingNode.js +31 -4
  254. package/src/nodes/display/ToonOutlinePassNode.js +8 -0
  255. package/src/nodes/fog/Fog.js +3 -2
  256. package/src/nodes/functions/BSDF/BRDF_GGX_Multiscatter.js +52 -0
  257. package/src/nodes/functions/BSDF/DFGApprox.js +60 -19
  258. package/src/nodes/functions/BasicLightingModel.js +2 -1
  259. package/src/nodes/functions/PhysicalLightingModel.js +3 -2
  260. package/src/nodes/functions/VolumetricLightingModel.js +5 -5
  261. package/src/nodes/geometry/RangeNode.js +40 -4
  262. package/src/nodes/gpgpu/ComputeBuiltinNode.js +2 -1
  263. package/src/nodes/gpgpu/ComputeNode.js +17 -5
  264. package/src/nodes/gpgpu/SubgroupFunctionNode.js +25 -0
  265. package/src/nodes/gpgpu/WorkgroupInfoNode.js +2 -1
  266. package/src/nodes/lighting/EnvironmentNode.js +6 -6
  267. package/src/nodes/lighting/LightsNode.js +2 -3
  268. package/src/nodes/lighting/PointShadowNode.js +6 -0
  269. package/src/nodes/lighting/ShadowFilterNode.js +2 -0
  270. package/src/nodes/lighting/ShadowNode.js +75 -8
  271. package/src/nodes/math/ConditionalNode.js +6 -5
  272. package/src/nodes/math/MathNode.js +22 -4
  273. package/src/nodes/math/OperatorNode.js +3 -2
  274. package/src/nodes/pmrem/PMREMUtils.js +117 -2
  275. package/src/nodes/shapes/Shapes.js +1 -1
  276. package/src/nodes/tsl/TSLBase.js +5 -2
  277. package/src/nodes/tsl/TSLCore.js +36 -15
  278. package/src/nodes/utils/DebugNode.js +2 -1
  279. package/src/nodes/utils/EventNode.js +36 -0
  280. package/src/nodes/utils/FunctionOverloadingNode.js +37 -19
  281. package/src/nodes/utils/JoinNode.js +3 -2
  282. package/src/nodes/utils/LoopNode.js +20 -24
  283. package/src/nodes/utils/MemberNode.js +2 -1
  284. package/src/nodes/utils/PostProcessingUtils.js +28 -1
  285. package/src/nodes/utils/RTTNode.js +12 -2
  286. package/src/nodes/utils/ReflectorNode.js +10 -3
  287. package/src/objects/Line.js +2 -1
  288. package/src/objects/LineSegments.js +2 -1
  289. package/src/objects/Skeleton.js +3 -2
  290. package/src/objects/SkinnedMesh.js +3 -1
  291. package/src/objects/Sprite.js +2 -1
  292. package/src/renderers/WebGLRenderer.js +49 -33
  293. package/src/renderers/common/Animation.js +13 -1
  294. package/src/renderers/common/Backend.js +93 -30
  295. package/src/renderers/common/Background.js +2 -1
  296. package/src/renderers/common/Bindings.js +56 -2
  297. package/src/renderers/common/CanvasTarget.js +341 -0
  298. package/src/renderers/common/Geometries.js +26 -0
  299. package/src/renderers/common/Info.js +4 -2
  300. package/src/renderers/common/InspectorBase.js +146 -0
  301. package/src/renderers/common/PostProcessing.js +6 -25
  302. package/src/renderers/common/QuadMesh.js +7 -1
  303. package/src/renderers/common/RenderList.js +7 -3
  304. package/src/renderers/common/RenderObject.js +3 -1
  305. package/src/renderers/common/RenderObjects.js +1 -1
  306. package/src/renderers/common/Renderer.js +436 -228
  307. package/src/renderers/common/RendererUtils.js +9 -0
  308. package/src/renderers/common/SampledTexture.js +8 -0
  309. package/src/renderers/common/Sampler.js +37 -11
  310. package/src/renderers/common/StorageTexture.js +9 -1
  311. package/src/renderers/common/Textures.js +89 -35
  312. package/src/renderers/common/TimestampQueryPool.js +63 -1
  313. package/src/renderers/common/UniformsGroup.js +2 -1
  314. package/src/renderers/common/XRManager.js +7 -3
  315. package/src/renderers/common/extras/PMREMGenerator.js +160 -65
  316. package/src/renderers/common/nodes/NodeLibrary.js +4 -2
  317. package/src/renderers/common/nodes/NodeSampler.js +13 -1
  318. package/src/renderers/common/nodes/Nodes.js +38 -16
  319. package/src/renderers/shaders/DFGLUTData.js +64 -0
  320. package/src/renderers/shaders/ShaderChunk/common.glsl.js +0 -12
  321. package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +1 -1
  322. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +1 -1
  323. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +52 -18
  324. package/src/renderers/shaders/UniformsLib.js +1 -0
  325. package/src/renderers/shaders/UniformsUtils.js +25 -4
  326. package/src/renderers/webgl/WebGLCapabilities.js +2 -1
  327. package/src/renderers/webgl/WebGLExtensions.js +2 -25
  328. package/src/renderers/webgl/WebGLInfo.js +3 -1
  329. package/src/renderers/webgl/WebGLProgram.js +11 -10
  330. package/src/renderers/webgl/WebGLPrograms.js +2 -1
  331. package/src/renderers/webgl/WebGLShadowMap.js +2 -1
  332. package/src/renderers/webgl/WebGLState.js +15 -14
  333. package/src/renderers/webgl/WebGLTextures.js +18 -14
  334. package/src/renderers/webgl/WebGLUniformsGroups.js +5 -3
  335. package/src/renderers/webgl-fallback/WebGLBackend.js +22 -41
  336. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +74 -11
  337. package/src/renderers/webgl-fallback/utils/WebGLConstants.js +2 -3
  338. package/src/renderers/webgl-fallback/utils/WebGLState.js +6 -5
  339. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +117 -16
  340. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +42 -12
  341. package/src/renderers/webgpu/WebGPUBackend.js +134 -108
  342. package/src/renderers/webgpu/WebGPURenderer.Nodes.js +2 -1
  343. package/src/renderers/webgpu/WebGPURenderer.js +3 -2
  344. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +21 -19
  345. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +2 -1
  346. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +5 -3
  347. package/src/renderers/webgpu/utils/WebGPUConstants.js +5 -0
  348. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +44 -16
  349. package/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js +6 -8
  350. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +146 -74
  351. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +29 -6
  352. package/src/renderers/webgpu/utils/WebGPUUtils.js +22 -2
  353. package/src/renderers/webxr/WebXRManager.js +3 -2
  354. package/src/textures/Source.js +2 -1
  355. package/src/textures/Texture.js +3 -2
  356. package/src/textures/VideoTexture.js +2 -0
  357. package/src/utils.js +67 -3
@@ -0,0 +1,488 @@
1
+ import { RedFormat, RenderTarget, Vector2, RendererUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType, UnsignedByteType } from 'three/webgpu';
2
+ import { reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, float, Break, Loop, int, max, abs, If, interleavedGradientNoise, screenCoordinate, nodeObject, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, lightPosition, lightTargetPosition, fract, rand, mix } from 'three/tsl';
3
+
4
+ const _quadMesh = /*@__PURE__*/ new QuadMesh();
5
+ const _size = /*@__PURE__*/ new Vector2();
6
+
7
+ const _spatialOffsets = [ 0, 0.5, 0.25, 0.75 ];
8
+
9
+ let _rendererState;
10
+
11
+ /**
12
+ * Post processing node for applying Screen-Space Shadows (SSS) to a scene.
13
+ *
14
+ * Screen-Space Shadows (also known as Contact Shadows) should ideally be used to complement
15
+ * traditional shadow maps. They are best suited for rendering detailed shadows of smaller
16
+ * objects at a closer scale like intricate shadowing on highly detailed models. In other words:
17
+ * Use Shadow Maps for the foundation and Screen-Space Shadows for the details.
18
+ *
19
+ * The shadows produced by this implementation might have too hard edges for certain use cases.
20
+ * Use a box, gaussian or hash blur to soften the edges before doing the composite with the
21
+ * beauty pass. Code example:
22
+ *
23
+ * ```js
24
+ * const sssPass = sss( scenePassDepth, camera, mainLight );
25
+ *
26
+ * const sssBlur = boxBlur( sssPass.r, { size: 2, separation: 1 } ); // optional blur
27
+ * ```
28
+ *
29
+ * Limitations:
30
+ *
31
+ * - Ideally the maximum shadow length should not exceed `1` meter. Otherwise the effect gets
32
+ * computationally very expensive since more samples during the ray marching process are evaluated.
33
+ * You can mitigate this issue by reducing the `quality` paramter.
34
+ * - The effect can only be used with a single directional light, the main light of your scene.
35
+ * This main light usually represents the sun or daylight.
36
+ * - Like other Screen-Space techniques SSS can only honor objects in the shadowing computation that
37
+ * are currently visible within the camera's view.
38
+ *
39
+ * References:
40
+ * - {@link https://panoskarabelas.com/posts/screen_space_shadows/}.
41
+ * - {@link https://www.bendstudio.com/blog/inside-bend-screen-space-shadows/}.
42
+ *
43
+ * @augments TempNode
44
+ * @three_import import { sss } from 'three/addons/tsl/display/SSSNode.js';
45
+ */
46
+ class SSSNode extends TempNode {
47
+
48
+ static get type() {
49
+
50
+ return 'SSSNode';
51
+
52
+ }
53
+
54
+ /**
55
+ * Constructs a new SSS node.
56
+ *
57
+ * @param {TextureNode} depthNode - A texture node that represents the scene's depth.
58
+ * @param {Camera} camera - The camera the scene is rendered with.
59
+ * @param {DirectionalLight} mainLight - The main directional light of the scene.
60
+ */
61
+ constructor( depthNode, camera, mainLight ) {
62
+
63
+ super( 'float' );
64
+
65
+ /**
66
+ * A node that represents the beauty pass's depth.
67
+ *
68
+ * @type {TextureNode}
69
+ */
70
+ this.depthNode = depthNode;
71
+
72
+ /**
73
+ * Maximum shadow length in world units. Longer shadows result in more computational
74
+ * overhead.
75
+ *
76
+ * @type {UniformNode<float>}
77
+ * @default 0.1
78
+ */
79
+ this.maxDistance = uniform( 0.1, 'float' );
80
+
81
+ /**
82
+ * Depth testing thickness.
83
+ *
84
+ * @type {UniformNode<float>}
85
+ * @default 0.01
86
+ */
87
+ this.thickness = uniform( 0.01, 'float' );
88
+
89
+ /**
90
+ * Shadow intensity. Must be in the range `[0, 1]`.
91
+ *
92
+ * @type {UniformNode<float>}
93
+ * @default 0.5
94
+ */
95
+ this.shadowIntensity = uniform( 0.5, 'float' );
96
+
97
+ /**
98
+ * This parameter controls how detailed the raymarching process works.
99
+ * The value ranges is `[0,1]` where `1` means best quality (the maximum number
100
+ * of raymarching iterations/samples) and `0` means no samples at all.
101
+ *
102
+ * A quality of `0.5` is usually sufficient for most use cases. Try to keep
103
+ * this parameter as low as possible. Larger values result in noticeable more
104
+ * overhead.
105
+ *
106
+ * @type {UniformNode<float>}
107
+ * @default 0.5
108
+ */
109
+ this.quality = uniform( 0.5 );
110
+
111
+ /**
112
+ * The resolution scale. Valid values are in the range
113
+ * `[0,1]`. `1` means best quality but also results in
114
+ * more computational overhead. Setting to `0.5` means
115
+ * the effect is computed in half-resolution.
116
+ *
117
+ * @type {number}
118
+ * @default 1
119
+ */
120
+ this.resolutionScale = 1;
121
+
122
+ /**
123
+ * Whether to use temporal filtering or not. Setting this property to
124
+ * `true` requires the usage of `TRAANode`. This will help to reduce noice
125
+ * although it introduces typical TAA artifacts like ghosting and temporal
126
+ * instabilities.
127
+ *
128
+ * @type {boolean}
129
+ * @default false
130
+ */
131
+ this.useTemporalFiltering = false;
132
+
133
+ /**
134
+ * The `updateBeforeType` is set to `NodeUpdateType.FRAME` since the node renders
135
+ * its effect once per frame in `updateBefore()`.
136
+ *
137
+ * @type {string}
138
+ * @default 'frame'
139
+ */
140
+ this.updateBeforeType = NodeUpdateType.FRAME;
141
+
142
+ // private uniforms
143
+
144
+ /**
145
+ * Represents the view matrix of the scene's camera.
146
+ *
147
+ * @private
148
+ * @type {UniformNode<mat4>}
149
+ */
150
+ this._cameraViewMatrix = uniform( camera.matrixWorldInverse );
151
+
152
+ /**
153
+ * Represents the projection matrix of the scene's camera.
154
+ *
155
+ * @private
156
+ * @type {UniformNode<mat4>}
157
+ */
158
+ this._cameraProjectionMatrix = uniform( camera.projectionMatrix );
159
+
160
+ /**
161
+ * Represents the inverse projection matrix of the scene's camera.
162
+ *
163
+ * @private
164
+ * @type {UniformNode<mat4>}
165
+ */
166
+ this._cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse );
167
+
168
+ /**
169
+ * Represents the near value of the scene's camera.
170
+ *
171
+ * @private
172
+ * @type {ReferenceNode<float>}
173
+ */
174
+ this._cameraNear = reference( 'near', 'float', camera );
175
+
176
+ /**
177
+ * Represents the far value of the scene's camera.
178
+ *
179
+ * @private
180
+ * @type {ReferenceNode<float>}
181
+ */
182
+ this._cameraFar = reference( 'far', 'float', camera );
183
+
184
+ /**
185
+ * The resolution of the pass.
186
+ *
187
+ * @private
188
+ * @type {UniformNode<vec2>}
189
+ */
190
+ this._resolution = uniform( new Vector2() );
191
+
192
+ /**
193
+ * Temporal offset added to the initial ray step.
194
+ *
195
+ * @type {UniformNode<float>}
196
+ */
197
+ this._temporalOffset = uniform( 0 );
198
+
199
+ /**
200
+ * The frame ID use when temporal filtering is enabled.
201
+ *
202
+ * @type {UniformNode<uint>}
203
+ */
204
+ this._frameId = uniform( 0 );
205
+
206
+ /**
207
+ * A reference to the scene's main light.
208
+ *
209
+ * @private
210
+ * @type {DirectionalLight}
211
+ */
212
+ this._mainLight = mainLight;
213
+
214
+ /**
215
+ * The camera the scene is rendered with.
216
+ *
217
+ * @private
218
+ * @type {Camera}
219
+ */
220
+ this._camera = camera;
221
+
222
+ /**
223
+ * The render target the SSS is rendered into.
224
+ *
225
+ * @private
226
+ * @type {RenderTarget}
227
+ */
228
+ this._sssRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false, format: RedFormat, type: UnsignedByteType } );
229
+ this._sssRenderTarget.texture.name = 'SSS';
230
+
231
+ /**
232
+ * The material that is used to render the effect.
233
+ *
234
+ * @private
235
+ * @type {NodeMaterial}
236
+ */
237
+ this._material = new NodeMaterial();
238
+ this._material.name = 'SSS';
239
+
240
+ /**
241
+ * The result of the effect is represented as a separate texture node.
242
+ *
243
+ * @private
244
+ * @type {PassTextureNode}
245
+ */
246
+ this._textureNode = passTexture( this, this._sssRenderTarget.texture );
247
+
248
+
249
+ }
250
+
251
+ /**
252
+ * Returns the result of the effect as a texture node.
253
+ *
254
+ * @return {PassTextureNode} A texture node that represents the result of the effect.
255
+ */
256
+ getTextureNode() {
257
+
258
+ return this._textureNode;
259
+
260
+ }
261
+
262
+ /**
263
+ * Sets the size of the effect.
264
+ *
265
+ * @param {number} width - The width of the effect.
266
+ * @param {number} height - The height of the effect.
267
+ */
268
+ setSize( width, height ) {
269
+
270
+ width = Math.round( this.resolutionScale * width );
271
+ height = Math.round( this.resolutionScale * height );
272
+
273
+ this._resolution.value.set( width, height );
274
+ this._sssRenderTarget.setSize( width, height );
275
+
276
+ }
277
+
278
+ /**
279
+ * This method is used to render the effect once per frame.
280
+ *
281
+ * @param {NodeFrame} frame - The current node frame.
282
+ */
283
+ updateBefore( frame ) {
284
+
285
+ const { renderer } = frame;
286
+
287
+ _rendererState = RendererUtils.resetRendererState( renderer, _rendererState );
288
+
289
+ //
290
+
291
+ const size = renderer.getDrawingBufferSize( _size );
292
+ this.setSize( size.width, size.height );
293
+
294
+ // update temporal uniforms
295
+
296
+ if ( this.useTemporalFiltering === true ) {
297
+
298
+ const frameId = frame.frameId;
299
+
300
+ this._temporalOffset.value = _spatialOffsets[ frameId % 4 ];
301
+ this._frameId = frame.frameId;
302
+
303
+ } else {
304
+
305
+ this._temporalOffset.value = 0;
306
+ this._frameId = 0;
307
+
308
+ }
309
+
310
+ //
311
+
312
+ _quadMesh.material = this._material;
313
+ _quadMesh.name = 'SSS';
314
+
315
+ // clear
316
+
317
+ renderer.setClearColor( 0xffffff, 1 );
318
+
319
+ // sss
320
+
321
+ renderer.setRenderTarget( this._sssRenderTarget );
322
+ _quadMesh.render( renderer );
323
+
324
+ // restore
325
+
326
+ RendererUtils.restoreRendererState( renderer, _rendererState );
327
+
328
+ }
329
+
330
+ /**
331
+ * This method is used to setup the effect's TSL code.
332
+ *
333
+ * @param {NodeBuilder} builder - The current node builder.
334
+ * @return {PassTextureNode}
335
+ */
336
+ setup( builder ) {
337
+
338
+ const uvNode = uv();
339
+
340
+ const getViewZ = Fn( ( [ depth ] ) => {
341
+
342
+ let viewZNode;
343
+
344
+ if ( this._camera.isPerspectiveCamera ) {
345
+
346
+ viewZNode = perspectiveDepthToViewZ( depth, this._cameraNear, this._cameraFar );
347
+
348
+ } else {
349
+
350
+ viewZNode = orthographicDepthToViewZ( depth, this._cameraNear, this._cameraFar );
351
+
352
+ }
353
+
354
+ return viewZNode;
355
+
356
+ } );
357
+
358
+ const sampleDepth = ( uv ) => {
359
+
360
+ const depth = this.depthNode.sample( uv ).r;
361
+
362
+ if ( builder.renderer.logarithmicDepthBuffer === true ) {
363
+
364
+ const viewZ = logarithmicDepthToViewZ( depth, this._cameraNear, this._cameraFar );
365
+
366
+ return viewZToPerspectiveDepth( viewZ, this._cameraNear, this._cameraFar );
367
+
368
+ }
369
+
370
+ return depth;
371
+
372
+ };
373
+
374
+ const sss = Fn( () => {
375
+
376
+ const depth = sampleDepth( uvNode ).toVar();
377
+ depth.greaterThanEqual( 1.0 ).discard();
378
+
379
+ // compute ray position and direction (in view-space)
380
+
381
+ const rayStartPosition = getViewPosition( uvNode, depth, this._cameraProjectionMatrixInverse ).toVar( 'rayStartPosition' );
382
+ const rayDirection = this._cameraViewMatrix.transformDirection( lightPosition( this._mainLight ).sub( lightTargetPosition( this._mainLight ) ) ).toConst( 'rayDirection' );
383
+ const rayEndPosition = rayStartPosition.add( rayDirection.mul( this.maxDistance ) ).toConst( 'rayEndPosition' );
384
+
385
+ // d0 and d1 are the start and maximum points of the ray in screen space
386
+ const d0 = screenCoordinate.xy.toVar();
387
+ const d1 = getScreenPosition( rayEndPosition, this._cameraProjectionMatrix ).mul( this._resolution ).toVar();
388
+
389
+ // below variables are used to control the raymarching process
390
+
391
+ // total length of the ray
392
+ const totalLen = d1.sub( d0 ).length().toVar();
393
+
394
+ // offset in x and y direction
395
+ const xLen = d1.x.sub( d0.x ).toVar();
396
+ const yLen = d1.y.sub( d0.y ).toVar();
397
+
398
+ // determine the larger delta
399
+ // The larger difference will help to determine how much to travel in the X and Y direction each iteration and
400
+ // how many iterations are needed to travel the entire ray
401
+ const totalStep = int( max( abs( xLen ), abs( yLen ) ).mul( this.quality.clamp() ) ).toConst();
402
+
403
+ // step sizes in the x and y directions
404
+ const xSpan = xLen.div( totalStep ).toVar();
405
+ const ySpan = yLen.div( totalStep ).toVar();
406
+
407
+ // compute noise based ray offset
408
+ const noise = interleavedGradientNoise( screenCoordinate );
409
+ const offset = fract( noise.add( this._temporalOffset ) ).add( rand( uvNode.add( this._frameId ) ) ).toConst( 'offset' );
410
+
411
+ const occlusion = float( 0 ).toVar();
412
+
413
+ Loop( totalStep, ( { i } ) => {
414
+
415
+ // advance on the ray by computing a new position in screen coordinates
416
+ const xy = vec2( d0.x.add( xSpan.mul( float( i ).add( offset ) ) ), d0.y.add( ySpan.mul( float( i ).add( offset ) ) ) ).toVar();
417
+
418
+ // stop processing if the new position lies outside of the screen
419
+ If( xy.x.lessThan( 0 ).or( xy.x.greaterThan( this._resolution.x ) ).or( xy.y.lessThan( 0 ) ).or( xy.y.greaterThan( this._resolution.y ) ), () => {
420
+
421
+ Break();
422
+
423
+ } );
424
+
425
+ // compute new uv, depth and viewZ for the next fragment
426
+
427
+ const uvNode = xy.div( this._resolution );
428
+ const fragmentDepth = sampleDepth( uvNode ).toConst();
429
+ const fragmentViewZ = getViewZ( fragmentDepth ).toConst( 'fragmentViewZ' );
430
+
431
+ const s = xy.sub( d0 ).length().div( totalLen ).toVar();
432
+ const rayPosition = mix( rayStartPosition, rayEndPosition, s );
433
+
434
+ const depthDelta = rayPosition.z.sub( fragmentViewZ ).negate(); // Port note: viewZ values are negative in three
435
+
436
+ // check if the camera can't "see" the ray (ray depth must be larger than the camera depth, so positive depth_delta)
437
+
438
+ If( depthDelta.greaterThan( 0 ).and( depthDelta.lessThan( this.thickness ) ), () => {
439
+
440
+ // mark as occluded
441
+
442
+ occlusion.assign( this.shadowIntensity );
443
+
444
+ Break();
445
+
446
+ } );
447
+
448
+
449
+ } );
450
+
451
+ return occlusion.oneMinus();
452
+
453
+ } );
454
+
455
+ this._material.fragmentNode = sss().context( builder.getSharedContext() );
456
+ this._material.needsUpdate = true;
457
+
458
+ return this._textureNode;
459
+
460
+ }
461
+
462
+ /**
463
+ * Frees internal resources. This method should be called
464
+ * when the effect is no longer required.
465
+ */
466
+ dispose() {
467
+
468
+ this._sssRenderTarget.dispose();
469
+
470
+ this._material.dispose();
471
+
472
+ }
473
+
474
+ }
475
+
476
+ export default SSSNode;
477
+
478
+ /**
479
+ * TSL function for creating a SSS effect.
480
+ *
481
+ * @tsl
482
+ * @function
483
+ * @param {TextureNode} depthNode - A texture node that represents the scene's depth.
484
+ * @param {Camera} camera - The camera the scene is rendered with.
485
+ * @param {DirectionalLight} mainLight - The main directional light of the scene.
486
+ * @returns {SSSNode}
487
+ */
488
+ export const sss = ( depthNode, camera, mainLight ) => nodeObject( new SSSNode( depthNode, camera, mainLight ) );
@@ -1,5 +1,5 @@
1
- import { HalfFloatType, Vector2, RenderTarget, RendererUtils, QuadMesh, NodeMaterial, TempNode, NodeUpdateType, Matrix4 } from 'three/webgpu';
2
- import { add, float, If, Loop, int, Fn, min, max, clamp, nodeObject, texture, uniform, uv, vec2, vec4, luminance, convertToTexture, passTexture, velocity } from 'three/tsl';
1
+ import { HalfFloatType, Vector2, RenderTarget, RendererUtils, QuadMesh, NodeMaterial, TempNode, NodeUpdateType, Matrix4, DepthTexture } from 'three/webgpu';
2
+ import { add, float, If, Loop, int, Fn, min, max, clamp, nodeObject, texture, uniform, uv, vec2, vec4, luminance, convertToTexture, passTexture, velocity, getViewPosition, length } from 'three/tsl';
3
3
 
4
4
  const _quadMesh = /*@__PURE__*/ new QuadMesh();
5
5
  const _size = /*@__PURE__*/ new Vector2();
@@ -100,13 +100,45 @@ class TRAANode extends TempNode {
100
100
  */
101
101
  this._invSize = uniform( new Vector2() );
102
102
 
103
+ /**
104
+ * A uniform node holding the camera world matrix.
105
+ *
106
+ * @private
107
+ * @type {UniformNode<mat4>}
108
+ */
109
+ this._cameraWorldMatrix = uniform( new Matrix4() );
110
+
111
+ /**
112
+ * A uniform node holding the camera projection matrix inverse.
113
+ *
114
+ * @private
115
+ * @type {UniformNode<mat4>}
116
+ */
117
+ this._cameraProjectionMatrixInverse = uniform( new Matrix4() );
118
+
119
+ /**
120
+ * A uniform node holding the previous frame's view matrix.
121
+ *
122
+ * @private
123
+ * @type {UniformNode<mat4>}
124
+ */
125
+ this._previousCameraWorldMatrix = uniform( new Matrix4() );
126
+
127
+ /**
128
+ * A uniform node holding the previous frame's projection matrix inverse.
129
+ *
130
+ * @private
131
+ * @type {UniformNode<mat4>}
132
+ */
133
+ this._previousCameraProjectionMatrixInverse = uniform( new Matrix4() );
134
+
103
135
  /**
104
136
  * The render target that represents the history of frame data.
105
137
  *
106
138
  * @private
107
139
  * @type {?RenderTarget}
108
140
  */
109
- this._historyRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false, type: HalfFloatType } );
141
+ this._historyRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false, type: HalfFloatType, depthTexture: new DepthTexture() } );
110
142
  this._historyRenderTarget.texture.name = 'TRAANode.history';
111
143
 
112
144
  /**
@@ -143,6 +175,14 @@ class TRAANode extends TempNode {
143
175
  */
144
176
  this._originalProjectionMatrix = new Matrix4();
145
177
 
178
+ /**
179
+ * A texture node for the previous depth buffer.
180
+ *
181
+ * @private
182
+ * @type {TextureNode}
183
+ */
184
+ this._previousDepthNode = texture( new DepthTexture( 1, 1 ) );
185
+
146
186
  /**
147
187
  * Sync the post processing stack with the TRAA node.
148
188
  * @private
@@ -246,6 +286,16 @@ class TRAANode extends TempNode {
246
286
 
247
287
  const { renderer } = frame;
248
288
 
289
+ // store previous frame matrices before updating current ones
290
+
291
+ this._previousCameraWorldMatrix.value.copy( this._cameraWorldMatrix.value );
292
+ this._previousCameraProjectionMatrixInverse.value.copy( this._cameraProjectionMatrixInverse.value );
293
+
294
+ // update camera matrices uniforms
295
+
296
+ this._cameraWorldMatrix.value.copy( this.camera.matrixWorld );
297
+ this._cameraProjectionMatrixInverse.value.copy( this.camera.projectionMatrixInverse );
298
+
249
299
  // keep the TRAA in sync with the dimensions of the beauty node
250
300
 
251
301
  const beautyRenderTarget = ( this.beautyNode.isRTTNode ) ? this.beautyNode.renderTarget : this.beautyNode.passNode.renderTarget;
@@ -293,6 +343,7 @@ class TRAANode extends TempNode {
293
343
 
294
344
  renderer.setRenderTarget( this._resolveRenderTarget );
295
345
  _quadMesh.material = this._resolveMaterial;
346
+ _quadMesh.name = 'TRAA';
296
347
  _quadMesh.render( renderer );
297
348
  renderer.setRenderTarget( null );
298
349
 
@@ -300,6 +351,23 @@ class TRAANode extends TempNode {
300
351
 
301
352
  renderer.copyTextureToTexture( this._resolveRenderTarget.texture, this._historyRenderTarget.texture );
302
353
 
354
+ // Copy current depth to previous depth buffer
355
+
356
+ const size = renderer.getDrawingBufferSize( _size );
357
+
358
+ // only allow the depth copy if the dimensions of the history render target match with the drawing
359
+ // render buffer and thus the depth texture of the scene. For some reasons, there are timing issues
360
+ // with WebGPU resulting in different size of the drawing buffer and the beauty render target when
361
+ // resizing the browser window. This does not happen with the WebGL backend
362
+
363
+ if ( this._historyRenderTarget.height === size.height && this._historyRenderTarget.width === size.width ) {
364
+
365
+ const currentDepth = this.depthNode.value;
366
+ renderer.copyTextureToTexture( currentDepth, this._historyRenderTarget.depthTexture );
367
+ this._previousDepthNode.value = this._historyRenderTarget.depthTexture;
368
+
369
+ }
370
+
303
371
  // restore
304
372
 
305
373
  RendererUtils.restoreRendererState( renderer, _rendererState );
@@ -347,6 +415,7 @@ class TRAANode extends TempNode {
347
415
  const minColor = vec4( 10000 ).toVar();
348
416
  const maxColor = vec4( - 10000 ).toVar();
349
417
  const closestDepth = float( 1 ).toVar();
418
+ const farthestDepth = float( 0 ).toVar();
350
419
  const closestDepthPixelPosition = vec2( 0 ).toVar();
351
420
 
352
421
  // sample a 3x3 neighborhood to create a box in color space
@@ -373,6 +442,14 @@ class TRAANode extends TempNode {
373
442
 
374
443
  } );
375
444
 
445
+ // find the farthest depth in the neighborhood (used to preserve edge anti-aliasing)
446
+
447
+ If( currentDepth.greaterThan( farthestDepth ), () => {
448
+
449
+ farthestDepth.assign( currentDepth );
450
+
451
+ } );
452
+
376
453
  } );
377
454
 
378
455
  } );
@@ -388,11 +465,49 @@ class TRAANode extends TempNode {
388
465
 
389
466
  const clampedHistoryColor = clamp( historyColor, minColor, maxColor );
390
467
 
391
- // flicker reduction based on luminance weighing
468
+ // calculate current frame world position
469
+
470
+ const currentDepth = depthTexture.sample( uvNode ).r;
471
+ const currentViewPosition = getViewPosition( uvNode, currentDepth, this._cameraProjectionMatrixInverse );
472
+ const currentWorldPosition = this._cameraWorldMatrix.mul( vec4( currentViewPosition, 1.0 ) ).xyz;
473
+
474
+ // calculate previous frame world position from history UV and previous depth
392
475
 
393
- const currentWeight = float( 0.05 ).toVar();
476
+ const historyUV = uvNode.sub( offset );
477
+ const previousDepth = this._previousDepthNode.sample( historyUV ).r;
478
+ const previousViewPosition = getViewPosition( historyUV, previousDepth, this._previousCameraProjectionMatrixInverse );
479
+ const previousWorldPosition = this._previousCameraWorldMatrix.mul( vec4( previousViewPosition, 1.0 ) ).xyz;
480
+
481
+ // calculate difference in world positions
482
+
483
+ const worldPositionDifference = length( currentWorldPosition.sub( previousWorldPosition ) ).toVar();
484
+ worldPositionDifference.assign( min( max( worldPositionDifference.sub( 1.0 ), 0.0 ), 1.0 ) );
485
+
486
+ // Adaptive blend weights based on velocity magnitude suggested by CLAUDE in #32133
487
+ // Higher velocity or position difference = more weight on current frame to reduce ghosting
488
+
489
+ const velocityMagnitude = length( offset ).toConst();
490
+ const motionFactor = max( worldPositionDifference.mul( 0.5 ), velocityMagnitude.mul( 10.0 ) ).toVar();
491
+ motionFactor.assign( min( motionFactor, 1.0 ) );
492
+
493
+ const currentWeight = float( 0.05 ).add( motionFactor.mul( 0.25 ) ).toVar();
394
494
  const historyWeight = currentWeight.oneMinus().toVar();
395
495
 
496
+ // zero out history weight if world positions are different (indicating motion) except on edges.
497
+ // note that the constants 0.00001 and 0.5 were suggested by CLAUDE in #32133
498
+
499
+ const isEdge = farthestDepth.sub( closestDepth ).greaterThan( 0.00001 );
500
+ const strongDisocclusion = worldPositionDifference.greaterThan( 0.5 ).and( isEdge.not() );
501
+
502
+ If( strongDisocclusion, () => {
503
+
504
+ currentWeight.assign( 1.0 );
505
+ historyWeight.assign( 0.0 );
506
+
507
+ } );
508
+
509
+ // flicker reduction based on luminance weighing
510
+
396
511
  const compressedCurrent = currentColor.mul( float( 1 ).div( ( max( currentColor.r, currentColor.g, currentColor.b ).add( 1.0 ) ) ) );
397
512
  const compressedHistory = clampedHistoryColor.mul( float( 1 ).div( ( max( clampedHistoryColor.r, clampedHistoryColor.g, clampedHistoryColor.b ).add( 1.0 ) ) ) );
398
513
 
@@ -402,7 +517,9 @@ class TRAANode extends TempNode {
402
517
  currentWeight.mulAssign( float( 1.0 ).div( luminanceCurrent.add( 1 ) ) );
403
518
  historyWeight.mulAssign( float( 1.0 ).div( luminanceHistory.add( 1 ) ) );
404
519
 
405
- return add( currentColor.mul( currentWeight ), clampedHistoryColor.mul( historyWeight ) ).div( max( currentWeight.add( historyWeight ), 0.00001 ) );
520
+ const smoothedOutput = add( currentColor.mul( currentWeight ), clampedHistoryColor.mul( historyWeight ) ).div( max( currentWeight.add( historyWeight ), 0.00001 ) ).toVar();
521
+
522
+ return smoothedOutput;
406
523
 
407
524
  } );
408
525
 
@@ -14,6 +14,7 @@ import { Fn, vec2, uv, Loop, vec4, premultiplyAlpha, unpremultiplyAlpha, max, in
14
14
  *
15
15
  * Reference: {@link https://github.com/lettier/3d-game-shaders-for-beginners/blob/master/demonstration/shaders/fragment/box-blur.frag}.
16
16
  *
17
+ * @tsl
17
18
  * @function
18
19
  * @param {Node<vec4>} textureNode - The texture node that should be blurred.
19
20
  * @param {Object} [options={}] - Additional options for the hash blur effect.
@@ -12,6 +12,7 @@ import { float, Fn, vec2, uv, sin, rand, degrees, cos, Loop, vec4, premultiplyAl
12
12
  *
13
13
  * Reference: {@link https://www.shadertoy.com/view/4lXXWn}.
14
14
  *
15
+ * @tsl
15
16
  * @function
16
17
  * @param {Node<vec4>} textureNode - The texture node that should be blurred.
17
18
  * @param {Node<float>} [bluramount=float(0.1)] - This node determines the amount of blur.