@plastic-software/three 0.175.13 → 0.178.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 (529) hide show
  1. package/README.md +3 -3
  2. package/build/three.cjs +7747 -6792
  3. package/build/three.core.js +7371 -6576
  4. package/build/three.core.min.js +1 -1
  5. package/build/three.module.js +190 -30
  6. package/build/three.module.min.js +1 -1
  7. package/build/three.tsl.js +19 -11
  8. package/build/three.tsl.min.js +1 -1
  9. package/build/three.webgpu.js +4989 -2235
  10. package/build/three.webgpu.min.js +1 -1
  11. package/build/three.webgpu.nodes.js +5082 -2469
  12. package/build/three.webgpu.nodes.min.js +1 -1
  13. package/examples/jsm/Addons.js +0 -1
  14. package/examples/jsm/animation/AnimationClipCreator.js +1 -0
  15. package/examples/jsm/animation/CCDIKSolver.js +6 -3
  16. package/examples/jsm/capabilities/WebGL.js +1 -27
  17. package/examples/jsm/capabilities/WebGPU.js +1 -0
  18. package/examples/jsm/controls/ArcballControls.js +15 -4
  19. package/examples/jsm/controls/DragControls.js +1 -0
  20. package/examples/jsm/controls/FirstPersonControls.js +1 -0
  21. package/examples/jsm/controls/FlyControls.js +1 -0
  22. package/examples/jsm/controls/MapControls.js +1 -0
  23. package/examples/jsm/controls/OrbitControls.js +1 -0
  24. package/examples/jsm/controls/PointerLockControls.js +5 -3
  25. package/examples/jsm/controls/TrackballControls.js +1 -0
  26. package/examples/jsm/controls/TransformControls.js +62 -14
  27. package/examples/jsm/csm/CSM.js +2 -0
  28. package/examples/jsm/csm/CSMFrustum.js +2 -0
  29. package/examples/jsm/csm/CSMHelper.js +1 -0
  30. package/examples/jsm/csm/CSMShader.js +4 -1
  31. package/examples/jsm/csm/CSMShadowNode.js +18 -4
  32. package/examples/jsm/curves/CurveExtras.js +14 -0
  33. package/examples/jsm/curves/NURBSCurve.js +1 -0
  34. package/examples/jsm/curves/NURBSSurface.js +2 -0
  35. package/examples/jsm/curves/NURBSUtils.js +4 -1
  36. package/examples/jsm/curves/NURBSVolume.js +2 -0
  37. package/examples/jsm/effects/AnaglyphEffect.js +2 -0
  38. package/examples/jsm/effects/AsciiEffect.js +2 -0
  39. package/examples/jsm/effects/OutlineEffect.js +2 -0
  40. package/examples/jsm/effects/ParallaxBarrierEffect.js +2 -0
  41. package/examples/jsm/effects/StereoEffect.js +2 -0
  42. package/examples/jsm/environments/DebugEnvironment.js +1 -0
  43. package/examples/jsm/environments/RoomEnvironment.js +49 -35
  44. package/examples/jsm/exporters/DRACOExporter.js +4 -2
  45. package/examples/jsm/exporters/EXRExporter.js +2 -0
  46. package/examples/jsm/exporters/GLTFExporter.js +7 -4
  47. package/examples/jsm/exporters/KTX2Exporter.js +2 -0
  48. package/examples/jsm/exporters/OBJExporter.js +3 -1
  49. package/examples/jsm/exporters/PLYExporter.js +4 -2
  50. package/examples/jsm/exporters/STLExporter.js +2 -0
  51. package/examples/jsm/exporters/USDZExporter.js +12 -10
  52. package/examples/jsm/geometries/BoxLineGeometry.js +1 -0
  53. package/examples/jsm/geometries/ConvexGeometry.js +1 -0
  54. package/examples/jsm/geometries/DecalGeometry.js +1 -0
  55. package/examples/jsm/geometries/ParametricFunctions.js +4 -1
  56. package/examples/jsm/geometries/ParametricGeometry.js +1 -0
  57. package/examples/jsm/geometries/RoundedBoxGeometry.js +2 -1
  58. package/examples/jsm/geometries/TeapotGeometry.js +1 -0
  59. package/examples/jsm/geometries/TextGeometry.js +1 -0
  60. package/examples/jsm/helpers/LightProbeHelper.js +1 -0
  61. package/examples/jsm/helpers/LightProbeHelperGPU.js +1 -0
  62. package/examples/jsm/helpers/OctreeHelper.js +1 -0
  63. package/examples/jsm/helpers/PositionalAudioHelper.js +1 -0
  64. package/examples/jsm/helpers/RapierHelper.js +59 -0
  65. package/examples/jsm/helpers/RectAreaLightHelper.js +1 -0
  66. package/examples/jsm/helpers/TextureHelper.js +1 -0
  67. package/examples/jsm/helpers/TextureHelperGPU.js +5 -4
  68. package/examples/jsm/helpers/VertexNormalsHelper.js +1 -0
  69. package/examples/jsm/helpers/VertexTangentsHelper.js +1 -0
  70. package/examples/jsm/helpers/ViewHelper.js +1 -0
  71. package/examples/jsm/interactive/HTMLMesh.js +7 -0
  72. package/examples/jsm/interactive/InteractiveGroup.js +1 -0
  73. package/examples/jsm/interactive/SelectionBox.js +2 -0
  74. package/examples/jsm/interactive/SelectionHelper.js +2 -0
  75. package/examples/jsm/lighting/TiledLighting.js +1 -0
  76. package/examples/jsm/lights/LightProbeGenerator.js +1 -0
  77. package/examples/jsm/lights/RectAreaLightTexturesLib.js +1 -0
  78. package/examples/jsm/lights/RectAreaLightUniformsLib.js +1 -0
  79. package/examples/jsm/lines/Line2.js +1 -0
  80. package/examples/jsm/lines/LineGeometry.js +1 -0
  81. package/examples/jsm/lines/LineMaterial.js +4 -4
  82. package/examples/jsm/lines/LineSegments2.js +1 -0
  83. package/examples/jsm/lines/LineSegmentsGeometry.js +1 -0
  84. package/examples/jsm/lines/Wireframe.js +1 -0
  85. package/examples/jsm/lines/WireframeGeometry2.js +1 -0
  86. package/examples/jsm/lines/webgpu/Line2.js +1 -0
  87. package/examples/jsm/lines/webgpu/LineSegments2.js +3 -1
  88. package/examples/jsm/lines/webgpu/Wireframe.js +1 -0
  89. package/examples/jsm/loaders/3DMLoader.js +1 -0
  90. package/examples/jsm/loaders/3MFLoader.js +1 -0
  91. package/examples/jsm/loaders/AMFLoader.js +1 -0
  92. package/examples/jsm/loaders/BVHLoader.js +1 -0
  93. package/examples/jsm/loaders/ColladaLoader.js +6 -5
  94. package/examples/jsm/loaders/DDSLoader.js +1 -0
  95. package/examples/jsm/loaders/DRACOLoader.js +2 -1
  96. package/examples/jsm/loaders/EXRLoader.js +1 -0
  97. package/examples/jsm/loaders/FBXLoader.js +25 -23
  98. package/examples/jsm/loaders/FontLoader.js +1 -0
  99. package/examples/jsm/loaders/GCodeLoader.js +1 -0
  100. package/examples/jsm/loaders/GLTFLoader.js +10 -82
  101. package/examples/jsm/loaders/HDRCubeTextureLoader.js +1 -0
  102. package/examples/jsm/loaders/IESLoader.js +1 -0
  103. package/examples/jsm/loaders/KMZLoader.js +1 -0
  104. package/examples/jsm/loaders/KTX2Loader.js +67 -26
  105. package/examples/jsm/loaders/KTXLoader.js +1 -0
  106. package/examples/jsm/loaders/LDrawLoader.js +55 -3
  107. package/examples/jsm/loaders/LUT3dlLoader.js +1 -0
  108. package/examples/jsm/loaders/LUTCubeLoader.js +1 -0
  109. package/examples/jsm/loaders/LUTImageLoader.js +1 -0
  110. package/examples/jsm/loaders/LWOLoader.js +1 -13
  111. package/examples/jsm/loaders/LottieLoader.js +15 -0
  112. package/examples/jsm/loaders/MD2Loader.js +1 -0
  113. package/examples/jsm/loaders/MDDLoader.js +1 -0
  114. package/examples/jsm/loaders/MTLLoader.js +4 -3
  115. package/examples/jsm/loaders/MaterialXLoader.js +1 -0
  116. package/examples/jsm/loaders/NRRDLoader.js +1 -0
  117. package/examples/jsm/loaders/OBJLoader.js +1 -0
  118. package/examples/jsm/loaders/PCDLoader.js +122 -19
  119. package/examples/jsm/loaders/PDBLoader.js +1 -0
  120. package/examples/jsm/loaders/PLYLoader.js +1 -0
  121. package/examples/jsm/loaders/PVRLoader.js +1 -0
  122. package/examples/jsm/loaders/RGBELoader.js +1 -0
  123. package/examples/jsm/loaders/RGBMLoader.js +1 -0
  124. package/examples/jsm/loaders/STLLoader.js +1 -0
  125. package/examples/jsm/loaders/SVGLoader.js +1 -0
  126. package/examples/jsm/loaders/TDSLoader.js +1 -0
  127. package/examples/jsm/loaders/TGALoader.js +1 -0
  128. package/examples/jsm/loaders/TIFFLoader.js +1 -0
  129. package/examples/jsm/loaders/TTFLoader.js +1 -0
  130. package/examples/jsm/loaders/USDZLoader.js +1 -0
  131. package/examples/jsm/loaders/UltraHDRLoader.js +1 -0
  132. package/examples/jsm/loaders/VOXLoader.js +1 -0
  133. package/examples/jsm/loaders/VRMLLoader.js +3 -2
  134. package/examples/jsm/loaders/VTKLoader.js +1 -0
  135. package/examples/jsm/loaders/XYZLoader.js +1 -0
  136. package/examples/jsm/loaders/lwo/IFFParser.js +74 -74
  137. package/examples/jsm/materials/LDrawConditionalLineMaterial.js +1 -0
  138. package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +1 -0
  139. package/examples/jsm/materials/MeshPostProcessingMaterial.js +1 -0
  140. package/examples/jsm/math/Capsule.js +2 -0
  141. package/examples/jsm/math/ColorConverter.js +1 -0
  142. package/examples/jsm/math/ConvexHull.js +2 -0
  143. package/examples/jsm/math/ImprovedNoise.js +19 -14
  144. package/examples/jsm/math/Lut.js +2 -0
  145. package/examples/jsm/math/MeshSurfaceSampler.js +2 -0
  146. package/examples/jsm/math/OBB.js +2 -0
  147. package/examples/jsm/math/Octree.js +20 -1
  148. package/examples/jsm/math/SimplexNoise.js +2 -0
  149. package/examples/jsm/misc/ConvexObjectBreaker.js +3 -1
  150. package/examples/jsm/misc/GPUComputationRenderer.js +2 -0
  151. package/examples/jsm/misc/Gyroscope.js +1 -0
  152. package/examples/jsm/misc/MD2Character.js +2 -0
  153. package/examples/jsm/misc/MD2CharacterComplex.js +5 -3
  154. package/examples/jsm/misc/MorphAnimMesh.js +1 -0
  155. package/examples/jsm/misc/MorphBlendMesh.js +1 -0
  156. package/examples/jsm/misc/ProgressiveLightMap.js +2 -0
  157. package/examples/jsm/misc/ProgressiveLightMapGPU.js +2 -0
  158. package/examples/jsm/misc/RollerCoaster.js +5 -0
  159. package/examples/jsm/misc/Timer.js +2 -0
  160. package/examples/jsm/misc/TubePainter.js +1 -0
  161. package/examples/jsm/misc/Volume.js +2 -0
  162. package/examples/jsm/misc/VolumeSlice.js +1 -0
  163. package/examples/jsm/modifiers/CurveModifier.js +3 -0
  164. package/examples/jsm/modifiers/CurveModifierGPU.js +2 -0
  165. package/examples/jsm/modifiers/EdgeSplitModifier.js +2 -0
  166. package/examples/jsm/modifiers/SimplifyModifier.js +2 -0
  167. package/examples/jsm/modifiers/TessellateModifier.js +2 -0
  168. package/examples/jsm/objects/GroundedSkybox.js +1 -0
  169. package/examples/jsm/objects/Lensflare.js +3 -0
  170. package/examples/jsm/objects/LensflareMesh.js +1 -0
  171. package/examples/jsm/objects/MarchingCubes.js +2 -0
  172. package/examples/jsm/objects/Reflector.js +1 -0
  173. package/examples/jsm/objects/ReflectorForSSRPass.js +1 -0
  174. package/examples/jsm/objects/Refractor.js +1 -0
  175. package/examples/jsm/objects/ShadowMesh.js +1 -0
  176. package/examples/jsm/objects/Sky.js +2 -1
  177. package/examples/jsm/objects/SkyMesh.js +20 -17
  178. package/examples/jsm/objects/Water.js +1 -0
  179. package/examples/jsm/objects/Water2.js +1 -0
  180. package/examples/jsm/objects/Water2Mesh.js +3 -1
  181. package/examples/jsm/objects/WaterMesh.js +2 -1
  182. package/examples/jsm/physics/AmmoPhysics.js +1 -0
  183. package/examples/jsm/physics/JoltPhysics.js +1 -0
  184. package/examples/jsm/physics/RapierPhysics.js +139 -12
  185. package/examples/jsm/postprocessing/AfterimagePass.js +20 -2
  186. package/examples/jsm/postprocessing/BloomPass.js +2 -1
  187. package/examples/jsm/postprocessing/BokehPass.js +2 -1
  188. package/examples/jsm/postprocessing/ClearPass.js +1 -0
  189. package/examples/jsm/postprocessing/CubeTexturePass.js +1 -0
  190. package/examples/jsm/postprocessing/DotScreenPass.js +1 -0
  191. package/examples/jsm/postprocessing/EffectComposer.js +4 -2
  192. package/examples/jsm/postprocessing/FXAAPass.js +40 -0
  193. package/examples/jsm/postprocessing/FilmPass.js +1 -0
  194. package/examples/jsm/postprocessing/GTAOPass.js +4 -3
  195. package/examples/jsm/postprocessing/GlitchPass.js +2 -1
  196. package/examples/jsm/postprocessing/HalftonePass.js +2 -1
  197. package/examples/jsm/postprocessing/LUTPass.js +1 -0
  198. package/examples/jsm/postprocessing/MaskPass.js +1 -0
  199. package/examples/jsm/postprocessing/OutlinePass.js +5 -2
  200. package/examples/jsm/postprocessing/OutputPass.js +1 -0
  201. package/examples/jsm/postprocessing/Pass.js +3 -1
  202. package/examples/jsm/postprocessing/RenderPass.js +1 -0
  203. package/examples/jsm/postprocessing/RenderPixelatedPass.js +2 -1
  204. package/examples/jsm/postprocessing/RenderTransitionPass.js +4 -3
  205. package/examples/jsm/postprocessing/SAOPass.js +3 -2
  206. package/examples/jsm/postprocessing/SMAAPass.js +3 -2
  207. package/examples/jsm/postprocessing/SSAARenderPass.js +2 -1
  208. package/examples/jsm/postprocessing/SSAOPass.js +2 -1
  209. package/examples/jsm/postprocessing/SSRPass.js +4 -3
  210. package/examples/jsm/postprocessing/SavePass.js +2 -1
  211. package/examples/jsm/postprocessing/ShaderPass.js +1 -0
  212. package/examples/jsm/postprocessing/TAARenderPass.js +1 -0
  213. package/examples/jsm/postprocessing/TexturePass.js +1 -0
  214. package/examples/jsm/postprocessing/UnrealBloomPass.js +2 -1
  215. package/examples/jsm/renderers/CSS2DRenderer.js +3 -0
  216. package/examples/jsm/renderers/CSS3DRenderer.js +4 -0
  217. package/examples/jsm/renderers/Projector.js +2 -0
  218. package/examples/jsm/renderers/SVGRenderer.js +3 -0
  219. package/examples/jsm/shaders/ACESFilmicToneMappingShader.js +4 -1
  220. package/examples/jsm/shaders/AfterimageShader.js +4 -1
  221. package/examples/jsm/shaders/BasicShader.js +4 -1
  222. package/examples/jsm/shaders/BleachBypassShader.js +4 -1
  223. package/examples/jsm/shaders/BlendShader.js +4 -1
  224. package/examples/jsm/shaders/BokehShader.js +4 -1
  225. package/examples/jsm/shaders/BokehShader2.js +4 -1
  226. package/examples/jsm/shaders/BrightnessContrastShader.js +4 -1
  227. package/examples/jsm/shaders/ColorCorrectionShader.js +4 -1
  228. package/examples/jsm/shaders/ColorifyShader.js +4 -1
  229. package/examples/jsm/shaders/ConvolutionShader.js +4 -1
  230. package/examples/jsm/shaders/CopyShader.js +4 -1
  231. package/examples/jsm/shaders/DOFMipMapShader.js +4 -1
  232. package/examples/jsm/shaders/DepthLimitedBlurShader.js +4 -1
  233. package/examples/jsm/shaders/DigitalGlitch.js +4 -1
  234. package/examples/jsm/shaders/DotScreenShader.js +4 -1
  235. package/examples/jsm/shaders/ExposureShader.js +4 -1
  236. package/examples/jsm/shaders/FXAAShader.js +4 -1
  237. package/examples/jsm/shaders/FilmShader.js +4 -1
  238. package/examples/jsm/shaders/FocusShader.js +4 -1
  239. package/examples/jsm/shaders/FreiChenShader.js +4 -1
  240. package/examples/jsm/shaders/GTAOShader.js +4 -1
  241. package/examples/jsm/shaders/GammaCorrectionShader.js +4 -1
  242. package/examples/jsm/shaders/GodRaysShader.js +4 -1
  243. package/examples/jsm/shaders/HalftoneShader.js +4 -1
  244. package/examples/jsm/shaders/HorizontalBlurShader.js +4 -1
  245. package/examples/jsm/shaders/HorizontalTiltShiftShader.js +4 -1
  246. package/examples/jsm/shaders/HueSaturationShader.js +4 -1
  247. package/examples/jsm/shaders/KaleidoShader.js +4 -1
  248. package/examples/jsm/shaders/LuminosityHighPassShader.js +4 -1
  249. package/examples/jsm/shaders/LuminosityShader.js +4 -1
  250. package/examples/jsm/shaders/MirrorShader.js +4 -1
  251. package/examples/jsm/shaders/NormalMapShader.js +4 -1
  252. package/examples/jsm/shaders/OutputShader.js +4 -1
  253. package/examples/jsm/shaders/PoissonDenoiseShader.js +4 -1
  254. package/examples/jsm/shaders/RGBShiftShader.js +4 -1
  255. package/examples/jsm/shaders/SAOShader.js +4 -1
  256. package/examples/jsm/shaders/SMAAShader.js +1 -0
  257. package/examples/jsm/shaders/SSAOShader.js +4 -1
  258. package/examples/jsm/shaders/SSRShader.js +1 -0
  259. package/examples/jsm/shaders/SepiaShader.js +4 -1
  260. package/examples/jsm/shaders/SobelOperatorShader.js +4 -1
  261. package/examples/jsm/shaders/SubsurfaceScatteringShader.js +4 -1
  262. package/examples/jsm/shaders/TechnicolorShader.js +4 -1
  263. package/examples/jsm/shaders/ToonShader.js +2 -1
  264. package/examples/jsm/shaders/TriangleBlurShader.js +4 -1
  265. package/examples/jsm/shaders/UnpackDepthRGBAShader.js +4 -1
  266. package/examples/jsm/shaders/VelocityShader.js +4 -1
  267. package/examples/jsm/shaders/VerticalBlurShader.js +4 -1
  268. package/examples/jsm/shaders/VerticalTiltShiftShader.js +4 -1
  269. package/examples/jsm/shaders/VignetteShader.js +4 -1
  270. package/examples/jsm/shaders/VolumeShader.js +5 -2
  271. package/examples/jsm/shaders/WaterRefractionShader.js +4 -1
  272. package/examples/jsm/textures/FlakesTexture.js +2 -0
  273. package/examples/jsm/transpiler/AST.js +381 -30
  274. package/examples/jsm/transpiler/GLSLDecoder.js +226 -87
  275. package/examples/jsm/transpiler/Linker.js +327 -0
  276. package/examples/jsm/transpiler/TSLEncoder.js +234 -85
  277. package/examples/jsm/transpiler/Transpiler.js +19 -1
  278. package/examples/jsm/transpiler/TranspilerUtils.js +29 -0
  279. package/examples/jsm/transpiler/WGSLEncoder.js +788 -0
  280. package/examples/jsm/tsl/display/AfterImageNode.js +2 -3
  281. package/examples/jsm/tsl/display/AnaglyphPassNode.js +1 -0
  282. package/examples/jsm/tsl/display/AnamorphicNode.js +5 -4
  283. package/examples/jsm/tsl/display/BloomNode.js +1 -0
  284. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +206 -0
  285. package/examples/jsm/tsl/display/DenoiseNode.js +33 -33
  286. package/examples/jsm/tsl/display/DepthOfFieldNode.js +1 -0
  287. package/examples/jsm/tsl/display/DotScreenNode.js +1 -0
  288. package/examples/jsm/tsl/display/FXAANode.js +3 -2
  289. package/examples/jsm/tsl/display/FilmNode.js +1 -0
  290. package/examples/jsm/tsl/display/GTAONode.js +1 -0
  291. package/examples/jsm/tsl/display/GaussianBlurNode.js +4 -29
  292. package/examples/jsm/tsl/display/LensflareNode.js +1 -0
  293. package/examples/jsm/tsl/display/Lut3DNode.js +1 -0
  294. package/examples/jsm/tsl/display/OutlineNode.js +1 -0
  295. package/examples/jsm/tsl/display/ParallaxBarrierPassNode.js +1 -0
  296. package/examples/jsm/tsl/display/PixelationPassNode.js +1 -0
  297. package/examples/jsm/tsl/display/RGBShiftNode.js +1 -0
  298. package/examples/jsm/tsl/display/SMAANode.js +9 -8
  299. package/examples/jsm/tsl/display/SSAAPassNode.js +5 -4
  300. package/examples/jsm/tsl/display/SSRNode.js +1 -0
  301. package/examples/jsm/tsl/display/SobelOperatorNode.js +1 -0
  302. package/examples/jsm/tsl/display/StereoCompositePassNode.js +1 -0
  303. package/examples/jsm/tsl/display/StereoPassNode.js +1 -0
  304. package/examples/jsm/tsl/display/TRAAPassNode.js +5 -4
  305. package/examples/jsm/tsl/display/TransitionNode.js +1 -0
  306. package/examples/jsm/tsl/display/hashBlur.js +28 -6
  307. package/examples/jsm/tsl/lighting/TiledLightsNode.js +4 -3
  308. package/examples/jsm/tsl/math/Bayer.js +4 -1
  309. package/examples/jsm/tsl/shadows/TileShadowNode.js +456 -0
  310. package/examples/jsm/tsl/shadows/TileShadowNodeHelper.js +212 -0
  311. package/examples/jsm/tsl/utils/Raymarching.js +6 -3
  312. package/examples/jsm/utils/BufferGeometryUtils.js +4 -1
  313. package/examples/jsm/utils/CameraUtils.js +4 -1
  314. package/examples/jsm/utils/GeometryCompressionUtils.js +4 -1
  315. package/examples/jsm/utils/GeometryUtils.js +4 -1
  316. package/examples/jsm/utils/LDrawUtils.js +2 -0
  317. package/examples/jsm/utils/SceneOptimizer.js +2 -0
  318. package/examples/jsm/utils/SceneUtils.js +4 -1
  319. package/examples/jsm/utils/ShadowMapViewer.js +2 -0
  320. package/examples/jsm/utils/ShadowMapViewerGPU.js +2 -0
  321. package/examples/jsm/utils/SkeletonUtils.js +4 -1
  322. package/examples/jsm/utils/SortUtils.js +4 -1
  323. package/examples/jsm/utils/UVsDebug.js +4 -1
  324. package/examples/jsm/utils/WebGLTextureUtils.js +4 -1
  325. package/examples/jsm/utils/WebGPUTextureUtils.js +4 -1
  326. package/examples/jsm/utils/WorkerPool.js +2 -0
  327. package/examples/jsm/webxr/ARButton.js +1 -0
  328. package/examples/jsm/webxr/OculusHandModel.js +1 -0
  329. package/examples/jsm/webxr/OculusHandPointerModel.js +1 -0
  330. package/examples/jsm/webxr/Text2D.js +4 -1
  331. package/examples/jsm/webxr/VRButton.js +1 -0
  332. package/examples/jsm/webxr/XRButton.js +1 -0
  333. package/examples/jsm/webxr/XRControllerModelFactory.js +2 -0
  334. package/examples/jsm/webxr/XREstimatedLight.js +1 -0
  335. package/examples/jsm/webxr/XRHandMeshModel.js +2 -0
  336. package/examples/jsm/webxr/XRHandModelFactory.js +2 -0
  337. package/examples/jsm/webxr/XRHandPrimitiveModel.js +2 -0
  338. package/examples/jsm/webxr/XRPlanes.js +1 -0
  339. package/package.json +6 -4
  340. package/src/Three.Core.js +1 -1
  341. package/src/Three.TSL.js +18 -10
  342. package/src/Three.WebGPU.Nodes.js +1 -0
  343. package/src/Three.WebGPU.js +3 -0
  344. package/src/audio/AudioListener.js +13 -10
  345. package/src/cameras/ArrayCamera.js +9 -1
  346. package/src/constants.js +47 -20
  347. package/src/core/BufferAttribute.js +3 -3
  348. package/src/core/BufferGeometry.js +2 -5
  349. package/src/core/Clock.js +2 -8
  350. package/src/core/GLBufferAttribute.js +13 -1
  351. package/src/core/Object3D.js +23 -22
  352. package/src/core/RenderTarget.js +65 -21
  353. package/src/core/RenderTarget3D.js +1 -0
  354. package/src/extras/TextureUtils.js +1 -5
  355. package/src/extras/core/Curve.js +1 -1
  356. package/src/extras/core/Path.js +22 -22
  357. package/src/geometries/CapsuleGeometry.js +167 -17
  358. package/src/geometries/ExtrudeGeometry.js +39 -29
  359. package/src/helpers/ArrowHelper.js +2 -2
  360. package/src/helpers/SkeletonHelper.js +1 -1
  361. package/src/lights/LightShadow.js +14 -0
  362. package/src/lights/SpotLightShadow.js +9 -1
  363. package/src/lights/webgpu/ProjectorLight.js +46 -0
  364. package/src/loaders/BufferGeometryLoader.js +1 -10
  365. package/src/loaders/FileLoader.js +2 -2
  366. package/src/loaders/ImageBitmapLoader.js +25 -9
  367. package/src/loaders/ImageLoader.js +55 -8
  368. package/src/loaders/ObjectLoader.js +44 -16
  369. package/src/loaders/nodes/NodeObjectLoader.js +2 -2
  370. package/src/materials/Material.js +1 -7
  371. package/src/materials/nodes/MeshBasicNodeMaterial.js +4 -3
  372. package/src/materials/nodes/MeshMatcapNodeMaterial.js +1 -1
  373. package/src/materials/nodes/MeshNormalNodeMaterial.js +2 -2
  374. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +2 -1
  375. package/src/materials/nodes/MeshSSSNodeMaterial.js +2 -2
  376. package/src/materials/nodes/NodeMaterial.js +105 -19
  377. package/src/materials/nodes/manager/NodeMaterialObserver.js +20 -2
  378. package/src/math/Box3.js +28 -0
  379. package/src/math/Color.js +7 -7
  380. package/src/math/ColorManagement.js +22 -3
  381. package/src/math/Frustum.js +6 -1
  382. package/src/math/FrustumArray.js +253 -0
  383. package/src/math/Quaternion.js +1 -1
  384. package/src/math/Ray.js +2 -0
  385. package/src/math/Sphere.js +28 -0
  386. package/src/nodes/Nodes.js +2 -3
  387. package/src/nodes/TSL.js +5 -3
  388. package/src/nodes/accessors/AccessorsUtils.js +7 -8
  389. package/src/nodes/accessors/Bitangent.js +54 -26
  390. package/src/nodes/accessors/Camera.js +31 -4
  391. package/src/nodes/accessors/CubeTextureNode.js +50 -2
  392. package/src/nodes/accessors/InstanceNode.js +5 -4
  393. package/src/nodes/accessors/Lights.js +2 -2
  394. package/src/nodes/accessors/MaterialNode.js +4 -0
  395. package/src/nodes/accessors/ModelNode.js +1 -1
  396. package/src/nodes/accessors/Normal.js +102 -16
  397. package/src/nodes/accessors/Object3DNode.js +7 -8
  398. package/src/nodes/accessors/Position.js +14 -4
  399. package/src/nodes/accessors/ReferenceBaseNode.js +1 -1
  400. package/src/nodes/accessors/ReferenceNode.js +1 -1
  401. package/src/nodes/accessors/ReflectVector.js +3 -3
  402. package/src/nodes/accessors/SkinningNode.js +3 -2
  403. package/src/nodes/accessors/StorageBufferNode.js +25 -0
  404. package/src/nodes/accessors/StorageTextureNode.js +14 -3
  405. package/src/nodes/accessors/Tangent.js +25 -17
  406. package/src/nodes/accessors/TangentUtils.js +46 -0
  407. package/src/nodes/accessors/TextureBicubic.js +21 -3
  408. package/src/nodes/accessors/TextureNode.js +59 -8
  409. package/src/nodes/accessors/UniformArrayNode.js +0 -16
  410. package/src/nodes/accessors/VelocityNode.js +1 -0
  411. package/src/nodes/accessors/VertexColorNode.js +4 -4
  412. package/src/nodes/code/CodeNode.js +8 -11
  413. package/src/nodes/core/AssignNode.js +27 -5
  414. package/src/nodes/core/AttributeNode.js +2 -2
  415. package/src/nodes/core/ContextNode.js +7 -3
  416. package/src/nodes/core/Node.js +69 -20
  417. package/src/nodes/core/NodeBuilder.js +248 -29
  418. package/src/nodes/core/NodeUtils.js +42 -0
  419. package/src/nodes/core/NodeVarying.js +19 -1
  420. package/src/nodes/core/PropertyNode.js +8 -12
  421. package/src/nodes/core/StackNode.js +129 -26
  422. package/src/nodes/core/StructTypeNode.js +26 -4
  423. package/src/nodes/core/SubBuildNode.js +89 -0
  424. package/src/nodes/core/VarNode.js +11 -2
  425. package/src/nodes/core/VaryingNode.js +45 -24
  426. package/src/nodes/display/BlendModes.js +42 -1
  427. package/src/nodes/display/ColorSpaceNode.js +4 -27
  428. package/src/nodes/display/FrontFacingNode.js +34 -2
  429. package/src/nodes/display/NormalMapNode.js +19 -50
  430. package/src/nodes/display/PassNode.js +18 -19
  431. package/src/nodes/display/ScreenNode.js +0 -26
  432. package/src/nodes/functions/BSDF/BRDF_GGX.js +2 -6
  433. package/src/nodes/functions/BSDF/BRDF_Sheen.js +4 -4
  434. package/src/nodes/functions/PhongLightingModel.js +3 -3
  435. package/src/nodes/functions/PhysicalLightingModel.js +14 -14
  436. package/src/nodes/functions/ShadowMaskModel.js +5 -1
  437. package/src/nodes/functions/material/getGeometryRoughness.js +2 -2
  438. package/src/nodes/functions/material/getParallaxCorrectNormal.js +1 -1
  439. package/src/nodes/gpgpu/AtomicFunctionNode.js +28 -10
  440. package/src/nodes/gpgpu/BarrierNode.js +3 -3
  441. package/src/nodes/gpgpu/ComputeNode.js +1 -1
  442. package/src/nodes/lighting/AnalyticLightNode.js +7 -13
  443. package/src/nodes/lighting/EnvironmentNode.js +5 -5
  444. package/src/nodes/lighting/HemisphereLightNode.js +2 -2
  445. package/src/nodes/lighting/IESSpotLightNode.js +2 -1
  446. package/src/nodes/lighting/LightsNode.js +29 -11
  447. package/src/nodes/lighting/ProjectorLightNode.js +78 -0
  448. package/src/nodes/lighting/ShadowBaseNode.js +1 -12
  449. package/src/nodes/lighting/ShadowFilterNode.js +274 -0
  450. package/src/nodes/lighting/ShadowNode.js +174 -242
  451. package/src/nodes/lighting/SpotLightNode.js +44 -7
  452. package/src/nodes/materialx/lib/mx_noise.js +1 -1
  453. package/src/nodes/math/ConditionalNode.js +0 -19
  454. package/src/nodes/math/MathNode.js +68 -21
  455. package/src/nodes/math/OperatorNode.js +108 -98
  456. package/src/nodes/shapes/Shapes.js +5 -4
  457. package/src/nodes/tsl/TSLBase.js +1 -0
  458. package/src/nodes/tsl/TSLCore.js +160 -65
  459. package/src/nodes/utils/DebugNode.js +15 -3
  460. package/src/nodes/utils/Discard.js +2 -2
  461. package/src/nodes/utils/EquirectUV.js +27 -0
  462. package/src/nodes/utils/LoopNode.js +64 -34
  463. package/src/nodes/utils/MatcapUV.js +22 -0
  464. package/src/nodes/utils/RTTNode.js +13 -5
  465. package/src/nodes/utils/ReflectorNode.js +77 -7
  466. package/src/nodes/utils/SampleNode.js +81 -0
  467. package/src/nodes/utils/TriplanarTextures.js +65 -0
  468. package/src/objects/BatchedMesh.js +16 -4
  469. package/src/objects/Mesh.js +9 -0
  470. package/src/objects/Skeleton.js +1 -1
  471. package/src/objects/Sprite.js +9 -0
  472. package/src/renderers/WebGL3DRenderTarget.js +1 -0
  473. package/src/renderers/WebGLArrayRenderTarget.js +1 -0
  474. package/src/renderers/WebGLCubeRenderTarget.js +2 -4
  475. package/src/renderers/WebGLRenderer.js +25 -11
  476. package/src/renderers/common/Animation.js +2 -2
  477. package/src/renderers/common/Background.js +13 -2
  478. package/src/renderers/common/CubeRenderTarget.js +1 -1
  479. package/src/renderers/common/RenderList.js +0 -4
  480. package/src/renderers/common/RenderObject.js +80 -4
  481. package/src/renderers/common/Renderer.js +116 -8
  482. package/src/renderers/common/Storage3DTexture.js +79 -0
  483. package/src/renderers/common/StorageArrayTexture.js +63 -0
  484. package/src/renderers/common/Textures.js +15 -21
  485. package/src/renderers/common/TimestampQueryPool.js +1 -0
  486. package/src/renderers/common/Uniform.js +1 -1
  487. package/src/renderers/common/UniformsGroup.js +14 -18
  488. package/src/renderers/common/XRManager.js +157 -27
  489. package/src/renderers/common/XRRenderTarget.js +21 -4
  490. package/src/renderers/common/extras/PMREMGenerator.js +30 -23
  491. package/src/renderers/common/nodes/Nodes.js +13 -3
  492. package/src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_maps.glsl.js +1 -1
  493. package/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl.js +1 -1
  494. package/src/renderers/shaders/ShaderLib/background.glsl.js +1 -1
  495. package/src/renderers/webgl/WebGLAttributes.js +4 -0
  496. package/src/renderers/webgl/WebGLPrograms.js +4 -2
  497. package/src/renderers/webgl/WebGLShadowMap.js +3 -2
  498. package/src/renderers/webgl/WebGLState.js +4 -4
  499. package/src/renderers/webgl/WebGLTextures.js +144 -4
  500. package/src/renderers/webgl/WebGLUtils.js +1 -3
  501. package/src/renderers/webgl-fallback/WebGLBackend.js +244 -87
  502. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +73 -7
  503. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +4 -0
  504. package/src/renderers/webgl-fallback/utils/WebGLConstants.js +1 -0
  505. package/src/renderers/webgl-fallback/utils/WebGLState.js +4 -4
  506. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +44 -29
  507. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +22 -21
  508. package/src/renderers/webgpu/WebGPUBackend.js +451 -128
  509. package/src/renderers/webgpu/WebGPURenderer.js +7 -0
  510. package/src/renderers/webgpu/nodes/BasicNodeLibrary.js +4 -1
  511. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +4 -1
  512. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +86 -33
  513. package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +3 -0
  514. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +9 -1
  515. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +28 -5
  516. package/src/renderers/webgpu/utils/WebGPUConstants.js +8 -2
  517. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +38 -8
  518. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +45 -50
  519. package/src/renderers/webxr/WebXRController.js +1 -1
  520. package/src/renderers/webxr/WebXRManager.js +2 -1
  521. package/src/textures/DepthTexture.js +6 -10
  522. package/src/textures/Source.js +22 -0
  523. package/src/textures/Texture.js +118 -1
  524. package/src/textures/VideoTexture.js +1 -1
  525. package/examples/jsm/effects/PeppersGhostEffect.js +0 -172
  526. package/src/core/RenderTargetArray.js +0 -40
  527. package/src/nodes/utils/EquirectUVNode.js +0 -65
  528. package/src/nodes/utils/MatcapUVNode.js +0 -49
  529. package/src/nodes/utils/TriplanarTexturesNode.js +0 -148
@@ -1,11 +1,10 @@
1
1
  import ShadowBaseNode, { shadowPositionWorld } from './ShadowBaseNode.js';
2
- import { float, vec2, vec3, vec4, If, int, Fn, nodeObject } from '../tsl/TSLBase.js';
2
+ import { float, vec2, vec3, int, Fn, nodeObject } from '../tsl/TSLBase.js';
3
3
  import { reference } from '../accessors/ReferenceNode.js';
4
4
  import { texture } from '../accessors/TextureNode.js';
5
- import { positionWorld } from '../accessors/Position.js';
6
- import { transformedNormalWorld } from '../accessors/Normal.js';
7
- import { mix, fract, step, max, clamp, sqrt } from '../math/MathNode.js';
8
- import { add, sub } from '../math/OperatorNode.js';
5
+ import { normalWorld } from '../accessors/Normal.js';
6
+ import { mix, sqrt } from '../math/MathNode.js';
7
+ import { add } from '../math/OperatorNode.js';
9
8
  import { DepthTexture } from '../../textures/DepthTexture.js';
10
9
  import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
11
10
  import QuadMesh from '../../renderers/common/QuadMesh.js';
@@ -14,219 +13,77 @@ import { screenCoordinate } from '../display/ScreenNode.js';
14
13
  import { HalfFloatType, LessCompare, RGFormat, VSMShadowMap, WebGPUCoordinateSystem } from '../../constants.js';
15
14
  import { renderGroup } from '../core/UniformGroupNode.js';
16
15
  import { viewZToLogarithmicDepth } from '../display/ViewportDepthNode.js';
17
- import { objectPosition } from '../accessors/Object3DNode.js';
18
16
  import { lightShadowMatrix } from '../accessors/Lights.js';
19
17
  import { resetRendererAndSceneState, restoreRendererAndSceneState } from '../../renderers/common/RendererUtils.js';
20
18
  import { getDataFromObject } from '../core/NodeUtils.js';
19
+ import { getShadowMaterial, BasicShadowFilter, PCFShadowFilter, PCFSoftShadowFilter, VSMShadowFilter } from './ShadowFilterNode.js';
20
+ import ChainMap from '../../renderers/common/ChainMap.js';
21
21
 
22
- const shadowMaterialLib = /*@__PURE__*/ new WeakMap();
23
- const linearDistance = /*@__PURE__*/ Fn( ( [ position, cameraNear, cameraFar ] ) => {
24
-
25
- let dist = positionWorld.sub( position ).length();
26
- dist = dist.sub( cameraNear ).div( cameraFar.sub( cameraNear ) );
27
- dist = dist.saturate(); // clamp to [ 0, 1 ]
28
-
29
- return dist;
30
-
31
- } );
32
-
33
- const linearShadowDistance = ( light ) => {
34
-
35
- const camera = light.shadow.camera;
36
-
37
- const nearDistance = reference( 'near', 'float', camera ).setGroup( renderGroup );
38
- const farDistance = reference( 'far', 'float', camera ).setGroup( renderGroup );
39
-
40
- const referencePosition = objectPosition( light );
41
-
42
- return linearDistance( referencePosition, nearDistance, farDistance );
43
-
44
- };
45
-
46
- const getShadowMaterial = ( light ) => {
47
-
48
- let material = shadowMaterialLib.get( light );
49
-
50
- if ( material === undefined ) {
51
-
52
- const depthNode = light.isPointLight ? linearShadowDistance( light ) : null;
22
+ //
53
23
 
54
- material = new NodeMaterial();
55
- material.colorNode = vec4( 0, 0, 0, 1 );
56
- material.depthNode = depthNode;
57
- material.isShadowPassMaterial = true; // Use to avoid other overrideMaterial override material.colorNode unintentionally when using material.shadowNode
58
- material.name = 'ShadowMaterial';
59
- material.fog = false;
24
+ const _shadowRenderObjectLibrary = /*@__PURE__*/ new ChainMap();
25
+ const _shadowRenderObjectKeys = [];
60
26
 
61
- shadowMaterialLib.set( light, material );
27
+ /**
28
+ * Creates a function to render shadow objects in a scene.
29
+ *
30
+ * @param {Renderer} renderer - The renderer.
31
+ * @param {LightShadow} shadow - The light shadow object containing shadow properties.
32
+ * @param {number} shadowType - The type of shadow map (e.g., BasicShadowMap).
33
+ * @param {boolean} useVelocity - Whether to use velocity data for rendering.
34
+ * @return {Function} A function that renders shadow objects.
35
+ *
36
+ * The returned function has the following parameters:
37
+ * @param {Object3D} object - The 3D object to render.
38
+ * @param {Scene} scene - The scene containing the object.
39
+ * @param {Camera} _camera - The camera used for rendering.
40
+ * @param {BufferGeometry} geometry - The geometry of the object.
41
+ * @param {Material} material - The material of the object.
42
+ * @param {Group} group - The group the object belongs to.
43
+ * @param {...any} params - Additional parameters for rendering.
44
+ */
45
+ export const getShadowRenderObjectFunction = ( renderer, shadow, shadowType, useVelocity ) => {
62
46
 
63
- }
47
+ _shadowRenderObjectKeys[ 0 ] = renderer;
48
+ _shadowRenderObjectKeys[ 1 ] = shadow;
64
49
 
65
- return material;
50
+ let renderObjectFunction = _shadowRenderObjectLibrary.get( _shadowRenderObjectKeys );
66
51
 
67
- };
52
+ if ( renderObjectFunction === undefined || ( renderObjectFunction.shadowType !== shadowType || renderObjectFunction.useVelocity !== useVelocity ) ) {
68
53
 
69
- /**
70
- * A shadow filtering function performing basic filtering. This is in fact an unfiltered version of the shadow map
71
- * with a binary `[0,1]` result.
72
- *
73
- * @method
74
- * @param {Object} inputs - The input parameter object.
75
- * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's texture data.
76
- * @param {Node<vec3>} inputs.shadowCoord - The shadow coordinates.
77
- * @return {Node<float>} The filtering result.
78
- */
79
- export const BasicShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord } ) => {
54
+ renderObjectFunction = ( object, scene, _camera, geometry, material, group, ...params ) => {
80
55
 
81
- return texture( depthTexture, shadowCoord.xy ).compare( shadowCoord.z );
56
+ if ( object.castShadow === true || ( object.receiveShadow && shadowType === VSMShadowMap ) ) {
82
57
 
83
- } );
58
+ if ( useVelocity ) {
84
59
 
85
- /**
86
- * A shadow filtering function performing PCF filtering.
87
- *
88
- * @method
89
- * @param {Object} inputs - The input parameter object.
90
- * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's texture data.
91
- * @param {Node<vec3>} inputs.shadowCoord - The shadow coordinates.
92
- * @param {LightShadow} inputs.shadow - The light shadow.
93
- * @return {Node<float>} The filtering result.
94
- */
95
- export const PCFShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord, shadow } ) => {
96
-
97
- const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare );
98
-
99
- const mapSize = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup );
100
- const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup );
101
-
102
- const texelSize = vec2( 1 ).div( mapSize );
103
- const dx0 = texelSize.x.negate().mul( radius );
104
- const dy0 = texelSize.y.negate().mul( radius );
105
- const dx1 = texelSize.x.mul( radius );
106
- const dy1 = texelSize.y.mul( radius );
107
- const dx2 = dx0.div( 2 );
108
- const dy2 = dy0.div( 2 );
109
- const dx3 = dx1.div( 2 );
110
- const dy3 = dy1.div( 2 );
111
-
112
- return add(
113
- depthCompare( shadowCoord.xy.add( vec2( dx0, dy0 ) ), shadowCoord.z ),
114
- depthCompare( shadowCoord.xy.add( vec2( 0, dy0 ) ), shadowCoord.z ),
115
- depthCompare( shadowCoord.xy.add( vec2( dx1, dy0 ) ), shadowCoord.z ),
116
- depthCompare( shadowCoord.xy.add( vec2( dx2, dy2 ) ), shadowCoord.z ),
117
- depthCompare( shadowCoord.xy.add( vec2( 0, dy2 ) ), shadowCoord.z ),
118
- depthCompare( shadowCoord.xy.add( vec2( dx3, dy2 ) ), shadowCoord.z ),
119
- depthCompare( shadowCoord.xy.add( vec2( dx0, 0 ) ), shadowCoord.z ),
120
- depthCompare( shadowCoord.xy.add( vec2( dx2, 0 ) ), shadowCoord.z ),
121
- depthCompare( shadowCoord.xy, shadowCoord.z ),
122
- depthCompare( shadowCoord.xy.add( vec2( dx3, 0 ) ), shadowCoord.z ),
123
- depthCompare( shadowCoord.xy.add( vec2( dx1, 0 ) ), shadowCoord.z ),
124
- depthCompare( shadowCoord.xy.add( vec2( dx2, dy3 ) ), shadowCoord.z ),
125
- depthCompare( shadowCoord.xy.add( vec2( 0, dy3 ) ), shadowCoord.z ),
126
- depthCompare( shadowCoord.xy.add( vec2( dx3, dy3 ) ), shadowCoord.z ),
127
- depthCompare( shadowCoord.xy.add( vec2( dx0, dy1 ) ), shadowCoord.z ),
128
- depthCompare( shadowCoord.xy.add( vec2( 0, dy1 ) ), shadowCoord.z ),
129
- depthCompare( shadowCoord.xy.add( vec2( dx1, dy1 ) ), shadowCoord.z )
130
- ).mul( 1 / 17 );
60
+ getDataFromObject( object ).useVelocity = true;
131
61
 
132
- } );
62
+ }
133
63
 
134
- /**
135
- * A shadow filtering function performing PCF soft filtering.
136
- *
137
- * @method
138
- * @param {Object} inputs - The input parameter object.
139
- * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's texture data.
140
- * @param {Node<vec3>} inputs.shadowCoord - The shadow coordinates.
141
- * @param {LightShadow} inputs.shadow - The light shadow.
142
- * @return {Node<float>} The filtering result.
143
- */
144
- export const PCFSoftShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord, shadow } ) => {
145
-
146
- const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare );
147
-
148
- const mapSize = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup );
149
-
150
- const texelSize = vec2( 1 ).div( mapSize );
151
- const dx = texelSize.x;
152
- const dy = texelSize.y;
153
-
154
- const uv = shadowCoord.xy;
155
- const f = fract( uv.mul( mapSize ).add( 0.5 ) );
156
- uv.subAssign( f.mul( texelSize ) );
157
-
158
- return add(
159
- depthCompare( uv, shadowCoord.z ),
160
- depthCompare( uv.add( vec2( dx, 0 ) ), shadowCoord.z ),
161
- depthCompare( uv.add( vec2( 0, dy ) ), shadowCoord.z ),
162
- depthCompare( uv.add( texelSize ), shadowCoord.z ),
163
- mix(
164
- depthCompare( uv.add( vec2( dx.negate(), 0 ) ), shadowCoord.z ),
165
- depthCompare( uv.add( vec2( dx.mul( 2 ), 0 ) ), shadowCoord.z ),
166
- f.x
167
- ),
168
- mix(
169
- depthCompare( uv.add( vec2( dx.negate(), dy ) ), shadowCoord.z ),
170
- depthCompare( uv.add( vec2( dx.mul( 2 ), dy ) ), shadowCoord.z ),
171
- f.x
172
- ),
173
- mix(
174
- depthCompare( uv.add( vec2( 0, dy.negate() ) ), shadowCoord.z ),
175
- depthCompare( uv.add( vec2( 0, dy.mul( 2 ) ) ), shadowCoord.z ),
176
- f.y
177
- ),
178
- mix(
179
- depthCompare( uv.add( vec2( dx, dy.negate() ) ), shadowCoord.z ),
180
- depthCompare( uv.add( vec2( dx, dy.mul( 2 ) ) ), shadowCoord.z ),
181
- f.y
182
- ),
183
- mix(
184
- mix(
185
- depthCompare( uv.add( vec2( dx.negate(), dy.negate() ) ), shadowCoord.z ),
186
- depthCompare( uv.add( vec2( dx.mul( 2 ), dy.negate() ) ), shadowCoord.z ),
187
- f.x
188
- ),
189
- mix(
190
- depthCompare( uv.add( vec2( dx.negate(), dy.mul( 2 ) ) ), shadowCoord.z ),
191
- depthCompare( uv.add( vec2( dx.mul( 2 ), dy.mul( 2 ) ) ), shadowCoord.z ),
192
- f.x
193
- ),
194
- f.y
195
- )
196
- ).mul( 1 / 9 );
64
+ object.onBeforeShadow( renderer, object, _camera, shadow.camera, geometry, scene.overrideMaterial, group );
197
65
 
198
- } );
66
+ renderer.renderObject( object, scene, _camera, geometry, material, group, ...params );
199
67
 
200
- /**
201
- * A shadow filtering function performing VSM filtering.
202
- *
203
- * @method
204
- * @param {Object} inputs - The input parameter object.
205
- * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's texture data.
206
- * @param {Node<vec3>} inputs.shadowCoord - The shadow coordinates.
207
- * @return {Node<float>} The filtering result.
208
- */
209
- export const VSMShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord } ) => {
68
+ object.onAfterShadow( renderer, object, _camera, shadow.camera, geometry, scene.overrideMaterial, group );
210
69
 
211
- const occlusion = float( 1 ).toVar();
70
+ }
212
71
 
213
- const distribution = texture( depthTexture ).sample( shadowCoord.xy ).rg;
72
+ };
214
73
 
215
- const hardShadow = step( shadowCoord.z, distribution.x );
74
+ renderObjectFunction.shadowType = shadowType;
75
+ renderObjectFunction.useVelocity = useVelocity;
216
76
 
217
- If( hardShadow.notEqual( float( 1.0 ) ), () => {
77
+ _shadowRenderObjectLibrary.set( _shadowRenderObjectKeys, renderObjectFunction );
218
78
 
219
- const distance = shadowCoord.z.sub( distribution.x );
220
- const variance = max( 0, distribution.y.mul( distribution.y ) );
221
- let softnessProbability = variance.div( variance.add( distance.mul( distance ) ) ); // Chebeyshevs inequality
222
- softnessProbability = clamp( sub( softnessProbability, 0.3 ).div( 0.95 - 0.3 ) );
223
- occlusion.assign( clamp( max( hardShadow, softnessProbability ) ) );
79
+ }
224
80
 
225
- } );
81
+ _shadowRenderObjectKeys[ 0 ] = null;
82
+ _shadowRenderObjectKeys[ 1 ] = null;
226
83
 
227
- return occlusion;
84
+ return renderObjectFunction;
228
85
 
229
- } );
86
+ };
230
87
 
231
88
  /**
232
89
  * Represents the shader code for the first VSM render pass.
@@ -239,10 +96,10 @@ export const VSMShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord }
239
96
  * @param {TextureNode} inputs.shadowPass - A reference to the render target's depth data.
240
97
  * @return {Node<vec2>} The VSM output.
241
98
  */
242
- const VSMPassVertical = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPass } ) => {
99
+ const VSMPassVertical = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPass, depthLayer } ) => {
243
100
 
244
- const mean = float( 0 ).toVar();
245
- const squaredMean = float( 0 ).toVar();
101
+ const mean = float( 0 ).toVar( 'meanVertical' );
102
+ const squaredMean = float( 0 ).toVar( 'squareMeanVertical' );
246
103
 
247
104
  const uvStride = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( 2 ).div( samples.sub( 1 ) ) );
248
105
  const uvStart = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( - 1 ) );
@@ -251,7 +108,16 @@ const VSMPassVertical = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPass
251
108
 
252
109
  const uvOffset = uvStart.add( float( i ).mul( uvStride ) );
253
110
 
254
- const depth = shadowPass.sample( add( screenCoordinate.xy, vec2( 0, uvOffset ).mul( radius ) ).div( size ) ).x;
111
+ let depth = shadowPass.sample( add( screenCoordinate.xy, vec2( 0, uvOffset ).mul( radius ) ).div( size ) );
112
+
113
+ if ( shadowPass.value.isArrayTexture ) {
114
+
115
+ depth = depth.depth( depthLayer );
116
+
117
+ }
118
+
119
+ depth = depth.x;
120
+
255
121
  mean.addAssign( depth );
256
122
  squaredMean.addAssign( depth.mul( depth ) );
257
123
 
@@ -276,10 +142,10 @@ const VSMPassVertical = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPass
276
142
  * @param {TextureNode} inputs.shadowPass - The result of the first VSM render pass.
277
143
  * @return {Node<vec2>} The VSM output.
278
144
  */
279
- const VSMPassHorizontal = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPass } ) => {
145
+ const VSMPassHorizontal = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPass, depthLayer } ) => {
280
146
 
281
- const mean = float( 0 ).toVar();
282
- const squaredMean = float( 0 ).toVar();
147
+ const mean = float( 0 ).toVar( 'meanHorizontal' );
148
+ const squaredMean = float( 0 ).toVar( 'squareMeanHorizontal' );
283
149
 
284
150
  const uvStride = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( 2 ).div( samples.sub( 1 ) ) );
285
151
  const uvStart = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( - 1 ) );
@@ -288,7 +154,14 @@ const VSMPassHorizontal = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPas
288
154
 
289
155
  const uvOffset = uvStart.add( float( i ).mul( uvStride ) );
290
156
 
291
- const distribution = shadowPass.sample( add( screenCoordinate.xy, vec2( uvOffset, 0 ).mul( radius ) ).div( size ) );
157
+ let distribution = shadowPass.sample( add( screenCoordinate.xy, vec2( uvOffset, 0 ).mul( radius ) ).div( size ) );
158
+
159
+ if ( shadowPass.value.isArrayTexture ) {
160
+
161
+ distribution = distribution.depth( depthLayer );
162
+
163
+ }
164
+
292
165
  mean.addAssign( distribution.x );
293
166
  squaredMean.addAssign( add( distribution.y.mul( distribution.y ), distribution.x.mul( distribution.x ) ) );
294
167
 
@@ -406,6 +279,15 @@ class ShadowNode extends ShadowBaseNode {
406
279
  */
407
280
  this.isShadowNode = true;
408
281
 
282
+ /**
283
+ * This index can be used when overriding setupRenderTarget with a RenderTarget Array to specify the depth layer.
284
+ *
285
+ * @type {number}
286
+ * @readonly
287
+ * @default true
288
+ */
289
+ this.depthLayer = 0;
290
+
409
291
  }
410
292
 
411
293
  /**
@@ -419,7 +301,7 @@ class ShadowNode extends ShadowBaseNode {
419
301
  * @param {LightShadow} inputs.shadow - The light shadow.
420
302
  * @return {Node<float>} The result node of the shadow filtering.
421
303
  */
422
- setupShadowFilter( builder, { filterFn, depthTexture, shadowCoord, shadow } ) {
304
+ setupShadowFilter( builder, { filterFn, depthTexture, shadowCoord, shadow, depthLayer } ) {
423
305
 
424
306
  const frustumTest = shadowCoord.x.greaterThanEqual( 0 )
425
307
  .and( shadowCoord.x.lessThanEqual( 1 ) )
@@ -427,7 +309,7 @@ class ShadowNode extends ShadowBaseNode {
427
309
  .and( shadowCoord.y.lessThanEqual( 1 ) )
428
310
  .and( shadowCoord.z.lessThanEqual( 1 ) );
429
311
 
430
- const shadowNode = filterFn( { depthTexture, shadowCoord, shadow } );
312
+ const shadowNode = filterFn( { depthTexture, shadowCoord, shadow, depthLayer } );
431
313
 
432
314
  return frustumTest.select( shadowNode, float( 1 ) );
433
315
 
@@ -499,6 +381,22 @@ class ShadowNode extends ShadowBaseNode {
499
381
 
500
382
  }
501
383
 
384
+
385
+ setupRenderTarget( shadow, builder ) {
386
+
387
+ const depthTexture = new DepthTexture( shadow.mapSize.width, shadow.mapSize.height );
388
+ depthTexture.name = 'ShadowDepthTexture';
389
+ depthTexture.compareFunction = LessCompare;
390
+
391
+ const shadowMap = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height );
392
+ shadowMap.texture.name = 'ShadowMap';
393
+ shadowMap.texture.type = shadow.mapType;
394
+ shadowMap.depthTexture = depthTexture;
395
+
396
+ return { shadowMap, depthTexture };
397
+
398
+ }
399
+
502
400
  /**
503
401
  * Setups the shadow output node.
504
402
  *
@@ -513,36 +411,70 @@ class ShadowNode extends ShadowBaseNode {
513
411
 
514
412
  const shadowMapType = renderer.shadowMap.type;
515
413
 
516
- const depthTexture = new DepthTexture( shadow.mapSize.width, shadow.mapSize.height );
517
- depthTexture.compareFunction = LessCompare;
518
-
519
- const shadowMap = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height );
520
- shadowMap.depthTexture = depthTexture;
414
+ const { depthTexture, shadowMap } = this.setupRenderTarget( shadow, builder );
521
415
 
522
416
  shadow.camera.updateProjectionMatrix();
523
417
 
524
418
  // VSM
525
419
 
526
- if ( shadowMapType === VSMShadowMap ) {
420
+ if ( shadowMapType === VSMShadowMap && shadow.isPointLightShadow !== true ) {
527
421
 
528
422
  depthTexture.compareFunction = null; // VSM does not use textureSampleCompare()/texture2DCompare()
529
423
 
530
- this.vsmShadowMapVertical = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType } );
531
- this.vsmShadowMapHorizontal = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType } );
424
+ if ( shadowMap.depth > 1 ) {
425
+
426
+ if ( ! shadowMap._vsmShadowMapVertical ) {
427
+
428
+ shadowMap._vsmShadowMapVertical = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType, depth: shadowMap.depth, depthBuffer: false } );
429
+ shadowMap._vsmShadowMapVertical.texture.name = 'VSMVertical';
430
+
431
+ }
432
+
433
+ this.vsmShadowMapVertical = shadowMap._vsmShadowMapVertical;
434
+
435
+ if ( ! shadowMap._vsmShadowMapHorizontal ) {
436
+
437
+ shadowMap._vsmShadowMapHorizontal = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType, depth: shadowMap.depth, depthBuffer: false } );
438
+ shadowMap._vsmShadowMapHorizontal.texture.name = 'VSMHorizontal';
439
+
440
+ }
441
+
442
+ this.vsmShadowMapHorizontal = shadowMap._vsmShadowMapHorizontal;
443
+
444
+ } else {
445
+
446
+ this.vsmShadowMapVertical = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType, depthBuffer: false } );
447
+ this.vsmShadowMapHorizontal = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType, depthBuffer: false } );
448
+
449
+ }
450
+
451
+
452
+ let shadowPassVertical = texture( depthTexture );
453
+
454
+ if ( depthTexture.isArrayTexture ) {
532
455
 
533
- const shadowPassVertical = texture( depthTexture );
534
- const shadowPassHorizontal = texture( this.vsmShadowMapVertical.texture );
456
+ shadowPassVertical = shadowPassVertical.depth( this.depthLayer );
457
+
458
+ }
459
+
460
+ let shadowPassHorizontal = texture( this.vsmShadowMapVertical.texture );
461
+
462
+ if ( depthTexture.isArrayTexture ) {
463
+
464
+ shadowPassHorizontal = shadowPassHorizontal.depth( this.depthLayer );
465
+
466
+ }
535
467
 
536
468
  const samples = reference( 'blurSamples', 'float', shadow ).setGroup( renderGroup );
537
469
  const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup );
538
470
  const size = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup );
539
471
 
540
472
  let material = this.vsmMaterialVertical || ( this.vsmMaterialVertical = new NodeMaterial() );
541
- material.fragmentNode = VSMPassVertical( { samples, radius, size, shadowPass: shadowPassVertical } ).context( builder.getSharedContext() );
473
+ material.fragmentNode = VSMPassVertical( { samples, radius, size, shadowPass: shadowPassVertical, depthLayer: this.depthLayer } ).context( builder.getSharedContext() );
542
474
  material.name = 'VSMVertical';
543
475
 
544
476
  material = this.vsmMaterialHorizontal || ( this.vsmMaterialHorizontal = new NodeMaterial() );
545
- material.fragmentNode = VSMPassHorizontal( { samples, radius, size, shadowPass: shadowPassHorizontal } ).context( builder.getSharedContext() );
477
+ material.fragmentNode = VSMPassHorizontal( { samples, radius, size, shadowPass: shadowPassHorizontal, depthLayer: this.depthLayer } ).context( builder.getSharedContext() );
546
478
  material.name = 'VSMHorizontal';
547
479
 
548
480
  }
@@ -552,7 +484,7 @@ class ShadowNode extends ShadowBaseNode {
552
484
  const shadowIntensity = reference( 'intensity', 'float', shadow ).setGroup( renderGroup );
553
485
  const normalBias = reference( 'normalBias', 'float', shadow ).setGroup( renderGroup );
554
486
 
555
- const shadowPosition = lightShadowMatrix( light ).mul( shadowPositionWorld.add( transformedNormalWorld.mul( normalBias ) ) );
487
+ const shadowPosition = lightShadowMatrix( light ).mul( shadowPositionWorld.add( normalWorld.mul( normalBias ) ) );
556
488
  const shadowCoord = this.setupShadowCoord( builder, shadowPosition );
557
489
 
558
490
  //
@@ -565,11 +497,18 @@ class ShadowNode extends ShadowBaseNode {
565
497
 
566
498
  }
567
499
 
568
- const shadowDepthTexture = ( shadowMapType === VSMShadowMap ) ? this.vsmShadowMapHorizontal.texture : depthTexture;
500
+ const shadowDepthTexture = ( shadowMapType === VSMShadowMap && shadow.isPointLightShadow !== true ) ? this.vsmShadowMapHorizontal.texture : depthTexture;
501
+
502
+ const shadowNode = this.setupShadowFilter( builder, { filterFn, shadowTexture: shadowMap.texture, depthTexture: shadowDepthTexture, shadowCoord, shadow, depthLayer: this.depthLayer } );
503
+
504
+ let shadowColor = texture( shadowMap.texture, shadowCoord );
505
+
506
+ if ( depthTexture.isArrayTexture ) {
569
507
 
570
- const shadowNode = this.setupShadowFilter( builder, { filterFn, shadowTexture: shadowMap.texture, depthTexture: shadowDepthTexture, shadowCoord, shadow } );
508
+ shadowColor = shadowColor.depth( this.depthLayer );
509
+
510
+ }
571
511
 
572
- const shadowColor = texture( shadowMap.texture, shadowCoord );
573
512
  const shadowOutput = mix( 1, shadowNode.rgb.mix( shadowColor, 1 ), shadowIntensity.mul( shadowColor.a ) ).toVar();
574
513
 
575
514
  this.shadowMap = shadowMap;
@@ -635,7 +574,7 @@ class ShadowNode extends ShadowBaseNode {
635
574
 
636
575
  shadow.updateMatrices( light );
637
576
 
638
- shadowMap.setSize( shadow.mapSize.width, shadow.mapSize.height );
577
+ shadowMap.setSize( shadow.mapSize.width, shadow.mapSize.height, shadowMap.depth );
639
578
 
640
579
  renderer.render( scene, shadow.camera );
641
580
 
@@ -656,7 +595,13 @@ class ShadowNode extends ShadowBaseNode {
656
595
  const depthVersion = shadowMap.depthTexture.version;
657
596
  this._depthVersionCached = depthVersion;
658
597
 
659
- shadow.camera.layers.mask = camera.layers.mask;
598
+ const _shadowCameraLayer = shadow.camera.layers.mask;
599
+
600
+ if ( ( shadow.camera.layers.mask & 0xFFFFFFFE ) === 0 ) {
601
+
602
+ shadow.camera.layers.mask = camera.layers.mask;
603
+
604
+ }
660
605
 
661
606
  const currentRenderObjectFunction = renderer.getRenderObjectFunction();
662
607
 
@@ -667,25 +612,9 @@ class ShadowNode extends ShadowBaseNode {
667
612
 
668
613
  scene.overrideMaterial = getShadowMaterial( light );
669
614
 
670
- renderer.setRenderObjectFunction( ( object, scene, _camera, geometry, material, group, ...params ) => {
615
+ renderer.setRenderObjectFunction( getShadowRenderObjectFunction( renderer, shadow, shadowType, useVelocity ) );
671
616
 
672
- if ( object.castShadow === true || ( object.receiveShadow && shadowType === VSMShadowMap ) ) {
673
-
674
- if ( useVelocity ) {
675
-
676
- getDataFromObject( object ).useVelocity = true;
677
-
678
- }
679
-
680
- object.onBeforeShadow( renderer, object, camera, shadow.camera, geometry, scene.overrideMaterial, group );
681
-
682
- renderer.renderObject( object, scene, _camera, geometry, material, group, ...params );
683
-
684
- object.onAfterShadow( renderer, object, camera, shadow.camera, geometry, scene.overrideMaterial, group );
685
-
686
- }
687
-
688
- } );
617
+ renderer.setClearColor( 0x000000, 0 );
689
618
 
690
619
  renderer.setRenderTarget( shadowMap );
691
620
 
@@ -695,12 +624,14 @@ class ShadowNode extends ShadowBaseNode {
695
624
 
696
625
  // vsm blur pass
697
626
 
698
- if ( light.isPointLight !== true && shadowType === VSMShadowMap ) {
627
+ if ( shadowType === VSMShadowMap && shadow.isPointLightShadow !== true ) {
699
628
 
700
629
  this.vsmPass( renderer );
701
630
 
702
631
  }
703
632
 
633
+ shadow.camera.layers.mask = _shadowCameraLayer;
634
+
704
635
  restoreRendererAndSceneState( renderer, scene, _rendererState );
705
636
 
706
637
  }
@@ -714,8 +645,9 @@ class ShadowNode extends ShadowBaseNode {
714
645
 
715
646
  const { shadow } = this;
716
647
 
717
- this.vsmShadowMapVertical.setSize( shadow.mapSize.width, shadow.mapSize.height );
718
- this.vsmShadowMapHorizontal.setSize( shadow.mapSize.width, shadow.mapSize.height );
648
+ const depth = this.shadowMap.depth;
649
+ this.vsmShadowMapVertical.setSize( shadow.mapSize.width, shadow.mapSize.height, depth );
650
+ this.vsmShadowMapHorizontal.setSize( shadow.mapSize.width, shadow.mapSize.height, depth );
719
651
 
720
652
  renderer.setRenderTarget( this.vsmShadowMapVertical );
721
653
  _quadMesh.material = this.vsmMaterialVertical;
@@ -56,6 +56,13 @@ class SpotLightNode extends AnalyticLightNode {
56
56
  */
57
57
  this.decayExponentNode = uniform( 0 ).setGroup( renderGroup );
58
58
 
59
+ /**
60
+ * Uniform node representing the light color.
61
+ *
62
+ * @type {UniformNode<Color>}
63
+ */
64
+ this.colorNode = uniform( this.color ).setGroup( renderGroup );
65
+
59
66
  }
60
67
 
61
68
  /**
@@ -80,10 +87,11 @@ class SpotLightNode extends AnalyticLightNode {
80
87
  /**
81
88
  * Computes the spot attenuation for the given angle.
82
89
  *
90
+ * @param {NodeBuilder} builder - The node builder.
83
91
  * @param {Node<float>} angleCosine - The angle to compute the spot attenuation for.
84
92
  * @return {Node<float>} The spot attenuation.
85
93
  */
86
- getSpotAttenuation( angleCosine ) {
94
+ getSpotAttenuation( builder, angleCosine ) {
87
95
 
88
96
  const { coneCosNode, penumbraCosNode } = this;
89
97
 
@@ -91,6 +99,23 @@ class SpotLightNode extends AnalyticLightNode {
91
99
 
92
100
  }
93
101
 
102
+ getLightCoord( builder ) {
103
+
104
+ const properties = builder.getNodeProperties( this );
105
+ let projectionUV = properties.projectionUV;
106
+
107
+ if ( projectionUV === undefined ) {
108
+
109
+ projectionUV = lightProjectionUV( this.light, builder.context.positionWorld );
110
+
111
+ properties.projectionUV = projectionUV;
112
+
113
+ }
114
+
115
+ return projectionUV;
116
+
117
+ }
118
+
94
119
  setupDirect( builder ) {
95
120
 
96
121
  const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this;
@@ -99,7 +124,8 @@ class SpotLightNode extends AnalyticLightNode {
99
124
 
100
125
  const lightDirection = lightVector.normalize();
101
126
  const angleCos = lightDirection.dot( lightTargetDirection( light ) );
102
- const spotAttenuation = this.getSpotAttenuation( angleCos );
127
+
128
+ const spotAttenuation = this.getSpotAttenuation( builder, angleCos );
103
129
 
104
130
  const lightDistance = lightVector.length();
105
131
 
@@ -111,14 +137,25 @@ class SpotLightNode extends AnalyticLightNode {
111
137
 
112
138
  let lightColor = colorNode.mul( spotAttenuation ).mul( lightAttenuation );
113
139
 
114
- if ( light.map ) {
140
+ let projected, lightCoord;
141
+
142
+ if ( light.colorNode ) {
143
+
144
+ lightCoord = this.getLightCoord( builder );
145
+ projected = light.colorNode( lightCoord );
146
+
147
+ } else if ( light.map ) {
148
+
149
+ lightCoord = this.getLightCoord( builder );
150
+ projected = texture( light.map, lightCoord.xy ).onRenderUpdate( () => light.map );
151
+
152
+ }
115
153
 
116
- const spotLightCoord = lightProjectionUV( light, builder.context.positionWorld );
117
- const projectedTexture = texture( light.map, spotLightCoord.xy ).onRenderUpdate( () => light.map );
154
+ if ( projected ) {
118
155
 
119
- const inSpotLightMap = spotLightCoord.mul( 2. ).sub( 1. ).abs().lessThan( 1. ).all();
156
+ const inSpotLightMap = lightCoord.mul( 2. ).sub( 1. ).abs().lessThan( 1. ).all();
120
157
 
121
- lightColor = inSpotLightMap.select( lightColor.mul( projectedTexture ), lightColor );
158
+ lightColor = inSpotLightMap.select( lightColor.mul( projected ), lightColor );
122
159
 
123
160
  }
124
161