@lampdotdev/lamp 0.0.0-stage → 0.35.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 (464) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +357 -2
  3. package/Resources/Devices/roku.json +410 -0
  4. package/Resources/Devices/xbox-one.json +367 -0
  5. package/Resources/GameKit/NOTICE.md +63 -0
  6. package/Resources/GameKit/apple/LampPage.swift +1646 -0
  7. package/Resources/GameKit/apple/LampPlayer.swift +46 -0
  8. package/Resources/GameKit/apple/LampWebApp.swift +63 -0
  9. package/Resources/GameKit/apple/LampWebGame.swift +87 -0
  10. package/Resources/GameKit/apple/Native.swift +12 -0
  11. package/Resources/GameKit/build.sh +55 -0
  12. package/Resources/GameKit/lamp_game.h +116 -0
  13. package/Resources/GameKit/lamp_host.h +19 -0
  14. package/Resources/GameKit/lamp_kit.cpp +61 -0
  15. package/Resources/GameKit/lamp_sound.cpp +455 -0
  16. package/Resources/GameKit/lamp_xbox.cpp +374 -0
  17. package/Resources/GameKit/libraries/HandmadeMath.h +3940 -0
  18. package/Resources/GameKit/libraries/cgltf.h +7240 -0
  19. package/Resources/GameKit/libraries/dr_mp3.h +5430 -0
  20. package/Resources/GameKit/libraries/dr_wav.h +9209 -0
  21. package/Resources/GameKit/libraries/sokol_debugtext.h +4754 -0
  22. package/Resources/GameKit/libraries/sokol_gfx.h +29558 -0
  23. package/Resources/GameKit/libraries/sokol_gl.h +4538 -0
  24. package/Resources/GameKit/libraries/sokol_log.h +335 -0
  25. package/Resources/GameKit/libraries/sokol_shape.h +1531 -0
  26. package/Resources/GameKit/libraries/stb_image.h +7988 -0
  27. package/Resources/GameKit/libraries/stb_vorbis.c +5584 -0
  28. package/Resources/GameKit/scaffold/Game/game.cpp +142 -0
  29. package/Resources/GameKit/scaffold/Game/scene.glsl +49 -0
  30. package/Resources/GameKit/scaffold-web/Web/game.js +31 -0
  31. package/Resources/GameKit/scaffold-web/Web/index.html +13 -0
  32. package/Resources/GameKit/scaffold-web/Web/making.js +33 -0
  33. package/Resources/GameKit/scaffold-web/Web/world.js +33 -0
  34. package/Resources/GameKit/web/lamp-game.js +3036 -0
  35. package/Resources/GameKit/web/lamp-phaser.js +128 -0
  36. package/Resources/WebHost/App.exe +0 -0
  37. package/Resources/WebHost/Microsoft.Web.WebView2.Core.dll +0 -0
  38. package/Resources/WebHost/WebView2-LICENSE.txt +27 -0
  39. package/Resources/WebHost/lamp_controllers.h +1506 -0
  40. package/Resources/WebHost/lamp_web_host.cpp +1173 -0
  41. package/Resources/WebLibraries/earlier.txt +318 -0
  42. package/Resources/WebLibraries/phaser/LICENSE.md +20 -0
  43. package/Resources/WebLibraries/phaser/NOTICE.md +2 -0
  44. package/Resources/WebLibraries/phaser/phaser.esm.min.js +1 -0
  45. package/Resources/WebLibraries/qrcode/LICENSE +21 -0
  46. package/Resources/WebLibraries/qrcode/NOTICE.md +4 -0
  47. package/Resources/WebLibraries/qrcode/qrcode.js +2297 -0
  48. package/Resources/WebLibraries/rapier/LICENSE +201 -0
  49. package/Resources/WebLibraries/rapier/NOTICE.md +3 -0
  50. package/Resources/WebLibraries/rapier/rapier.js +2 -0
  51. package/Resources/WebLibraries/three/LICENSE +21 -0
  52. package/Resources/WebLibraries/three/NOTICE.md +4 -0
  53. package/Resources/WebLibraries/three/addons/animation/AnimationClipCreator.js +168 -0
  54. package/Resources/WebLibraries/three/addons/animation/CCDIKSolver.js +607 -0
  55. package/Resources/WebLibraries/three/addons/controls/ArcballControls.js +3543 -0
  56. package/Resources/WebLibraries/three/addons/controls/DragControls.js +452 -0
  57. package/Resources/WebLibraries/three/addons/controls/FirstPersonControls.js +512 -0
  58. package/Resources/WebLibraries/three/addons/controls/FlyControls.js +384 -0
  59. package/Resources/WebLibraries/three/addons/controls/MapControls.js +116 -0
  60. package/Resources/WebLibraries/three/addons/controls/OrbitControls.js +1985 -0
  61. package/Resources/WebLibraries/three/addons/controls/PointerLockControls.js +264 -0
  62. package/Resources/WebLibraries/three/addons/controls/TrackballControls.js +1106 -0
  63. package/Resources/WebLibraries/three/addons/controls/TransformControls.js +2003 -0
  64. package/Resources/WebLibraries/three/addons/curves/CurveExtras.js +694 -0
  65. package/Resources/WebLibraries/three/addons/curves/NURBSCurve.js +169 -0
  66. package/Resources/WebLibraries/three/addons/curves/NURBSSurface.js +98 -0
  67. package/Resources/WebLibraries/three/addons/curves/NURBSUtils.js +532 -0
  68. package/Resources/WebLibraries/three/addons/curves/NURBSVolume.js +82 -0
  69. package/Resources/WebLibraries/three/addons/effects/AnaglyphEffect.js +274 -0
  70. package/Resources/WebLibraries/three/addons/effects/AsciiEffect.js +323 -0
  71. package/Resources/WebLibraries/three/addons/effects/OutlineEffect.js +489 -0
  72. package/Resources/WebLibraries/three/addons/effects/ParallaxBarrierEffect.js +155 -0
  73. package/Resources/WebLibraries/three/addons/effects/StereoEffect.js +91 -0
  74. package/Resources/WebLibraries/three/addons/environments/ColorEnvironment.js +59 -0
  75. package/Resources/WebLibraries/three/addons/environments/DebugEnvironment.js +102 -0
  76. package/Resources/WebLibraries/three/addons/environments/RoomEnvironment.js +185 -0
  77. package/Resources/WebLibraries/three/addons/geometries/BoxLineGeometry.js +92 -0
  78. package/Resources/WebLibraries/three/addons/geometries/ConvexGeometry.js +72 -0
  79. package/Resources/WebLibraries/three/addons/geometries/DecalGeometry.js +420 -0
  80. package/Resources/WebLibraries/three/addons/geometries/LoftGeometry.js +355 -0
  81. package/Resources/WebLibraries/three/addons/geometries/ParametricFunctions.js +100 -0
  82. package/Resources/WebLibraries/three/addons/geometries/ParametricGeometry.js +172 -0
  83. package/Resources/WebLibraries/three/addons/geometries/RoundedBoxGeometry.js +216 -0
  84. package/Resources/WebLibraries/three/addons/geometries/TeapotGeometry.js +689 -0
  85. package/Resources/WebLibraries/three/addons/geometries/TextGeometry.js +102 -0
  86. package/Resources/WebLibraries/three/addons/helpers/AnimationPathHelper.js +302 -0
  87. package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelper.js +166 -0
  88. package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelperWebGL.js +221 -0
  89. package/Resources/WebLibraries/three/addons/helpers/LightProbeHelper.js +166 -0
  90. package/Resources/WebLibraries/three/addons/helpers/LightProbeHelperGPU.js +102 -0
  91. package/Resources/WebLibraries/three/addons/helpers/OctreeHelper.js +109 -0
  92. package/Resources/WebLibraries/three/addons/helpers/PositionalAudioHelper.js +169 -0
  93. package/Resources/WebLibraries/three/addons/helpers/RapierHelper.js +59 -0
  94. package/Resources/WebLibraries/three/addons/helpers/RectAreaLightHelper.js +118 -0
  95. package/Resources/WebLibraries/three/addons/helpers/TextureHelper.js +265 -0
  96. package/Resources/WebLibraries/three/addons/helpers/TextureHelperGPU.js +214 -0
  97. package/Resources/WebLibraries/three/addons/helpers/VertexNormalsHelper.js +155 -0
  98. package/Resources/WebLibraries/three/addons/helpers/VertexTangentsHelper.js +133 -0
  99. package/Resources/WebLibraries/three/addons/helpers/ViewHelper.js +529 -0
  100. package/Resources/WebLibraries/three/addons/interactive/HTMLMesh.js +617 -0
  101. package/Resources/WebLibraries/three/addons/interactive/InteractiveGroup.js +224 -0
  102. package/Resources/WebLibraries/three/addons/interactive/SelectionBox.js +324 -0
  103. package/Resources/WebLibraries/three/addons/interactive/SelectionHelper.js +150 -0
  104. package/Resources/WebLibraries/three/addons/libs/fflate.module.js +2699 -0
  105. package/Resources/WebLibraries/three/addons/libs/lil-gui.module.min.js +8 -0
  106. package/Resources/WebLibraries/three/addons/libs/meshopt_decoder.module.js +196 -0
  107. package/Resources/WebLibraries/three/addons/libs/potpack.module.js +125 -0
  108. package/Resources/WebLibraries/three/addons/libs/stats.module.js +167 -0
  109. package/Resources/WebLibraries/three/addons/libs/tween.module.js +876 -0
  110. package/Resources/WebLibraries/three/addons/lighting/ClusteredLighting.js +153 -0
  111. package/Resources/WebLibraries/three/addons/lighting/DynamicLighting.js +82 -0
  112. package/Resources/WebLibraries/three/addons/lighting/LightMapper.js +295 -0
  113. package/Resources/WebLibraries/three/addons/lighting/LightProbeGrid.js +923 -0
  114. package/Resources/WebLibraries/three/addons/lighting/LightProbeGridUtils.js +107 -0
  115. package/Resources/WebLibraries/three/addons/lighting/LightProbeGridWebGL.js +846 -0
  116. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIConeTracer.js +243 -0
  117. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIIrradiance.js +43 -0
  118. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGINode.js +617 -0
  119. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGISceneCollector.js +793 -0
  120. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIVolume.js +1440 -0
  121. package/Resources/WebLibraries/three/addons/lights/LightProbeGenerator.js +337 -0
  122. package/Resources/WebLibraries/three/addons/lights/RectAreaLightTexturesLib.js +127 -0
  123. package/Resources/WebLibraries/three/addons/lights/RectAreaLightUniformsLib.js +40 -0
  124. package/Resources/WebLibraries/three/addons/lights/SunLight.js +100 -0
  125. package/Resources/WebLibraries/three/addons/lights/SunLightNode.js +56 -0
  126. package/Resources/WebLibraries/three/addons/lights/SunLightShadow.js +319 -0
  127. package/Resources/WebLibraries/three/addons/lights/SunShadowNode.js +312 -0
  128. package/Resources/WebLibraries/three/addons/lines/Line2.js +56 -0
  129. package/Resources/WebLibraries/three/addons/lines/LineGeometry.js +157 -0
  130. package/Resources/WebLibraries/three/addons/lines/LineMaterial.js +742 -0
  131. package/Resources/WebLibraries/three/addons/lines/LineSegments2.js +434 -0
  132. package/Resources/WebLibraries/three/addons/lines/LineSegmentsGeometry.js +298 -0
  133. package/Resources/WebLibraries/three/addons/lines/Wireframe.js +108 -0
  134. package/Resources/WebLibraries/three/addons/lines/WireframeGeometry2.js +49 -0
  135. package/Resources/WebLibraries/three/addons/lines/webgpu/Line2.js +46 -0
  136. package/Resources/WebLibraries/three/addons/lines/webgpu/LineSegments2.js +419 -0
  137. package/Resources/WebLibraries/three/addons/lines/webgpu/Wireframe.js +86 -0
  138. package/Resources/WebLibraries/three/addons/loaders/EXRLoader.js +3411 -0
  139. package/Resources/WebLibraries/three/addons/loaders/FBXLoader.js +4660 -0
  140. package/Resources/WebLibraries/three/addons/loaders/FontLoader.js +262 -0
  141. package/Resources/WebLibraries/three/addons/loaders/GLTFLoader.js +5006 -0
  142. package/Resources/WebLibraries/three/addons/loaders/HDRLoader.js +463 -0
  143. package/Resources/WebLibraries/three/addons/loaders/MTLLoader.js +601 -0
  144. package/Resources/WebLibraries/three/addons/loaders/OBJLoader.js +961 -0
  145. package/Resources/WebLibraries/three/addons/loaders/PLYLoader.js +992 -0
  146. package/Resources/WebLibraries/three/addons/loaders/RGBELoader.js +18 -0
  147. package/Resources/WebLibraries/three/addons/loaders/STLLoader.js +423 -0
  148. package/Resources/WebLibraries/three/addons/loaders/SVGLoader.js +3297 -0
  149. package/Resources/WebLibraries/three/addons/loaders/TGALoader.js +539 -0
  150. package/Resources/WebLibraries/three/addons/loaders/UltraHDRLoader.js +757 -0
  151. package/Resources/WebLibraries/three/addons/math/Capsule.js +159 -0
  152. package/Resources/WebLibraries/three/addons/math/ColorConverter.js +62 -0
  153. package/Resources/WebLibraries/three/addons/math/ColorSpaces.js +147 -0
  154. package/Resources/WebLibraries/three/addons/math/ConvexHull.js +1695 -0
  155. package/Resources/WebLibraries/three/addons/math/ImprovedNoise.js +88 -0
  156. package/Resources/WebLibraries/three/addons/math/Lut.js +317 -0
  157. package/Resources/WebLibraries/three/addons/math/MeshSurfaceSampler.js +315 -0
  158. package/Resources/WebLibraries/three/addons/math/OBB.js +535 -0
  159. package/Resources/WebLibraries/three/addons/math/Octree.js +825 -0
  160. package/Resources/WebLibraries/three/addons/math/SimplexNoise.js +470 -0
  161. package/Resources/WebLibraries/three/addons/misc/ConvexObjectBreaker.js +539 -0
  162. package/Resources/WebLibraries/three/addons/misc/GPUComputationRenderer.js +508 -0
  163. package/Resources/WebLibraries/three/addons/misc/Gyroscope.js +78 -0
  164. package/Resources/WebLibraries/three/addons/misc/MorphAnimMesh.js +119 -0
  165. package/Resources/WebLibraries/three/addons/misc/MorphBlendMesh.js +425 -0
  166. package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMap.js +370 -0
  167. package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMapGPU.js +322 -0
  168. package/Resources/WebLibraries/three/addons/misc/RollerCoaster.js +661 -0
  169. package/Resources/WebLibraries/three/addons/misc/Sculptor.js +1679 -0
  170. package/Resources/WebLibraries/three/addons/misc/SculptorMesh.js +1504 -0
  171. package/Resources/WebLibraries/three/addons/misc/SculptorTools.js +1180 -0
  172. package/Resources/WebLibraries/three/addons/misc/SculptorUtils.js +345 -0
  173. package/Resources/WebLibraries/three/addons/misc/TileCreasedNormalsPlugin.js +270 -0
  174. package/Resources/WebLibraries/three/addons/misc/TubePainter.js +611 -0
  175. package/Resources/WebLibraries/three/addons/misc/Volume.js +520 -0
  176. package/Resources/WebLibraries/three/addons/misc/VolumeSlice.js +275 -0
  177. package/Resources/WebLibraries/three/addons/modifiers/CurveModifier.js +374 -0
  178. package/Resources/WebLibraries/three/addons/modifiers/CurveModifierGPU.js +256 -0
  179. package/Resources/WebLibraries/three/addons/modifiers/EdgeSplitModifier.js +299 -0
  180. package/Resources/WebLibraries/three/addons/modifiers/TessellateModifier.js +340 -0
  181. package/Resources/WebLibraries/three/addons/objects/GroundedSkybox.js +69 -0
  182. package/Resources/WebLibraries/three/addons/objects/Lensflare.js +489 -0
  183. package/Resources/WebLibraries/three/addons/objects/LensflareMesh.js +376 -0
  184. package/Resources/WebLibraries/three/addons/objects/MarchingCubes.js +1261 -0
  185. package/Resources/WebLibraries/three/addons/objects/Reflector.js +390 -0
  186. package/Resources/WebLibraries/three/addons/objects/ReflectorForSSRPass.js +393 -0
  187. package/Resources/WebLibraries/three/addons/objects/Refractor.js +389 -0
  188. package/Resources/WebLibraries/three/addons/objects/ShadowMesh.js +130 -0
  189. package/Resources/WebLibraries/three/addons/objects/Sky.js +342 -0
  190. package/Resources/WebLibraries/three/addons/objects/SkyMesh.js +403 -0
  191. package/Resources/WebLibraries/three/addons/objects/Water.js +374 -0
  192. package/Resources/WebLibraries/three/addons/objects/Water2.js +403 -0
  193. package/Resources/WebLibraries/three/addons/objects/Water2Mesh.js +199 -0
  194. package/Resources/WebLibraries/three/addons/objects/WaterMesh.js +194 -0
  195. package/Resources/WebLibraries/three/addons/postprocessing/AfterimagePass.js +187 -0
  196. package/Resources/WebLibraries/three/addons/postprocessing/BloomPass.js +274 -0
  197. package/Resources/WebLibraries/three/addons/postprocessing/BokehPass.js +218 -0
  198. package/Resources/WebLibraries/three/addons/postprocessing/ClearPass.js +97 -0
  199. package/Resources/WebLibraries/three/addons/postprocessing/CubeTexturePass.js +146 -0
  200. package/Resources/WebLibraries/three/addons/postprocessing/DotScreenPass.js +114 -0
  201. package/Resources/WebLibraries/three/addons/postprocessing/EffectComposer.js +365 -0
  202. package/Resources/WebLibraries/three/addons/postprocessing/FXAAPass.js +40 -0
  203. package/Resources/WebLibraries/three/addons/postprocessing/FilmPass.js +113 -0
  204. package/Resources/WebLibraries/three/addons/postprocessing/GTAOPass.js +735 -0
  205. package/Resources/WebLibraries/three/addons/postprocessing/GlitchPass.js +177 -0
  206. package/Resources/WebLibraries/three/addons/postprocessing/HalftonePass.js +134 -0
  207. package/Resources/WebLibraries/three/addons/postprocessing/LUTPass.js +138 -0
  208. package/Resources/WebLibraries/three/addons/postprocessing/MaskPass.js +195 -0
  209. package/Resources/WebLibraries/three/addons/postprocessing/OutlinePass.js +776 -0
  210. package/Resources/WebLibraries/three/addons/postprocessing/OutputPass.js +148 -0
  211. package/Resources/WebLibraries/three/addons/postprocessing/Pass.js +191 -0
  212. package/Resources/WebLibraries/three/addons/postprocessing/RenderPass.js +193 -0
  213. package/Resources/WebLibraries/three/addons/postprocessing/RenderPixelatedPass.js +314 -0
  214. package/Resources/WebLibraries/three/addons/postprocessing/RenderTransitionPass.js +267 -0
  215. package/Resources/WebLibraries/three/addons/postprocessing/SAOPass.js +407 -0
  216. package/Resources/WebLibraries/three/addons/postprocessing/SMAAPass.js +230 -0
  217. package/Resources/WebLibraries/three/addons/postprocessing/SSAARenderPass.js +313 -0
  218. package/Resources/WebLibraries/three/addons/postprocessing/SSAOPass.js +527 -0
  219. package/Resources/WebLibraries/three/addons/postprocessing/SSRPass.js +858 -0
  220. package/Resources/WebLibraries/three/addons/postprocessing/SavePass.js +132 -0
  221. package/Resources/WebLibraries/three/addons/postprocessing/ShaderPass.js +135 -0
  222. package/Resources/WebLibraries/three/addons/postprocessing/TAARenderPass.js +243 -0
  223. package/Resources/WebLibraries/three/addons/postprocessing/TexturePass.js +131 -0
  224. package/Resources/WebLibraries/three/addons/postprocessing/UnrealBloomPass.js +541 -0
  225. package/Resources/WebLibraries/three/addons/shaders/ACESFilmicToneMappingShader.js +96 -0
  226. package/Resources/WebLibraries/three/addons/shaders/AfterimageShader.js +63 -0
  227. package/Resources/WebLibraries/three/addons/shaders/BasicShader.js +36 -0
  228. package/Resources/WebLibraries/three/addons/shaders/BleachBypassShader.js +68 -0
  229. package/Resources/WebLibraries/three/addons/shaders/BlendShader.js +56 -0
  230. package/Resources/WebLibraries/three/addons/shaders/BokehShader.js +151 -0
  231. package/Resources/WebLibraries/three/addons/shaders/BokehShader2.js +404 -0
  232. package/Resources/WebLibraries/three/addons/shaders/BrightnessContrastShader.js +62 -0
  233. package/Resources/WebLibraries/three/addons/shaders/ColorCorrectionShader.js +59 -0
  234. package/Resources/WebLibraries/three/addons/shaders/ColorifyShader.js +57 -0
  235. package/Resources/WebLibraries/three/addons/shaders/ConvolutionShader.js +74 -0
  236. package/Resources/WebLibraries/three/addons/shaders/CopyShader.js +52 -0
  237. package/Resources/WebLibraries/three/addons/shaders/DOFMipMapShader.js +63 -0
  238. package/Resources/WebLibraries/three/addons/shaders/DepthLimitedBlurShader.js +183 -0
  239. package/Resources/WebLibraries/three/addons/shaders/DigitalGlitch.js +104 -0
  240. package/Resources/WebLibraries/three/addons/shaders/DotScreenShader.js +75 -0
  241. package/Resources/WebLibraries/three/addons/shaders/ExposureShader.js +51 -0
  242. package/Resources/WebLibraries/three/addons/shaders/FXAAShader.js +298 -0
  243. package/Resources/WebLibraries/three/addons/shaders/FilmShader.js +73 -0
  244. package/Resources/WebLibraries/three/addons/shaders/FocusShader.js +94 -0
  245. package/Resources/WebLibraries/three/addons/shaders/FreiChenShader.js +103 -0
  246. package/Resources/WebLibraries/three/addons/shaders/GTAOShader.js +437 -0
  247. package/Resources/WebLibraries/three/addons/shaders/GammaCorrectionShader.js +52 -0
  248. package/Resources/WebLibraries/three/addons/shaders/HalftoneShader.js +332 -0
  249. package/Resources/WebLibraries/three/addons/shaders/HorizontalBlurShader.js +68 -0
  250. package/Resources/WebLibraries/three/addons/shaders/HorizontalTiltShiftShader.js +70 -0
  251. package/Resources/WebLibraries/three/addons/shaders/HueSaturationShader.js +74 -0
  252. package/Resources/WebLibraries/three/addons/shaders/KaleidoShader.js +65 -0
  253. package/Resources/WebLibraries/three/addons/shaders/LuminosityHighPassShader.js +68 -0
  254. package/Resources/WebLibraries/three/addons/shaders/LuminosityShader.js +54 -0
  255. package/Resources/WebLibraries/three/addons/shaders/MirrorShader.js +62 -0
  256. package/Resources/WebLibraries/three/addons/shaders/NormalMapShader.js +60 -0
  257. package/Resources/WebLibraries/three/addons/shaders/OutputShader.js +103 -0
  258. package/Resources/WebLibraries/three/addons/shaders/PoissonDenoiseShader.js +230 -0
  259. package/Resources/WebLibraries/three/addons/shaders/RGBShiftShader.js +61 -0
  260. package/Resources/WebLibraries/three/addons/shaders/SAOShader.js +201 -0
  261. package/Resources/WebLibraries/three/addons/shaders/SMAAShader.js +489 -0
  262. package/Resources/WebLibraries/three/addons/shaders/SSAOShader.js +331 -0
  263. package/Resources/WebLibraries/three/addons/shaders/SSRShader.js +396 -0
  264. package/Resources/WebLibraries/three/addons/shaders/SepiaShader.js +57 -0
  265. package/Resources/WebLibraries/three/addons/shaders/SobelOperatorShader.js +98 -0
  266. package/Resources/WebLibraries/three/addons/shaders/SubsurfaceScatteringShader.js +95 -0
  267. package/Resources/WebLibraries/three/addons/shaders/TechnicolorShader.js +51 -0
  268. package/Resources/WebLibraries/three/addons/shaders/ToonShader.js +349 -0
  269. package/Resources/WebLibraries/three/addons/shaders/TriangleBlurShader.js +79 -0
  270. package/Resources/WebLibraries/three/addons/shaders/UnpackDepthRGBAShader.js +60 -0
  271. package/Resources/WebLibraries/three/addons/shaders/VelocityShader.js +137 -0
  272. package/Resources/WebLibraries/three/addons/shaders/VerticalBlurShader.js +66 -0
  273. package/Resources/WebLibraries/three/addons/shaders/VerticalTiltShiftShader.js +70 -0
  274. package/Resources/WebLibraries/three/addons/shaders/VignetteShader.js +56 -0
  275. package/Resources/WebLibraries/three/addons/shaders/VolumeShader.js +285 -0
  276. package/Resources/WebLibraries/three/addons/shaders/WaterRefractionShader.js +106 -0
  277. package/Resources/WebLibraries/three/addons/textures/FlakesTexture.js +54 -0
  278. package/Resources/WebLibraries/three/addons/tsl/WebGLNodesHandler.js +607 -0
  279. package/Resources/WebLibraries/three/addons/tsl/display/AfterImageNode.js +256 -0
  280. package/Resources/WebLibraries/three/addons/tsl/display/AnaglyphPassNode.js +550 -0
  281. package/Resources/WebLibraries/three/addons/tsl/display/BilateralBlurNode.js +377 -0
  282. package/Resources/WebLibraries/three/addons/tsl/display/BleachBypass.js +33 -0
  283. package/Resources/WebLibraries/three/addons/tsl/display/BloomNode.js +599 -0
  284. package/Resources/WebLibraries/three/addons/tsl/display/CRT.js +150 -0
  285. package/Resources/WebLibraries/three/addons/tsl/display/ChromaticAberrationNode.js +163 -0
  286. package/Resources/WebLibraries/three/addons/tsl/display/DenoiseNode.js +354 -0
  287. package/Resources/WebLibraries/three/addons/tsl/display/DepthOfFieldNode.js +572 -0
  288. package/Resources/WebLibraries/three/addons/tsl/display/DotScreenNode.js +104 -0
  289. package/Resources/WebLibraries/three/addons/tsl/display/FSR1Node.js +481 -0
  290. package/Resources/WebLibraries/three/addons/tsl/display/FXAANode.js +357 -0
  291. package/Resources/WebLibraries/three/addons/tsl/display/FilmNode.js +101 -0
  292. package/Resources/WebLibraries/three/addons/tsl/display/GTAONode.js +727 -0
  293. package/Resources/WebLibraries/three/addons/tsl/display/GaussianBlurNode.js +412 -0
  294. package/Resources/WebLibraries/three/addons/tsl/display/GodraysNode.js +604 -0
  295. package/Resources/WebLibraries/three/addons/tsl/display/ImportanceSampledEnvironment.js +564 -0
  296. package/Resources/WebLibraries/three/addons/tsl/display/LensflareNode.js +282 -0
  297. package/Resources/WebLibraries/three/addons/tsl/display/Lut3DNode.js +109 -0
  298. package/Resources/WebLibraries/three/addons/tsl/display/MotionBlur.js +33 -0
  299. package/Resources/WebLibraries/three/addons/tsl/display/OITPassNode.js +341 -0
  300. package/Resources/WebLibraries/three/addons/tsl/display/OutlineNode.js +916 -0
  301. package/Resources/WebLibraries/three/addons/tsl/display/ParallaxBarrierPassNode.js +90 -0
  302. package/Resources/WebLibraries/three/addons/tsl/display/PixelationPassNode.js +227 -0
  303. package/Resources/WebLibraries/three/addons/tsl/display/RGBShiftNode.js +96 -0
  304. package/Resources/WebLibraries/three/addons/tsl/display/RecurrentDenoiseNode.js +812 -0
  305. package/Resources/WebLibraries/three/addons/tsl/display/RetroPassNode.js +263 -0
  306. package/Resources/WebLibraries/three/addons/tsl/display/SMAANode.js +729 -0
  307. package/Resources/WebLibraries/three/addons/tsl/display/SSAAPassNode.js +344 -0
  308. package/Resources/WebLibraries/three/addons/tsl/display/SSAONode.js +422 -0
  309. package/Resources/WebLibraries/three/addons/tsl/display/SSGINode.js +698 -0
  310. package/Resources/WebLibraries/three/addons/tsl/display/SSRNode.js +1430 -0
  311. package/Resources/WebLibraries/three/addons/tsl/display/SSSNode.js +479 -0
  312. package/Resources/WebLibraries/three/addons/tsl/display/Sepia.js +24 -0
  313. package/Resources/WebLibraries/three/addons/tsl/display/Shape.js +29 -0
  314. package/Resources/WebLibraries/three/addons/tsl/display/SharpenNode.js +284 -0
  315. package/Resources/WebLibraries/three/addons/tsl/display/SobelOperatorNode.js +168 -0
  316. package/Resources/WebLibraries/three/addons/tsl/display/StereoCompositePassNode.js +190 -0
  317. package/Resources/WebLibraries/three/addons/tsl/display/StereoPassNode.js +117 -0
  318. package/Resources/WebLibraries/three/addons/tsl/display/TAAUNode.js +700 -0
  319. package/Resources/WebLibraries/three/addons/tsl/display/TRAANode.js +609 -0
  320. package/Resources/WebLibraries/three/addons/tsl/display/TemporalReprojectNode.js +1024 -0
  321. package/Resources/WebLibraries/three/addons/tsl/display/TransitionNode.js +141 -0
  322. package/Resources/WebLibraries/three/addons/tsl/display/boxBlur.js +65 -0
  323. package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlend.js +80 -0
  324. package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlur.js +63 -0
  325. package/Resources/WebLibraries/three/addons/tsl/display/hashBlur.js +55 -0
  326. package/Resources/WebLibraries/three/addons/tsl/display/lensDirt.js +30 -0
  327. package/Resources/WebLibraries/three/addons/tsl/display/radialBlur.js +68 -0
  328. package/Resources/WebLibraries/three/addons/tsl/lighting/ClusteredLightsNode.js +994 -0
  329. package/Resources/WebLibraries/three/addons/tsl/lighting/DynamicLightsNode.js +201 -0
  330. package/Resources/WebLibraries/three/addons/tsl/lighting/LightProbeGridNode.js +183 -0
  331. package/Resources/WebLibraries/three/addons/tsl/lighting/data/AmbientLightDataNode.js +67 -0
  332. package/Resources/WebLibraries/three/addons/tsl/lighting/data/DirectionalLightDataNode.js +117 -0
  333. package/Resources/WebLibraries/three/addons/tsl/lighting/data/HemisphereLightDataNode.js +105 -0
  334. package/Resources/WebLibraries/three/addons/tsl/lighting/data/PointLightDataNode.js +140 -0
  335. package/Resources/WebLibraries/three/addons/tsl/lighting/data/SpotLightDataNode.js +167 -0
  336. package/Resources/WebLibraries/three/addons/tsl/math/Bayer.js +84 -0
  337. package/Resources/WebLibraries/three/addons/tsl/math/curlNoise.js +107 -0
  338. package/Resources/WebLibraries/three/addons/tsl/math/voronoiNoise.js +112 -0
  339. package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNode.js +542 -0
  340. package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNodeHelper.js +212 -0
  341. package/Resources/WebLibraries/three/addons/tsl/utils/GroundedSkybox.js +62 -0
  342. package/Resources/WebLibraries/three/addons/tsl/utils/RNoise.js +51 -0
  343. package/Resources/WebLibraries/three/addons/tsl/utils/Raymarching.js +70 -0
  344. package/Resources/WebLibraries/three/addons/tsl/utils/SoftParticles.js +53 -0
  345. package/Resources/WebLibraries/three/addons/tsl/utils/SpecularHelpers.js +302 -0
  346. package/Resources/WebLibraries/three/addons/tsl/utils/TAAUtils.js +184 -0
  347. package/Resources/WebLibraries/three/addons/utils/BufferGeometryUtils.js +1523 -0
  348. package/Resources/WebLibraries/three/addons/utils/CameraUtils.js +82 -0
  349. package/Resources/WebLibraries/three/addons/utils/ColorUtils.js +76 -0
  350. package/Resources/WebLibraries/three/addons/utils/GaussianSplatUtils.js +229 -0
  351. package/Resources/WebLibraries/three/addons/utils/GeometryCompressionUtils.js +547 -0
  352. package/Resources/WebLibraries/three/addons/utils/GeometryUtils.js +226 -0
  353. package/Resources/WebLibraries/three/addons/utils/LDrawUtils.js +211 -0
  354. package/Resources/WebLibraries/three/addons/utils/SceneOptimizer.js +459 -0
  355. package/Resources/WebLibraries/three/addons/utils/SceneUtils.js +363 -0
  356. package/Resources/WebLibraries/three/addons/utils/ShadowMapViewer.js +244 -0
  357. package/Resources/WebLibraries/three/addons/utils/ShadowMapViewerGPU.js +233 -0
  358. package/Resources/WebLibraries/three/addons/utils/SkeletonUtils.js +496 -0
  359. package/Resources/WebLibraries/three/addons/utils/SortUtils.js +175 -0
  360. package/Resources/WebLibraries/three/addons/utils/UVsDebug.js +173 -0
  361. package/Resources/WebLibraries/three/addons/utils/WebGLTextureUtils.js +115 -0
  362. package/Resources/WebLibraries/three/addons/utils/WebGPUTextureUtils.js +81 -0
  363. package/Resources/WebLibraries/three/addons/utils/WorkerPool.js +167 -0
  364. package/Resources/WebLibraries/three/addons/utils/unwrapUVs.js +865 -0
  365. package/Resources/WebLibraries/three/three.core.js +61162 -0
  366. package/Resources/WebLibraries/three/three.module.js +19537 -0
  367. package/Resources/WebLibraries/three/three.tsl.js +41903 -0
  368. package/Resources/WebLibraries/three/three.webgpu.js +53714 -0
  369. package/Resources/skills/2d-game/SKILL.md +305 -0
  370. package/Resources/skills/3d-game/SKILL.md +274 -0
  371. package/Resources/skills/accounts/SKILL.md +41 -0
  372. package/Resources/skills/android-design/SKILL.md +159 -0
  373. package/Resources/skills/app-ai/SKILL.md +154 -0
  374. package/Resources/skills/app-intents/SKILL.md +31 -0
  375. package/Resources/skills/app-kinds/SKILL.md +122 -0
  376. package/Resources/skills/apple-watch/SKILL.md +43 -0
  377. package/Resources/skills/assets/SKILL.md +183 -0
  378. package/Resources/skills/building-blocks/SKILL.md +97 -0
  379. package/Resources/skills/device-control/SKILL.md +56 -0
  380. package/Resources/skills/device-integrations/SKILL.md +278 -0
  381. package/Resources/skills/finder-files/SKILL.md +19 -0
  382. package/Resources/skills/game/SKILL.md +414 -0
  383. package/Resources/skills/game-3d/SKILL.md +12 -0
  384. package/Resources/skills/game-art/SKILL.md +11 -0
  385. package/Resources/skills/game-feel/SKILL.md +13 -0
  386. package/Resources/skills/game-levels/SKILL.md +12 -0
  387. package/Resources/skills/game-live/SKILL.md +12 -0
  388. package/Resources/skills/game-physics/SKILL.md +13 -0
  389. package/Resources/skills/game-playtest/SKILL.md +26 -0
  390. package/Resources/skills/game-ui/SKILL.md +278 -0
  391. package/Resources/skills/github-projects/SKILL.md +59 -0
  392. package/Resources/skills/icloud-sync/SKILL.md +30 -0
  393. package/Resources/skills/iphone-hardware/SKILL.md +57 -0
  394. package/Resources/skills/iphone-widgets/SKILL.md +53 -0
  395. package/Resources/skills/lg-developer-mode/SKILL.md +152 -0
  396. package/Resources/skills/mac-widgets/SKILL.md +60 -0
  397. package/Resources/skills/maps/SKILL.md +8 -0
  398. package/Resources/skills/menu-bar/SKILL.md +36 -0
  399. package/Resources/skills/more-apps/SKILL.md +53 -0
  400. package/Resources/skills/phone-controllers/SKILL.md +79 -0
  401. package/Resources/skills/phone-pages/SKILL.md +173 -0
  402. package/Resources/skills/roku-developer-mode/SKILL.md +106 -0
  403. package/Resources/skills/scene-3d/SKILL.md +27 -0
  404. package/Resources/skills/scripting/SKILL.md +17 -0
  405. package/Resources/skills/share-extension/SKILL.md +22 -0
  406. package/Resources/skills/tv-design/SKILL.md +72 -0
  407. package/Resources/skills/web-app/SKILL.md +136 -0
  408. package/Resources/skills/web-game/SKILL.md +95 -0
  409. package/Resources/skills/web-or-native/SKILL.md +103 -0
  410. package/Resources/skills/wish-links/SKILL.md +156 -0
  411. package/THIRD_PARTY_NOTICES.md +170 -0
  412. package/cli/android.mjs +941 -0
  413. package/cli/browser.mjs +268 -0
  414. package/cli/calls.mjs +390 -0
  415. package/cli/dev.mjs +773 -0
  416. package/cli/devices.mjs +984 -0
  417. package/cli/lamp.mjs +1016 -0
  418. package/cli/lampapp.mjs +332 -0
  419. package/cli/lamps/android-host/LampPageGateway.kt +345 -0
  420. package/cli/lamps/android-host/app/build.gradle.kts +40 -0
  421. package/cli/lamps/android-host/build.gradle.kts +4 -0
  422. package/cli/lamps/android-host/game/AndroidManifest.xml +33 -0
  423. package/cli/lamps/android-host/game/MainActivity.kt +173 -0
  424. package/cli/lamps/android-host/gradle/libs.versions.toml +39 -0
  425. package/cli/lamps/android-host/gradle.properties +8 -0
  426. package/cli/lamps/android-host/page/AndroidManifest.xml +35 -0
  427. package/cli/lamps/android-host/page/MainActivity.kt +193 -0
  428. package/cli/lamps/android-host/settings.gradle.kts +30 -0
  429. package/cli/lamps/android-host/tools.json +43 -0
  430. package/cli/lamps/lamp-controllers.js +2 -0
  431. package/cli/lamps/lamp-for-games.js +6863 -0
  432. package/cli/lamps/lamp.js +7023 -0
  433. package/cli/lamps/mac-starter/.lamp/meta.json +1 -0
  434. package/cli/lamps/mac-starter/APP.md +12 -0
  435. package/cli/lamps/mac-starter/Package.swift +8 -0
  436. package/cli/lamps/mac-starter/Sources/App.swift +11 -0
  437. package/cli/lamps/mac-starter/Sources/ContentView.swift +17 -0
  438. package/cli/lamps/mac-starter/Sources/LampSupport.swift +18097 -0
  439. package/cli/lamps/mac-starter/build.sh +336 -0
  440. package/cli/lamps/mac-starter/gitignore +3 -0
  441. package/cli/lamps/mac-starter/lamp-starter.json +6 -0
  442. package/cli/lamps/web-starter/APP.md +8 -0
  443. package/cli/lamps/web-starter/app.js +1 -0
  444. package/cli/lamps/web-starter/index.html +17 -0
  445. package/cli/lamps/web-starter/lamp-starter.json +5 -0
  446. package/cli/lamps/web-starter/lamp.js +7023 -0
  447. package/cli/lamps/web-starter/style.css +25 -0
  448. package/cli/link.mjs +138 -0
  449. package/cli/mac.mjs +621 -0
  450. package/cli/mdns.mjs +205 -0
  451. package/cli/msix.mjs +413 -0
  452. package/cli/network.mjs +209 -0
  453. package/cli/outside.mjs +140 -0
  454. package/cli/page.js +165 -0
  455. package/cli/place.mjs +298 -0
  456. package/cli/png.mjs +184 -0
  457. package/cli/share.mjs +202 -0
  458. package/cli/skill/SKILL.md +255 -0
  459. package/cli/skills.mjs +71 -0
  460. package/cli/state.mjs +173 -0
  461. package/cli/update.mjs +57 -0
  462. package/package.json +20 -4
  463. package/site/lib/quota.js +59 -0
  464. package/site/lib/shared-wishes.js +996 -0
@@ -0,0 +1,994 @@
1
+ import { DataTexture, FloatType, RGBAFormat, Vector2, Vector3, LightsNode, NodeUpdateType, NodeUtils, PointLightNode, SpotLightNode } from 'three/webgpu';
2
+
3
+ import {
4
+ instancedArray, nodeProxy, int, float, vec3, vec4, ivec2, ivec4, uniform, Break, Loop, positionView,
5
+ Fn, If, textureLoad, instanceIndex, screenCoordinate, directPointLight,
6
+ renderGroup,
7
+ min, max, pow, log, clamp, dot, smoothstep
8
+ } from 'three/tsl';
9
+
10
+ const _vector3 = /*@__PURE__*/ new Vector3();
11
+ const _direction = /*@__PURE__*/ new Vector3();
12
+ const _targetPosition = /*@__PURE__*/ new Vector3();
13
+ const _size = /*@__PURE__*/ new Vector2();
14
+
15
+ // light data texture rows
16
+
17
+ const POSITION_ROW = 0; // world position, cutoff distance
18
+ const COLOR_ROW = 1; // color * intensity, decay
19
+ const SPOT_ROW = 2; // scaled world spot direction, scaled cone cosine
20
+ const BOUNDS_ROW = 3; // world bounding sphere center, radius ( negative if unbounded )
21
+ const ROWS = 4;
22
+
23
+ /**
24
+ * A custom version of `LightsNode` implementing Forward+ clustered shading:
25
+ * the view frustum is subdivided into a 3D grid of clusters (X × Y screen tiles
26
+ * times an exponentially-spaced set of Z depth slices), and each cluster holds
27
+ * only the point and spot lights whose bounding spheres intersect it. At shading time each fragment
28
+ * looks up its cluster and loops over just that cluster's lights. Unlike 2D tiled
29
+ * lighting, clustered shading culls lights that share screen pixels but lie at
30
+ * different depths — suitable for 3D scenes with real depth complexity.
31
+ *
32
+ * @augments LightsNode
33
+ * @three_import import { clusteredLights } from 'three/addons/tsl/lighting/ClusteredLightsNode.js';
34
+ */
35
+ class ClusteredLightsNode extends LightsNode {
36
+
37
+ static get type() {
38
+
39
+ return 'ClusteredLightsNode';
40
+
41
+ }
42
+
43
+ /**
44
+ * Constructs a new clustered lights node.
45
+ *
46
+ * @param {number} [maxLights=1024] - Maximum number of point and spot lights.
47
+ * @param {number} [tileSize=32] - Screen tile size in pixels (cluster XY size).
48
+ * @param {number} [zSlices=24] - Number of exponential depth slices.
49
+ * @param {number} [maxLightsPerCluster=64] - Per-cluster light-list capacity.
50
+ */
51
+ constructor( maxLights = 1024, tileSize = 32, zSlices = 24, maxLightsPerCluster = 64 ) {
52
+
53
+ super();
54
+
55
+ /**
56
+ * This flag can be used for type testing.
57
+ *
58
+ * @type {boolean}
59
+ * @readonly
60
+ * @default true
61
+ */
62
+ this.isClusteredLightsNode = true;
63
+
64
+ this.materialLights = [];
65
+ this.clusteredLights = [];
66
+
67
+ this.maxLights = maxLights;
68
+ this.tileSize = tileSize;
69
+ this.zSlices = zSlices;
70
+ this.maxLightsPerCluster = maxLightsPerCluster;
71
+
72
+ this._chunksPerCluster = Math.ceil( maxLightsPerCluster / 4 );
73
+
74
+ this._bufferSize = null;
75
+ this._isWebGLBackend = false;
76
+ this._needsRebuild = false;
77
+ this._invocationsPerCluster = 1;
78
+ this._lightIndexes = null;
79
+ this._renderer = null;
80
+ this._screenClusterIndex = null;
81
+ this._compute = null;
82
+
83
+ const lightsData = new Float32Array( maxLights * 4 * ROWS );
84
+ this._lightsTexture = new DataTexture( lightsData, maxLights, ROWS, RGBAFormat, FloatType );
85
+
86
+ // Per Z-slice light range for Z-culling (CPU-sorted, uploaded each frame)
87
+
88
+ this._zSliceRangesData = new Float32Array( zSlices * 4 );
89
+ this._zSliceRangesTexture = new DataTexture( this._zSliceRangesData, zSlices, 1, RGBAFormat, FloatType );
90
+
91
+ this._lightViewZ = new Float32Array( maxLights );
92
+ this._lightSortOrder = [];
93
+
94
+ this._lightsCount = uniform( 0, 'int' );
95
+
96
+ // Render-group uniforms: shared between compute and fragment passes,
97
+ // updated manually each frame in updateBefore (compute lacks a camera context).
98
+ this._cameraNear = uniform( 0 ).setName( 'clusteredCameraNear' ).setGroup( renderGroup );
99
+ this._cameraFar = uniform( 0 ).setName( 'clusteredCameraFar' ).setGroup( renderGroup );
100
+ this._cameraViewMatrix = uniform( 'mat4' ).setName( 'clusteredCameraViewMatrix' ).setGroup( renderGroup );
101
+ this._cameraProjectionMatrix = uniform( 'mat4' ).setName( 'clusteredCameraProjectionMatrix' ).setGroup( renderGroup );
102
+
103
+ this._gridDimensions = uniform( new Vector2() );
104
+
105
+ this.updateBeforeType = NodeUpdateType.RENDER;
106
+
107
+ }
108
+
109
+ /**
110
+ * Overwrites the default {@link LightsNode#customCacheKey} implementation by
111
+ * including the node identity and resource version into the cache key.
112
+ *
113
+ * @return {number} The custom cache key.
114
+ */
115
+ customCacheKey() {
116
+
117
+ // First use allocates the grid after material cache keys have been computed.
118
+ // Keep that allocation stable, but never share bindings between lights nodes.
119
+ return NodeUtils.hash( this.id, this.version, super.customCacheKey() );
120
+
121
+ }
122
+
123
+ /**
124
+ * Updates the light data and the light ranges of the depth slices.
125
+ *
126
+ * @private
127
+ * @param {Camera} camera - The camera.
128
+ */
129
+ _updateLightsTexture( camera ) {
130
+
131
+ const { _lightsTexture: lightsTexture, clusteredLights } = this;
132
+
133
+ const data = lightsTexture.image.data;
134
+ const lineSize = lightsTexture.image.width * 4;
135
+ const count = Math.min( clusteredLights.length, this.maxLights );
136
+
137
+ this._lightsCount.value = count;
138
+
139
+ // Sort lights by the view-space depth of their bounding spheres for Z-culling
140
+
141
+ const viewZ = this._lightViewZ;
142
+ const order = this._lightSortOrder;
143
+
144
+ for ( let i = 0; i < count; i ++ ) {
145
+
146
+ this._getBoundingSphereCenter( clusteredLights[ i ], _vector3 );
147
+ _vector3.applyMatrix4( camera.matrixWorldInverse );
148
+ viewZ[ i ] = _vector3.z;
149
+ order[ i ] = i;
150
+
151
+ }
152
+
153
+ order.length = count;
154
+ order.sort( ( a, b ) => viewZ[ a ] - viewZ[ b ] );
155
+
156
+ // Write sorted lights to texture
157
+
158
+ for ( let i = 0; i < count; i ++ ) {
159
+
160
+ const light = clusteredLights[ order[ i ] ];
161
+
162
+ const offset = i * 4;
163
+
164
+ _vector3.setFromMatrixPosition( light.matrixWorld );
165
+
166
+ let rowOffset = lineSize * POSITION_ROW + offset;
167
+
168
+ data[ rowOffset + 0 ] = _vector3.x;
169
+ data[ rowOffset + 1 ] = _vector3.y;
170
+ data[ rowOffset + 2 ] = _vector3.z;
171
+ data[ rowOffset + 3 ] = light.distance;
172
+
173
+ rowOffset = lineSize * COLOR_ROW + offset;
174
+
175
+ data[ rowOffset + 0 ] = light.color.r * light.intensity;
176
+ data[ rowOffset + 1 ] = light.color.g * light.intensity;
177
+ data[ rowOffset + 2 ] = light.color.b * light.intensity;
178
+ data[ rowOffset + 3 ] = light.decay;
179
+
180
+ // The spot attenuation smoothstep( coneCos, penumbraCos, dot( L, direction ) ) is stored
181
+ // as smoothstep( 0, 1, dot( L, direction * scale ) - coneCos * scale ) with
182
+ // scale = 1 / ( penumbraCos - coneCos ). Point lights store a constant attenuation of 1.
183
+
184
+ rowOffset = lineSize * SPOT_ROW + offset;
185
+
186
+ if ( light.isSpotLight === true ) {
187
+
188
+ const coneCos = Math.cos( light.angle );
189
+ const penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
190
+ const scale = 1 / Math.max( penumbraCos - coneCos, 1e-4 );
191
+
192
+ this._getSpotDirection( light, _direction ).multiplyScalar( scale );
193
+
194
+ data[ rowOffset + 0 ] = _direction.x;
195
+ data[ rowOffset + 1 ] = _direction.y;
196
+ data[ rowOffset + 2 ] = _direction.z;
197
+ data[ rowOffset + 3 ] = coneCos * scale;
198
+
199
+ } else {
200
+
201
+ data[ rowOffset + 0 ] = 0;
202
+ data[ rowOffset + 1 ] = 0;
203
+ data[ rowOffset + 2 ] = 0;
204
+ data[ rowOffset + 3 ] = - 1;
205
+
206
+ }
207
+
208
+ this._getBoundingSphereCenter( light, _vector3 );
209
+
210
+ rowOffset = lineSize * BOUNDS_ROW + offset;
211
+
212
+ data[ rowOffset + 0 ] = _vector3.x;
213
+ data[ rowOffset + 1 ] = _vector3.y;
214
+ data[ rowOffset + 2 ] = _vector3.z;
215
+ data[ rowOffset + 3 ] = this._getBoundingSphereRadius( light );
216
+
217
+ }
218
+
219
+ lightsTexture.needsUpdate = true;
220
+
221
+ // Compute per Z-slice light ranges
222
+
223
+ const zRanges = this._zSliceRangesData;
224
+
225
+ const near = camera.near;
226
+ const far = camera.far;
227
+ const NZ = this.zSlices;
228
+
229
+ for ( let z = 0; z < NZ; z ++ ) {
230
+
231
+ // Exponential Z-slice bounds (view-space, negative values)
232
+ const sliceNear = - ( near * Math.pow( far / near, z / NZ ) );
233
+ const sliceFar = - ( near * Math.pow( far / near, ( z + 1 ) / NZ ) );
234
+
235
+ let rangeStart = count;
236
+ let rangeEnd = 0;
237
+
238
+ for ( let i = 0; i < count; i ++ ) {
239
+
240
+ const vz = viewZ[ order[ i ] ];
241
+ const r = data[ lineSize * BOUNDS_ROW + i * 4 + 3 ];
242
+ const radius = r >= 0 ? r : far;
243
+
244
+ // Bounding sphere Z: [vz - radius, vz + radius]
245
+ // Slice Z: [sliceFar, sliceNear] (both negative, sliceFar < sliceNear)
246
+ if ( vz + radius >= sliceFar && vz - radius <= sliceNear ) {
247
+
248
+ if ( i < rangeStart ) rangeStart = i;
249
+ if ( i + 1 > rangeEnd ) rangeEnd = i + 1;
250
+
251
+ }
252
+
253
+ }
254
+
255
+ if ( rangeStart >= count ) {
256
+
257
+ rangeStart = 0;
258
+ rangeEnd = 0;
259
+
260
+ }
261
+
262
+ zRanges[ z * 4 ] = rangeStart;
263
+ zRanges[ z * 4 + 1 ] = rangeEnd;
264
+
265
+ }
266
+
267
+ this._zSliceRangesTexture.needsUpdate = true;
268
+
269
+ }
270
+
271
+ /**
272
+ * Returns the normalized world-space direction pointing from the spot light's
273
+ * target to the spot light.
274
+ *
275
+ * @private
276
+ * @param {SpotLight} light - The spot light.
277
+ * @param {Vector3} target - The target vector.
278
+ * @return {Vector3} The direction.
279
+ */
280
+ _getSpotDirection( light, target ) {
281
+
282
+ _targetPosition.setFromMatrixPosition( light.target.matrixWorld );
283
+
284
+ return target.setFromMatrixPosition( light.matrixWorld ).sub( _targetPosition ).normalize();
285
+
286
+ }
287
+
288
+ /**
289
+ * Returns the world-space center of the light's bounding sphere. For spot lights,
290
+ * this is the center of the smallest sphere enclosing the cone.
291
+ *
292
+ * @private
293
+ * @param {PointLight|SpotLight} light - The light.
294
+ * @param {Vector3} target - The target vector.
295
+ * @return {Vector3} The bounding sphere center.
296
+ */
297
+ _getBoundingSphereCenter( light, target ) {
298
+
299
+ target.setFromMatrixPosition( light.matrixWorld );
300
+
301
+ if ( light.isSpotLight === true && light.distance > 0 ) {
302
+
303
+ const angle = Math.min( light.angle, Math.PI / 2 );
304
+ const offset = angle > Math.PI / 4 ? light.distance * Math.cos( angle ) : light.distance / ( 2 * Math.cos( angle ) );
305
+
306
+ // _getSpotDirection() points away from the cone, so step backwards
307
+
308
+ target.addScaledVector( this._getSpotDirection( light, _direction ), - offset );
309
+
310
+ }
311
+
312
+ return target;
313
+
314
+ }
315
+
316
+ /**
317
+ * Returns the radius of the light's bounding sphere.
318
+ *
319
+ * @private
320
+ * @param {PointLight|SpotLight} light - The light.
321
+ * @return {number} The bounding sphere radius. `-1` if the light has no cutoff distance.
322
+ */
323
+ _getBoundingSphereRadius( light ) {
324
+
325
+ if ( light.distance <= 0 ) return - 1;
326
+
327
+ if ( light.isSpotLight === true ) {
328
+
329
+ const angle = Math.min( light.angle, Math.PI / 2 );
330
+
331
+ return angle > Math.PI / 4 ? light.distance * Math.sin( angle ) : light.distance / ( 2 * Math.cos( angle ) );
332
+
333
+ }
334
+
335
+ return light.distance;
336
+
337
+ }
338
+
339
+ /**
340
+ * Updates the light data and assigns the lights to the clusters.
341
+ *
342
+ * @param {NodeFrame} frame - A reference to the current node frame.
343
+ */
344
+ updateBefore( frame ) {
345
+
346
+ const { renderer, camera } = frame;
347
+
348
+ this._initGrid( renderer );
349
+
350
+ this._updateLightsTexture( camera );
351
+
352
+ this._cameraNear.value = camera.near;
353
+ this._cameraFar.value = camera.far;
354
+ this._cameraViewMatrix.value = camera.matrixWorldInverse;
355
+ this._cameraProjectionMatrix.value = camera.projectionMatrix;
356
+
357
+ renderer.compute( this._compute );
358
+
359
+ }
360
+
361
+ /**
362
+ * Configures this node with an array of lights. Point and spot lights without
363
+ * shadows are clustered (except lights with a `colorNode`, spot lights with a
364
+ * projected `map` and light types with their own light node, like `IESSpotLight`
365
+ * or `ProjectorLight`), all other lights use the default lighting.
366
+ *
367
+ * @param {Array<Light>} lights - An array of lights.
368
+ * @return {ClusteredLightsNode} A reference to this node.
369
+ */
370
+ setLights( lights ) {
371
+
372
+ const { clusteredLights, materialLights } = this;
373
+
374
+ let materialIndex = 0;
375
+ let clusteredIndex = 0;
376
+
377
+ for ( const light of lights ) {
378
+
379
+ if ( this._isClusteredLight( light ) ) {
380
+
381
+ clusteredLights[ clusteredIndex ++ ] = light;
382
+
383
+ } else {
384
+
385
+ materialLights[ materialIndex ++ ] = light;
386
+
387
+ }
388
+
389
+ }
390
+
391
+ materialLights.length = materialIndex;
392
+ clusteredLights.length = clusteredIndex;
393
+
394
+ return super.setLights( lights );
395
+
396
+ }
397
+
398
+ /**
399
+ * Returns `true` if the given light can be clustered.
400
+ *
401
+ * @private
402
+ * @param {Light} light - The light.
403
+ * @return {boolean} Whether the light is clustered or not.
404
+ */
405
+ _isClusteredLight( light ) {
406
+
407
+ // Shadows, color nodes (any light) and projected maps (spot lights) are not supported.
408
+
409
+ if ( light.castShadow === true || light.colorNode ) return false;
410
+
411
+ // Only lights shaded by the plain point and spot light nodes are clustered. Subclasses
412
+ // registered with their own light node (e.g. IESSpotLight, ProjectorLight) keep the
413
+ // default lighting, since clustering would shade them as plain spot lights.
414
+
415
+ if ( light._lightNode === PointLightNode ) return true;
416
+
417
+ return light._lightNode === SpotLightNode && ! light.map;
418
+
419
+ }
420
+
421
+ /**
422
+ * Returns the lights that are not clustered.
423
+ *
424
+ * @return {Array<Light>} The lights using the default lighting.
425
+ */
426
+ getBuiltinLights() {
427
+
428
+ return this.materialLights;
429
+
430
+ }
431
+
432
+ /**
433
+ * Returns the light index stored at the given slot of the fragment's cluster.
434
+ *
435
+ * @private
436
+ * @param {number|Node<int>} element - The slot.
437
+ * @return {Node<int>} The 1-based light index. `0` marks the end of the list.
438
+ */
439
+ _getTile( element ) {
440
+
441
+ element = int( element );
442
+
443
+ const stride = int( 4 );
444
+ const chunkOffset = element.div( stride );
445
+ const idx = this._screenClusterIndex.mul( int( this._chunksPerCluster ) ).add( chunkOffset );
446
+
447
+ return this._lightIndexes.element( idx ).element( element.mod( stride ) );
448
+
449
+ }
450
+
451
+ /**
452
+ * Returns the number of lights in the fragment's cluster. Useful for debugging.
453
+ *
454
+ * @param {Node<int>} zSliceNode - The depth slice to inspect. A negative value selects the fragment's own cluster.
455
+ * @return {Node<int>} The light count.
456
+ */
457
+ getClusterLightCount( zSliceNode ) {
458
+
459
+ const getCount = Fn( ( [ zSliceNode ] ) => {
460
+
461
+ const count = int( 0 ).toVar();
462
+
463
+ const debugClusterIndex = this._screenClusterIndex.toVar();
464
+
465
+ If( zSliceNode.greaterThanEqual( int( 0 ) ), () => {
466
+
467
+ const tileSize = int( this.tileSize );
468
+ const screenTile = screenCoordinate.div( tileSize ).floor();
469
+ const NX = int( this._gridDimensions.x );
470
+ const NY = int( this._gridDimensions.y );
471
+
472
+ debugClusterIndex.assign(
473
+ int( screenTile.x )
474
+ .add( int( screenTile.y ).mul( NX ) )
475
+ .add( zSliceNode.mul( NX.mul( NY ) ) )
476
+ );
477
+
478
+ } );
479
+
480
+ Loop( this.maxLightsPerCluster, ( { i } ) => {
481
+
482
+ const element = int( i );
483
+ const stride = int( 4 );
484
+ const chunkOffset = element.div( stride );
485
+ const idx = debugClusterIndex.mul( int( this._chunksPerCluster ) ).add( chunkOffset );
486
+ const lightIndex = this._lightIndexes.element( idx ).element( element.mod( stride ) );
487
+
488
+ If( lightIndex.equal( int( 0 ) ), () => {
489
+
490
+ Break();
491
+
492
+ } );
493
+
494
+ count.addAssign( int( 1 ) );
495
+
496
+ } );
497
+
498
+ return count;
499
+
500
+ } );
501
+
502
+ return getCount( zSliceNode );
503
+
504
+ }
505
+
506
+ /**
507
+ * Returns the shading data of the light at the given index.
508
+ *
509
+ * @private
510
+ * @param {number|Node<int>} index - The light index.
511
+ * @return {Object} The light's view position, distance, color, decay, view-space spot direction and spot offset.
512
+ */
513
+ _getLightData( index ) {
514
+
515
+ index = int( index );
516
+
517
+ const dataA = textureLoad( this._lightsTexture, ivec2( index, POSITION_ROW ) );
518
+ const dataB = textureLoad( this._lightsTexture, ivec2( index, COLOR_ROW ) );
519
+ const dataC = textureLoad( this._lightsTexture, ivec2( index, SPOT_ROW ) );
520
+
521
+ const viewPosition = this._cameraViewMatrix.mul( vec4( dataA.xyz, 1.0 ) ).xyz;
522
+ const distance = dataA.w;
523
+ const color = dataB.rgb;
524
+ const decay = dataB.w;
525
+ const spotDirection = this._cameraViewMatrix.mul( vec4( dataC.xyz, 0.0 ) ).xyz;
526
+ const spotOffset = dataC.w;
527
+
528
+ return {
529
+ viewPosition,
530
+ distance,
531
+ color,
532
+ decay,
533
+ spotDirection,
534
+ spotOffset
535
+ };
536
+
537
+ }
538
+
539
+ /**
540
+ * Returns the culling data of the light at the given index.
541
+ *
542
+ * @private
543
+ * @param {number|Node<int>} index - The light index.
544
+ * @return {Object} The view-space center and the radius of the light's bounding sphere. A negative radius marks an unbounded light.
545
+ */
546
+ _getLightBounds( index ) {
547
+
548
+ const data = textureLoad( this._lightsTexture, ivec2( int( index ), BOUNDS_ROW ) );
549
+
550
+ const center = this._cameraViewMatrix.mul( vec4( data.xyz, 1.0 ) ).xyz;
551
+ const radius = data.w;
552
+
553
+ return { center, radius };
554
+
555
+ }
556
+
557
+ /**
558
+ * Sets up the default lights and the clustered point and spot lights.
559
+ *
560
+ * @param {NodeBuilder} builder - A reference to the current node builder.
561
+ * @param {Array<LightingNode>} lightNodes - An array of lighting nodes.
562
+ */
563
+ setupLights( builder, lightNodes ) {
564
+
565
+ this._initGrid( builder.renderer );
566
+
567
+ //
568
+
569
+ const lightingModel = builder.context.reflectedLight;
570
+
571
+ lightingModel.directDiffuse.toStack();
572
+ lightingModel.directSpecular.toStack();
573
+
574
+ super.setupLights( builder, lightNodes );
575
+
576
+ Fn( () => {
577
+
578
+ Loop( this.maxLightsPerCluster, ( { i } ) => {
579
+
580
+ const lightIndex = this._getTile( i );
581
+
582
+ If( lightIndex.equal( int( 0 ) ), () => {
583
+
584
+ Break();
585
+
586
+ } );
587
+
588
+ const { color, decay, viewPosition, distance, spotDirection, spotOffset } = this._getLightData( lightIndex.sub( 1 ) );
589
+
590
+ const lightVector = viewPosition.sub( positionView );
591
+
592
+ // spot cone attenuation, always 1 for point lights
593
+ const spotAttenuation = smoothstep( 0, 1, dot( lightVector.normalize(), spotDirection ).sub( spotOffset ) ).toVar();
594
+
595
+ // Early-out: skip full BRDF if fragment is beyond the light's cutoff or outside the spot cone
596
+ const inRange = distance.equal( 0 ).or( dot( lightVector, lightVector ).lessThanEqual( distance.mul( distance ) ) );
597
+
598
+ If( inRange.and( spotAttenuation.greaterThan( 0 ) ), () => {
599
+
600
+ builder.lightsNode.setupDirectLight( builder, this, directPointLight( {
601
+ color: color.mul( spotAttenuation ),
602
+ lightVector,
603
+ cutoffDistance: distance,
604
+ decayExponent: decay
605
+ } ) );
606
+
607
+ } );
608
+
609
+ } );
610
+
611
+ }, 'void' )();
612
+
613
+ }
614
+
615
+ /**
616
+ * Rounds the given size up to a multiple of the tile size.
617
+ *
618
+ * @private
619
+ * @param {number} value - The size.
620
+ * @return {number} The fitted size.
621
+ */
622
+ _getBufferFitSize( value ) {
623
+
624
+ const multiple = this.tileSize;
625
+
626
+ return Math.ceil( value / multiple ) * multiple;
627
+
628
+ }
629
+
630
+ /**
631
+ * Sets the size of the cluster grid. Must be called outside of rendering. Not required
632
+ * with {@link ClusteredLighting}, which fits the grid at the beginning of each render.
633
+ *
634
+ * @param {number} width - The drawing buffer width.
635
+ * @param {number} height - The drawing buffer height.
636
+ * @return {ClusteredLightsNode} A reference to this node.
637
+ */
638
+ setSize( width, height ) {
639
+
640
+ this._resize( this._getBufferFitSize( width ), this._getBufferFitSize( height ) );
641
+
642
+ return this;
643
+
644
+ }
645
+
646
+ /**
647
+ * Fits the cluster grid to the framebuffer of the render that is about to start. Called by
648
+ * {@link ClusteredLighting} before the render objects of the render are prepared. Since each
649
+ * render depth has its own node, no pending command buffer uses the resources of this node at
650
+ * this point, so a rebuild can free the replaced resources immediately.
651
+ */
652
+ updateSize() {
653
+
654
+ if ( this._renderer !== null ) this._fitToRenderer( this._renderer );
655
+
656
+ }
657
+
658
+ /**
659
+ * Creates the cluster grid on first use. While rendering, the grid is never rebuilt: the
660
+ * replaced resources could still be used by a command buffer that was not submitted yet.
661
+ *
662
+ * @private
663
+ * @param {Renderer} renderer - The renderer.
664
+ */
665
+ _initGrid( renderer ) {
666
+
667
+ this._renderer = renderer;
668
+
669
+ if ( this._compute === null ) this._fitToRenderer( renderer );
670
+
671
+ }
672
+
673
+ /**
674
+ * Fits the cluster grid to the framebuffer the renderer is rendering to.
675
+ *
676
+ * @private
677
+ * @param {Renderer} renderer - The renderer.
678
+ */
679
+ _fitToRenderer( renderer ) {
680
+
681
+ // the grid must match the framebuffer being rendered: a render target (e.g. a reflector
682
+ // with a resolution scale) can differ from the drawing buffer
683
+
684
+ const renderTarget = renderer.getRenderTarget();
685
+
686
+ if ( renderTarget !== null ) {
687
+
688
+ _size.set( renderTarget.width, renderTarget.height );
689
+
690
+ } else {
691
+
692
+ renderer.getDrawingBufferSize( _size );
693
+
694
+ }
695
+
696
+ // the compute differs per backend, so a backend change requires a rebuild
697
+
698
+ const isWebGLBackend = renderer.backend.isWebGLBackend === true;
699
+
700
+ if ( this._compute !== null && this._isWebGLBackend !== isWebGLBackend ) this._needsRebuild = true;
701
+
702
+ this._isWebGLBackend = isWebGLBackend;
703
+
704
+ this._resize( this._getBufferFitSize( _size.width ), this._getBufferFitSize( _size.height ) );
705
+
706
+ }
707
+
708
+ /**
709
+ * Resizes the cluster grid. The grid dimensions are uniforms, so resizing only updates
710
+ * them and the compute count; the compute and the storage are rebuilt only when the
711
+ * storage has to grow (or the backend changed).
712
+ *
713
+ * @private
714
+ * @param {number} width - The fitted width.
715
+ * @param {number} height - The fitted height.
716
+ */
717
+ _resize( width, height ) {
718
+
719
+ if ( this._needsRebuild === false && this._bufferSize !== null && this._bufferSize.width === width && this._bufferSize.height === height ) return;
720
+
721
+ const NX = Math.floor( width / this.tileSize );
722
+ const NY = Math.floor( height / this.tileSize );
723
+ const clusterCount = NX * NY * this.zSlices;
724
+
725
+ const requiredElements = clusterCount * this._chunksPerCluster;
726
+
727
+ if ( this._needsRebuild === true || this._compute === null || this._lightIndexes.value.array.length / 4 < requiredElements ) {
728
+
729
+ this._create( clusterCount );
730
+
731
+ }
732
+
733
+ this._gridDimensions.value.set( NX, NY );
734
+ this._compute.count = clusterCount * this._invocationsPerCluster;
735
+
736
+ if ( this._bufferSize === null ) this._bufferSize = new Vector2();
737
+
738
+ this._bufferSize.set( width, height );
739
+
740
+ }
741
+
742
+ /**
743
+ * Creates the light index storage, the compute node and the fragment cluster lookup.
744
+ * The storage is allocated with headroom so that most resizes do not need a rebuild.
745
+ *
746
+ * @private
747
+ * @param {number} clusterCount - The number of clusters of the current grid.
748
+ */
749
+ _create( clusterCount ) {
750
+
751
+ const { tileSize, zSlices, _chunksPerCluster: chunksPerCluster } = this;
752
+
753
+ const NZ = zSlices;
754
+
755
+ // grid dimensions as uniforms: shaders do not depend on the drawing buffer size
756
+
757
+ const grid = this._gridDimensions;
758
+ const NX = int( grid.x );
759
+ const NY = int( grid.y );
760
+
761
+ // Per-cluster light-index storage (ivec4 chunks), grown geometrically.
762
+
763
+ const requiredElements = clusterCount * chunksPerCluster;
764
+ const previousElements = this._lightIndexes !== null ? this._lightIndexes.value.array.length / 4 : 0;
765
+ const elements = previousElements === 0 ? Math.ceil( requiredElements * 1.5 ) : Math.max( requiredElements, previousElements * 2 );
766
+
767
+ // rebuilds only happen outside of rendering (see _initGrid()), so the replaced resources can be freed
768
+
769
+ if ( this._compute !== null ) {
770
+
771
+ // Replacing storage requires new material bindings. The initial allocation does not.
772
+ this.needsUpdate = true;
773
+
774
+ this._compute.dispose();
775
+ this._lightIndexes.value.dispose();
776
+
777
+ }
778
+
779
+ // instanced storage: WebGL computes use gl_InstanceID as instanceIndex; PBO: random access in the fragment stage
780
+ const lightIndexes = instancedArray( new Int32Array( elements * 4 ), 'ivec4' ).setPBO( true ).setName( 'lightIndexes' );
781
+
782
+ // view-space AABB of the given cluster
783
+
784
+ const getClusterBounds = ( clusterIndex ) => {
785
+
786
+ // view-space scale factors derived from the projection matrix:
787
+ // view_x = ndc_x * (-view_z) / focal_x = ndc_x * (-view_z) * invFocalX
788
+ // view_y = ndc_y * (-view_z) / focal_y = ndc_y * (-view_z) * invFocalY
789
+ // where focal_x = projMatrix[0][0] and focal_y = projMatrix[1][1].
790
+ const invFocalX = float( 1 ).div( this._cameraProjectionMatrix.element( 0 ).element( 0 ) );
791
+ const invFocalY = float( 1 ).div( this._cameraProjectionMatrix.element( 1 ).element( 1 ) );
792
+
793
+ // 3D cluster coordinates
794
+ const cx = clusterIndex.mod( NX );
795
+ const cy = clusterIndex.div( NX ).mod( NY );
796
+ const cz = clusterIndex.div( NX.mul( NY ) );
797
+
798
+ // NDC X/Y bounds of the cluster.
799
+ // Y is flipped: cy=0 is the top screen row (fragment y=0), which is NDC y=+1.
800
+ const ndcXmin = float( cx ).mul( 2.0 ).div( grid.x ).sub( 1.0 );
801
+ const ndcXmax = float( cx.add( int( 1 ) ) ).mul( 2.0 ).div( grid.x ).sub( 1.0 );
802
+ const ndcYmax = float( 1 ).sub( float( cy ).mul( 2.0 ).div( grid.y ) );
803
+ const ndcYmin = float( 1 ).sub( float( cy.add( int( 1 ) ) ).mul( 2.0 ).div( grid.y ) );
804
+
805
+ // View-space Z bounds (negative, exponential slicing)
806
+ const farOverNear = this._cameraFar.div( this._cameraNear );
807
+ const zNearCluster = this._cameraNear.mul( pow( farOverNear, float( cz ).mul( 1.0 / NZ ) ) ).negate();
808
+ const zFarCluster = this._cameraNear.mul( pow( farOverNear, float( cz.add( int( 1 ) ) ).mul( 1.0 / NZ ) ) ).negate();
809
+
810
+ const scaleNearX = zNearCluster.negate().mul( invFocalX );
811
+ const scaleFarX = zFarCluster.negate().mul( invFocalX );
812
+ const scaleNearY = zNearCluster.negate().mul( invFocalY );
813
+ const scaleFarY = zFarCluster.negate().mul( invFocalY );
814
+
815
+ const xMinNear = ndcXmin.mul( scaleNearX );
816
+ const xMaxNear = ndcXmax.mul( scaleNearX );
817
+ const xMinFar = ndcXmin.mul( scaleFarX );
818
+ const xMaxFar = ndcXmax.mul( scaleFarX );
819
+
820
+ const yMinNear = ndcYmin.mul( scaleNearY );
821
+ const yMaxNear = ndcYmax.mul( scaleNearY );
822
+ const yMinFar = ndcYmin.mul( scaleFarY );
823
+ const yMaxFar = ndcYmax.mul( scaleFarY );
824
+
825
+ // AABB of the 8 view-space corners (tile boundaries can straddle the view axis)
826
+ const aabbMinX = min( xMinNear, xMinFar );
827
+ const aabbMaxX = max( xMaxNear, xMaxFar );
828
+ const aabbMinY = min( yMinNear, yMinFar );
829
+ const aabbMaxY = max( yMaxNear, yMaxFar );
830
+
831
+ const aabbMin = vec3( aabbMinX, aabbMinY, zFarCluster );
832
+ const aabbMax = vec3( aabbMaxX, aabbMaxY, zNearCluster );
833
+
834
+ return { cz, aabbMin, aabbMax };
835
+
836
+ };
837
+
838
+ // sphere-AABB intersection in view space
839
+
840
+ const intersectsCluster = ( lightIdx, aabbMin, aabbMax ) => {
841
+
842
+ const { center, radius } = this._getLightBounds( lightIdx );
843
+
844
+ const closest = max( aabbMin, min( center, aabbMax ) );
845
+ const diff = center.sub( closest );
846
+ const distSq = dot( diff, diff );
847
+
848
+ return radius.lessThan( 0 ).or( distSq.lessThanEqual( radius.mul( radius ) ) );
849
+
850
+ };
851
+
852
+ // Each invocation fills `chunksPerInvocation` ivec4 chunks of one cluster. WebGL computes
853
+ // run via transform feedback and can only write their own element, so there each
854
+ // invocation fills a single chunk; WebGPU uses one invocation per cluster.
855
+
856
+ const chunksPerInvocation = this._isWebGLBackend ? 1 : chunksPerCluster;
857
+ const invocationsPerCluster = chunksPerCluster / chunksPerInvocation;
858
+
859
+ this._invocationsPerCluster = invocationsPerCluster;
860
+
861
+ const compute = Fn( () => {
862
+
863
+ const clusterIndex = int( instanceIndex.div( invocationsPerCluster ) );
864
+ const firstChunk = int( instanceIndex.mod( invocationsPerCluster ) ).mul( chunksPerInvocation );
865
+ const firstSlot = firstChunk.mul( 4 );
866
+ const lastSlot = firstSlot.add( chunksPerInvocation * 4 );
867
+
868
+ const { cz, aabbMin, aabbMax } = getClusterBounds( clusterIndex );
869
+
870
+ const chunks = ivec4( 0 ).toArray( chunksPerInvocation ).toVar();
871
+ const index = int( 0 ).toVar();
872
+
873
+ // Z-culling: only test lights that can reach this cluster's Z-slice
874
+ const zRange = textureLoad( this._zSliceRangesTexture, ivec2( cz, 0 ) );
875
+ const rangeStart = int( zRange.x );
876
+ const rangeEnd = int( zRange.y );
877
+
878
+ Loop( this.maxLights, ( { i } ) => {
879
+
880
+ const lightIdx = rangeStart.add( i );
881
+
882
+ If( index.greaterThanEqual( lastSlot ).or( lightIdx.greaterThanEqual( rangeEnd ) ), () => {
883
+
884
+ Break();
885
+
886
+ } );
887
+
888
+ If( intersectsCluster( lightIdx, aabbMin, aabbMax ), () => {
889
+
890
+ // slots before firstSlot belong to other invocations of this cluster
891
+ If( index.greaterThanEqual( firstSlot ), () => {
892
+
893
+ const slot = index.sub( firstSlot );
894
+
895
+ chunks.element( slot.div( 4 ) ).element( slot.mod( 4 ) ).assign( lightIdx.add( int( 1 ) ) );
896
+
897
+ } );
898
+
899
+ index.addAssign( int( 1 ) );
900
+
901
+ } );
902
+
903
+ } );
904
+
905
+ const firstElement = clusterIndex.mul( chunksPerCluster ).add( firstChunk );
906
+
907
+ const writeChunks = () => {
908
+
909
+ Loop( chunksPerInvocation, ( { i } ) => {
910
+
911
+ lightIndexes.element( firstElement.add( i ) ).assign( chunks.element( i ) );
912
+
913
+ } );
914
+
915
+ };
916
+
917
+ if ( this._isWebGLBackend === true ) {
918
+
919
+ // WebGL binds the transform feedback buffers per compute program, and programs are shared by
920
+ // identical code. The (always true) capacity and node id constants give each node and storage
921
+ // allocation its own program, so a compute never writes to the storage of another one.
922
+
923
+ If( firstElement.lessThan( int( elements ) ).and( int( this.id ).notEqual( int( - 1 ) ) ), writeChunks );
924
+
925
+ } else {
926
+
927
+ writeChunks();
928
+
929
+ }
930
+
931
+ } )().compute( clusterCount * invocationsPerCluster ).setName( 'Update Clustered Lights' );
932
+
933
+ // shading-side: fragment → cluster index
934
+
935
+ const getScreenClusterIndex = Fn( () => {
936
+
937
+ const screenTile = screenCoordinate.div( tileSize ).floor();
938
+
939
+ // view-space depth from positionView (negative in front); take magnitude
940
+ const viewDepth = positionView.z.negate();
941
+
942
+ // exponential Z slice: tz = floor( log(depth/near) / log(far/near) * NZ )
943
+ const invLogFarOverNear = float( 1 ).div( log( this._cameraFar.div( this._cameraNear ) ) );
944
+ const sliceFloat = log( viewDepth.div( this._cameraNear ) ).mul( invLogFarOverNear ).mul( float( NZ ) );
945
+ const zSlice = clamp( sliceFloat.floor(), float( 0 ), float( NZ - 1 ) );
946
+
947
+ return int( screenTile.x )
948
+ .add( int( screenTile.y ).mul( NX ) )
949
+ .add( int( zSlice ).mul( NX.mul( NY ) ) );
950
+
951
+ } );
952
+
953
+ const screenClusterIndex = getScreenClusterIndex().toVar();
954
+
955
+ // assigns
956
+
957
+ this._lightIndexes = lightIndexes;
958
+ this._screenClusterIndex = screenClusterIndex;
959
+ this._compute = compute;
960
+ this._needsRebuild = false;
961
+
962
+ }
963
+
964
+ /**
965
+ * Frees the GPU resources allocated by this node.
966
+ */
967
+ dispose() {
968
+
969
+ if ( this._compute !== null ) this._compute.dispose();
970
+ if ( this._lightIndexes !== null ) this._lightIndexes.value.dispose();
971
+
972
+ this._lightsTexture.dispose();
973
+ this._zSliceRangesTexture.dispose();
974
+
975
+ super.dispose();
976
+
977
+ }
978
+
979
+ }
980
+
981
+ export default ClusteredLightsNode;
982
+
983
+ /**
984
+ * TSL function that creates a clustered lights node.
985
+ *
986
+ * @tsl
987
+ * @function
988
+ * @param {number} [maxLights=1024] - Maximum number of point and spot lights.
989
+ * @param {number} [tileSize=32] - Screen tile size in pixels.
990
+ * @param {number} [zSlices=24] - Depth slice count.
991
+ * @param {number} [maxLightsPerCluster=64] - Per-cluster light-list capacity.
992
+ * @return {ClusteredLightsNode} The clustered lights node.
993
+ */
994
+ export const clusteredLights = /*@__PURE__*/ nodeProxy( ClusteredLightsNode );