@plastic-software/three 0.183.4 → 0.184.1

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 (277) hide show
  1. package/build/three.cjs +775 -287
  2. package/build/three.core.js +372 -110
  3. package/build/three.core.min.js +1 -1
  4. package/build/three.module.js +428 -181
  5. package/build/three.module.min.js +1 -1
  6. package/build/three.tsl.js +7 -1
  7. package/build/three.tsl.min.js +1 -1
  8. package/build/three.webgpu.js +2979 -1281
  9. package/build/three.webgpu.min.js +1 -1
  10. package/build/three.webgpu.nodes.js +2942 -1281
  11. package/build/three.webgpu.nodes.min.js +1 -1
  12. package/examples/jsm/Addons.js +11 -0
  13. package/examples/jsm/animation/CCDIKSolver.js +5 -1
  14. package/examples/jsm/controls/ArcballControls.js +4 -1
  15. package/examples/jsm/controls/DragControls.js +2 -2
  16. package/examples/jsm/controls/FirstPersonControls.js +58 -54
  17. package/examples/jsm/controls/FlyControls.js +4 -0
  18. package/examples/jsm/controls/OrbitControls.js +2 -2
  19. package/examples/jsm/controls/TrackballControls.js +2 -2
  20. package/examples/jsm/controls/TransformControls.js +34 -2
  21. package/examples/jsm/csm/CSMShadowNode.js +6 -2
  22. package/examples/jsm/exporters/GLTFExporter.js +21 -5
  23. package/examples/jsm/geometries/TextGeometry.js +18 -0
  24. package/examples/jsm/helpers/LightProbeGridHelper.js +221 -0
  25. package/examples/jsm/inspector/Extension.js +13 -0
  26. package/examples/jsm/inspector/Inspector.js +169 -114
  27. package/examples/jsm/inspector/RendererInspector.js +2 -2
  28. package/examples/jsm/inspector/extensions/extensions.json +6 -0
  29. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js +916 -0
  30. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphLoader.js +281 -0
  31. package/examples/jsm/inspector/tabs/Memory.js +128 -0
  32. package/examples/jsm/inspector/tabs/Parameters.js +34 -2
  33. package/examples/jsm/inspector/tabs/Performance.js +2 -2
  34. package/examples/jsm/inspector/tabs/Settings.js +264 -0
  35. package/examples/jsm/inspector/tabs/Timeline.js +1611 -0
  36. package/examples/jsm/inspector/tabs/Viewer.js +105 -3
  37. package/examples/jsm/inspector/ui/Graph.js +2 -2
  38. package/examples/jsm/inspector/ui/List.js +1 -1
  39. package/examples/jsm/inspector/ui/Profiler.js +273 -176
  40. package/examples/jsm/inspector/ui/Style.js +64 -10
  41. package/examples/jsm/inspector/ui/Tab.js +39 -7
  42. package/examples/jsm/inspector/ui/Values.js +39 -2
  43. package/examples/jsm/inspector/ui/utils.js +13 -0
  44. package/examples/jsm/interaction/InteractionManager.js +226 -0
  45. package/examples/jsm/libs/meshopt_decoder.module.js +8 -8
  46. package/examples/jsm/lighting/DynamicLighting.js +82 -0
  47. package/examples/jsm/lighting/LightProbeGrid.js +651 -0
  48. package/examples/jsm/lines/LineMaterial.js +1 -1
  49. package/examples/jsm/loaders/EXRLoader.js +682 -43
  50. package/examples/jsm/loaders/FBXLoader.js +233 -33
  51. package/examples/jsm/loaders/GLTFLoader.js +24 -7
  52. package/examples/jsm/loaders/HDRLoader.js +1 -1
  53. package/examples/jsm/loaders/KTX2Loader.js +8 -2
  54. package/examples/jsm/loaders/LDrawLoader.js +39 -47
  55. package/examples/jsm/loaders/SVGLoader.js +1 -1
  56. package/examples/jsm/loaders/VTKLoader.js +5 -1
  57. package/examples/jsm/loaders/collada/ColladaComposer.js +101 -7
  58. package/examples/jsm/loaders/collada/ColladaParser.js +19 -4
  59. package/examples/jsm/loaders/usd/USDAParser.js +6 -0
  60. package/examples/jsm/loaders/usd/USDCParser.js +26 -0
  61. package/examples/jsm/loaders/usd/USDComposer.js +656 -103
  62. package/examples/jsm/misc/GPUComputationRenderer.js +2 -0
  63. package/examples/jsm/misc/RollerCoaster.js +42 -4
  64. package/examples/jsm/modifiers/TessellateModifier.js +1 -1
  65. package/examples/jsm/objects/Reflector.js +73 -25
  66. package/examples/jsm/objects/Sky.js +14 -2
  67. package/examples/jsm/objects/SkyMesh.js +23 -6
  68. package/examples/jsm/renderers/Projector.js +18 -38
  69. package/examples/jsm/renderers/SVGRenderer.js +6 -25
  70. package/examples/jsm/transpiler/GLSLDecoder.js +2 -2
  71. package/examples/jsm/tsl/WebGLNodesHandler.js +605 -0
  72. package/examples/jsm/tsl/display/AfterImageNode.js +10 -0
  73. package/examples/jsm/tsl/display/AnamorphicNode.js +11 -0
  74. package/examples/jsm/tsl/display/BilateralBlurNode.js +10 -0
  75. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +3 -36
  76. package/examples/jsm/tsl/display/FSR1Node.js +477 -0
  77. package/examples/jsm/tsl/display/GTAONode.js +2 -1
  78. package/examples/jsm/tsl/display/GaussianBlurNode.js +10 -0
  79. package/examples/jsm/tsl/display/GodraysNode.js +2 -11
  80. package/examples/jsm/tsl/display/OutlineNode.js +66 -16
  81. package/examples/jsm/tsl/display/SSGINode.js +0 -4
  82. package/examples/jsm/tsl/display/SharpenNode.js +283 -0
  83. package/examples/jsm/tsl/display/TAAUNode.js +835 -0
  84. package/examples/jsm/tsl/display/TRAANode.js +48 -7
  85. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +300 -0
  86. package/examples/jsm/tsl/lighting/data/AmbientLightDataNode.js +61 -0
  87. package/examples/jsm/tsl/lighting/data/DirectionalLightDataNode.js +111 -0
  88. package/examples/jsm/tsl/lighting/data/HemisphereLightDataNode.js +99 -0
  89. package/examples/jsm/tsl/lighting/data/PointLightDataNode.js +134 -0
  90. package/examples/jsm/tsl/lighting/data/SpotLightDataNode.js +161 -0
  91. package/examples/jsm/tsl/math/Bayer.js +13 -2
  92. package/examples/jsm/utils/BufferGeometryUtils.js +2 -3
  93. package/examples/jsm/utils/ColorUtils.js +76 -0
  94. package/examples/jsm/utils/SkeletonUtils.js +14 -8
  95. package/examples/jsm/webxr/XRHandMeshModel.js +36 -10
  96. package/examples/jsm/webxr/XRHandModelFactory.js +2 -1
  97. package/package.json +4 -4
  98. package/src/Three.Core.js +1 -0
  99. package/src/Three.TSL.js +6 -0
  100. package/src/Three.WebGPU.Nodes.js +3 -0
  101. package/src/Three.WebGPU.js +6 -0
  102. package/src/animation/AnimationAction.js +11 -1
  103. package/src/audio/AudioContext.js +2 -2
  104. package/src/constants.js +1 -1
  105. package/src/core/BufferAttribute.js +13 -1
  106. package/src/core/Clock.js +1 -1
  107. package/src/core/Object3D.js +1 -5
  108. package/src/core/RenderTarget.js +1 -0
  109. package/src/extras/curves/CatmullRomCurve3.js +3 -2
  110. package/src/loaders/AudioLoader.js +11 -1
  111. package/src/loaders/DataTextureLoader.js +6 -4
  112. package/src/loaders/FileLoader.js +1 -2
  113. package/src/loaders/ImageBitmapLoader.js +4 -6
  114. package/src/loaders/MaterialLoader.js +1 -1
  115. package/src/loaders/ObjectLoader.js +25 -4
  116. package/src/loaders/nodes/NodeObjectLoader.js +18 -0
  117. package/src/materials/MeshToonMaterial.js +1 -1
  118. package/src/materials/nodes/Line2NodeMaterial.js +27 -0
  119. package/src/materials/nodes/NodeMaterial.js +0 -27
  120. package/src/materials/nodes/manager/NodeMaterialObserver.js +188 -89
  121. package/src/math/Line3.js +3 -0
  122. package/src/math/Matrix2.js +13 -9
  123. package/src/math/Matrix3.js +13 -9
  124. package/src/math/Matrix4.js +13 -9
  125. package/src/math/Plane.js +4 -3
  126. package/src/math/Triangle.js +1 -1
  127. package/src/math/Vector2.js +11 -7
  128. package/src/math/Vector3.js +12 -8
  129. package/src/math/Vector4.js +13 -9
  130. package/src/nodes/Nodes.js +0 -1
  131. package/src/nodes/TSL.js +1 -1
  132. package/src/nodes/accessors/BufferAttributeNode.js +9 -3
  133. package/src/nodes/accessors/CubeTextureNode.js +7 -1
  134. package/src/nodes/accessors/MaterialProperties.js +2 -5
  135. package/src/nodes/accessors/Object3DNode.js +1 -1
  136. package/src/nodes/accessors/ReferenceBaseNode.js +2 -2
  137. package/src/nodes/accessors/ReferenceNode.js +4 -4
  138. package/src/nodes/accessors/SceneProperties.js +2 -8
  139. package/src/nodes/accessors/StorageBufferNode.js +10 -4
  140. package/src/nodes/accessors/StorageTextureNode.js +4 -9
  141. package/src/nodes/accessors/TextureNode.js +10 -2
  142. package/src/nodes/accessors/UniformArrayNode.js +2 -2
  143. package/src/nodes/code/FunctionCallNode.js +1 -1
  144. package/src/nodes/code/FunctionNode.js +1 -1
  145. package/src/nodes/core/ArrayNode.js +1 -1
  146. package/src/nodes/core/AssignNode.js +1 -1
  147. package/src/nodes/core/AttributeNode.js +1 -1
  148. package/src/nodes/core/BypassNode.js +1 -1
  149. package/src/nodes/core/ContextNode.js +1 -1
  150. package/src/nodes/core/IndexNode.js +2 -1
  151. package/src/nodes/core/InputNode.js +1 -1
  152. package/src/nodes/core/InspectorNode.js +1 -1
  153. package/src/nodes/core/IsolateNode.js +1 -1
  154. package/src/nodes/core/Node.js +83 -12
  155. package/src/nodes/core/NodeBuilder.js +117 -16
  156. package/src/nodes/core/NodeUtils.js +1 -1
  157. package/src/nodes/core/OutputStructNode.js +1 -1
  158. package/src/nodes/core/ParameterNode.js +1 -1
  159. package/src/nodes/core/StackNode.js +1 -1
  160. package/src/nodes/core/StructNode.js +1 -1
  161. package/src/nodes/core/StructTypeNode.js +1 -1
  162. package/src/nodes/core/SubBuildNode.js +1 -1
  163. package/src/nodes/core/UniformGroupNode.js +36 -6
  164. package/src/nodes/core/VarNode.js +1 -1
  165. package/src/nodes/core/VaryingNode.js +1 -1
  166. package/src/nodes/display/NormalMapNode.js +2 -2
  167. package/src/nodes/display/PassNode.js +27 -7
  168. package/src/nodes/display/RenderOutputNode.js +4 -4
  169. package/src/nodes/display/ScreenNode.js +1 -1
  170. package/src/nodes/display/ViewportDepthTextureNode.js +11 -15
  171. package/src/nodes/display/ViewportTextureNode.js +18 -7
  172. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +2 -2
  173. package/src/nodes/geometry/RangeNode.js +1 -1
  174. package/src/nodes/gpgpu/AtomicFunctionNode.js +1 -1
  175. package/src/nodes/gpgpu/BarrierNode.js +9 -0
  176. package/src/nodes/gpgpu/ComputeBuiltinNode.js +1 -1
  177. package/src/nodes/gpgpu/ComputeNode.js +69 -44
  178. package/src/nodes/gpgpu/SubgroupFunctionNode.js +1 -1
  179. package/src/nodes/lighting/LightsNode.js +6 -27
  180. package/src/nodes/lighting/ShadowNode.js +24 -2
  181. package/src/nodes/math/BitcastNode.js +1 -1
  182. package/src/nodes/math/ConditionalNode.js +1 -1
  183. package/src/nodes/math/MathNode.js +73 -1
  184. package/src/nodes/math/OperatorNode.js +1 -1
  185. package/src/nodes/math/PackFloatNode.js +1 -1
  186. package/src/nodes/math/UnpackFloatNode.js +1 -1
  187. package/src/nodes/tsl/TSLBase.js +1 -1
  188. package/src/nodes/tsl/TSLCore.js +21 -3
  189. package/src/nodes/utils/ArrayElementNode.js +1 -1
  190. package/src/nodes/utils/ConvertNode.js +1 -1
  191. package/src/nodes/utils/DebugNode.js +1 -1
  192. package/src/nodes/utils/EventNode.js +30 -0
  193. package/src/nodes/utils/FlipNode.js +1 -1
  194. package/src/nodes/utils/FunctionOverloadingNode.js +1 -1
  195. package/src/nodes/utils/JoinNode.js +1 -1
  196. package/src/nodes/utils/MemberNode.js +1 -1
  197. package/src/nodes/utils/Remap.js +48 -0
  198. package/src/nodes/utils/RotateNode.js +1 -1
  199. package/src/nodes/utils/SetNode.js +1 -1
  200. package/src/nodes/utils/SplitNode.js +1 -1
  201. package/src/objects/BatchedMesh.js +17 -2
  202. package/src/objects/InstancedMesh.js +19 -3
  203. package/src/objects/SkinnedMesh.js +26 -9
  204. package/src/renderers/WebGLRenderer.js +147 -48
  205. package/src/renderers/common/Animation.js +3 -3
  206. package/src/renderers/common/Attributes.js +15 -1
  207. package/src/renderers/common/Backend.js +0 -8
  208. package/src/renderers/common/Background.js +2 -2
  209. package/src/renderers/common/BindGroup.js +1 -8
  210. package/src/renderers/common/Bindings.js +2 -2
  211. package/src/renderers/common/ComputePipeline.js +1 -1
  212. package/src/renderers/common/CubeRenderTarget.js +1 -1
  213. package/src/renderers/common/Info.js +333 -4
  214. package/src/renderers/common/InspectorBase.js +6 -1
  215. package/src/renderers/common/Pipelines.js +36 -3
  216. package/src/renderers/common/ReadbackBuffer.js +78 -0
  217. package/src/renderers/common/RenderBundle.js +3 -1
  218. package/src/renderers/common/RenderBundles.js +5 -2
  219. package/src/renderers/common/RenderObject.js +2 -2
  220. package/src/renderers/common/RenderObjects.js +3 -3
  221. package/src/renderers/common/RenderPipeline.js +35 -6
  222. package/src/renderers/common/Renderer.js +232 -53
  223. package/src/renderers/common/Textures.js +72 -3
  224. package/src/renderers/common/UniformsGroup.js +1 -1
  225. package/src/renderers/common/XRManager.js +34 -27
  226. package/src/renderers/common/extras/PMREMGenerator.js +23 -15
  227. package/src/renderers/common/nodes/NodeBuilderState.js +1 -1
  228. package/src/renderers/common/nodes/NodeManager.js +230 -99
  229. package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +0 -1
  230. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +1 -1
  231. package/src/renderers/shaders/ShaderChunk/lightprobes_pars_fragment.glsl.js +80 -0
  232. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +8 -0
  233. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +2 -0
  234. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +1 -3
  235. package/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js +7 -0
  236. package/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl.js +0 -1
  237. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +12 -2
  238. package/src/renderers/shaders/ShaderChunk.js +2 -0
  239. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +1 -2
  240. package/src/renderers/shaders/ShaderLib.js +0 -1
  241. package/src/renderers/shaders/UniformsLib.js +7 -2
  242. package/src/renderers/shaders/UniformsUtils.js +27 -5
  243. package/src/renderers/webgl/WebGLAnimation.js +2 -1
  244. package/src/renderers/webgl/WebGLBackground.js +13 -13
  245. package/src/renderers/webgl/WebGLBufferRenderer.js +0 -32
  246. package/src/renderers/webgl/WebGLCapabilities.js +6 -0
  247. package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +0 -32
  248. package/src/renderers/webgl/WebGLMaterials.js +12 -13
  249. package/src/renderers/webgl/WebGLOutput.js +4 -1
  250. package/src/renderers/webgl/WebGLProgram.js +4 -0
  251. package/src/renderers/webgl/WebGLPrograms.js +21 -4
  252. package/src/renderers/webgl/WebGLRenderStates.js +13 -2
  253. package/src/renderers/webgl/WebGLState.js +43 -0
  254. package/src/renderers/webgl/WebGLTextures.js +129 -26
  255. package/src/renderers/webgl/WebGLUniformsGroups.js +19 -0
  256. package/src/renderers/webgl-fallback/WebGLBackend.js +106 -65
  257. package/src/renderers/webgl-fallback/WebGLBufferRenderer.js +0 -41
  258. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +29 -51
  259. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +53 -19
  260. package/src/renderers/webgl-fallback/utils/WebGLCapabilities.js +25 -0
  261. package/src/renderers/webgl-fallback/utils/WebGLState.js +42 -1
  262. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +63 -50
  263. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +1 -1
  264. package/src/renderers/webgpu/WebGPUBackend.js +160 -146
  265. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +55 -33
  266. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +103 -17
  267. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +1 -1
  268. package/src/renderers/webgpu/utils/WebGPUCapabilities.js +48 -0
  269. package/src/renderers/webgpu/utils/WebGPUConstants.js +8 -0
  270. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +91 -17
  271. package/src/renderers/webgpu/utils/WebGPUUtils.js +18 -2
  272. package/src/renderers/webxr/WebXRController.js +12 -0
  273. package/src/textures/HTMLTexture.js +74 -0
  274. package/src/textures/Source.js +1 -1
  275. package/src/textures/Texture.js +13 -2
  276. package/src/utils.js +23 -1
  277. package/src/nodes/utils/RemapNode.js +0 -125
@@ -339,6 +339,8 @@ class GPUComputationRenderer {
339
339
 
340
340
  }
341
341
 
342
+ variable.material.dispose();
343
+
342
344
  }
343
345
 
344
346
  };
@@ -195,6 +195,10 @@ class RollerCoasterGeometry extends BufferGeometry {
195
195
 
196
196
  const offset = new Vector3();
197
197
 
198
+ const sample1 = new Vector3();
199
+ const sample2 = new Vector3();
200
+ const rollQuaternion = new Quaternion();
201
+
198
202
  for ( let i = 1; i <= divisions; i ++ ) {
199
203
 
200
204
  point.copy( curve.getPointAt( i / divisions ) );
@@ -209,6 +213,20 @@ class RollerCoasterGeometry extends BufferGeometry {
209
213
 
210
214
  quaternion.setFromAxisAngle( up, angle );
211
215
 
216
+ // banking
217
+
218
+ const bankDelta = 0.01;
219
+ const t = i / divisions;
220
+
221
+ sample1.copy( curve.getTangentAt( ( ( t - bankDelta ) % 1 + 1 ) % 1 ) );
222
+ sample2.copy( curve.getTangentAt( ( t + bankDelta ) % 1 ) );
223
+
224
+ let headingChange = Math.atan2( sample2.x, sample2.z ) - Math.atan2( sample1.x, sample1.z );
225
+ if ( headingChange > Math.PI ) headingChange -= Math.PI * 2;
226
+ if ( headingChange < -Math.PI ) headingChange += Math.PI * 2;
227
+
228
+ quaternion.premultiply( rollQuaternion.setFromAxisAngle( forward, - Math.atan( headingChange * 8 ) * 0.5 ) );
229
+
212
230
  if ( i % 2 === 0 ) {
213
231
 
214
232
  drawShape( step, color2 );
@@ -356,6 +374,11 @@ class RollerCoasterLiftersGeometry extends BufferGeometry {
356
374
  const fromPoint = new Vector3();
357
375
  const toPoint = new Vector3();
358
376
 
377
+ const sample1 = new Vector3();
378
+ const sample2 = new Vector3();
379
+ const bankedQuaternion = new Quaternion();
380
+ const rollQuaternion = new Quaternion();
381
+
359
382
  for ( let i = 1; i <= divisions; i ++ ) {
360
383
 
361
384
  point.copy( curve.getPointAt( i / divisions ) );
@@ -365,6 +388,22 @@ class RollerCoasterLiftersGeometry extends BufferGeometry {
365
388
 
366
389
  quaternion.setFromAxisAngle( up, angle );
367
390
 
391
+ // banking
392
+
393
+ const bankDelta = 0.01;
394
+ const t = i / divisions;
395
+
396
+ sample1.copy( curve.getTangentAt( ( ( t - bankDelta ) % 1 + 1 ) % 1 ) );
397
+ sample2.copy( curve.getTangentAt( ( t + bankDelta ) % 1 ) );
398
+
399
+ let headingChange = Math.atan2( sample2.x, sample2.z ) - Math.atan2( sample1.x, sample1.z );
400
+ if ( headingChange > Math.PI ) headingChange -= Math.PI * 2;
401
+ if ( headingChange < -Math.PI ) headingChange += Math.PI * 2;
402
+
403
+ bankedQuaternion.copy( quaternion );
404
+ rollQuaternion.setFromAxisAngle( tangent, - Math.atan( headingChange * 8 ) * 0.5 );
405
+ bankedQuaternion.premultiply( rollQuaternion );
406
+
368
407
  //
369
408
 
370
409
  if ( point.y > 10 ) {
@@ -402,12 +441,11 @@ class RollerCoasterLiftersGeometry extends BufferGeometry {
402
441
  } else {
403
442
 
404
443
  fromPoint.set( 0, - 0.2, 0 );
405
- fromPoint.applyQuaternion( quaternion );
444
+ fromPoint.applyQuaternion( bankedQuaternion );
406
445
  fromPoint.add( point );
407
446
 
408
- toPoint.set( 0, - point.y, 0 );
409
- toPoint.applyQuaternion( quaternion );
410
- toPoint.add( point );
447
+ toPoint.copy( fromPoint );
448
+ toPoint.y = 0;
411
449
 
412
450
  extrudeShape( tube3, fromPoint, toPoint );
413
451
 
@@ -46,7 +46,7 @@ class TessellateModifier {
46
46
  }
47
47
 
48
48
  /**
49
- * Returns a new, modified version of the given geometry by applying a tesselation.
49
+ * Returns a new, modified version of the given geometry by applying a tessellation.
50
50
  * Please note that the resulting geometry is always non-indexed.
51
51
  *
52
52
  * @param {BufferGeometry} geometry - The geometry to modify.
@@ -2,7 +2,6 @@ import {
2
2
  Color,
3
3
  Matrix4,
4
4
  Mesh,
5
- PerspectiveCamera,
6
5
  Plane,
7
6
  ShaderMaterial,
8
7
  UniformsUtils,
@@ -67,12 +66,12 @@ class Reflector extends Mesh {
67
66
  this.forceUpdate = false;
68
67
 
69
68
  /**
70
- * The reflector's virtual camera. This is used to render
71
- * the scene from the mirror's point of view.
69
+ * Weak map for managing reflection cameras.
72
70
  *
73
- * @type {PerspectiveCamera}
71
+ * @private
72
+ * @type {WeakMap<Camera, Camera>}
74
73
  */
75
- this.camera = new PerspectiveCamera();
74
+ this._reflectionCameras = new WeakMap();
76
75
 
77
76
  const scope = this;
78
77
 
@@ -98,7 +97,6 @@ class Reflector extends Mesh {
98
97
  const q = new Vector4();
99
98
 
100
99
  const textureMatrix = new Matrix4();
101
- const virtualCamera = this.camera;
102
100
 
103
101
  const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, { samples: multisample, type: HalfFloatType } );
104
102
 
@@ -117,6 +115,8 @@ class Reflector extends Mesh {
117
115
 
118
116
  this.onBeforeRender = function ( renderer, scene, camera ) {
119
117
 
118
+ const reflectionCamera = this._getReflectionCamera( camera );
119
+
120
120
  reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
121
121
  cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
122
122
 
@@ -145,16 +145,16 @@ class Reflector extends Mesh {
145
145
  target.reflect( normal ).negate();
146
146
  target.add( reflectorWorldPosition );
147
147
 
148
- virtualCamera.position.copy( view );
149
- virtualCamera.up.set( 0, 1, 0 );
150
- virtualCamera.up.applyMatrix4( rotationMatrix );
151
- virtualCamera.up.reflect( normal );
152
- virtualCamera.lookAt( target );
148
+ reflectionCamera.position.copy( view );
149
+ reflectionCamera.up.set( 0, 1, 0 );
150
+ reflectionCamera.up.applyMatrix4( rotationMatrix );
151
+ reflectionCamera.up.reflect( normal );
152
+ reflectionCamera.lookAt( target );
153
153
 
154
- virtualCamera.far = camera.far; // Used in WebGLBackground
154
+ reflectionCamera.far = camera.far; // Used in WebGLBackground
155
155
 
156
- virtualCamera.updateMatrixWorld();
157
- virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
156
+ reflectionCamera.updateMatrixWorld();
157
+ reflectionCamera.projectionMatrix.copy( camera.projectionMatrix );
158
158
 
159
159
  // Update the texture matrix
160
160
  textureMatrix.set(
@@ -163,23 +163,34 @@ class Reflector extends Mesh {
163
163
  0.0, 0.0, 0.5, 0.5,
164
164
  0.0, 0.0, 0.0, 1.0
165
165
  );
166
- textureMatrix.multiply( virtualCamera.projectionMatrix );
167
- textureMatrix.multiply( virtualCamera.matrixWorldInverse );
166
+ textureMatrix.multiply( reflectionCamera.projectionMatrix );
167
+ textureMatrix.multiply( reflectionCamera.matrixWorldInverse );
168
168
  textureMatrix.multiply( scope.matrixWorld );
169
169
 
170
170
  // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
171
171
  // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
172
172
  reflectorPlane.setFromNormalAndCoplanarPoint( normal, reflectorWorldPosition );
173
- reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse );
173
+ reflectorPlane.applyMatrix4( reflectionCamera.matrixWorldInverse );
174
174
 
175
175
  clipPlane.set( reflectorPlane.normal.x, reflectorPlane.normal.y, reflectorPlane.normal.z, reflectorPlane.constant );
176
176
 
177
- const projectionMatrix = virtualCamera.projectionMatrix;
177
+ const projectionMatrix = reflectionCamera.projectionMatrix;
178
+
179
+ if ( reflectionCamera.isOrthographicCamera ) {
180
+
181
+ q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
182
+ q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
183
+ q.z = - camera.far; // actual view-space z at the far plane, no normalization needed
184
+ q.w = 1.0; // w_clip = 1 in orthographic (no perspective division)
185
+
186
+ } else {
178
187
 
179
- q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
180
- q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
181
- q.z = - 1.0;
182
- q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
188
+ q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
189
+ q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
190
+ q.z = - 1.0;
191
+ q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
192
+
193
+ }
183
194
 
184
195
  // Calculate the scaled plane vector
185
196
  clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) );
@@ -187,8 +198,21 @@ class Reflector extends Mesh {
187
198
  // Replacing the third row of the projection matrix
188
199
  projectionMatrix.elements[ 2 ] = clipPlane.x;
189
200
  projectionMatrix.elements[ 6 ] = clipPlane.y;
190
- projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias;
191
- projectionMatrix.elements[ 14 ] = clipPlane.w;
201
+
202
+ if ( reflectionCamera.isOrthographicCamera ) {
203
+
204
+ // For orthographic cameras, w_clip = 1 always (no perspective division),
205
+ // so the -1 near-plane offset must go into the constant term (elements[14])
206
+ // rather than the z coefficient (elements[10]).
207
+ projectionMatrix.elements[ 10 ] = clipPlane.z - clipBias;
208
+ projectionMatrix.elements[ 14 ] = clipPlane.w - 1.0;
209
+
210
+ } else {
211
+
212
+ projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias;
213
+ projectionMatrix.elements[ 14 ] = clipPlane.w;
214
+
215
+ }
192
216
 
193
217
  // Render
194
218
  scope.visible = false;
@@ -206,7 +230,7 @@ class Reflector extends Mesh {
206
230
  renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
207
231
 
208
232
  if ( renderer.autoClear === false ) renderer.clear();
209
- renderer.render( scene, virtualCamera );
233
+ renderer.render( scene, reflectionCamera );
210
234
 
211
235
  renderer.xr.enabled = currentXrEnabled;
212
236
  renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
@@ -250,6 +274,30 @@ class Reflector extends Mesh {
250
274
 
251
275
  };
252
276
 
277
+ /**
278
+ * Returns a reflection camera for the given camera. The reflection camera is used to
279
+ * render the scene from the reflector's view so correct reflections can be produced.
280
+ *
281
+ * @private
282
+ * @param {Camera} camera - The scene's camera.
283
+ * @return {Camera} The corresponding reflection camera.
284
+ */
285
+ this._getReflectionCamera = function ( camera ) {
286
+
287
+ let reflectionCamera = this._reflectionCameras.get( camera );
288
+
289
+ if ( reflectionCamera === undefined ) {
290
+
291
+ reflectionCamera = camera.clone();
292
+
293
+ this._reflectionCameras.set( camera, reflectionCamera );
294
+
295
+ }
296
+
297
+ return reflectionCamera;
298
+
299
+ };
300
+
253
301
  }
254
302
 
255
303
  }
@@ -25,6 +25,16 @@ import {
25
25
  * sky.scale.setScalar( 10000 );
26
26
  * scene.add( sky );
27
27
  * ```
28
+ *
29
+ * It can be useful to hide the sun disc when generating an environment map to avoid artifacts
30
+ *
31
+ * ```js
32
+ * // disable before rendering environment map
33
+ * sky.material.uniforms.showSunDisc.value = false;
34
+ * // ...
35
+ * // re-enable before scene sky box rendering
36
+ * sky.material.uniforms.showSunDisc.value = true;
37
+ * ```
28
38
  *
29
39
  * @augments Mesh
30
40
  * @three_import import { Sky } from 'three/addons/objects/Sky.js';
@@ -78,6 +88,7 @@ Sky.SkyShader = {
78
88
  'cloudCoverage': { value: 0.4 },
79
89
  'cloudDensity': { value: 0.4 },
80
90
  'cloudElevation': { value: 0.5 },
91
+ 'showSunDisc': { value: 1 },
81
92
  'time': { value: 0.0 }
82
93
  },
83
94
 
@@ -167,6 +178,7 @@ Sky.SkyShader = {
167
178
  uniform float cloudCoverage;
168
179
  uniform float cloudDensity;
169
180
  uniform float cloudElevation;
181
+ uniform float showSunDisc;
170
182
  uniform float time;
171
183
 
172
184
  // Cloud noise functions
@@ -256,8 +268,8 @@ Sky.SkyShader = {
256
268
  vec3 L0 = vec3( 0.1 ) * Fex;
257
269
 
258
270
  // composition + solar disc
259
- float sundisk = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos + 0.00002, cosTheta );
260
- L0 += ( vSunE * 19000.0 * Fex ) * sundisk;
271
+ float sundisc = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos + 0.00002, cosTheta ) * showSunDisc;
272
+ L0 += ( vSunE * 19000.0 * Fex ) * sundisc;
261
273
 
262
274
  vec3 texColor = ( Lin + L0 ) * 0.04 + vec3( 0.0, 0.0003, 0.00075 );
263
275
 
@@ -26,6 +26,16 @@ import { Fn, float, vec2, vec3, acos, add, mul, clamp, cos, dot, exp, max, mix,
26
26
  * scene.add( sky );
27
27
  * ```
28
28
  *
29
+ * It can be useful to hide the sun disc when generating an environment map to avoid artifacts
30
+ *
31
+ * ```js
32
+ * // disable before rendering environment map
33
+ * sky.showSunDisc.value = false;
34
+ * // ...
35
+ * // re-enable before scene sky box rendering
36
+ * sky.showSunDisc.value = true;
37
+ * ```
38
+ *
29
39
  * @augments Mesh
30
40
  * @three_import import { SkyMesh } from 'three/addons/objects/SkyMesh.js';
31
41
  */
@@ -117,6 +127,13 @@ class SkyMesh extends Mesh {
117
127
  */
118
128
  this.cloudElevation = uniform( 0.5 );
119
129
 
130
+ /**
131
+ * Whether to render the solar disc.
132
+ *
133
+ * @type {UniformNode<float>}
134
+ */
135
+ this.showSunDisc = uniform( 1 );
136
+
120
137
  /**
121
138
  * This flag can be used for type testing.
122
139
  *
@@ -146,8 +163,8 @@ class SkyMesh extends Mesh {
146
163
  const vertexNode = /*@__PURE__*/ Fn( () => {
147
164
 
148
165
  // constants for atmospheric scattering
149
- const e = float( 2.71828182845904523536028747135266249775724709369995957 );
150
- // const pi = float( 3.141592653589793238462643383279502884197169 );
166
+ const e = float( 2.718281828459045 );
167
+ // const pi = float( 3.141592653589793 );
151
168
 
152
169
  // wavelength of used primaries, according to preetham
153
170
  // const lambda = vec3( 680E-9, 550E-9, 450E-9 );
@@ -211,13 +228,13 @@ class SkyMesh extends Mesh {
211
228
  const colorNode = /*@__PURE__*/ Fn( () => {
212
229
 
213
230
  // constants for atmospheric scattering
214
- const pi = float( 3.141592653589793238462643383279502884197169 );
231
+ const pi = float( 3.141592653589793 );
215
232
 
216
233
  // optical length at zenith for molecules
217
234
  const rayleighZenithLength = float( 8.4E3 );
218
235
  const mieZenithLength = float( 1.25E3 );
219
236
  // 66 arc seconds -> degrees, and the cosine of that
220
- const sunAngularDiameterCos = float( 0.999956676946448443553574619906976478926848692873900859324 );
237
+ const sunAngularDiameterCos = float( 0.9999566769464484 );
221
238
 
222
239
  // 3.0 / ( 16.0 * pi )
223
240
  const THREE_OVER_SIXTEENPI = float( 0.05968310365946075 );
@@ -262,8 +279,8 @@ class SkyMesh extends Mesh {
262
279
  const L0 = vec3( 0.1 ).mul( Fex );
263
280
 
264
281
  // composition + solar disc
265
- const sundisk = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos.add( 0.00002 ), cosTheta );
266
- L0.addAssign( vSunE.mul( 19000.0 ).mul( Fex ).mul( sundisk ) );
282
+ const sundisc = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos.add( 0.00002 ), cosTheta ).mul( this.showSunDisc );
283
+ L0.addAssign( vSunE.mul( 19000.0 ).mul( Fex ).mul( sundisc ) );
267
284
 
268
285
  const texColor = add( Lin, L0 ).mul( 0.04 ).add( vec3( 0.0, 0.0003, 0.00075 ) ).toVar();
269
286
 
@@ -310,18 +310,18 @@ class Projector {
310
310
  const v2 = _vertexPool[ b ];
311
311
  const v3 = _vertexPool[ c ];
312
312
 
313
- // Get homogeneous clip space positions (before perspective divide)
314
- _clipPos1.copy( v1.positionWorld ).applyMatrix4( _viewProjectionMatrix );
315
- _clipPos2.copy( v2.positionWorld ).applyMatrix4( _viewProjectionMatrix );
316
- _clipPos3.copy( v3.positionWorld ).applyMatrix4( _viewProjectionMatrix );
317
-
318
- // Check if triangle needs clipping
319
- const nearDist1 = _clipPos1.z + _clipPos1.w;
320
- const nearDist2 = _clipPos2.z + _clipPos2.w;
321
- const nearDist3 = _clipPos3.z + _clipPos3.w;
322
- const farDist1 = - _clipPos1.z + _clipPos1.w;
323
- const farDist2 = - _clipPos2.z + _clipPos2.w;
324
- const farDist3 = - _clipPos3.z + _clipPos3.w;
313
+ // Derive near/far clip distances from NDC z and stored clip-space w
314
+ // (projectVertex already computed positionScreen = clipPos / w, with w preserved)
315
+ const w1 = v1.positionScreen.w;
316
+ const w2 = v2.positionScreen.w;
317
+ const w3 = v3.positionScreen.w;
318
+
319
+ const nearDist1 = w1 * ( v1.positionScreen.z + 1 );
320
+ const nearDist2 = w2 * ( v2.positionScreen.z + 1 );
321
+ const nearDist3 = w3 * ( v3.positionScreen.z + 1 );
322
+ const farDist1 = w1 * ( 1 - v1.positionScreen.z );
323
+ const farDist2 = w2 * ( 1 - v2.positionScreen.z );
324
+ const farDist3 = w3 * ( 1 - v3.positionScreen.z );
325
325
 
326
326
  // Check if completely outside
327
327
  if ( ( nearDist1 < 0 && nearDist2 < 0 && nearDist3 < 0 ) ||
@@ -385,7 +385,10 @@ class Projector {
385
385
 
386
386
  }
387
387
 
388
- // Triangle needs clipping
388
+ // Triangle needs clipping - reconstruct clip-space positions from NDC + w
389
+ _clipPos1.set( v1.positionScreen.x * w1, v1.positionScreen.y * w1, v1.positionScreen.z * w1, w1 );
390
+ _clipPos2.set( v2.positionScreen.x * w2, v2.positionScreen.y * w2, v2.positionScreen.z * w2, w2 );
391
+ _clipPos3.set( v3.positionScreen.x * w3, v3.positionScreen.y * w3, v3.positionScreen.z * w3, w3 );
389
392
  _clipInputVertices[ 0 ] = _clipPos1;
390
393
  _clipInputVertices[ 1 ] = _clipPos2;
391
394
  _clipInputVertices[ 2 ] = _clipPos3;
@@ -577,7 +580,7 @@ class Projector {
577
580
 
578
581
  if ( sortObjects === true ) {
579
582
 
580
- painterSortStable( _renderData.objects, 0, _renderData.objects.length );
583
+ _renderData.objects.sort( painterSort );
581
584
 
582
585
  }
583
586
 
@@ -843,7 +846,7 @@ class Projector {
843
846
 
844
847
  if ( sortElements === true ) {
845
848
 
846
- painterSortStable( _renderData.elements, 0, _renderData.elements.length );
849
+ _renderData.elements.sort( painterSort );
847
850
 
848
851
  }
849
852
 
@@ -987,29 +990,6 @@ class Projector {
987
990
 
988
991
  }
989
992
 
990
- function painterSortStable( array, start, length ) {
991
-
992
- // A stable insertion sort for sorting render items
993
- // This avoids the GC overhead of Array.prototype.sort()
994
-
995
- for ( let i = start + 1; i < start + length; i ++ ) {
996
-
997
- const item = array[ i ];
998
- let j = i - 1;
999
-
1000
- while ( j >= start && painterSort( array[ j ], item ) > 0 ) {
1001
-
1002
- array[ j + 1 ] = array[ j ];
1003
- j --;
1004
-
1005
- }
1006
-
1007
- array[ j + 1 ] = item;
1008
-
1009
- }
1010
-
1011
- }
1012
-
1013
993
  // Sutherland-Hodgman triangle clipping in homogeneous clip space
1014
994
  // Returns count of vertices in clipped polygon (0 if completely clipped, 3+ if partially clipped)
1015
995
  // Result vertices are in _clipInput array
@@ -300,29 +300,6 @@ class SVGRenderer {
300
300
 
301
301
  }
302
302
 
303
- function arraySortStable( array, start, length ) {
304
-
305
- // A stable insertion sort for sorting the render list
306
- // This avoids the GC overhead of Array.prototype.sort()
307
-
308
- for ( let i = start + 1; i < start + length; i ++ ) {
309
-
310
- const item = array[ i ];
311
- let j = i - 1;
312
-
313
- while ( j >= start && renderSort( array[ j ], item ) > 0 ) {
314
-
315
- array[ j + 1 ] = array[ j ];
316
- j --;
317
-
318
- }
319
-
320
- array[ j + 1 ] = item;
321
-
322
- }
323
-
324
- }
325
-
326
303
  /**
327
304
  * Performs a manual clear with the defined clear color.
328
305
  */
@@ -416,9 +393,13 @@ class SVGRenderer {
416
393
 
417
394
  } );
418
395
 
419
- if ( this.sortElements ) {
396
+ _renderListPool.length = _renderListCount;
397
+
398
+ if ( this.sortElements && _svgObjectCount > 0 ) {
420
399
 
421
- arraySortStable( _renderListPool, 0, _renderListCount );
400
+ // Elements are already sorted by the Projector.
401
+ // Only re-sort when SVGObjects need depth-interleaving.
402
+ _renderListPool.sort( renderSort );
422
403
 
423
404
  }
424
405
 
@@ -170,7 +170,7 @@ class Tokenizer {
170
170
 
171
171
  skip( ...params ) {
172
172
 
173
- let remainingCode = this.source.substr( this.position );
173
+ let remainingCode = this.source.slice( this.position );
174
174
  let i = params.length;
175
175
 
176
176
  while ( i -- ) {
@@ -182,7 +182,7 @@ class Tokenizer {
182
182
 
183
183
  this.position += skipLength;
184
184
 
185
- remainingCode = this.source.substr( this.position );
185
+ remainingCode = this.source.slice( this.position );
186
186
 
187
187
  // re-skip, new remainingCode is generated
188
188
  // maybe exist previous regexp non detected