@plastic-software/three 0.182.0 → 0.183.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 (298) hide show
  1. package/LICENSE +1 -1
  2. package/build/three.cjs +11520 -10877
  3. package/build/three.core.js +11732 -11340
  4. package/build/three.core.min.js +2 -2
  5. package/build/three.module.js +509 -262
  6. package/build/three.module.min.js +2 -2
  7. package/build/three.tsl.js +7 -11
  8. package/build/three.tsl.min.js +2 -2
  9. package/build/three.webgpu.js +3072 -2607
  10. package/build/three.webgpu.min.js +2 -2
  11. package/build/three.webgpu.nodes.js +3071 -2607
  12. package/build/three.webgpu.nodes.min.js +2 -2
  13. package/examples/jsm/Addons.js +0 -3
  14. package/examples/jsm/animation/CCDIKSolver.js +2 -2
  15. package/examples/jsm/controls/ArcballControls.js +3 -3
  16. package/examples/jsm/controls/OrbitControls.js +103 -0
  17. package/examples/jsm/effects/AnaglyphEffect.js +102 -7
  18. package/examples/jsm/environments/ColorEnvironment.js +59 -0
  19. package/examples/jsm/environments/RoomEnvironment.js +1 -0
  20. package/examples/jsm/exporters/EXRExporter.js +1 -1
  21. package/examples/jsm/exporters/GLTFExporter.js +131 -4
  22. package/examples/jsm/exporters/USDZExporter.js +22 -3
  23. package/examples/jsm/helpers/AnimationPathHelper.js +302 -0
  24. package/examples/jsm/helpers/ViewHelper.js +67 -8
  25. package/examples/jsm/inspector/Inspector.js +21 -5
  26. package/examples/jsm/inspector/tabs/Console.js +39 -5
  27. package/examples/jsm/inspector/tabs/Parameters.js +16 -0
  28. package/examples/jsm/inspector/ui/Style.js +25 -1
  29. package/examples/jsm/libs/meshopt_decoder.module.js +6 -5
  30. package/examples/jsm/lines/LineMaterial.js +6 -0
  31. package/examples/jsm/loaders/3MFLoader.js +2 -2
  32. package/examples/jsm/loaders/AMFLoader.js +2 -2
  33. package/examples/jsm/loaders/ColladaLoader.js +24 -4026
  34. package/examples/jsm/loaders/EXRLoader.js +5 -5
  35. package/examples/jsm/loaders/FBXLoader.js +2 -2
  36. package/examples/jsm/loaders/GCodeLoader.js +34 -8
  37. package/examples/jsm/loaders/GLTFLoader.js +122 -171
  38. package/examples/jsm/loaders/KMZLoader.js +5 -5
  39. package/examples/jsm/loaders/KTX2Loader.js +5 -5
  40. package/examples/jsm/loaders/LWOLoader.js +7 -39
  41. package/examples/jsm/loaders/NRRDLoader.js +2 -2
  42. package/examples/jsm/loaders/PCDLoader.js +3 -2
  43. package/examples/jsm/loaders/USDLoader.js +100 -40
  44. package/examples/jsm/loaders/UltraHDRLoader.js +182 -30
  45. package/examples/jsm/loaders/VRMLLoader.js +77 -0
  46. package/examples/jsm/loaders/VTKLoader.js +37 -24
  47. package/examples/jsm/loaders/collada/ColladaComposer.js +2950 -0
  48. package/examples/jsm/loaders/collada/ColladaParser.js +1962 -0
  49. package/examples/jsm/loaders/usd/USDAParser.js +447 -366
  50. package/examples/jsm/loaders/usd/USDCParser.js +1841 -6
  51. package/examples/jsm/loaders/usd/USDComposer.js +4041 -0
  52. package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +2 -2
  53. package/examples/jsm/objects/LensflareMesh.js +1 -1
  54. package/examples/jsm/objects/Sky.js +76 -4
  55. package/examples/jsm/objects/SkyMesh.js +114 -7
  56. package/examples/jsm/objects/Water.js +4 -3
  57. package/examples/jsm/objects/Water2.js +5 -3
  58. package/examples/jsm/objects/WaterMesh.js +5 -7
  59. package/examples/jsm/physics/JoltPhysics.js +7 -5
  60. package/examples/jsm/physics/RapierPhysics.js +6 -4
  61. package/examples/jsm/postprocessing/EffectComposer.js +7 -5
  62. package/examples/jsm/postprocessing/RenderTransitionPass.js +1 -1
  63. package/examples/jsm/renderers/CSS3DRenderer.js +1 -1
  64. package/examples/jsm/renderers/SVGRenderer.js +2 -2
  65. package/examples/jsm/shaders/GTAOShader.js +19 -6
  66. package/examples/jsm/shaders/HalftoneShader.js +12 -1
  67. package/examples/jsm/shaders/PoissonDenoiseShader.js +6 -2
  68. package/examples/jsm/shaders/SAOShader.js +17 -4
  69. package/examples/jsm/shaders/SSAOShader.js +11 -1
  70. package/examples/jsm/shaders/SSRShader.js +6 -5
  71. package/examples/jsm/shaders/VignetteShader.js +1 -1
  72. package/examples/jsm/tsl/display/AfterImageNode.js +1 -1
  73. package/examples/jsm/tsl/display/AnaglyphPassNode.js +456 -16
  74. package/examples/jsm/tsl/display/AnamorphicNode.js +1 -1
  75. package/examples/jsm/tsl/display/BilateralBlurNode.js +364 -0
  76. package/examples/jsm/tsl/display/BloomNode.js +5 -5
  77. package/examples/jsm/tsl/display/CRT.js +150 -0
  78. package/examples/jsm/tsl/display/DenoiseNode.js +1 -1
  79. package/examples/jsm/tsl/display/DepthOfFieldNode.js +1 -1
  80. package/examples/jsm/tsl/display/DotScreenNode.js +1 -1
  81. package/examples/jsm/tsl/display/FXAANode.js +2 -2
  82. package/examples/jsm/tsl/display/GTAONode.js +2 -2
  83. package/examples/jsm/tsl/display/GaussianBlurNode.js +11 -2
  84. package/examples/jsm/tsl/display/GodraysNode.js +624 -0
  85. package/examples/jsm/tsl/display/LensflareNode.js +1 -1
  86. package/examples/jsm/tsl/display/Lut3DNode.js +1 -1
  87. package/examples/jsm/tsl/display/OutlineNode.js +3 -3
  88. package/examples/jsm/tsl/display/ParallaxBarrierPassNode.js +2 -2
  89. package/examples/jsm/tsl/display/PixelationPassNode.js +5 -5
  90. package/examples/jsm/tsl/display/RGBShiftNode.js +2 -2
  91. package/examples/jsm/tsl/display/RetroPassNode.js +263 -0
  92. package/examples/jsm/tsl/display/SMAANode.js +2 -2
  93. package/examples/jsm/tsl/display/SSAAPassNode.js +2 -2
  94. package/examples/jsm/tsl/display/SSGINode.js +2 -2
  95. package/examples/jsm/tsl/display/SSRNode.js +7 -7
  96. package/examples/jsm/tsl/display/SSSNode.js +2 -2
  97. package/examples/jsm/tsl/display/Shape.js +29 -0
  98. package/examples/jsm/tsl/display/SobelOperatorNode.js +2 -2
  99. package/examples/jsm/tsl/display/StereoPassNode.js +1 -2
  100. package/examples/jsm/tsl/display/TRAANode.js +9 -12
  101. package/examples/jsm/tsl/display/TransitionNode.js +1 -1
  102. package/examples/jsm/tsl/display/depthAwareBlend.js +80 -0
  103. package/examples/jsm/tsl/math/Bayer.js +40 -1
  104. package/examples/jsm/utils/LDrawUtils.js +1 -1
  105. package/package.json +11 -19
  106. package/src/Three.Core.js +1 -1
  107. package/src/Three.TSL.js +5 -9
  108. package/src/Three.WebGPU.Nodes.js +2 -0
  109. package/src/Three.WebGPU.js +3 -0
  110. package/src/Three.js +1 -0
  111. package/src/animation/AnimationAction.js +1 -1
  112. package/src/animation/AnimationClip.js +1 -1
  113. package/src/animation/AnimationMixer.js +6 -0
  114. package/src/animation/KeyframeTrack.js +46 -7
  115. package/src/animation/PropertyMixer.js +4 -4
  116. package/src/audio/Audio.js +1 -1
  117. package/src/audio/AudioListener.js +5 -3
  118. package/src/cameras/Camera.js +32 -2
  119. package/src/cameras/CubeCamera.js +20 -0
  120. package/src/constants.js +30 -1
  121. package/src/core/Clock.js +7 -0
  122. package/src/core/Object3D.js +56 -4
  123. package/src/core/RenderTarget.js +3 -4
  124. package/src/extras/PMREMGenerator.js +4 -8
  125. package/src/geometries/TorusGeometry.js +8 -3
  126. package/src/helpers/CameraHelper.js +3 -0
  127. package/src/helpers/DirectionalLightHelper.js +4 -1
  128. package/src/helpers/HemisphereLightHelper.js +3 -0
  129. package/src/helpers/PointLightHelper.js +0 -24
  130. package/src/helpers/SpotLightHelper.js +3 -0
  131. package/src/lights/LightShadow.js +15 -3
  132. package/src/lights/webgpu/IESSpotLight.js +2 -1
  133. package/src/loaders/Cache.js +28 -0
  134. package/src/loaders/FileLoader.js +1 -1
  135. package/src/loaders/ImageBitmapLoader.js +8 -3
  136. package/src/loaders/Loader.js +6 -0
  137. package/src/loaders/ObjectLoader.js +18 -1
  138. package/src/materials/MeshLambertMaterial.js +9 -0
  139. package/src/materials/MeshPhongMaterial.js +9 -0
  140. package/src/materials/nodes/Line2NodeMaterial.js +5 -5
  141. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +2 -0
  142. package/src/materials/nodes/NodeMaterial.js +15 -24
  143. package/src/materials/nodes/manager/NodeMaterialObserver.js +9 -3
  144. package/src/math/Line3.js +3 -5
  145. package/src/math/MathUtils.js +10 -10
  146. package/src/math/Matrix4.js +35 -26
  147. package/src/math/Quaternion.js +3 -29
  148. package/src/math/Vector3.js +3 -3
  149. package/src/math/interpolants/BezierInterpolant.js +108 -0
  150. package/src/nodes/Nodes.js +87 -68
  151. package/src/nodes/TSL.js +2 -5
  152. package/src/nodes/accessors/Arrays.js +1 -1
  153. package/src/nodes/accessors/Bitangent.js +5 -5
  154. package/src/nodes/accessors/BufferAttributeNode.js +1 -1
  155. package/src/nodes/accessors/Camera.js +149 -28
  156. package/src/nodes/accessors/InstanceNode.js +105 -40
  157. package/src/nodes/accessors/Normal.js +9 -9
  158. package/src/nodes/accessors/Position.js +34 -2
  159. package/src/nodes/accessors/SceneProperties.js +53 -0
  160. package/src/nodes/accessors/SkinningNode.js +12 -24
  161. package/src/nodes/accessors/StorageBufferNode.js +0 -19
  162. package/src/nodes/accessors/StorageTextureNode.js +37 -1
  163. package/src/nodes/accessors/Tangent.js +3 -3
  164. package/src/nodes/accessors/Texture3DNode.js +6 -34
  165. package/src/nodes/accessors/TextureNode.js +58 -22
  166. package/src/nodes/accessors/UniformArrayNode.js +2 -0
  167. package/src/nodes/core/MRTNode.js +48 -2
  168. package/src/nodes/core/Node.js +29 -3
  169. package/src/nodes/core/NodeBuilder.js +115 -40
  170. package/src/nodes/core/NodeError.js +28 -0
  171. package/src/nodes/core/NodeUtils.js +5 -3
  172. package/src/nodes/core/OutputStructNode.js +12 -10
  173. package/src/nodes/core/ParameterNode.js +2 -1
  174. package/src/nodes/core/StackNode.js +9 -8
  175. package/src/nodes/core/StackTrace.js +139 -0
  176. package/src/nodes/core/StructNode.js +15 -0
  177. package/src/nodes/core/SubBuildNode.js +1 -1
  178. package/src/nodes/core/UniformNode.js +2 -1
  179. package/src/nodes/core/VarNode.js +1 -1
  180. package/src/nodes/core/VaryingNode.js +1 -18
  181. package/src/nodes/display/BlendModes.js +0 -64
  182. package/src/nodes/display/ColorAdjustment.js +17 -0
  183. package/src/nodes/display/ColorSpaceNode.js +3 -3
  184. package/src/nodes/display/NormalMapNode.js +2 -2
  185. package/src/nodes/display/PassNode.js +21 -2
  186. package/src/nodes/display/RenderOutputNode.js +3 -3
  187. package/src/nodes/display/ScreenNode.js +2 -1
  188. package/src/nodes/display/ToneMappingNode.js +1 -1
  189. package/src/nodes/display/ToonOutlinePassNode.js +2 -2
  190. package/src/nodes/display/ViewportDepthNode.js +52 -4
  191. package/src/nodes/display/ViewportTextureNode.js +21 -4
  192. package/src/nodes/fog/Fog.js +18 -35
  193. package/src/nodes/functions/PhysicalLightingModel.js +25 -3
  194. package/src/nodes/geometry/RangeNode.js +4 -2
  195. package/src/nodes/gpgpu/ComputeNode.js +5 -4
  196. package/src/nodes/gpgpu/WorkgroupInfoNode.js +2 -1
  197. package/src/nodes/lighting/EnvironmentNode.js +28 -3
  198. package/src/nodes/lighting/PointShadowNode.js +24 -12
  199. package/src/nodes/lighting/ShadowFilterNode.js +15 -43
  200. package/src/nodes/lighting/ShadowNode.js +54 -32
  201. package/src/nodes/math/ConditionalNode.js +2 -2
  202. package/src/nodes/math/MathNode.js +3 -40
  203. package/src/nodes/math/OperatorNode.js +2 -1
  204. package/src/nodes/pmrem/PMREMUtils.js +9 -15
  205. package/src/nodes/tsl/TSLCore.js +13 -10
  206. package/src/nodes/utils/DebugNode.js +11 -11
  207. package/src/nodes/utils/JoinNode.js +2 -2
  208. package/src/nodes/utils/LoopNode.js +1 -1
  209. package/src/nodes/utils/MemberNode.js +1 -1
  210. package/src/nodes/utils/RTTNode.js +1 -1
  211. package/src/nodes/utils/ReflectorNode.js +2 -3
  212. package/src/nodes/utils/SpriteSheetUV.js +35 -0
  213. package/src/nodes/utils/UVUtils.js +4 -2
  214. package/src/objects/BatchedMesh.js +22 -12
  215. package/src/objects/InstancedMesh.js +11 -0
  216. package/src/renderers/WebGLRenderer.js +34 -60
  217. package/src/renderers/common/Backend.js +21 -0
  218. package/src/renderers/common/Background.js +7 -4
  219. package/src/renderers/common/BindGroup.js +1 -9
  220. package/src/renderers/common/Bindings.js +20 -5
  221. package/src/renderers/common/BlendMode.js +143 -0
  222. package/src/renderers/common/BundleGroup.js +1 -1
  223. package/src/renderers/common/CubeRenderTarget.js +50 -6
  224. package/src/renderers/common/Geometries.js +17 -3
  225. package/src/renderers/common/Lighting.js +5 -21
  226. package/src/renderers/common/Pipelines.js +4 -4
  227. package/src/renderers/common/PostProcessing.js +8 -206
  228. package/src/renderers/common/RenderBundles.js +2 -1
  229. package/src/renderers/common/RenderContext.js +16 -0
  230. package/src/renderers/common/RenderContexts.js +33 -56
  231. package/src/renderers/common/RenderLists.js +2 -1
  232. package/src/renderers/common/RenderObject.js +2 -3
  233. package/src/renderers/common/RenderObjectPipeline.js +40 -0
  234. package/src/renderers/common/RenderObjects.js +18 -2
  235. package/src/renderers/common/RenderPipeline.js +203 -17
  236. package/src/renderers/common/Renderer.js +207 -40
  237. package/src/renderers/common/Sampler.js +4 -4
  238. package/src/renderers/common/StorageBuffer.js +13 -1
  239. package/src/renderers/common/Textures.js +16 -0
  240. package/src/renderers/common/TimestampQueryPool.js +5 -3
  241. package/src/renderers/common/Uniform.js +8 -0
  242. package/src/renderers/common/UniformsGroup.js +60 -0
  243. package/src/renderers/common/XRManager.js +2 -2
  244. package/src/renderers/common/nodes/NodeBuilderState.js +1 -1
  245. package/src/renderers/common/nodes/{Nodes.js → NodeManager.js} +18 -6
  246. package/src/renderers/common/nodes/NodeStorageBuffer.js +13 -2
  247. package/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js +2 -2
  248. package/src/renderers/shaders/ShaderChunk/color_fragment.glsl.js +1 -5
  249. package/src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl.js +1 -5
  250. package/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js +1 -5
  251. package/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js +8 -10
  252. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +7 -11
  253. package/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js +6 -0
  254. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +6 -2
  255. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +23 -1
  256. package/src/renderers/shaders/ShaderChunk/packing.glsl.js +20 -4
  257. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +55 -24
  258. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +2 -0
  259. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +2 -0
  260. package/src/renderers/shaders/ShaderLib/shadow.glsl.js +1 -0
  261. package/src/renderers/shaders/ShaderLib.js +4 -2
  262. package/src/renderers/shaders/UniformsLib.js +0 -3
  263. package/src/renderers/webgl/WebGLBackground.js +2 -2
  264. package/src/renderers/webgl/WebGLBindingStates.js +99 -27
  265. package/src/renderers/webgl/WebGLEnvironments.js +228 -0
  266. package/src/renderers/webgl/WebGLGeometries.js +10 -7
  267. package/src/renderers/webgl/WebGLMaterials.js +12 -0
  268. package/src/renderers/webgl/WebGLObjects.js +3 -1
  269. package/src/renderers/webgl/WebGLProgram.js +2 -2
  270. package/src/renderers/webgl/WebGLPrograms.js +10 -4
  271. package/src/renderers/webgl/WebGLRenderLists.js +15 -0
  272. package/src/renderers/webgl/WebGLShadowMap.js +5 -4
  273. package/src/renderers/webgl/WebGLState.js +12 -17
  274. package/src/renderers/webgl-fallback/WebGLBackend.js +71 -7
  275. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +98 -29
  276. package/src/renderers/webgl-fallback/utils/WebGLState.js +168 -7
  277. package/src/renderers/webgpu/WebGPUBackend.js +58 -9
  278. package/src/renderers/webgpu/WebGPURenderer.js +1 -0
  279. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +257 -45
  280. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +8 -19
  281. package/src/renderers/webgpu/utils/WebGPUConstants.js +1 -1
  282. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +56 -31
  283. package/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js +152 -200
  284. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +25 -25
  285. package/src/renderers/webgpu/utils/WebGPUUtils.js +10 -6
  286. package/src/renderers/webxr/WebXRManager.js +2 -2
  287. package/src/textures/Texture.js +2 -2
  288. package/src/utils.js +246 -3
  289. package/examples/jsm/materials/MeshGouraudMaterial.js +0 -433
  290. package/examples/jsm/materials/MeshPostProcessingMaterial.js +0 -167
  291. package/examples/jsm/shaders/GodRaysShader.js +0 -333
  292. package/src/nodes/accessors/SceneNode.js +0 -145
  293. package/src/nodes/code/ScriptableNode.js +0 -726
  294. package/src/nodes/code/ScriptableValueNode.js +0 -253
  295. package/src/nodes/display/PosterizeNode.js +0 -65
  296. package/src/nodes/utils/SpriteSheetUVNode.js +0 -90
  297. package/src/renderers/webgl/WebGLCubeMaps.js +0 -99
  298. package/src/renderers/webgl/WebGLCubeUVMaps.js +0 -134
@@ -80,13 +80,13 @@ class PixelationNode extends TempNode {
80
80
  this._resolution = uniform( new Vector4() );
81
81
 
82
82
  /**
83
- * The `updateBeforeType` is set to `NodeUpdateType.FRAME` since the node updates
83
+ * The `updateType` is set to `NodeUpdateType.FRAME` since the node updates
84
84
  * its internal uniforms once per frame in `updateBefore()`.
85
85
  *
86
86
  * @type {string}
87
87
  * @default 'frame'
88
88
  */
89
- this.updateBeforeType = NodeUpdateType.FRAME;
89
+ this.updateType = NodeUpdateType.FRAME;
90
90
 
91
91
  }
92
92
 
@@ -95,7 +95,7 @@ class PixelationNode extends TempNode {
95
95
  *
96
96
  * @param {NodeFrame} frame - The current node frame.
97
97
  */
98
- updateBefore() {
98
+ update() {
99
99
 
100
100
  const map = this.textureNode.value;
101
101
 
@@ -214,7 +214,7 @@ class PixelationNode extends TempNode {
214
214
 
215
215
  }
216
216
 
217
- const pixelation = ( node, depthNode, normalNode, pixelSize = 6, normalEdgeStrength = 0.3, depthEdgeStrength = 0.4 ) => nodeObject( new PixelationNode( convertToTexture( node ), convertToTexture( depthNode ), convertToTexture( normalNode ), nodeObject( pixelSize ), nodeObject( normalEdgeStrength ), nodeObject( depthEdgeStrength ) ) );
217
+ const pixelation = ( node, depthNode, normalNode, pixelSize = 6, normalEdgeStrength = 0.3, depthEdgeStrength = 0.4 ) => new PixelationNode( convertToTexture( node ), convertToTexture( depthNode ), convertToTexture( normalNode ), nodeObject( pixelSize ), nodeObject( normalEdgeStrength ), nodeObject( depthEdgeStrength ) );
218
218
 
219
219
  /**
220
220
  * A special render pass node that renders the scene with a pixelation effect.
@@ -330,6 +330,6 @@ class PixelationPassNode extends PassNode {
330
330
  * @param {Node<float> | number} [depthEdgeStrength=0.4] - The depth edge strength.
331
331
  * @returns {PixelationPassNode}
332
332
  */
333
- export const pixelationPass = ( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength ) => nodeObject( new PixelationPassNode( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength ) );
333
+ export const pixelationPass = ( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength ) => new PixelationPassNode( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength );
334
334
 
335
335
  export default PixelationPassNode;
@@ -1,5 +1,5 @@
1
1
  import { TempNode } from 'three/webgpu';
2
- import { nodeObject, Fn, uv, uniform, vec2, sin, cos, vec4, convertToTexture } from 'three/tsl';
2
+ import { Fn, uv, uniform, vec2, sin, cos, vec4, convertToTexture } from 'three/tsl';
3
3
 
4
4
  /**
5
5
  * Post processing node for shifting/splitting RGB color channels. The effect
@@ -93,4 +93,4 @@ export default RGBShiftNode;
93
93
  * @param {number} [angle=0] - Defines in which direction colors are shifted.
94
94
  * @returns {RGBShiftNode}
95
95
  */
96
- export const rgbShift = ( node, amount, angle ) => nodeObject( new RGBShiftNode( convertToTexture( node ), amount, angle ) );
96
+ export const rgbShift = ( node, amount, angle ) => new RGBShiftNode( convertToTexture( node ), amount, angle );
@@ -0,0 +1,263 @@
1
+ import { MeshBasicNodeMaterial, PassNode, UnsignedByteType, NearestFilter, CubeMapNode, MeshPhongNodeMaterial } from 'three/webgpu';
2
+ import { float, vec2, vec4, Fn, uv, varying, cameraProjectionMatrix, cameraViewMatrix, positionWorld, screenSize, materialColor, uint, texture, uniform, context, reflectVector } from 'three/tsl';
3
+
4
+ const _affineUv = varying( vec2() );
5
+ const _w = varying( float() );
6
+
7
+ const _clipSpaceRetro = Fn( () => {
8
+
9
+ const defaultPosition = cameraProjectionMatrix
10
+ .mul( cameraViewMatrix )
11
+ .mul( positionWorld );
12
+
13
+ const roundedPosition = defaultPosition.xy
14
+ .div( defaultPosition.w.mul( 2 ) )
15
+ .mul( screenSize.xy )
16
+ .round()
17
+ .div( screenSize.xy )
18
+ .mul( defaultPosition.w.mul( 2 ) );
19
+
20
+ _affineUv.assign( uv().mul( defaultPosition.w ) );
21
+ _w.assign( defaultPosition.w );
22
+
23
+ return vec4( roundedPosition.xy, defaultPosition.zw );
24
+
25
+ } )();
26
+
27
+ /**
28
+ * A post-processing pass that applies a retro PS1-style effect to the scene.
29
+ *
30
+ * This node renders the scene with classic PlayStation 1 visual characteristics:
31
+ * - **Vertex snapping**: Vertices are snapped to screen pixels, creating the iconic "wobbly" geometry
32
+ * - **Affine texture mapping**: Textures are sampled without perspective correction, resulting in distortion effects
33
+ * - **Low resolution**: Default 0.25 scale (typical 320x240 equivalent)
34
+ * - **Nearest-neighbor filtering**: Sharp pixelated textures without smoothing
35
+ *
36
+ * @augments PassNode
37
+ */
38
+ class RetroPassNode extends PassNode {
39
+
40
+ /**
41
+ * Creates a new RetroPassNode instance.
42
+ *
43
+ * @param {Scene} scene - The scene to render.
44
+ * @param {Camera} camera - The camera to render from.
45
+ * @param {Object} [options={}] - Additional options for the retro pass.
46
+ * @param {Node} [options.affineDistortion=null] - An optional node to apply affine distortion to UVs.
47
+ */
48
+ constructor( scene, camera, options = {} ) {
49
+
50
+ super( PassNode.COLOR, scene, camera );
51
+
52
+ const {
53
+ affineDistortion = null,
54
+ filterTextures = false
55
+ } = options;
56
+
57
+ this.setResolutionScale( .25 );
58
+
59
+ this.renderTarget.texture.type = UnsignedByteType;
60
+ this.renderTarget.texture.magFilter = NearestFilter;
61
+ this.renderTarget.texture.minFilter = NearestFilter;
62
+
63
+ this.affineDistortionNode = affineDistortion;
64
+
65
+ this.filterTextures = filterTextures;
66
+
67
+ this._materialCache = new Map();
68
+
69
+ }
70
+
71
+ /**
72
+ * Updates the retro pass before rendering.
73
+ *
74
+ * @override
75
+ * @param {Frame} frame - The current frame information.
76
+ * @returns {void}
77
+ */
78
+ updateBefore( frame ) {
79
+
80
+ const renderer = frame.renderer;
81
+
82
+ const currentRenderObjectFunction = renderer.getRenderObjectFunction();
83
+
84
+ renderer.setRenderObjectFunction( ( object, scene, camera, geometry, material, ...params ) => {
85
+
86
+ const retroMaterialData = this._materialCache.get( material );
87
+
88
+ let retroMaterial;
89
+
90
+ if ( retroMaterialData === undefined || retroMaterialData.version !== material.version ) {
91
+
92
+ if ( retroMaterialData !== undefined ) {
93
+
94
+ retroMaterialData.material.dispose();
95
+
96
+ }
97
+
98
+ if ( material.isMeshBasicMaterial || material.isMeshBasicNodeMaterial ) {
99
+
100
+ retroMaterial = new MeshBasicNodeMaterial();
101
+
102
+ } else {
103
+
104
+ retroMaterial = new MeshPhongNodeMaterial();
105
+
106
+ }
107
+
108
+ retroMaterial.colorNode = material.colorNode || null;
109
+ retroMaterial.opacityNode = material.opacityNode || null;
110
+ retroMaterial.positionNode = material.positionNode || null;
111
+ retroMaterial.vertexNode = material.vertexNode || _clipSpaceRetro;
112
+
113
+ let colorNode = material.colorNode || materialColor;
114
+
115
+ if ( material.isMeshStandardNodeMaterial || material.isMeshStandardMaterial ) {
116
+
117
+ const envMap = material.envMap || scene.environment;
118
+
119
+ if ( envMap ) {
120
+
121
+ const reflection = new CubeMapNode( texture( envMap ) );
122
+
123
+ let metalness;
124
+
125
+ if ( material.metalnessNode ) {
126
+
127
+ metalness = material.metalnessNode;
128
+
129
+ } else {
130
+
131
+ metalness = uniform( material.metalness ).onRenderUpdate( ( { material } ) => material.metalness );
132
+
133
+ if ( material.metalnessMap ) {
134
+
135
+ const textureUniform = texture( material.metalnessMap ).onRenderUpdate( ( { material } ) => material.metalnessMap );
136
+
137
+ metalness = metalness.mul( textureUniform.b );
138
+
139
+ }
140
+
141
+ }
142
+
143
+ colorNode = metalness.mix( colorNode, reflection );
144
+
145
+ }
146
+
147
+ }
148
+
149
+ retroMaterial.colorNode = colorNode;
150
+
151
+ //
152
+
153
+ const contextData = {};
154
+
155
+ if ( this.affineDistortionNode ) {
156
+
157
+ contextData.getUV = ( texture ) => {
158
+
159
+ let finalUV;
160
+
161
+ if ( texture.isCubeTextureNode ) {
162
+
163
+ finalUV = reflectVector;
164
+
165
+ } else {
166
+
167
+ finalUV = this.affineDistortionNode.mix( uv(), _affineUv.div( _w ) );
168
+
169
+ }
170
+
171
+ return finalUV;
172
+
173
+ };
174
+
175
+ }
176
+
177
+ if ( this.filterTextures !== true ) {
178
+
179
+ contextData.getTextureLevel = () => uint( 0 );
180
+
181
+ }
182
+
183
+ retroMaterial.contextNode = context( contextData );
184
+
185
+ //
186
+
187
+ this._materialCache.set( material, {
188
+ material: retroMaterial,
189
+ version: material.version
190
+ } );
191
+
192
+ } else {
193
+
194
+ retroMaterial = retroMaterialData.material;
195
+
196
+ }
197
+
198
+ for ( const property in material ) {
199
+
200
+ if ( retroMaterial[ property ] === undefined ) continue;
201
+
202
+ retroMaterial[ property ] = material[ property ];
203
+
204
+ }
205
+
206
+ renderer.renderObject( object, scene, camera, geometry, retroMaterial, ...params );
207
+
208
+ } );
209
+
210
+ super.updateBefore( frame );
211
+
212
+ renderer.setRenderObjectFunction( currentRenderObjectFunction );
213
+
214
+ }
215
+
216
+ /**
217
+ * Disposes the retro pass and its internal resources.
218
+ *
219
+ * @override
220
+ * @returns {void}
221
+ */
222
+ dispose() {
223
+
224
+ super.dispose();
225
+
226
+ this._materialCache.forEach( ( data ) => {
227
+
228
+ data.material.dispose();
229
+
230
+ } );
231
+
232
+ this._materialCache.clear();
233
+
234
+ }
235
+
236
+ }
237
+
238
+ export default RetroPassNode;
239
+
240
+ /**
241
+ * Creates a new RetroPassNode instance for PS1-style rendering.
242
+ *
243
+ * The retro pass applies vertex snapping, affine texture mapping, and low-resolution
244
+ * rendering to achieve an authentic PlayStation 1 aesthetic. Combine with other
245
+ * post-processing effects like dithering, posterization, and scanlines for full retro look.
246
+ *
247
+ * ```js
248
+ * // Combined with other effects
249
+ * let pipeline = retroPass( scene, camera );
250
+ * pipeline = bayerDither( pipeline, 32 );
251
+ * pipeline = posterize( pipeline, 32 );
252
+ * renderPipeline.outputNode = pipeline;
253
+ * ```
254
+ *
255
+ * @tsl
256
+ * @function
257
+ * @param {Scene} scene - The scene to render.
258
+ * @param {Camera} camera - The camera to render from.
259
+ * @param {Object} [options={}] - Additional options for the retro pass.
260
+ * @param {Node} [options.affineDistortion=null] - An optional node to apply affine distortion to UVs.
261
+ * @return {RetroPassNode} A new RetroPassNode instance.
262
+ */
263
+ export const retroPass = ( scene, camera, options = {} ) => new RetroPassNode( scene, camera, options );
@@ -1,5 +1,5 @@
1
1
  import { HalfFloatType, LinearFilter, NearestFilter, RenderTarget, Texture, Vector2, QuadMesh, NodeMaterial, TempNode, RendererUtils } from 'three/webgpu';
2
- import { abs, nodeObject, Fn, NodeUpdateType, uv, uniform, convertToTexture, varyingProperty, vec2, vec4, modelViewProjection, passTexture, max, step, dot, float, texture, If, Loop, int, Break, sqrt, sign, mix } from 'three/tsl';
2
+ import { abs, Fn, NodeUpdateType, uv, uniform, convertToTexture, varyingProperty, vec2, vec4, modelViewProjection, passTexture, max, step, dot, float, texture, If, Loop, int, Break, sqrt, sign, mix } from 'three/tsl';
3
3
 
4
4
  const _quadMesh = /*@__PURE__*/ new QuadMesh();
5
5
  const _size = /*@__PURE__*/ new Vector2();
@@ -765,4 +765,4 @@ export default SMAANode;
765
765
  * @param {Node<vec4>} node - The node that represents the input of the effect.
766
766
  * @returns {SMAANode}
767
767
  */
768
- export const smaa = ( node ) => nodeObject( new SMAANode( convertToTexture( node ) ) );
768
+ export const smaa = ( node ) => new SMAANode( convertToTexture( node ) );
@@ -1,5 +1,5 @@
1
1
  import { AdditiveBlending, Color, Vector2, RendererUtils, PassNode, QuadMesh, NodeMaterial } from 'three/webgpu';
2
- import { nodeObject, uniform, mrt, texture, getTextureIndex, unpremultiplyAlpha } from 'three/tsl';
2
+ import { uniform, mrt, texture, getTextureIndex, unpremultiplyAlpha } from 'three/tsl';
3
3
 
4
4
  const _size = /*@__PURE__*/ new Vector2();
5
5
 
@@ -355,4 +355,4 @@ const _JitterVectors = [
355
355
  * @param {Camera} camera - The camera to render the scene with.
356
356
  * @returns {SSAAPassNode}
357
357
  */
358
- export const ssaaPass = ( scene, camera ) => nodeObject( new SSAAPassNode( scene, camera ) );
358
+ export const ssaaPass = ( scene, camera ) => new SSAAPassNode( scene, camera );
@@ -1,5 +1,5 @@
1
1
  import { RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, RendererUtils, MathUtils } from 'three/webgpu';
2
- import { clamp, normalize, reference, nodeObject, Fn, NodeUpdateType, uniform, vec4, passTexture, uv, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getViewPosition, screenCoordinate, float, sub, fract, dot, vec2, rand, vec3, Loop, mul, PI, cos, sin, uint, cross, acos, sign, pow, luminance, If, max, abs, Break, sqrt, HALF_PI, div, ceil, shiftRight, convertToTexture, bool, getNormalFromDepth, countOneBits, interleavedGradientNoise } from 'three/tsl';
2
+ import { clamp, normalize, reference, Fn, NodeUpdateType, uniform, vec4, passTexture, uv, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getViewPosition, screenCoordinate, float, sub, fract, dot, vec2, rand, vec3, Loop, mul, PI, cos, sin, uint, cross, acos, sign, pow, luminance, If, max, abs, Break, sqrt, HALF_PI, div, ceil, shiftRight, convertToTexture, bool, getNormalFromDepth, countOneBits, interleavedGradientNoise } from 'three/tsl';
3
3
 
4
4
  const _quadMesh = /*@__PURE__*/ new QuadMesh();
5
5
  const _size = /*@__PURE__*/ new Vector2();
@@ -639,4 +639,4 @@ export default SSGINode;
639
639
  * @param {Camera} camera - The camera the scene is rendered with.
640
640
  * @returns {SSGINode}
641
641
  */
642
- export const ssgi = ( beautyNode, depthNode, normalNode, camera ) => nodeObject( new SSGINode( convertToTexture( beautyNode ), depthNode, normalNode, camera ) );
642
+ export const ssgi = ( beautyNode, depthNode, normalNode, camera ) => new SSGINode( convertToTexture( beautyNode ), depthNode, normalNode, camera );
@@ -1,5 +1,5 @@
1
1
  import { HalfFloatType, RenderTarget, Vector2, RendererUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType, LinearFilter, LinearMipmapLinearFilter } from 'three/webgpu';
2
- import { texture, reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, sqrt, mul, div, cross, float, Continue, Break, Loop, int, max, abs, sub, If, dot, reflect, normalize, screenCoordinate, nodeObject, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, vec3, vec4 } from 'three/tsl';
2
+ import { texture, reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, mul, div, cross, float, Continue, Break, Loop, int, max, abs, sub, If, dot, reflect, normalize, screenCoordinate, nodeObject, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, vec3, vec4 } from 'three/tsl';
3
3
  import { boxBlur } from './boxBlur.js';
4
4
 
5
5
  const _quadMesh = /*@__PURE__*/ new QuadMesh();
@@ -275,7 +275,8 @@ class SSRNode extends TempNode {
275
275
  if ( this.roughnessNode !== null ) {
276
276
 
277
277
  const mips = this._blurRenderTarget.texture.mipmaps.length - 1;
278
- const lod = float( this.roughnessNode ).mul( mips ).clamp( 0, mips );
278
+ const r = float( this.roughnessNode );
279
+ const lod = r.mul( r ).mul( mips ).clamp( 0, mips );
279
280
 
280
281
  blurredTextureNode = passTexture( this, this._blurRenderTarget.texture ).level( lod );
281
282
 
@@ -399,10 +400,9 @@ class SSRNode extends TempNode {
399
400
  // https://en.wikipedia.org/wiki/Plane_(geometry)
400
401
  // http://paulbourke.net/geometry/pointlineplane/
401
402
 
403
+ // planeNormal is already normalized, so denominator is 1
402
404
  const d = mul( planeNormal.x, planePoint.x ).add( mul( planeNormal.y, planePoint.y ) ).add( mul( planeNormal.z, planePoint.z ) ).negate().toVar();
403
-
404
- const denominator = sqrt( mul( planeNormal.x, planeNormal.x, ).add( mul( planeNormal.y, planeNormal.y ) ).add( mul( planeNormal.z, planeNormal.z ) ) ).toVar();
405
- const distance = div( mul( planeNormal.x, point.x ).add( mul( planeNormal.y, point.y ) ).add( mul( planeNormal.z, point.z ) ).add( d ), denominator );
405
+ const distance = mul( planeNormal.x, point.x ).add( mul( planeNormal.y, point.y ) ).add( mul( planeNormal.z, point.z ) ).add( d );
406
406
  return distance;
407
407
 
408
408
  } );
@@ -589,7 +589,7 @@ class SSRNode extends TempNode {
589
589
 
590
590
  // output
591
591
  const reflectColor = this.colorNode.sample( uvNode );
592
- output.assign( vec4( reflectColor.rgb, op ) );
592
+ output.assign( vec4( reflectColor.rgb.mul( op ), 1 ) );
593
593
  Break();
594
594
 
595
595
  } );
@@ -653,4 +653,4 @@ export default SSRNode;
653
653
  * @param {?Camera} [camera=null] - The camera the scene is rendered with.
654
654
  * @returns {SSRNode}
655
655
  */
656
- export const ssr = ( colorNode, depthNode, normalNode, metalnessNode, roughnessNode = null, camera = null ) => nodeObject( new SSRNode( nodeObject( colorNode ), nodeObject( depthNode ), nodeObject( normalNode ), nodeObject( metalnessNode ), nodeObject( roughnessNode ), camera ) );
656
+ export const ssr = ( colorNode, depthNode, normalNode, metalnessNode, roughnessNode = null, camera = null ) => new SSRNode( nodeObject( colorNode ), nodeObject( depthNode ), nodeObject( normalNode ), nodeObject( metalnessNode ), nodeObject( roughnessNode ), camera );
@@ -1,5 +1,5 @@
1
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';
2
+ import { reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, float, Break, Loop, int, max, abs, If, interleavedGradientNoise, screenCoordinate, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, lightPosition, lightTargetPosition, fract, rand, mix } from 'three/tsl';
3
3
 
4
4
  const _quadMesh = /*@__PURE__*/ new QuadMesh();
5
5
  const _size = /*@__PURE__*/ new Vector2();
@@ -487,4 +487,4 @@ export default SSSNode;
487
487
  * @param {DirectionalLight} mainLight - The main directional light of the scene.
488
488
  * @returns {SSSNode}
489
489
  */
490
- export const sss = ( depthNode, camera, mainLight ) => nodeObject( new SSSNode( depthNode, camera, mainLight ) );
490
+ export const sss = ( depthNode, camera, mainLight ) => new SSSNode( depthNode, camera, mainLight );
@@ -0,0 +1,29 @@
1
+ import { Fn, float, length, smoothstep, uv } from 'three/tsl';
2
+
3
+ /**
4
+ * Returns a radial gradient from center (white) to edges (black).
5
+ * Useful for masking effects based on distance from center.
6
+ *
7
+ * @tsl
8
+ * @function
9
+ * @param {Node<float>} [scale=1.0] - Controls the size of the gradient (0 = all black, 1 = full circle).
10
+ * @param {Node<float>} [softness=0.5] - Controls the edge softness (0 = hard edge, 1 = soft gradient).
11
+ * @param {Node<vec2>} [coord=uv()] - The input UV coordinates.
12
+ * @return {Node<float>} 1.0 at center, 0.0 at edges.
13
+ */
14
+ export const circle = Fn( ( [ scale = float( 1.0 ), softness = float( 0.5 ), coord = uv() ] ) => {
15
+
16
+ // Center UV coordinates (-0.5 to 0.5)
17
+ const centered = coord.sub( 0.5 );
18
+
19
+ // Calculate distance from center (0 at center, ~0.707 at corners)
20
+ const dist = length( centered ).mul( 2.0 );
21
+
22
+ // Calculate inner and outer edges based on scale and softness
23
+ const outer = scale;
24
+ const inner = scale.sub( softness.mul( scale ) );
25
+
26
+ // Smoothstep for soft/hard transition
27
+ return smoothstep( outer, inner, dist );
28
+
29
+ } );
@@ -1,5 +1,5 @@
1
1
  import { Vector2, TempNode, NodeUpdateType } from 'three/webgpu';
2
- import { nodeObject, Fn, uv, uniform, convertToTexture, vec2, vec3, vec4, mat3, luminance, add } from 'three/tsl';
2
+ import { Fn, uv, uniform, convertToTexture, vec2, vec3, vec4, mat3, luminance, add } from 'three/tsl';
3
3
 
4
4
  /**
5
5
  * Post processing node for detecting edges with a sobel filter.
@@ -165,4 +165,4 @@ export default SobelOperatorNode;
165
165
  * @param {Node<vec4>} node - The node that represents the input of the effect.
166
166
  * @returns {SobelOperatorNode}
167
167
  */
168
- export const sobel = ( node ) => nodeObject( new SobelOperatorNode( convertToTexture( node ) ) );
168
+ export const sobel = ( node ) => new SobelOperatorNode( convertToTexture( node ) );
@@ -1,5 +1,4 @@
1
1
  import { StereoCamera, Vector2, PassNode, RendererUtils } from 'three/webgpu';
2
- import { nodeObject } from 'three/tsl';
3
2
 
4
3
  const _size = /*@__PURE__*/ new Vector2();
5
4
 
@@ -117,4 +116,4 @@ export default StereoPassNode;
117
116
  * @param {Camera} camera - The camera to render the scene with.
118
117
  * @returns {StereoPassNode}
119
118
  */
120
- export const stereoPass = ( scene, camera ) => nodeObject( new StereoPassNode( scene, camera ) );
119
+ export const stereoPass = ( scene, camera ) => new StereoPassNode( scene, camera );
@@ -1,5 +1,5 @@
1
1
  import { HalfFloatType, Vector2, RenderTarget, RendererUtils, QuadMesh, NodeMaterial, TempNode, NodeUpdateType, Matrix4, DepthTexture } from 'three/webgpu';
2
- import { add, float, If, Fn, max, nodeObject, texture, uniform, uv, vec2, vec4, luminance, convertToTexture, passTexture, velocity, getViewPosition, viewZToPerspectiveDepth, struct, ivec2, mix } from 'three/tsl';
2
+ import { add, float, If, Fn, max, texture, uniform, uv, vec2, vec4, luminance, convertToTexture, passTexture, velocity, getViewPosition, viewZToPerspectiveDepth, struct, ivec2, mix } from 'three/tsl';
3
3
 
4
4
  const _quadMesh = /*@__PURE__*/ new QuadMesh();
5
5
  const _size = /*@__PURE__*/ new Vector2();
@@ -376,13 +376,10 @@ class TRAANode extends TempNode {
376
376
 
377
377
  if ( needsRestart === true ) {
378
378
 
379
- // bind and clear render target to make sure they are initialized after the resize which triggers a dispose()
379
+ // make sure render targets are initialized after the resize which triggers a dispose()
380
380
 
381
- renderer.setRenderTarget( this._historyRenderTarget );
382
- renderer.clear();
383
-
384
- renderer.setRenderTarget( this._resolveRenderTarget );
385
- renderer.clear();
381
+ renderer.initRenderTarget( this._historyRenderTarget );
382
+ renderer.initRenderTarget( this._resolveRenderTarget );
386
383
 
387
384
  // make sure to reset the history with the contents of the beauty buffer otherwise subsequent frames after the
388
385
  // resize will fade from a darker color to the correct one because the history was cleared with black.
@@ -434,20 +431,20 @@ class TRAANode extends TempNode {
434
431
  */
435
432
  setup( builder ) {
436
433
 
437
- const postProcessing = builder.context.postProcessing;
434
+ const renderPipeline = builder.context.renderPipeline;
438
435
 
439
- if ( postProcessing ) {
436
+ if ( renderPipeline ) {
440
437
 
441
438
  this._needsPostProcessingSync = true;
442
439
 
443
- postProcessing.context.onBeforePostProcessing = () => {
440
+ renderPipeline.context.onBeforeRenderPipeline = () => {
444
441
 
445
442
  const size = builder.renderer.getDrawingBufferSize( _size );
446
443
  this.setViewOffset( size.width, size.height );
447
444
 
448
445
  };
449
446
 
450
- postProcessing.context.onAfterPostProcessing = () => {
447
+ renderPipeline.context.onAfterRenderPipeline = () => {
451
448
 
452
449
  this.clearViewOffset();
453
450
 
@@ -726,4 +723,4 @@ const _haltonOffsets = /*@__PURE__*/ Array.from(
726
723
  * @param {Camera} camera - The camera the scene is rendered with.
727
724
  * @returns {TRAANode}
728
725
  */
729
- export const traa = ( beautyNode, depthNode, velocityNode, camera ) => nodeObject( new TRAANode( convertToTexture( beautyNode ), depthNode, velocityNode, camera ) );
726
+ export const traa = ( beautyNode, depthNode, velocityNode, camera ) => new TRAANode( convertToTexture( beautyNode ), depthNode, velocityNode, camera );
@@ -138,4 +138,4 @@ export default TransitionNode;
138
138
  * @param {Node<float> | number} useTexture - Whether `mixTextureNode` should influence the transition or not.
139
139
  * @returns {TransitionNode}
140
140
  */
141
- export const transition = ( nodeA, nodeB, mixTextureNode, mixRatio, threshold, useTexture ) => nodeObject( new TransitionNode( convertToTexture( nodeA ), convertToTexture( nodeB ), convertToTexture( mixTextureNode ), nodeObject( mixRatio ), nodeObject( threshold ), nodeObject( useTexture ) ) );
141
+ export const transition = ( nodeA, nodeB, mixTextureNode, mixRatio, threshold, useTexture ) => new TransitionNode( convertToTexture( nodeA ), convertToTexture( nodeB ), convertToTexture( mixTextureNode ), nodeObject( mixRatio ), nodeObject( threshold ), nodeObject( useTexture ) );
@@ -0,0 +1,80 @@
1
+ import { abs, color, float, Fn, Loop, mix, nodeObject, perspectiveDepthToViewZ, reference, textureSize, uv, vec2, vec4, viewZToOrthographicDepth, int, If, array, ivec2 } from 'three/tsl';
2
+
3
+ /**
4
+ * Performs a depth-aware blend between a base scene and a secondary effect (like godrays).
5
+ * This function uses a Poisson disk sampling pattern to detect depth discontinuities
6
+ * in the neighborhood of the current pixel. If an edge is detected, it shifts the
7
+ * sampling coordinate for the blend node away from the edge to prevent light leaking/haloing.
8
+ *
9
+ * @param {Node} baseNode - The main scene/beauty pass texture node.
10
+ * @param {Node} blendNode - The effect to be blended (e.g., Godrays, Bloom).
11
+ * @param {Node} depthNode - The scene depth texture node.
12
+ * @param {Camera} camera - The camera used for the scene.
13
+ * @param {Object} [options={}] - Configuration for the blend effect.
14
+ * @param {Node|Color} [options.blendColor=Color(0xff0000)] - The color applied to the blend node.
15
+ * @param {Node<int> | number} [options.edgeRadius=2] - The search radius (in pixels) for detecting depth edges.
16
+ * @param {Node<float> | number} [options.edgeStrength=2] - How far to "push" the UV away from detected edges.
17
+ * @returns {Node<vec4>} The resulting blended color node.
18
+ */
19
+ export const depthAwareBlend = /*#__PURE__*/ Fn( ( [ baseNode, blendNode, depthNode, camera, options = {} ] ) => {
20
+
21
+ const uvNode = baseNode.uvNode || uv();
22
+
23
+ const cameraNear = reference( 'near', 'float', camera );
24
+ const cameraFar = reference( 'far', 'float', camera );
25
+
26
+ const blendColor = nodeObject( options.blendColor ) || color( 0xffffff );
27
+ const edgeRadius = nodeObject( options.edgeRadius ) || int( 2 );
28
+ const edgeStrength = nodeObject( options.edgeStrength ) || float( 2 );
29
+
30
+ const viewZ = perspectiveDepthToViewZ( depthNode, cameraNear, cameraFar );
31
+ const correctDepth = viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );
32
+
33
+ const pushDir = vec2( 0.0 ).toVar();
34
+ const count = float( 0 ).toVar();
35
+
36
+ const resolution = ivec2( textureSize( baseNode ) ).toConst();
37
+ const pixelStep = vec2( 1 ).div( resolution );
38
+
39
+ const poissonDisk = array( [
40
+ vec2( 0.493393, 0.394269 ),
41
+ vec2( 0.798547, 0.885922 ),
42
+ vec2( 0.259143, 0.650754 ),
43
+ vec2( 0.605322, 0.023588 ),
44
+ vec2( - 0.574681, 0.137452 ),
45
+ vec2( - 0.430397, - 0.638423 ),
46
+ vec2( - 0.849487, - 0.366258 ),
47
+ vec2( 0.170621, - 0.569941 )
48
+ ] );
49
+
50
+ Loop( 8, ( { i } ) => {
51
+
52
+ const offset = poissonDisk.element( i ).mul( edgeRadius );
53
+
54
+ const sampleUv = uvNode.add( offset.mul( pixelStep ) );
55
+ const sampleDepth = depthNode.sample( sampleUv );
56
+
57
+ const sampleViewZ = perspectiveDepthToViewZ( sampleDepth, cameraNear, cameraFar );
58
+ const sampleLinearDepth = viewZToOrthographicDepth( sampleViewZ, cameraNear, cameraFar );
59
+
60
+ If( abs( sampleLinearDepth.sub( correctDepth ) ).lessThan( float( 0.05 ).mul( correctDepth ) ), () => {
61
+
62
+ pushDir.addAssign( offset );
63
+ count.addAssign( 1 );
64
+
65
+ } );
66
+
67
+ } );
68
+
69
+ count.assign( count.equal( 0 ).select( 1, count ) );
70
+
71
+ pushDir.divAssign( count ).normalize();
72
+
73
+ const sampleUv = pushDir.length().greaterThan( 0 ).select( uvNode.add( edgeStrength.mul( pushDir.div( resolution ) ) ), uvNode );
74
+
75
+ const bestChoice = blendNode.sample( sampleUv ).r;
76
+ const baseColor = baseNode.sample( uvNode );
77
+
78
+ return vec4( mix( baseColor, vec4( blendColor, 1 ), bestChoice ) );
79
+
80
+ } );
@@ -1,5 +1,5 @@
1
1
  import { TextureLoader } from 'three';
2
- import { Fn, int, ivec2, textureLoad } from 'three/tsl';
2
+ import { Fn, int, ivec2, textureLoad, screenUV, screenSize, mod, floor, float, vec3 } from 'three/tsl';
3
3
 
4
4
  /**
5
5
  * @module Bayer
@@ -32,3 +32,42 @@ export const bayer16 = Fn( ( [ uv ] ) => {
32
32
  return textureLoad( bayer16Texture, ivec2( uv ).mod( int( 16 ) ) );
33
33
 
34
34
  } );
35
+
36
+ /**
37
+ * This TSL function applies Bayer dithering to a color input. It uses a 4x4 Bayer matrix
38
+ * pattern to add structured noise before color quantization, which helps reduce visible
39
+ * color banding when limiting color depth.
40
+ *
41
+ * @tsl
42
+ * @function
43
+ * @param {Node<vec3>} color - The input color to apply dithering to.
44
+ * @param {Node<float>} [steps=32] - The number of color steps per channel.
45
+ * @return {Node<vec3>} The dithered color ready for quantization.
46
+ *
47
+ * @example
48
+ * // Apply dithering with posterize
49
+ * const ditheredColor = bayerDither( inputColor, 32 );
50
+ * const finalColor = posterize( ditheredColor, 32 );
51
+ */
52
+ export const bayerDither = Fn( ( [ color, steps = float( 32.0 ) ] ) => {
53
+
54
+ const screenPos = screenUV.mul( screenSize );
55
+ const x = mod( floor( screenPos.x ), float( 4.0 ) );
56
+ const y = mod( floor( screenPos.y ), float( 4.0 ) );
57
+
58
+ // Simplified Bayer matrix approximation
59
+ const bayer = mod(
60
+ floor( x.add( 1.0 ) ).mul( floor( y.add( 1.0 ) ) ).mul( 17.0 ),
61
+ 16.0
62
+ ).div( 16.0 ).sub( 0.5 );
63
+
64
+ // Apply dither offset before quantization
65
+ const ditherOffset = bayer.div( steps );
66
+
67
+ return vec3(
68
+ color.r.add( ditherOffset ),
69
+ color.g.add( ditherOffset ),
70
+ color.b.add( ditherOffset )
71
+ );
72
+
73
+ } );