@plastic-software/three 0.178.0 → 0.180.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 (245) hide show
  1. package/README.md +1 -1
  2. package/build/three.cjs +950 -230
  3. package/build/three.core.js +754 -138
  4. package/build/three.core.min.js +1 -1
  5. package/build/three.module.js +197 -96
  6. package/build/three.module.min.js +1 -1
  7. package/build/three.tsl.js +99 -25
  8. package/build/three.tsl.min.js +1 -1
  9. package/build/three.webgpu.js +4586 -1499
  10. package/build/three.webgpu.min.js +1 -1
  11. package/build/three.webgpu.nodes.js +4544 -1499
  12. package/build/three.webgpu.nodes.min.js +1 -1
  13. package/examples/jsm/Addons.js +2 -3
  14. package/examples/jsm/capabilities/WebGPU.js +1 -1
  15. package/examples/jsm/controls/ArcballControls.js +7 -7
  16. package/examples/jsm/controls/DragControls.js +6 -56
  17. package/examples/jsm/controls/FirstPersonControls.js +2 -2
  18. package/examples/jsm/controls/PointerLockControls.js +0 -8
  19. package/examples/jsm/csm/CSMShadowNode.js +4 -4
  20. package/examples/jsm/environments/RoomEnvironment.js +8 -3
  21. package/examples/jsm/exporters/GLTFExporter.js +30 -22
  22. package/examples/jsm/exporters/KTX2Exporter.js +4 -2
  23. package/examples/jsm/exporters/PLYExporter.js +1 -1
  24. package/examples/jsm/exporters/USDZExporter.js +676 -299
  25. package/examples/jsm/geometries/RoundedBoxGeometry.js +47 -8
  26. package/examples/jsm/interactive/HTMLMesh.js +5 -3
  27. package/examples/jsm/libs/ktx-parse.module.js +1 -1
  28. package/examples/jsm/libs/meshopt_decoder.module.js +75 -58
  29. package/examples/jsm/lights/LightProbeGenerator.js +14 -3
  30. package/examples/jsm/lines/Line2.js +3 -3
  31. package/examples/jsm/lines/LineGeometry.js +1 -1
  32. package/examples/jsm/lines/LineSegments2.js +2 -2
  33. package/examples/jsm/lines/Wireframe.js +2 -2
  34. package/examples/jsm/lines/WireframeGeometry2.js +1 -1
  35. package/examples/jsm/lines/webgpu/LineSegments2.js +1 -1
  36. package/examples/jsm/lines/webgpu/Wireframe.js +1 -1
  37. package/examples/jsm/loaders/ColladaLoader.js +1 -1
  38. package/examples/jsm/loaders/EXRLoader.js +210 -22
  39. package/examples/jsm/loaders/FBXLoader.js +1 -1
  40. package/examples/jsm/loaders/GLTFLoader.js +9 -5
  41. package/examples/jsm/loaders/HDRCubeTextureLoader.js +5 -5
  42. package/examples/jsm/loaders/HDRLoader.js +486 -0
  43. package/examples/jsm/loaders/KTX2Loader.js +112 -32
  44. package/examples/jsm/loaders/MaterialXLoader.js +212 -30
  45. package/examples/jsm/loaders/RGBELoader.js +7 -473
  46. package/examples/jsm/loaders/TTFLoader.js +13 -1
  47. package/examples/jsm/loaders/USDLoader.js +219 -0
  48. package/examples/jsm/loaders/USDZLoader.js +4 -892
  49. package/examples/jsm/loaders/UltraHDRLoader.js +1 -1
  50. package/examples/jsm/loaders/lwo/IFFParser.js +1 -1
  51. package/examples/jsm/loaders/usd/USDAParser.js +741 -0
  52. package/examples/jsm/loaders/usd/USDCParser.js +17 -0
  53. package/examples/jsm/materials/WoodNodeMaterial.js +533 -0
  54. package/examples/jsm/math/ColorSpaces.js +19 -1
  55. package/examples/jsm/math/ConvexHull.js +2 -2
  56. package/examples/jsm/math/Lut.js +2 -2
  57. package/examples/jsm/misc/MD2CharacterComplex.js +1 -1
  58. package/examples/jsm/misc/ProgressiveLightMap.js +1 -1
  59. package/examples/jsm/misc/Volume.js +1 -1
  60. package/examples/jsm/objects/LensflareMesh.js +3 -3
  61. package/examples/jsm/objects/SkyMesh.js +2 -2
  62. package/examples/jsm/physics/RapierPhysics.js +14 -5
  63. package/examples/jsm/postprocessing/GTAOPass.js +10 -9
  64. package/examples/jsm/postprocessing/OutlinePass.js +17 -17
  65. package/examples/jsm/postprocessing/SSAOPass.js +10 -9
  66. package/examples/jsm/postprocessing/SSRPass.js +37 -8
  67. package/examples/jsm/shaders/UnpackDepthRGBAShader.js +11 -2
  68. package/examples/jsm/transpiler/GLSLDecoder.js +23 -20
  69. package/examples/jsm/transpiler/TSLEncoder.js +2 -10
  70. package/examples/jsm/transpiler/WGSLEncoder.js +24 -0
  71. package/examples/jsm/tsl/display/AnamorphicNode.js +27 -4
  72. package/examples/jsm/tsl/display/BloomNode.js +7 -6
  73. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +2 -1
  74. package/examples/jsm/tsl/display/DepthOfFieldNode.js +439 -90
  75. package/examples/jsm/tsl/display/GTAONode.js +8 -0
  76. package/examples/jsm/tsl/display/GaussianBlurNode.js +51 -41
  77. package/examples/jsm/tsl/display/OutlineNode.js +2 -2
  78. package/examples/jsm/tsl/display/SSRNode.js +180 -65
  79. package/examples/jsm/tsl/display/{TRAAPassNode.js → TRAANode.js} +181 -172
  80. package/examples/jsm/tsl/display/boxBlur.js +64 -0
  81. package/examples/jsm/tsl/display/hashBlur.js +15 -18
  82. package/examples/jsm/tsl/lighting/TiledLightsNode.js +1 -1
  83. package/examples/jsm/utils/BufferGeometryUtils.js +1 -1
  84. package/examples/jsm/utils/ShadowMapViewerGPU.js +12 -5
  85. package/examples/jsm/webxr/OculusHandModel.js +1 -1
  86. package/package.json +1 -1
  87. package/src/Three.Core.js +2 -0
  88. package/src/Three.TSL.js +98 -24
  89. package/src/animation/AnimationClip.js +17 -2
  90. package/src/animation/KeyframeTrack.js +1 -1
  91. package/src/animation/tracks/BooleanKeyframeTrack.js +1 -1
  92. package/src/animation/tracks/StringKeyframeTrack.js +1 -1
  93. package/src/cameras/Camera.js +14 -0
  94. package/src/cameras/OrthographicCamera.js +1 -1
  95. package/src/cameras/PerspectiveCamera.js +1 -1
  96. package/src/constants.js +11 -3
  97. package/src/core/BufferGeometry.js +2 -2
  98. package/{examples/jsm/misc → src/core}/Timer.js +4 -42
  99. package/src/extras/PMREMGenerator.js +11 -0
  100. package/src/extras/TextureUtils.js +2 -1
  101. package/src/extras/lib/earcut.js +1 -1
  102. package/src/helpers/CameraHelper.js +41 -11
  103. package/src/helpers/SkeletonHelper.js +35 -6
  104. package/src/lights/LightShadow.js +21 -8
  105. package/src/lights/PointLightShadow.js +1 -1
  106. package/src/lights/webgpu/ProjectorLight.js +1 -1
  107. package/src/loaders/FileLoader.js +25 -2
  108. package/src/loaders/ImageBitmapLoader.js +23 -0
  109. package/src/loaders/Loader.js +14 -0
  110. package/src/loaders/LoadingManager.js +23 -0
  111. package/src/materials/Material.js +12 -0
  112. package/src/materials/MeshBasicMaterial.js +1 -1
  113. package/src/materials/MeshDistanceMaterial.js +1 -1
  114. package/src/materials/nodes/Line2NodeMaterial.js +0 -8
  115. package/src/materials/nodes/NodeMaterial.js +1 -1
  116. package/src/materials/nodes/PointsNodeMaterial.js +86 -28
  117. package/src/materials/nodes/SpriteNodeMaterial.js +3 -15
  118. package/src/materials/nodes/manager/NodeMaterialObserver.js +87 -2
  119. package/src/math/ColorManagement.js +7 -1
  120. package/src/math/Frustum.js +19 -8
  121. package/src/math/FrustumArray.js +10 -5
  122. package/src/math/Line3.js +129 -2
  123. package/src/math/Matrix4.js +48 -27
  124. package/src/math/Spherical.js +2 -2
  125. package/src/nodes/Nodes.js +4 -0
  126. package/src/nodes/TSL.js +4 -0
  127. package/src/nodes/accessors/BufferNode.js +1 -1
  128. package/src/nodes/accessors/Camera.js +142 -16
  129. package/src/nodes/accessors/ClippingNode.js +6 -5
  130. package/src/nodes/accessors/CubeTextureNode.js +2 -2
  131. package/src/nodes/accessors/InstanceNode.js +3 -1
  132. package/src/nodes/accessors/Normal.js +11 -11
  133. package/src/nodes/accessors/Object3DNode.js +1 -1
  134. package/src/nodes/accessors/ReferenceBaseNode.js +1 -1
  135. package/src/nodes/accessors/ReferenceNode.js +19 -4
  136. package/src/nodes/accessors/SceneNode.js +1 -1
  137. package/src/nodes/accessors/StorageTextureNode.js +1 -1
  138. package/src/nodes/accessors/Texture3DNode.js +13 -0
  139. package/src/nodes/accessors/TextureNode.js +83 -19
  140. package/src/nodes/code/FunctionCallNode.js +19 -0
  141. package/src/nodes/code/FunctionNode.js +23 -0
  142. package/src/nodes/core/ArrayNode.js +12 -0
  143. package/src/nodes/core/AssignNode.js +6 -2
  144. package/src/nodes/core/ContextNode.js +44 -1
  145. package/src/nodes/core/Node.js +30 -22
  146. package/src/nodes/core/NodeBuilder.js +71 -32
  147. package/src/nodes/core/NodeFrame.js +1 -1
  148. package/src/nodes/core/NodeUniform.js +1 -1
  149. package/src/nodes/core/NodeUtils.js +5 -3
  150. package/src/nodes/core/StackNode.js +71 -4
  151. package/src/nodes/core/StructNode.js +5 -5
  152. package/src/nodes/core/StructTypeNode.js +1 -0
  153. package/src/nodes/core/SubBuildNode.js +2 -2
  154. package/src/nodes/core/UniformNode.js +79 -14
  155. package/src/nodes/core/VarNode.js +83 -15
  156. package/src/nodes/display/FrontFacingNode.js +4 -8
  157. package/src/nodes/display/PassNode.js +148 -2
  158. package/src/nodes/display/ScreenNode.js +42 -13
  159. package/src/nodes/display/ViewportDepthTextureNode.js +16 -4
  160. package/src/nodes/display/ViewportSharedTextureNode.js +12 -0
  161. package/src/nodes/display/ViewportTextureNode.js +94 -4
  162. package/src/nodes/functions/PhysicalLightingModel.js +2 -2
  163. package/src/nodes/gpgpu/AtomicFunctionNode.js +1 -1
  164. package/src/nodes/gpgpu/ComputeNode.js +67 -23
  165. package/src/nodes/gpgpu/SubgroupFunctionNode.js +430 -0
  166. package/src/nodes/gpgpu/WorkgroupInfoNode.js +28 -3
  167. package/src/nodes/lighting/LightsNode.js +1 -1
  168. package/src/nodes/lighting/ProjectorLightNode.js +19 -6
  169. package/src/nodes/lighting/ShadowFilterNode.js +1 -1
  170. package/src/nodes/materialx/MaterialXNodes.js +131 -2
  171. package/src/nodes/materialx/lib/mx_noise.js +165 -1
  172. package/src/nodes/math/BitcastNode.js +156 -0
  173. package/src/nodes/math/ConditionalNode.js +19 -3
  174. package/src/nodes/math/MathNode.js +72 -60
  175. package/src/nodes/math/OperatorNode.js +26 -25
  176. package/src/nodes/tsl/TSLCore.js +477 -142
  177. package/src/nodes/utils/DebugNode.js +1 -1
  178. package/src/nodes/utils/EventNode.js +83 -0
  179. package/src/nodes/utils/JoinNode.js +3 -1
  180. package/src/nodes/utils/MemberNode.js +58 -7
  181. package/src/nodes/utils/RTTNode.js +10 -1
  182. package/src/nodes/utils/ReflectorNode.js +51 -7
  183. package/src/nodes/utils/SampleNode.js +12 -2
  184. package/src/nodes/utils/SplitNode.js +11 -0
  185. package/src/nodes/utils/Timer.js +0 -47
  186. package/src/objects/BatchedMesh.js +6 -4
  187. package/src/objects/LOD.js +1 -1
  188. package/src/objects/Sprite.js +2 -2
  189. package/src/renderers/WebGLRenderer.js +21 -31
  190. package/src/renderers/common/Attributes.js +1 -1
  191. package/src/renderers/common/Backend.js +19 -1
  192. package/src/renderers/common/Bindings.js +21 -18
  193. package/src/renderers/common/ChainMap.js +1 -1
  194. package/src/renderers/common/Color4.js +2 -2
  195. package/src/renderers/common/DataMap.js +1 -1
  196. package/src/renderers/common/Pipelines.js +1 -1
  197. package/src/renderers/common/PostProcessing.js +60 -5
  198. package/src/renderers/common/RenderContext.js +2 -2
  199. package/src/renderers/common/RenderObject.js +14 -2
  200. package/src/renderers/common/Renderer.js +55 -32
  201. package/src/renderers/common/SampledTexture.js +4 -72
  202. package/src/renderers/common/Sampler.js +91 -0
  203. package/src/renderers/common/Storage3DTexture.js +21 -0
  204. package/src/renderers/common/StorageArrayTexture.js +21 -0
  205. package/src/renderers/common/StorageTexture.js +19 -0
  206. package/src/renderers/common/Textures.js +52 -14
  207. package/src/renderers/common/TimestampQueryPool.js +3 -3
  208. package/src/renderers/common/XRManager.js +51 -17
  209. package/src/renderers/common/nodes/NodeBuilderState.js +1 -1
  210. package/src/renderers/common/nodes/NodeLibrary.js +5 -5
  211. package/src/renderers/common/nodes/NodeSampledTexture.js +0 -12
  212. package/src/renderers/shaders/ShaderChunk/logdepthbuf_fragment.glsl.js +1 -1
  213. package/src/renderers/shaders/ShaderChunk/logdepthbuf_pars_fragment.glsl.js +1 -1
  214. package/src/renderers/shaders/ShaderChunk/logdepthbuf_pars_vertex.glsl.js +1 -1
  215. package/src/renderers/shaders/ShaderChunk/logdepthbuf_vertex.glsl.js +1 -1
  216. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +21 -11
  217. package/src/renderers/shaders/ShaderLib/depth.glsl.js +11 -2
  218. package/src/renderers/webgl/WebGLCapabilities.js +2 -2
  219. package/src/renderers/webgl/WebGLMaterials.js +6 -6
  220. package/src/renderers/webgl/WebGLProgram.js +24 -18
  221. package/src/renderers/webgl/WebGLPrograms.js +4 -4
  222. package/src/renderers/webgl/WebGLShadowMap.js +11 -1
  223. package/src/renderers/webgl/WebGLTextures.js +20 -7
  224. package/src/renderers/webgl/WebGLUtils.js +3 -2
  225. package/src/renderers/webgl-fallback/WebGLBackend.js +207 -146
  226. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +112 -19
  227. package/src/renderers/webgl-fallback/utils/WebGLState.js +1 -1
  228. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +52 -3
  229. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +9 -10
  230. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +3 -2
  231. package/src/renderers/webgpu/WebGPUBackend.js +87 -44
  232. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +169 -99
  233. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +35 -31
  234. package/src/renderers/webgpu/utils/WebGPUConstants.js +2 -2
  235. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +10 -19
  236. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +120 -84
  237. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +3 -3
  238. package/src/renderers/webgpu/utils/WebGPUUtils.js +2 -17
  239. package/src/renderers/webxr/WebXRDepthSensing.js +6 -10
  240. package/src/renderers/webxr/WebXRManager.js +86 -11
  241. package/src/textures/ExternalTexture.js +56 -0
  242. package/src/textures/FramebufferTexture.js +2 -2
  243. package/src/textures/Source.js +12 -2
  244. package/src/textures/VideoTexture.js +27 -2
  245. package/examples/jsm/loaders/RGBMLoader.js +0 -1148
@@ -1,5 +1,5 @@
1
1
  import { RenderTarget, Vector2, NodeMaterial, RendererUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
2
- import { nodeObject, Fn, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, mul, premultiplyAlpha, unpremultiplyAlpha } from 'three/tsl';
2
+ import { nodeObject, Fn, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, premultiplyAlpha, unpremultiplyAlpha } from 'three/tsl';
3
3
 
4
4
  const _quadMesh = /*@__PURE__*/ new QuadMesh();
5
5
 
@@ -25,8 +25,11 @@ class GaussianBlurNode extends TempNode {
25
25
  * @param {TextureNode} textureNode - The texture node that represents the input of the effect.
26
26
  * @param {Node<vec2|float>} directionNode - Defines the direction and radius of the blur.
27
27
  * @param {number} sigma - Controls the kernel of the blur filter. Higher values mean a wider blur radius.
28
+ * @param {Object} [options={}] - Additional options for the gaussian blur effect.
29
+ * @param {boolean} [options.premultipliedAlpha=false] - Whether to use premultiplied alpha for the blur effect.
30
+ * @param {Vector2} [options.resolution=new Vector2(1, 1)] - The resolution of the effect. 0.5 means half the resolution of the texture node.
28
31
  */
29
- constructor( textureNode, directionNode = null, sigma = 2 ) {
32
+ constructor( textureNode, directionNode = null, sigma = 4, options = {} ) {
30
33
 
31
34
  super( 'vec4' );
32
35
 
@@ -105,12 +108,12 @@ class GaussianBlurNode extends TempNode {
105
108
  this.updateBeforeType = NodeUpdateType.FRAME;
106
109
 
107
110
  /**
108
- * Controls the resolution of the effect.
111
+ * The resolution scale.
109
112
  *
110
- * @type {Vector2}
111
- * @default (1,1)
113
+ * @type {float}
114
+ * @default (1)
112
115
  */
113
- this.resolution = new Vector2( 1, 1 );
116
+ this.resolutionScale = options.resolutionScale || 1;
114
117
 
115
118
  /**
116
119
  * Whether the effect should use premultiplied alpha or not. Set this to `true`
@@ -119,32 +122,7 @@ class GaussianBlurNode extends TempNode {
119
122
  * @type {boolean}
120
123
  * @default false
121
124
  */
122
- this.premultipliedAlpha = false;
123
-
124
- }
125
-
126
- /**
127
- * Sets the given premultiplied alpha value.
128
- *
129
- * @param {boolean} value - Whether the effect should use premultiplied alpha or not.
130
- * @return {GaussianBlurNode} height - A reference to this node.
131
- */
132
- setPremultipliedAlpha( value ) {
133
-
134
- this.premultipliedAlpha = value;
135
-
136
- return this;
137
-
138
- }
139
-
140
- /**
141
- * Returns the premultiplied alpha value.
142
- *
143
- * @return {boolean} Whether the effect should use premultiplied alpha or not.
144
- */
145
- getPremultipliedAlpha() {
146
-
147
- return this.premultipliedAlpha;
125
+ this.premultipliedAlpha = options.premultipliedAlpha || false;
148
126
 
149
127
  }
150
128
 
@@ -156,8 +134,8 @@ class GaussianBlurNode extends TempNode {
156
134
  */
157
135
  setSize( width, height ) {
158
136
 
159
- width = Math.max( Math.round( width * this.resolution.x ), 1 );
160
- height = Math.max( Math.round( height * this.resolution.y ), 1 );
137
+ width = Math.max( Math.round( width * this.resolutionScale ), 1 );
138
+ height = Math.max( Math.round( height * this.resolutionScale ), 1 );
161
139
 
162
140
  this._invSize.value.set( 1 / width, 1 / height );
163
141
  this._horizontalRT.setSize( width, height );
@@ -267,8 +245,7 @@ class GaussianBlurNode extends TempNode {
267
245
  const invSize = this._invSize;
268
246
  const direction = directionNode.mul( this._passDirection );
269
247
 
270
- const weightSum = float( gaussianCoefficients[ 0 ] ).toVar();
271
- const diffuseSum = vec4( sampleTexture( uvNode ).mul( weightSum ) ).toVar();
248
+ const diffuseSum = vec4( sampleTexture( uvNode ).mul( gaussianCoefficients[ 0 ] ) ).toVar();
272
249
 
273
250
  for ( let i = 1; i < kernelSize; i ++ ) {
274
251
 
@@ -281,11 +258,10 @@ class GaussianBlurNode extends TempNode {
281
258
  const sample2 = sampleTexture( uvNode.sub( uvOffset ) );
282
259
 
283
260
  diffuseSum.addAssign( sample1.add( sample2 ).mul( w ) );
284
- weightSum.addAssign( mul( 2.0, w ) );
285
261
 
286
262
  }
287
263
 
288
- return output( diffuseSum.div( weightSum ) );
264
+ return output( diffuseSum );
289
265
 
290
266
  } );
291
267
 
@@ -328,10 +304,11 @@ class GaussianBlurNode extends TempNode {
328
304
  _getCoefficients( kernelRadius ) {
329
305
 
330
306
  const coefficients = [];
307
+ const sigma = kernelRadius / 3;
331
308
 
332
309
  for ( let i = 0; i < kernelRadius; i ++ ) {
333
310
 
334
- coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius );
311
+ coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( sigma * sigma ) ) / sigma );
335
312
 
336
313
  }
337
314
 
@@ -339,6 +316,29 @@ class GaussianBlurNode extends TempNode {
339
316
 
340
317
  }
341
318
 
319
+ /**
320
+ * The resolution scale.
321
+ *
322
+ * @deprecated
323
+ * @type {Vector2}
324
+ * @default {(1,1)}
325
+ */
326
+ get resolution() {
327
+
328
+ console.warn( 'THREE.GaussianBlurNode: The "resolution" property has been renamed to "resolutionScale" and is now of type `number`.' ); // @deprecated r180
329
+
330
+ return new Vector2( this.resolutionScale, this.resolutionScale );
331
+
332
+ }
333
+
334
+ set resolution( value ) {
335
+
336
+ console.warn( 'THREE.GaussianBlurNode: The "resolution" property has been renamed to "resolutionScale" and is now of type `number`.' ); // @deprecated r180
337
+
338
+ this.resolutionScale = value.x;
339
+
340
+ }
341
+
342
342
  }
343
343
 
344
344
  export default GaussianBlurNode;
@@ -351,18 +351,28 @@ export default GaussianBlurNode;
351
351
  * @param {Node<vec4>} node - The node that represents the input of the effect.
352
352
  * @param {Node<vec2|float>} directionNode - Defines the direction and radius of the blur.
353
353
  * @param {number} sigma - Controls the kernel of the blur filter. Higher values mean a wider blur radius.
354
+ * @param {Object} [options={}] - Additional options for the gaussian blur effect.
355
+ * @param {boolean} [options.premultipliedAlpha=false] - Whether to use premultiplied alpha for the blur effect.
356
+ * @param {Vector2} [options.resolution=new Vector2(1, 1)] - The resolution of the effect. 0.5 means half the resolution of the texture node.
354
357
  * @returns {GaussianBlurNode}
355
358
  */
356
- export const gaussianBlur = ( node, directionNode, sigma ) => nodeObject( new GaussianBlurNode( convertToTexture( node ), directionNode, sigma ) );
359
+ export const gaussianBlur = ( node, directionNode, sigma, options = {} ) => nodeObject( new GaussianBlurNode( convertToTexture( node ), directionNode, sigma, options ) );
357
360
 
358
361
  /**
359
362
  * TSL function for creating a gaussian blur node for post processing with enabled premultiplied alpha.
360
363
  *
361
364
  * @tsl
362
365
  * @function
366
+ * @deprecated since r180. Use `gaussianBlur()` with `premultipliedAlpha: true` option instead.
363
367
  * @param {Node<vec4>} node - The node that represents the input of the effect.
364
368
  * @param {Node<vec2|float>} directionNode - Defines the direction and radius of the blur.
365
369
  * @param {number} sigma - Controls the kernel of the blur filter. Higher values mean a wider blur radius.
366
370
  * @returns {GaussianBlurNode}
367
371
  */
368
- export const premultipliedGaussianBlur = ( node, directionNode, sigma ) => nodeObject( new GaussianBlurNode( convertToTexture( node ), directionNode, sigma ).setPremultipliedAlpha( true ) );
372
+ export function premultipliedGaussianBlur( node, directionNode, sigma ) {
373
+
374
+ console.warn( 'THREE.TSL: "premultipliedGaussianBlur()" is deprecated. Use "gaussianBlur()" with "premultipliedAlpha: true" option instead.' ); // deprecated, r180
375
+
376
+ return gaussianBlur( node, directionNode, sigma, { premultipliedAlpha: true } );
377
+
378
+ }
@@ -56,7 +56,7 @@ class OutlineNode extends TempNode {
56
56
  * @param {Scene} scene - A reference to the scene.
57
57
  * @param {Camera} camera - The camera the scene is rendered with.
58
58
  * @param {Object} params - The configuration parameters.
59
- * @param {Array<Object3D>} params.selectedObjects - An array of selected objects.
59
+ * @param {Array<Object3D>} [params.selectedObjects] - An array of selected objects.
60
60
  * @param {Node<float>} [params.edgeThickness=float(1)] - The thickness of the edges.
61
61
  * @param {Node<float>} [params.edgeGlow=float(0)] - Can be used for an animated glow/pulse effects.
62
62
  * @param {number} [params.downSampleRatio=2] - The downsample ratio.
@@ -742,7 +742,7 @@ export default OutlineNode;
742
742
  * @param {Scene} scene - A reference to the scene.
743
743
  * @param {Camera} camera - The camera the scene is rendered with.
744
744
  * @param {Object} params - The configuration parameters.
745
- * @param {Array<Object3D>} params.selectedObjects - An array of selected objects.
745
+ * @param {Array<Object3D>} [params.selectedObjects] - An array of selected objects.
746
746
  * @param {Node<float>} [params.edgeThickness=float(1)] - The thickness of the edges.
747
747
  * @param {Node<float>} [params.edgeGlow=float(0)] - Can be used for animated glow/pulse effects.
748
748
  * @param {number} [params.downSampleRatio=2] - The downsample ratio.
@@ -1,5 +1,6 @@
1
- import { NearestFilter, RenderTarget, Vector2, RendererUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType } from 'three/webgpu';
2
- import { reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, sqrt, mul, div, cross, float, Continue, Break, Loop, int, max, abs, sub, If, dot, reflect, normalize, screenCoordinate, nodeObject, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, vec3, vec4 } from 'three/tsl';
1
+ import { 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';
3
+ import { boxBlur } from './boxBlur.js';
3
4
 
4
5
  const _quadMesh = /*@__PURE__*/ new QuadMesh();
5
6
  const _size = /*@__PURE__*/ new Vector2();
@@ -28,9 +29,10 @@ class SSRNode extends TempNode {
28
29
  * @param {Node<float>} depthNode - A node that represents the beauty pass's depth.
29
30
  * @param {Node<vec3>} normalNode - A node that represents the beauty pass's normals.
30
31
  * @param {Node<float>} metalnessNode - A node that represents the beauty pass's metalness.
31
- * @param {Camera} camera - The camera the scene is rendered with.
32
+ * @param {?Node<float>} [roughnessNode=null] - A node that represents the beauty pass's roughness.
33
+ * @param {?Camera} [camera=null] - The camera the scene is rendered with.
32
34
  */
33
- constructor( colorNode, depthNode, normalNode, metalnessNode, camera ) {
35
+ constructor( colorNode, depthNode, normalNode, metalnessNode, roughnessNode = null, camera = null ) {
34
36
 
35
37
  super( 'vec4' );
36
38
 
@@ -63,22 +65,26 @@ class SSRNode extends TempNode {
63
65
  this.metalnessNode = metalnessNode;
64
66
 
65
67
  /**
66
- * The camera the scene is rendered with.
68
+ * Whether the SSR reflections should be blurred or not. Blurring is a costly
69
+ * operation so turn it off if you encounter performance issues on certain
70
+ * devices.
67
71
  *
68
- * @type {Camera}
72
+ * @private
73
+ * @type {Node<float>}
74
+ * @default false
69
75
  */
70
- this.camera = camera;
76
+ this.roughnessNode = roughnessNode;
71
77
 
72
78
  /**
73
- * The resolution scale. By default SSR reflections
74
- * are computed in half resolutions. Setting the value
75
- * to `1` improves quality but also results in more
76
- * computational overhead.
79
+ * The resolution scale. Valid values are in the range
80
+ * `[0,1]`. `1` means best quality but also results in
81
+ * more computational overhead. Setting to `0.5` means
82
+ * the effect is computed in half-resolution.
77
83
  *
78
84
  * @type {number}
79
- * @default 0.5
85
+ * @default 1
80
86
  */
81
- this.resolutionScale = 0.5;
87
+ this.resolutionScale = 1;
82
88
 
83
89
  /**
84
90
  * The `updateBeforeType` is set to `NodeUpdateType.FRAME` since the node renders
@@ -90,17 +96,8 @@ class SSRNode extends TempNode {
90
96
  this.updateBeforeType = NodeUpdateType.FRAME;
91
97
 
92
98
  /**
93
- * The render target the SSR is rendered into.
94
- *
95
- * @private
96
- * @type {RenderTarget}
97
- */
98
- this._ssrRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false, minFilter: NearestFilter, magFilter: NearestFilter } );
99
- this._ssrRenderTarget.texture.name = 'SSRNode.SSR';
100
-
101
- /**
102
- * Controls how far a fragment can reflect.
103
- *
99
+ * Controls how far a fragment can reflect. Increasing this value result in more
100
+ * computational overhead but also increases the reflection distance.
104
101
  *
105
102
  * @type {UniformNode<float>}
106
103
  */
@@ -114,12 +111,63 @@ class SSRNode extends TempNode {
114
111
  this.thickness = uniform( 0.1 );
115
112
 
116
113
  /**
117
- * Controls the transparency of the reflected colors.
114
+ * Controls how the SSR reflections are blended with the beauty pass.
118
115
  *
119
116
  * @type {UniformNode<float>}
120
117
  */
121
118
  this.opacity = uniform( 1 );
122
119
 
120
+ /**
121
+ * This parameter controls how detailed the raymarching process works.
122
+ * The value ranges is `[0,1]` where `1` means best quality (the maximum number
123
+ * of raymarching iterations/samples) and `0` means no samples at all.
124
+ *
125
+ * A quality of `0.5` is usually sufficient for most use cases. Try to keep
126
+ * this parameter as low as possible. Larger values result in noticeable more
127
+ * overhead.
128
+ *
129
+ * @type {UniformNode<float>}
130
+ */
131
+ this.quality = uniform( 0.5 );
132
+
133
+ /**
134
+ * The quality of the blur. Must be an integer in the range `[1,3]`.
135
+ *
136
+ * @type {UniformNode<int>}
137
+ */
138
+ this.blurQuality = uniform( 2 );
139
+
140
+ //
141
+
142
+ if ( camera === null ) {
143
+
144
+ if ( this.colorNode.passNode && this.colorNode.passNode.isPassNode === true ) {
145
+
146
+ camera = this.colorNode.passNode.camera;
147
+
148
+ } else {
149
+
150
+ throw new Error( 'THREE.TSL: No camera found. ssr() requires a camera.' );
151
+
152
+ }
153
+
154
+ }
155
+
156
+ /**
157
+ * The camera the scene is rendered with.
158
+ *
159
+ * @type {Camera}
160
+ */
161
+ this.camera = camera;
162
+
163
+ /**
164
+ * The spread of the blur. Automatically set when generating mips.
165
+ *
166
+ * @private
167
+ * @type {UniformNode<int>}
168
+ */
169
+ this._blurSpread = uniform( 1 );
170
+
123
171
  /**
124
172
  * Represents the projection matrix of the scene's camera.
125
173
  *
@@ -158,7 +206,7 @@ class SSRNode extends TempNode {
158
206
  * @private
159
207
  * @type {UniformNode<bool>}
160
208
  */
161
- this._isPerspectiveCamera = uniform( camera.isPerspectiveCamera ? 1 : 0 );
209
+ this._isPerspectiveCamera = uniform( camera.isPerspectiveCamera );
162
210
 
163
211
  /**
164
212
  * The resolution of the pass.
@@ -169,13 +217,23 @@ class SSRNode extends TempNode {
169
217
  this._resolution = uniform( new Vector2() );
170
218
 
171
219
  /**
172
- * This value is derived from the resolution and restricts
173
- * the maximum raymarching steps in the fragment shader.
220
+ * The render target the SSR is rendered into.
174
221
  *
175
222
  * @private
176
- * @type {UniformNode<float>}
223
+ * @type {RenderTarget}
224
+ */
225
+ this._ssrRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false, type: HalfFloatType } );
226
+ this._ssrRenderTarget.texture.name = 'SSRNode.SSR';
227
+
228
+ /**
229
+ * The render target for the blurred SSR reflections.
230
+ *
231
+ * @private
232
+ * @type {RenderTarget}
177
233
  */
178
- this._maxStep = uniform( 0 );
234
+ this._blurRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false, type: HalfFloatType, minFilter: LinearMipmapLinearFilter, magFilter: LinearFilter } );
235
+ this._blurRenderTarget.texture.name = 'SSRNode.Blur';
236
+ this._blurRenderTarget.texture.mipmaps.push( {}, {}, {}, {}, {} );
179
237
 
180
238
  /**
181
239
  * The material that is used to render the effect.
@@ -183,8 +241,26 @@ class SSRNode extends TempNode {
183
241
  * @private
184
242
  * @type {NodeMaterial}
185
243
  */
186
- this._material = new NodeMaterial();
187
- this._material.name = 'SSRNode.SSR';
244
+ this._ssrMaterial = new NodeMaterial();
245
+ this._ssrMaterial.name = 'SSRNode.SSR';
246
+
247
+ /**
248
+ * The blur material.
249
+ *
250
+ * @private
251
+ * @type {NodeMaterial}
252
+ */
253
+ this._blurMaterial = new NodeMaterial();
254
+ this._blurMaterial.name = 'SSRNode.Blur';
255
+
256
+ /**
257
+ * The copy material.
258
+ *
259
+ * @private
260
+ * @type {NodeMaterial}
261
+ */
262
+ this._copyMaterial = new NodeMaterial();
263
+ this._copyMaterial.name = 'SSRNode.Copy';
188
264
 
189
265
  /**
190
266
  * The result of the effect is represented as a separate texture node.
@@ -194,6 +270,25 @@ class SSRNode extends TempNode {
194
270
  */
195
271
  this._textureNode = passTexture( this, this._ssrRenderTarget.texture );
196
272
 
273
+ let blurredTextureNode = null;
274
+
275
+ if ( this.roughnessNode !== null ) {
276
+
277
+ const mips = this._blurRenderTarget.texture.mipmaps.length - 1;
278
+ const lod = float( this.roughnessNode ).mul( mips ).clamp( 0, mips );
279
+
280
+ blurredTextureNode = passTexture( this, this._blurRenderTarget.texture ).level( lod );
281
+
282
+ }
283
+
284
+ /**
285
+ * Holds the blurred SSR reflections.
286
+ *
287
+ * @private
288
+ * @type {?PassTextureNode}
289
+ */
290
+ this._blurredTextureNode = blurredTextureNode;
291
+
197
292
  }
198
293
 
199
294
  /**
@@ -203,7 +298,7 @@ class SSRNode extends TempNode {
203
298
  */
204
299
  getTextureNode() {
205
300
 
206
- return this._textureNode;
301
+ return this.roughnessNode !== null ? this._blurredTextureNode : this._textureNode;
207
302
 
208
303
  }
209
304
 
@@ -219,9 +314,8 @@ class SSRNode extends TempNode {
219
314
  height = Math.round( this.resolutionScale * height );
220
315
 
221
316
  this._resolution.value.set( width, height );
222
- this._maxStep.value = Math.round( Math.sqrt( width * width + height * height ) );
223
-
224
317
  this._ssrRenderTarget.setSize( width, height );
318
+ this._blurRenderTarget.setSize( width, height );
225
319
 
226
320
  }
227
321
 
@@ -236,9 +330,12 @@ class SSRNode extends TempNode {
236
330
 
237
331
  _rendererState = RendererUtils.resetRendererState( renderer, _rendererState );
238
332
 
333
+ const ssrRenderTarget = this._ssrRenderTarget;
334
+ const blurRenderTarget = this._blurRenderTarget;
335
+
239
336
  const size = renderer.getDrawingBufferSize( _size );
240
337
 
241
- _quadMesh.material = this._material;
338
+ _quadMesh.material = this._ssrMaterial;
242
339
 
243
340
  this.setSize( size.width, size.height );
244
341
 
@@ -249,9 +346,27 @@ class SSRNode extends TempNode {
249
346
 
250
347
  // ssr
251
348
 
252
- renderer.setRenderTarget( this._ssrRenderTarget );
349
+ renderer.setRenderTarget( ssrRenderTarget );
253
350
  _quadMesh.render( renderer );
254
351
 
352
+ // blur (optional)
353
+
354
+ if ( this.roughnessNode !== null ) {
355
+
356
+ // blur mips but leave the base mip unblurred
357
+
358
+ for ( let i = 0; i < blurRenderTarget.texture.mipmaps.length; i ++ ) {
359
+
360
+ _quadMesh.material = ( i === 0 ) ? this._copyMaterial : this._blurMaterial;
361
+
362
+ this._blurSpread.value = i;
363
+ renderer.setRenderTarget( blurRenderTarget, 0, i );
364
+ _quadMesh.render( renderer );
365
+
366
+ }
367
+
368
+ }
369
+
255
370
  // restore
256
371
 
257
372
  RendererUtils.restoreRendererState( renderer, _rendererState );
@@ -326,7 +441,7 @@ class SSRNode extends TempNode {
326
441
 
327
442
  const ssr = Fn( () => {
328
443
 
329
- const metalness = this.metalnessNode.sample( uvNode ).r;
444
+ const metalness = float( this.metalnessNode );
330
445
 
331
446
  // fragments with no metalness do not reflect their environment
332
447
  metalness.equal( 0.0 ).discard();
@@ -349,7 +464,7 @@ class SSRNode extends TempNode {
349
464
  const d1viewPosition = viewPosition.add( viewReflectDir.mul( maxReflectRayLen ) ).toVar();
350
465
 
351
466
  // check if d1viewPosition lies behind the camera near plane
352
- If( this._isPerspectiveCamera.equal( float( 1 ) ).and( d1viewPosition.z.greaterThan( this._cameraNear.negate() ) ), () => {
467
+ If( this._isPerspectiveCamera.and( d1viewPosition.z.greaterThan( this._cameraNear.negate() ) ), () => {
353
468
 
354
469
  // if so, ensure d1viewPosition is clamped on the near plane.
355
470
  // this prevents artifacts during the ray marching process
@@ -374,7 +489,7 @@ class SSRNode extends TempNode {
374
489
  // determine the larger delta
375
490
  // The larger difference will help to determine how much to travel in the X and Y direction each iteration and
376
491
  // how many iterations are needed to travel the entire ray
377
- const totalStep = max( abs( xLen ), abs( yLen ) ).toVar();
492
+ const totalStep = int( max( abs( xLen ), abs( yLen ) ).mul( this.quality.clamp() ) ).toConst();
378
493
 
379
494
  // step sizes in the x and y directions
380
495
  const xSpan = xLen.div( totalStep ).toVar();
@@ -385,23 +500,9 @@ class SSRNode extends TempNode {
385
500
  // the actual ray marching loop
386
501
  // starting from d0, the code gradually travels along the ray and looks for an intersection with the geometry.
387
502
  // it does not exceed d1 (the maximum ray extend)
388
- Loop( { start: int( 0 ), end: int( this._maxStep ), type: 'int', condition: '<' }, ( { i } ) => {
389
-
390
- // TODO: Remove this when Chrome is fixed, see https://issues.chromium.org/issues/372714384#comment14
391
- If( metalness.equal( 0 ), () => {
503
+ Loop( totalStep, ( { i } ) => {
392
504
 
393
- Break();
394
-
395
- } );
396
-
397
- // stop if the maximum number of steps is reached for this specific ray
398
- If( float( i ).greaterThanEqual( totalStep ), () => {
399
-
400
- Break();
401
-
402
- } );
403
-
404
- // advance on the ray by computing a new position in screen space
505
+ // advance on the ray by computing a new position in screen coordinates
405
506
  const xy = vec2( d0.x.add( xSpan.mul( float( i ) ) ), d0.y.add( ySpan.mul( float( i ) ) ) ).toVar();
406
507
 
407
508
  // stop processing if the new position lies outside of the screen
@@ -411,11 +512,10 @@ class SSRNode extends TempNode {
411
512
 
412
513
  } );
413
514
 
414
- // compute new uv, depth, viewZ and viewPosition for the new location on the ray
515
+ // compute new uv, depth and viewZ for the next fragment
415
516
  const uvNode = xy.div( this._resolution );
416
517
  const d = sampleDepth( uvNode ).toVar();
417
518
  const vZ = getViewZ( d ).toVar();
418
- const vP = getViewPosition( uvNode, d, this._cameraProjectionMatrixInverse ).toVar();
419
519
 
420
520
  const viewReflectRayZ = float( 0 ).toVar();
421
521
 
@@ -423,7 +523,7 @@ class SSRNode extends TempNode {
423
523
  const s = xy.sub( d0 ).length().div( totalLen );
424
524
 
425
525
  // depending on the camera type, we now compute the z-coordinate of the reflected ray at the current step in view space
426
- If( this._isPerspectiveCamera.equal( float( 1 ) ), () => {
526
+ If( this._isPerspectiveCamera, () => {
427
527
 
428
528
  const recipVPZ = float( 1 ).div( viewPosition.z ).toVar();
429
529
  viewReflectRayZ.assign( float( 1 ).div( recipVPZ.add( s.mul( float( 1 ).div( d1viewPosition.z ).sub( recipVPZ ) ) ) ) );
@@ -439,6 +539,7 @@ class SSRNode extends TempNode {
439
539
 
440
540
  // compute the distance of the new location to the ray in view space
441
541
  // to clarify vP is the fragment's view position which is not an exact point on the ray
542
+ const vP = getViewPosition( uvNode, d, this._cameraProjectionMatrixInverse ).toVar();
442
543
  const away = pointToLineDistance( vP, viewPosition, d1viewPosition ).toVar();
443
544
 
444
545
  // compute the minimum thickness between the current fragment and its neighbor in the x-direction.
@@ -499,12 +600,22 @@ class SSRNode extends TempNode {
499
600
 
500
601
  } );
501
602
 
502
- this._material.fragmentNode = ssr().context( builder.getSharedContext() );
503
- this._material.needsUpdate = true;
603
+ this._ssrMaterial.fragmentNode = ssr().context( builder.getSharedContext() );
604
+ this._ssrMaterial.needsUpdate = true;
605
+
606
+ // below materials are used for blurring
607
+
608
+ const reflectionBuffer = texture( this._ssrRenderTarget.texture );
609
+
610
+ this._blurMaterial.fragmentNode = boxBlur( reflectionBuffer, { size: this.blurQuality, separation: this._blurSpread } );
611
+ this._blurMaterial.needsUpdate = true;
612
+
613
+ this._copyMaterial.fragmentNode = reflectionBuffer;
614
+ this._copyMaterial.needsUpdate = true;
504
615
 
505
616
  //
506
617
 
507
- return this._textureNode;
618
+ return this.getTextureNode();
508
619
 
509
620
  }
510
621
 
@@ -515,8 +626,11 @@ class SSRNode extends TempNode {
515
626
  dispose() {
516
627
 
517
628
  this._ssrRenderTarget.dispose();
629
+ this._blurRenderTarget.dispose();
518
630
 
519
- this._material.dispose();
631
+ this._ssrMaterial.dispose();
632
+ this._blurMaterial.dispose();
633
+ this._copyMaterial.dispose();
520
634
 
521
635
  }
522
636
 
@@ -533,7 +647,8 @@ export default SSRNode;
533
647
  * @param {Node<float>} depthNode - A node that represents the beauty pass's depth.
534
648
  * @param {Node<vec3>} normalNode - A node that represents the beauty pass's normals.
535
649
  * @param {Node<float>} metalnessNode - A node that represents the beauty pass's metalness.
536
- * @param {Camera} camera - The camera the scene is rendered with.
650
+ * @param {?Node<float>} [roughnessNode=null] - A node that represents the beauty pass's roughness.
651
+ * @param {?Camera} [camera=null] - The camera the scene is rendered with.
537
652
  * @returns {SSRNode}
538
653
  */
539
- export const ssr = ( colorNode, depthNode, normalNode, metalnessNode, camera ) => nodeObject( new SSRNode( nodeObject( colorNode ), nodeObject( depthNode ), nodeObject( normalNode ), nodeObject( metalnessNode ), camera ) );
654
+ 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 ) );