@gnsx/three 0.185.16 → 0.186.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 (418) hide show
  1. package/build/three.cjs +10 -82600
  2. package/build/three.core.js +1309 -807
  3. package/build/three.module.js +439 -338
  4. package/build/three.tsl.js +74 -44
  5. package/build/three.webgpu.js +6036 -2184
  6. package/build/three.webgpu.nodes.js +6020 -2184
  7. package/examples/jsm/Addons.js +6 -6
  8. package/examples/jsm/controls/ArcballControls.js +1 -1
  9. package/examples/jsm/controls/FirstPersonControls.js +44 -20
  10. package/examples/jsm/controls/OrbitControls.js +9 -0
  11. package/examples/jsm/controls/TrackballControls.js +109 -4
  12. package/examples/jsm/csm/CSMShadowNode.js +13 -0
  13. package/examples/jsm/exporters/GLTFExporter.js +23 -7
  14. package/examples/jsm/exporters/USDZExporter.js +2 -2
  15. package/examples/jsm/generators/CityGenerator.js +377 -45
  16. package/examples/jsm/generators/ForestGenerator.js +12 -12
  17. package/examples/jsm/generators/TerrainGenerator.js +49 -37
  18. package/examples/jsm/generators/TreeGenerator.js +70 -76
  19. package/examples/jsm/generators/city/BenchGenerator.js +127 -0
  20. package/examples/jsm/generators/city/CarGenerator.js +479 -0
  21. package/examples/jsm/generators/city/CityGeneratorUtils.js +31 -0
  22. package/examples/jsm/generators/city/HydrantGenerator.js +106 -0
  23. package/examples/jsm/generators/city/InstancedMeshGenerator.js +86 -0
  24. package/examples/jsm/generators/city/PersonGenerator.js +447 -0
  25. package/examples/jsm/generators/city/SidewalkGenerator.js +33 -38
  26. package/examples/jsm/generators/city/SkyscraperGenerator.js +448 -48
  27. package/examples/jsm/generators/city/StreetTreeGenerator.js +231 -0
  28. package/examples/jsm/generators/city/StreetlightGenerator.js +100 -0
  29. package/examples/jsm/generators/city/TrafficlightGenerator.js +106 -0
  30. package/examples/jsm/generators/city/TrashcanGenerator.js +100 -0
  31. package/examples/jsm/geometries/BoxLineGeometry.js +1 -1
  32. package/examples/jsm/geometries/ParametricGeometry.js +1 -1
  33. package/examples/jsm/geometries/RoundedBoxGeometry.js +1 -1
  34. package/examples/jsm/gpgpu/CountingSort.js +271 -0
  35. package/examples/jsm/helpers/LightProbeGridHelper.js +60 -239
  36. package/examples/jsm/helpers/LightProbeGridHelperWebGL.js +221 -0
  37. package/examples/jsm/inspector/Extension.js +94 -0
  38. package/examples/jsm/inspector/Inspector.js +145 -41
  39. package/examples/jsm/inspector/RendererInspector.js +100 -52
  40. package/examples/jsm/inspector/extensions/color-grading/ColorGrading.js +2609 -0
  41. package/examples/jsm/inspector/extensions/color-grading/ColorWheel.js +352 -0
  42. package/examples/jsm/inspector/extensions/color-grading/CurveEditor.js +599 -0
  43. package/examples/jsm/inspector/extensions/color-grading/LUT3DStyle.js +1201 -0
  44. package/examples/jsm/inspector/extensions/color-grading/LUTMath.js +788 -0
  45. package/examples/jsm/inspector/extensions/color-grading/modules/BrightnessModule.js +72 -0
  46. package/examples/jsm/inspector/extensions/color-grading/modules/ColorWheelModule.js +112 -0
  47. package/examples/jsm/inspector/extensions/color-grading/modules/ContrastModule.js +82 -0
  48. package/examples/jsm/inspector/extensions/color-grading/modules/CurvesModule.js +109 -0
  49. package/examples/jsm/inspector/extensions/color-grading/modules/ExposureHueModule.js +110 -0
  50. package/examples/jsm/inspector/extensions/color-grading/modules/ExposureModule.js +73 -0
  51. package/examples/jsm/inspector/extensions/color-grading/modules/HueModule.js +78 -0
  52. package/examples/jsm/inspector/extensions/color-grading/modules/ImportedCubeModule.js +89 -0
  53. package/examples/jsm/inspector/extensions/color-grading/modules/Module.js +285 -0
  54. package/examples/jsm/inspector/extensions/color-grading/modules/OutputModule.js +101 -0
  55. package/examples/jsm/inspector/extensions/color-grading/modules/RendererModule.js +225 -0
  56. package/examples/jsm/inspector/extensions/color-grading/modules/SatVibranceModule.js +102 -0
  57. package/examples/jsm/inspector/extensions/color-grading/modules/SaturationModule.js +76 -0
  58. package/examples/jsm/inspector/extensions/color-grading/modules/VibranceModule.js +76 -0
  59. package/examples/jsm/inspector/extensions/color-grading/modules/WhiteBalanceModule.js +86 -0
  60. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js +26 -31
  61. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphLoader.js +1 -0
  62. package/examples/jsm/inspector/tabs/Memory.js +0 -2
  63. package/examples/jsm/inspector/tabs/Settings.js +4 -0
  64. package/examples/jsm/inspector/tabs/Timeline.js +223 -171
  65. package/examples/jsm/inspector/tabs/Viewer.js +515 -21
  66. package/examples/jsm/inspector/ui/List.js +15 -9
  67. package/examples/jsm/inspector/ui/Profiler.js +170 -14
  68. package/examples/jsm/inspector/ui/Style.js +269 -23
  69. package/examples/jsm/inspector/ui/Tab.js +2 -0
  70. package/examples/jsm/inspector/ui/Values.js +14 -2
  71. package/examples/jsm/interactive/HTMLMesh.js +19 -3
  72. package/examples/jsm/lighting/LightProbeGrid.js +484 -889
  73. package/examples/jsm/lighting/LightProbeGridUtils.js +107 -0
  74. package/examples/jsm/lighting/LightProbeGridWebGL.js +841 -0
  75. package/examples/jsm/lighting/vxgi/VXGIConeTracer.js +194 -0
  76. package/examples/jsm/lighting/vxgi/VXGINode.js +660 -0
  77. package/examples/jsm/lighting/vxgi/VXGISceneCollector.js +478 -0
  78. package/examples/jsm/lighting/vxgi/VXGIVolume.js +1430 -0
  79. package/examples/jsm/lights/SunLight.js +95 -0
  80. package/examples/jsm/lights/SunLightNode.js +56 -0
  81. package/examples/jsm/lights/SunLightShadow.js +319 -0
  82. package/examples/jsm/lights/SunShadowNode.js +312 -0
  83. package/examples/jsm/loaders/3DMLoader.js +150 -49
  84. package/examples/jsm/loaders/3MFLoader.js +202 -1
  85. package/examples/jsm/loaders/FBXLoader.js +81 -5
  86. package/examples/jsm/loaders/GLTFGaussianSplatLoaderExtension.js +330 -0
  87. package/examples/jsm/loaders/GLTFLoader.js +79 -14
  88. package/examples/jsm/loaders/GaussianSplatPLYLoader.js +386 -0
  89. package/examples/jsm/loaders/KSPLATLoader.js +463 -0
  90. package/examples/jsm/loaders/MaterialXLoader.js +111 -1010
  91. package/examples/jsm/loaders/PCDLoader.js +1 -1
  92. package/examples/jsm/loaders/SPLATLoader.js +139 -0
  93. package/examples/jsm/loaders/SPZLoader.js +561 -0
  94. package/examples/jsm/loaders/materialx/MaterialXArchive.js +108 -0
  95. package/examples/jsm/loaders/materialx/MaterialXDocument.js +878 -0
  96. package/examples/jsm/loaders/materialx/MaterialXHextile.js +183 -0
  97. package/examples/jsm/loaders/materialx/MaterialXInterfaceValidation.js +376 -0
  98. package/examples/jsm/loaders/materialx/MaterialXLog.js +75 -0
  99. package/examples/jsm/loaders/materialx/MaterialXNodeInterfaceRegistry.js +4 -0
  100. package/examples/jsm/loaders/materialx/MaterialXNodeLibrary.js +1021 -0
  101. package/examples/jsm/loaders/materialx/MaterialXSurfaceMappings.js +661 -0
  102. package/examples/jsm/loaders/materialx/MaterialXUtils.js +57 -0
  103. package/examples/jsm/loaders/materialx/compile/MaterialXCompileRegistry.js +997 -0
  104. package/examples/jsm/loaders/materialx/parse/MaterialXParser.js +28 -0
  105. package/examples/jsm/loaders/usd/USDAParser.js +15 -2
  106. package/examples/jsm/loaders/usd/USDCParser.js +1 -4
  107. package/examples/jsm/loaders/usd/USDComposer.js +80 -42
  108. package/examples/jsm/materials/WoodNodeMaterial.js +6 -108
  109. package/examples/jsm/misc/RollerCoaster.js +2 -2
  110. package/examples/jsm/misc/SculptGL.LICENSE.txt +21 -0
  111. package/examples/jsm/misc/Sculptor.js +1679 -0
  112. package/examples/jsm/misc/SculptorMesh.js +1504 -0
  113. package/examples/jsm/misc/SculptorTools.js +1180 -0
  114. package/examples/jsm/misc/SculptorUtils.js +345 -0
  115. package/examples/jsm/misc/TubePainter.js +28 -16
  116. package/examples/jsm/misc/VolumeSlice.js +24 -24
  117. package/examples/jsm/modifiers/SimplifyModifier.js +63 -556
  118. package/examples/jsm/objects/GaussianSplat.js +1039 -0
  119. package/examples/jsm/objects/Sky.js +66 -45
  120. package/examples/jsm/objects/SkyMesh.js +70 -51
  121. package/examples/jsm/physics/JoltPhysics.js +1 -1
  122. package/examples/jsm/postprocessing/AfterimagePass.js +4 -2
  123. package/examples/jsm/postprocessing/BloomPass.js +2 -2
  124. package/examples/jsm/postprocessing/GTAOPass.js +1 -1
  125. package/examples/jsm/postprocessing/OutlinePass.js +5 -5
  126. package/examples/jsm/postprocessing/SAOPass.js +1 -1
  127. package/examples/jsm/postprocessing/SSAOPass.js +1 -1
  128. package/examples/jsm/postprocessing/SSRPass.js +4 -2
  129. package/examples/jsm/postprocessing/SavePass.js +1 -1
  130. package/examples/jsm/postprocessing/TAARenderPass.js +1 -1
  131. package/examples/jsm/postprocessing/UnrealBloomPass.js +30 -13
  132. package/examples/jsm/renderers/CSS2DRenderer.js +29 -5
  133. package/examples/jsm/shaders/DepthLimitedBlurShader.js +4 -1
  134. package/examples/jsm/shaders/ExposureShader.js +1 -1
  135. package/examples/jsm/shaders/FilmShader.js +2 -1
  136. package/examples/jsm/transpiler/AST.js +21 -2
  137. package/examples/jsm/transpiler/GLSLDecoder.js +498 -8
  138. package/examples/jsm/transpiler/TSLEncoder.js +82 -10
  139. package/examples/jsm/transpiler/WGSLEncoder.js +33 -4
  140. package/examples/jsm/tsl/WebGLNodesHandler.js +29 -39
  141. package/examples/jsm/tsl/display/AfterImageNode.js +2 -0
  142. package/examples/jsm/tsl/display/AnaglyphPassNode.js +3 -2
  143. package/examples/jsm/tsl/display/BilateralBlurNode.js +5 -2
  144. package/examples/jsm/tsl/display/BloomNode.js +55 -30
  145. package/examples/jsm/tsl/display/DenoiseNode.js +21 -1
  146. package/examples/jsm/tsl/display/DepthOfFieldNode.js +24 -6
  147. package/examples/jsm/tsl/display/DotScreenNode.js +11 -11
  148. package/examples/jsm/tsl/display/FSR1Node.js +8 -4
  149. package/examples/jsm/tsl/display/GTAONode.js +199 -86
  150. package/examples/jsm/tsl/display/GaussianBlurNode.js +65 -52
  151. package/examples/jsm/tsl/display/GodraysNode.js +5 -2
  152. package/examples/jsm/tsl/display/ImportanceSampledEnvironment.js +2 -2
  153. package/examples/jsm/tsl/display/LensflareNode.js +5 -2
  154. package/examples/jsm/tsl/display/OITPassNode.js +352 -0
  155. package/examples/jsm/tsl/display/OutlineNode.js +2 -0
  156. package/examples/jsm/tsl/display/ParallaxBarrierPassNode.js +3 -2
  157. package/examples/jsm/tsl/display/RGBShiftNode.js +9 -9
  158. package/examples/jsm/tsl/display/RecurrentDenoiseNode.js +7 -4
  159. package/examples/jsm/tsl/display/RetroPassNode.js +1 -1
  160. package/examples/jsm/tsl/display/SMAANode.js +22 -61
  161. package/examples/jsm/tsl/display/SSAAPassNode.js +2 -4
  162. package/examples/jsm/tsl/display/SSAONode.js +436 -0
  163. package/examples/jsm/tsl/display/SSGINode.js +5 -2
  164. package/examples/jsm/tsl/display/SSRNode.js +7 -2
  165. package/examples/jsm/tsl/display/SSSNode.js +5 -2
  166. package/examples/jsm/tsl/display/SharpenNode.js +5 -4
  167. package/examples/jsm/tsl/display/StereoCompositePassNode.js +1 -3
  168. package/examples/jsm/tsl/display/StereoPassNode.js +1 -3
  169. package/examples/jsm/tsl/display/TAAUNode.js +22 -125
  170. package/examples/jsm/tsl/display/TRAANode.js +16 -142
  171. package/examples/jsm/tsl/display/TemporalReprojectNode.js +21 -15
  172. package/examples/jsm/tsl/display/depthAwareBlur.js +63 -0
  173. package/examples/jsm/tsl/display/hashBlur.js +3 -2
  174. package/examples/jsm/tsl/lighting/ClusteredLightsNode.js +38 -27
  175. package/examples/jsm/tsl/lighting/LightProbeGridNode.js +136 -0
  176. package/examples/jsm/tsl/math/voronoiNoise.js +112 -0
  177. package/examples/jsm/tsl/shadows/TileShadowNode.js +4 -6
  178. package/examples/jsm/tsl/utils/Raymarching.js +5 -5
  179. package/examples/jsm/tsl/utils/SoftParticles.js +60 -0
  180. package/examples/jsm/tsl/utils/TAAUtils.js +195 -0
  181. package/examples/jsm/utils/BufferGeometryUtils.js +14 -14
  182. package/examples/jsm/utils/GaussianSplatUtils.js +229 -0
  183. package/examples/jsm/utils/WebGLTextureUtils.js +1 -1
  184. package/examples/jsm/utils/WebGPUTextureUtils.js +1 -1
  185. package/examples/jsm/webxr/WebGLXRFallback.js +2 -16
  186. package/examples/jsm/webxr/XRControllerModelFactory.js +16 -4
  187. package/package.json +9 -16
  188. package/src/Three.Core.js +2 -1
  189. package/src/Three.TSL.js +73 -43
  190. package/src/Three.WebGPU.Nodes.js +1 -0
  191. package/src/Three.WebGPU.js +1 -0
  192. package/src/animation/AnimationClip.js +15 -2
  193. package/src/animation/AnimationObjectGroup.js +18 -6
  194. package/src/animation/AnimationUtils.js +26 -0
  195. package/src/animation/KeyframeTrack.js +37 -0
  196. package/src/constants.js +23 -1
  197. package/src/core/BufferAttribute.js +3 -2
  198. package/src/core/BufferGeometry.js +1 -1
  199. package/src/core/InterleavedBuffer.js +5 -1
  200. package/src/core/Object3D.js +40 -12
  201. package/src/core/Raycaster.js +4 -0
  202. package/src/core/RenderTarget.js +99 -9
  203. package/src/core/RenderTarget3D.js +12 -8
  204. package/src/extras/Controls.js +0 -8
  205. package/src/extras/PMREMGenerator.js +99 -205
  206. package/src/geometries/TorusGeometry.js +1 -1
  207. package/src/helpers/ArrowHelper.js +2 -0
  208. package/src/helpers/AxesHelper.js +2 -0
  209. package/src/helpers/Box3Helper.js +2 -0
  210. package/src/helpers/BoxHelper.js +2 -0
  211. package/src/helpers/CameraHelper.js +2 -0
  212. package/src/helpers/DirectionalLightHelper.js +2 -0
  213. package/src/helpers/GridHelper.js +2 -0
  214. package/src/helpers/HemisphereLightHelper.js +2 -0
  215. package/src/helpers/PlaneHelper.js +2 -0
  216. package/src/helpers/PointLightHelper.js +2 -0
  217. package/src/helpers/PolarGridHelper.js +2 -0
  218. package/src/helpers/SkeletonHelper.js +2 -0
  219. package/src/helpers/SpotLightHelper.js +2 -0
  220. package/src/lights/Light.js +0 -10
  221. package/src/lights/LightShadow.js +43 -12
  222. package/src/lights/SpotLightShadow.js +18 -0
  223. package/src/loaders/BufferGeometryLoader.js +5 -0
  224. package/src/loaders/ImageBitmapLoader.js +3 -1
  225. package/src/loaders/ObjectLoader.js +8 -5
  226. package/src/materials/Material.js +80 -57
  227. package/src/materials/MeshPhysicalMaterial.js +32 -0
  228. package/src/materials/nodes/Line2NodeMaterial.js +17 -8
  229. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +42 -5
  230. package/src/materials/nodes/NodeMaterial.js +19 -13
  231. package/src/materials/nodes/PointsNodeMaterial.js +2 -1
  232. package/src/materials/nodes/manager/NodeMaterialObserver.js +282 -55
  233. package/src/math/Frustum.js +9 -0
  234. package/src/math/FrustumArray.js +1 -1
  235. package/src/math/MathUtils.js +5 -3
  236. package/src/math/Matrix4.js +2 -9
  237. package/src/math/Plane.js +30 -1
  238. package/src/math/Quaternion.js +0 -10
  239. package/src/math/Ray.js +95 -45
  240. package/src/math/Triangle.js +0 -2
  241. package/src/math/Vector3.js +2 -2
  242. package/src/math/Vector4.js +0 -4
  243. package/src/math/interpolants/BezierInterpolant.js +36 -23
  244. package/src/nodes/Nodes.js +2 -0
  245. package/src/nodes/TSL.js +11 -3
  246. package/src/nodes/accessors/Batch.js +85 -13
  247. package/src/nodes/accessors/BufferAttributeNode.js +1 -1
  248. package/src/nodes/accessors/BuiltinNode.js +1 -1
  249. package/src/nodes/accessors/Instance.js +19 -18
  250. package/src/nodes/accessors/MaterialNode.js +9 -0
  251. package/src/nodes/accessors/ModelNode.js +85 -9
  252. package/src/nodes/accessors/ReferenceBaseNode.js +1 -70
  253. package/src/nodes/accessors/ReferenceElementNode.js +72 -0
  254. package/src/nodes/accessors/ReferenceNode.js +1 -70
  255. package/src/nodes/accessors/Skinning.js +124 -12
  256. package/src/nodes/accessors/StorageTextureNode.js +7 -3
  257. package/src/nodes/accessors/Texture3DNode.js +1 -1
  258. package/src/nodes/accessors/TextureNode.js +51 -21
  259. package/src/nodes/accessors/TextureSizeNode.js +4 -2
  260. package/src/nodes/accessors/UniformArrayNode.js +30 -5
  261. package/src/nodes/code/CodeNode.js +1 -1
  262. package/src/nodes/code/FunctionNode.js +12 -2
  263. package/src/nodes/core/ArrayNode.js +2 -2
  264. package/src/nodes/core/ContextNode.js +57 -4
  265. package/src/nodes/core/IndexNode.js +69 -4
  266. package/src/nodes/core/InspectorNode.js +2 -2
  267. package/src/nodes/core/MRTNode.js +44 -2
  268. package/src/nodes/core/Node.js +6 -3
  269. package/src/nodes/core/NodeBuilder.js +65 -50
  270. package/src/nodes/core/NodeFrame.js +11 -3
  271. package/src/nodes/core/NodeUtils.js +88 -0
  272. package/src/nodes/core/PropertyNode.js +8 -0
  273. package/src/nodes/core/StackNode.js +0 -1
  274. package/src/nodes/core/StructNode.js +4 -3
  275. package/src/nodes/core/UniformGroupNode.js +3 -2
  276. package/src/nodes/core/UniformNode.js +26 -12
  277. package/src/nodes/core/VarNode.js +0 -1
  278. package/src/nodes/display/BumpMapNode.js +2 -2
  279. package/src/nodes/display/ColorAdjustment.js +1 -1
  280. package/src/nodes/display/PassNode.js +76 -15
  281. package/src/nodes/display/ScreenNode.js +22 -65
  282. package/src/nodes/fog/Fog.js +4 -4
  283. package/src/nodes/functions/BSDF/BRDF_GGX.js +6 -6
  284. package/src/nodes/functions/BSDF/BRDF_Sheen.js +1 -1
  285. package/src/nodes/functions/BSDF/DFGLUT.js +2 -1
  286. package/src/nodes/functions/BSDF/LTC.js +1 -1
  287. package/src/nodes/functions/PhongLightingModel.js +1 -1
  288. package/src/nodes/functions/PhysicalLightingModel.js +83 -25
  289. package/src/nodes/functions/ToonLightingModel.js +2 -2
  290. package/src/nodes/functions/material/getParallaxCorrectNormal.js +3 -3
  291. package/src/nodes/gpgpu/AtomicFunctionNode.js +64 -13
  292. package/src/nodes/gpgpu/BarrierNode.js +13 -4
  293. package/src/nodes/gpgpu/ComputeBuiltinNode.js +1 -1
  294. package/src/nodes/gpgpu/ComputeNode.js +20 -17
  295. package/src/nodes/gpgpu/SubgroupFunctionNode.js +165 -37
  296. package/src/nodes/gpgpu/WorkgroupInfoNode.js +44 -6
  297. package/src/nodes/lighting/EnvironmentNode.js +40 -4
  298. package/src/nodes/lighting/LightsNode.js +20 -4
  299. package/src/nodes/lighting/ShadowBaseNode.js +158 -1
  300. package/src/nodes/lighting/ShadowFilterNode.js +2 -106
  301. package/src/nodes/lighting/ShadowNode.js +22 -91
  302. package/src/nodes/materialx/{lib/mx_hsv.js → MaterialXColor.js} +3 -6
  303. package/src/nodes/materialx/{lib/mx_transform_color.js → MaterialXColorTransform.js} +3 -6
  304. package/src/nodes/materialx/MaterialXCore.js +37 -0
  305. package/src/nodes/materialx/MaterialXNodes.js +64 -72
  306. package/src/nodes/materialx/{lib/mx_noise.js → MaterialXNoise.js} +426 -197
  307. package/src/nodes/math/BitcountNode.js +24 -4
  308. package/src/nodes/math/MathNode.js +4 -4
  309. package/src/nodes/math/MathUtils.js +15 -4
  310. package/src/nodes/math/OperatorNode.js +2 -2
  311. package/src/nodes/math/PackFloatNode.js +29 -1
  312. package/src/nodes/math/Packed4x8IntegerNode.js +433 -0
  313. package/src/nodes/math/UnpackFloatNode.js +30 -2
  314. package/src/nodes/parsers/GLSLNodeFunction.js +1 -1
  315. package/src/nodes/pmrem/PMREMNode.js +1 -1
  316. package/src/nodes/pmrem/PMREMUtils.js +31 -74
  317. package/src/nodes/shapes/Shapes.js +1 -1
  318. package/src/nodes/tsl/TSLCore.js +1 -31
  319. package/src/nodes/utils/EventNode.js +75 -0
  320. package/src/nodes/utils/LoopNode.js +54 -13
  321. package/src/nodes/utils/PostProcessingUtils.js +23 -2
  322. package/src/nodes/utils/RTTNode.js +97 -32
  323. package/src/nodes/utils/ReflectorNode.js +8 -4
  324. package/src/nodes/utils/RotateNode.js +85 -8
  325. package/src/nodes/utils/SpriteUtils.js +58 -23
  326. package/src/objects/BatchedMesh.js +6 -0
  327. package/src/objects/InstancedMesh.js +1 -1
  328. package/src/objects/LOD.js +1 -1
  329. package/src/objects/Line.js +12 -0
  330. package/src/objects/Mesh.js +12 -0
  331. package/src/objects/Points.js +12 -0
  332. package/src/objects/Sprite.js +12 -0
  333. package/src/renderers/WebGLRenderer.js +93 -27
  334. package/src/renderers/common/Animation.js +12 -2
  335. package/src/renderers/common/Backend.js +38 -10
  336. package/src/renderers/common/BindGroup.js +0 -1
  337. package/src/renderers/common/Bindings.js +50 -4
  338. package/src/renderers/common/BundleGroup.js +4 -0
  339. package/src/renderers/common/ClippingContext.js +11 -1
  340. package/src/renderers/common/Color4.js +9 -0
  341. package/src/renderers/common/Constants.js +0 -5
  342. package/src/renderers/common/DirectRenderPipeline.js +233 -0
  343. package/src/renderers/common/Geometries.js +24 -3
  344. package/src/renderers/common/Info.js +3 -3
  345. package/src/renderers/common/InspectorBase.js +37 -8
  346. package/src/renderers/common/Lighting.js +11 -4
  347. package/src/renderers/common/Pipelines.js +6 -4
  348. package/src/renderers/common/QuadMesh.js +16 -2
  349. package/src/renderers/common/RenderContext.js +8 -0
  350. package/src/renderers/common/RenderList.js +53 -19
  351. package/src/renderers/common/RenderLists.js +58 -11
  352. package/src/renderers/common/RenderObject.js +14 -0
  353. package/src/renderers/common/RenderObjects.js +14 -9
  354. package/src/renderers/common/RenderPipeline.js +52 -44
  355. package/src/renderers/common/Renderer.js +226 -55
  356. package/src/renderers/common/Storage3DTexture.js +16 -0
  357. package/src/renderers/common/Textures.js +3 -3
  358. package/src/renderers/common/XRManager.js +79 -72
  359. package/src/renderers/common/extras/PMREMGenerator.js +76 -144
  360. package/src/renderers/common/nodes/NodeManager.js +144 -6
  361. package/src/renderers/common/nodes/NodeStorageBuffer.js +3 -1
  362. package/src/renderers/common/nodes/NodeUniformBuffer.js +3 -1
  363. package/src/renderers/shaders/DFGLUTData.js +2 -1
  364. package/src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js +4 -2
  365. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +48 -0
  366. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +53 -4
  367. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +20 -2
  368. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +20 -0
  369. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +6 -0
  370. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +61 -57
  371. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +82 -0
  372. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js +9 -0
  373. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +8 -1
  374. package/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js +15 -0
  375. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +4 -0
  376. package/src/renderers/shaders/ShaderLib.js +1 -0
  377. package/src/renderers/shaders/UniformsLib.js +16 -0
  378. package/src/renderers/webgl/WebGLAnimation.js +2 -2
  379. package/src/renderers/webgl/WebGLCapabilities.js +2 -2
  380. package/src/renderers/webgl/WebGLLights.js +74 -4
  381. package/src/renderers/webgl/WebGLMaterials.js +6 -0
  382. package/src/renderers/webgl/WebGLOutput.js +36 -24
  383. package/src/renderers/webgl/WebGLProgram.js +3 -0
  384. package/src/renderers/webgl/WebGLPrograms.js +8 -0
  385. package/src/renderers/webgl/WebGLRenderLists.js +6 -10
  386. package/src/renderers/webgl/WebGLShadowMap.js +47 -44
  387. package/src/renderers/webgl/WebGLTextures.js +7 -7
  388. package/src/renderers/webgl-fallback/WebGLBackend.js +153 -45
  389. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +83 -29
  390. package/src/renderers/webgl-fallback/utils/WebGLState.js +163 -17
  391. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +32 -5
  392. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +11 -4
  393. package/src/renderers/webgpu/WebGPUBackend.js +513 -145
  394. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +99 -20
  395. package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +2 -1
  396. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +3 -12
  397. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +24 -14
  398. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +80 -14
  399. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +62 -7
  400. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +9 -3
  401. package/src/renderers/webgpu/utils/WebGPUUtils.js +16 -4
  402. package/src/renderers/webxr/WebXRManager.js +25 -2
  403. package/src/scenes/Scene.js +3 -3
  404. package/src/textures/CompressedArrayTexture.js +16 -0
  405. package/src/textures/Data3DTexture.js +16 -0
  406. package/src/textures/DataArrayTexture.js +16 -0
  407. package/src/textures/DepthTexture.js +3 -3
  408. package/src/textures/Texture.js +3 -3
  409. package/src/textures/{Source.js → TextureSource.js} +39 -8
  410. package/src/utils.js +6 -79
  411. package/build/three.core.min.js +0 -6
  412. package/build/three.module.min.js +0 -6
  413. package/build/three.tsl.min.js +0 -6
  414. package/build/three.webgpu.min.js +0 -6
  415. package/build/three.webgpu.nodes.min.js +0 -6
  416. package/examples/jsm/libs/ecsy.module.js +0 -1792
  417. package/examples/jsm/loaders/LottieLoader.js +0 -130
  418. package/src/nodes/functions/BSDF/BRDF_GGX_Multiscatter.js +0 -52
@@ -0,0 +1,841 @@
1
+ import {
2
+ Box3,
3
+ CubeCamera,
4
+ Data3DTexture,
5
+ FloatType,
6
+ HalfFloatType,
7
+ LinearFilter,
8
+ MathUtils,
9
+ Mesh,
10
+ NearestFilter,
11
+ Object3D,
12
+ OrthographicCamera,
13
+ PlaneGeometry,
14
+ RGBAFormat,
15
+ Scene,
16
+ ShaderMaterial,
17
+ Vector3,
18
+ WebGL3DRenderTarget,
19
+ WebGLCubeRenderTarget,
20
+ WebGLRenderTarget
21
+ } from '@gnsx/three';
22
+
23
+ import { replaceSunLights, restoreSunLights } from './LightProbeGridUtils.js';
24
+
25
+ // Shared fullscreen-quad scene / camera
26
+ let _scene = null;
27
+ let _camera = null;
28
+ let _mesh = null;
29
+
30
+ // SH projection material (depends on cubemapSize)
31
+ let _shMaterial = null;
32
+ let _lastCubemapSize = 0;
33
+
34
+ // Repack materials (one per output sub-volume / texture index)
35
+ let _repackMaterials = null;
36
+
37
+ // Cached bake resources
38
+ let _cubeRenderTarget = null;
39
+ let _cubeCamera = null;
40
+ let _cachedCubemapSize = 0;
41
+ let _cachedNear = 0;
42
+ let _cachedFar = 0;
43
+
44
+ // Cached batch render target
45
+ let _batchTarget = null;
46
+ let _batchTargetProbes = 0;
47
+
48
+ // Reusable temp objects
49
+ const _position = /*@__PURE__*/ new Vector3();
50
+ const _size = /*@__PURE__*/ new Vector3();
51
+ const _copyRegion = /*@__PURE__*/ new Box3();
52
+
53
+ // Direct-light captures use a black atlas without changing the light layout.
54
+ let _emptyAtlas = null;
55
+
56
+ // Number of padding texels added at each boundary of every sub-volume in the atlas.
57
+ const ATLAS_PADDING = 1;
58
+
59
+ /**
60
+ * A 3D grid of L2 Spherical Harmonic irradiance probes that provides
61
+ * position-dependent diffuse global illumination.
62
+ *
63
+ * Note that this class can only be used with {@link WebGLRenderer}.
64
+ * For {@link WebGPURenderer}, use {@link LightProbeGrid}.
65
+ *
66
+ * All seven packed SH sub-volumes are stored in a **single** RGBA
67
+ * `WebGL3DRenderTarget` using a texture-atlas layout along the Z axis.
68
+ * Each sub-volume occupies `( nz + 2 )` atlas slices: one padding slice at
69
+ * each end (a copy of the nearest edge data slice) to prevent color bleeding
70
+ * when the hardware trilinear filter reads across a sub-volume boundary.
71
+ *
72
+ * Atlas layout (nz = resolution.z, PADDING = 1):
73
+ * ```
74
+ * slice 0 : padding (copy of sub-volume 0, data slice 0)
75
+ * slices 1 … nz : sub-volume 0 data
76
+ * slice nz + 1 : padding (copy of sub-volume 0, data slice nz-1)
77
+ * slice nz + 2 : padding (copy of sub-volume 1, data slice 0)
78
+ * slices nz+3 … 2*nz+2 : sub-volume 1 data
79
+ * …
80
+ * ```
81
+ * Total atlas depth = `7 * ( nz + 2 )`.
82
+ *
83
+ * Baking is fully GPU-resident: cubemap rendering, SH projection, and
84
+ * texture packing all happen on the GPU with zero CPU readback.
85
+ *
86
+ * @three_import import { LightProbeGridWebGL } from 'three/addons/lighting/LightProbeGridWebGL.js';
87
+ */
88
+ class LightProbeGridWebGL extends Object3D {
89
+
90
+ /**
91
+ * Constructs a new irradiance probe grid.
92
+ *
93
+ * The volume is centered at the object's position.
94
+ *
95
+ * @param {number} [width=1] - Full width of the volume along X.
96
+ * @param {number} [height=1] - Full height of the volume along Y.
97
+ * @param {number} [depth=1] - Full depth of the volume along Z.
98
+ * @param {number} [widthProbes] - Number of probes along X. Defaults to `Math.max( 2, Math.round( width ) + 1 )`.
99
+ * @param {number} [heightProbes] - Number of probes along Y. Defaults to `Math.max( 2, Math.round( height ) + 1 )`.
100
+ * @param {number} [depthProbes] - Number of probes along Z. Defaults to `Math.max( 2, Math.round( depth ) + 1 )`.
101
+ */
102
+ constructor( width = 1, height = 1, depth = 1, widthProbes, heightProbes, depthProbes ) {
103
+
104
+ super();
105
+
106
+ /**
107
+ * This flag can be used for type testing.
108
+ *
109
+ * @type {boolean}
110
+ * @readonly
111
+ * @default true
112
+ */
113
+ this.isLightProbeGrid = true;
114
+
115
+ /**
116
+ * The full width of the volume along X.
117
+ *
118
+ * @type {number}
119
+ */
120
+ this.width = width;
121
+
122
+ /**
123
+ * The full height of the volume along Y.
124
+ *
125
+ * @type {number}
126
+ */
127
+ this.height = height;
128
+
129
+ /**
130
+ * The full depth of the volume along Z.
131
+ *
132
+ * @type {number}
133
+ */
134
+ this.depth = depth;
135
+
136
+ /**
137
+ * The number of probes along each axis.
138
+ *
139
+ * @type {Vector3}
140
+ */
141
+ this.resolution = new Vector3(
142
+ widthProbes !== undefined ? widthProbes : Math.max( 2, Math.round( width ) + 1 ),
143
+ heightProbes !== undefined ? heightProbes : Math.max( 2, Math.round( height ) + 1 ),
144
+ depthProbes !== undefined ? depthProbes : Math.max( 2, Math.round( depth ) + 1 )
145
+ );
146
+
147
+ /**
148
+ * The world-space bounding box for the grid. Updated automatically
149
+ * by {@link LightProbeGridWebGL#bake}.
150
+ *
151
+ * @type {Box3}
152
+ */
153
+ this.boundingBox = new Box3();
154
+
155
+ /**
156
+ * The single RGBA atlas 3D texture storing all seven packed SH sub-volumes.
157
+ *
158
+ * @type {?Data3DTexture}
159
+ * @default null
160
+ */
161
+ this.texture = null;
162
+
163
+ /**
164
+ * Internal render target for GPU-resident baking.
165
+ *
166
+ * @private
167
+ * @type {?WebGL3DRenderTarget}
168
+ * @default null
169
+ */
170
+ this._renderTarget = null;
171
+
172
+ // Indirect captures read a snapshot while the live atlas is updated in place.
173
+ this._bounceTarget = null;
174
+ this._bouncePass = - 1;
175
+
176
+ this.updateBoundingBox();
177
+
178
+ }
179
+
180
+ /**
181
+ * Returns the world-space position of the probe at grid indices (ix, iy, iz).
182
+ *
183
+ * @param {number} ix - X index.
184
+ * @param {number} iy - Y index.
185
+ * @param {number} iz - Z index.
186
+ * @param {Vector3} target - The target vector.
187
+ * @return {Vector3} The world-space position.
188
+ */
189
+ getProbePosition( ix, iy, iz, target ) {
190
+
191
+ // WITH_GENESYS
192
+ const pos = _position;
193
+ this.getWorldPosition( pos );
194
+ // !WITH_GENESYS
195
+ // const pos = this.position;
196
+ const res = this.resolution;
197
+ const w = this.width, h = this.height, d = this.depth;
198
+
199
+ target.set(
200
+ res.x > 1 ? pos.x - w / 2 + ix * w / ( res.x - 1 ) : pos.x,
201
+ res.y > 1 ? pos.y - h / 2 + iy * h / ( res.y - 1 ) : pos.y,
202
+ res.z > 1 ? pos.z - d / 2 + iz * d / ( res.z - 1 ) : pos.z
203
+ );
204
+
205
+ return target;
206
+
207
+ }
208
+
209
+ /**
210
+ * Updates the world-space bounding box from the current position and size.
211
+ */
212
+ updateBoundingBox() {
213
+
214
+ // WITH_GENESYS
215
+ this.getWorldPosition( _position );
216
+ _size.set( this.width, this.height, this.depth );
217
+ this.boundingBox.setFromCenterAndSize( _position, _size );
218
+ // !WITH_GENESYS
219
+ /*
220
+ _size.set( this.width, this.height, this.depth );
221
+ this.boundingBox.setFromCenterAndSize( this.position, _size );
222
+ */
223
+
224
+ }
225
+
226
+ /**
227
+ * Bakes probes by rendering cubemaps at each probe position and
228
+ * projecting to L2 SH. Optionally iterates additional passes to capture
229
+ * indirect bounces: each extra pass samples the previous pass's data as
230
+ * indirect light, so a grid added to the scene before baking accumulates
231
+ * one bounce per extra pass.
232
+ *
233
+ * Use `start` and `count` to bake a range and publish its cells immediately.
234
+ * Indices advance along X, then Z, then Y, filling horizontal layers from bottom
235
+ * to top. For incremental indirect bounces, finish the whole grid for `pass: 0`,
236
+ * then repeat with `pass: 1`, etc. Start each pass at index 0 to snapshot the
237
+ * previous pass before updating its cells.
238
+ *
239
+ * Shadow-casting instances of `SunLight` are temporarily replaced with
240
+ * equivalent directional lights, since their view-fitted shadow cascades
241
+ * cannot be frozen across probe renders.
242
+ *
243
+ * @param {WebGLRenderer} renderer - The renderer.
244
+ * @param {Scene} scene - The scene to render.
245
+ * @param {Object} [options] - Bake options.
246
+ * @param {number} [options.cubemapSize=8] - Resolution of each cubemap face.
247
+ * @param {number} [options.near=0.1] - Near plane for the cube camera.
248
+ * @param {number} [options.far=100] - Far plane for the cube camera.
249
+ * @param {number} [options.bounces=0] - Additional bounce passes. Only available when baking the whole grid.
250
+ * @param {number} [options.start=0] - Index of the first probe to bake.
251
+ * @param {number} [options.count] - Number of probes to bake. Defaults to the remaining probes.
252
+ * @param {number} [options.pass=0] - Starting pass. Zero captures direct light; later passes sample the previous pass. Ranged calls require `bounces: 0`.
253
+ */
254
+ bake( renderer, scene, options = {} ) {
255
+
256
+ const res = this.resolution;
257
+ const totalProbes = res.x * res.y * res.z;
258
+ const {
259
+ bounces = 0,
260
+ start = 0,
261
+ count = totalProbes - start,
262
+ pass: firstPass = 0
263
+ } = options;
264
+ const end = start + count;
265
+
266
+ if ( ! Number.isInteger( start ) || ! Number.isInteger( count ) || start < 0 || count < 0 || end > totalProbes ) {
267
+
268
+ throw new RangeError( 'THREE.LightProbeGridWebGL: Invalid probe range.' );
269
+
270
+ }
271
+
272
+ if ( ! Number.isInteger( firstPass ) || firstPass < 0 || ! Number.isInteger( bounces ) || bounces < 0 ) {
273
+
274
+ throw new RangeError( 'THREE.LightProbeGridWebGL: Pass and bounce counts must be non-negative integers.' );
275
+
276
+ }
277
+
278
+ if ( bounces > 0 && count !== totalProbes ) {
279
+
280
+ throw new RangeError( 'THREE.LightProbeGridWebGL: For ranged baking, use pass instead of bounces.' );
281
+
282
+ }
283
+
284
+ if ( count === 0 ) return;
285
+
286
+ if ( firstPass > 0 && start > 0 && this._bouncePass !== firstPass ) {
287
+
288
+ throw new Error( 'THREE.LightProbeGridWebGL: Start each indirect pass at probe 0.' );
289
+
290
+ }
291
+
292
+ this._ensureTextures();
293
+ this.updateBoundingBox();
294
+ _ensureBakeResources( options );
295
+ _ensureBatchTarget( totalProbes );
296
+ _ensureRepackResources();
297
+
298
+ const currentRenderTarget = renderer.getRenderTarget();
299
+ const currentActiveCubeFace = renderer.getActiveCubeFace();
300
+ const currentActiveMipmapLevel = renderer.getActiveMipmapLevel();
301
+ const currentAutoClear = renderer.autoClear;
302
+ const currentXrEnabled = renderer.xr.enabled;
303
+ const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
304
+ const currentMatrixWorldAutoUpdate = scene.matrixWorldAutoUpdate;
305
+ const currentVisible = this.visible;
306
+ const currentTexture = this.texture;
307
+ const renderTarget = this._renderTarget;
308
+ const currentViewport = renderTarget.viewport.clone();
309
+ let replacedSunLights = null;
310
+
311
+ try {
312
+
313
+ this.visible = true;
314
+
315
+ // Scene is static during the bake: update once, disable auto-update.
316
+
317
+ if ( currentMatrixWorldAutoUpdate === true ) {
318
+
319
+ scene.updateMatrixWorld( true );
320
+ scene.matrixWorldAutoUpdate = false;
321
+
322
+ }
323
+
324
+ replacedSunLights = replaceSunLights( scene );
325
+
326
+ // Render shadow maps once, not once per cube face.
327
+
328
+ renderer.shadowMap.autoUpdate = false;
329
+ renderer.shadowMap.needsUpdate = true;
330
+
331
+ for ( let pass = firstPass; pass <= firstPass + bounces; pass ++ ) {
332
+
333
+ this._updateBakeTexture( renderer, pass, start );
334
+ this._captureProbes( renderer, scene, start, end );
335
+ this._repackProbes( renderer, start, end );
336
+
337
+ }
338
+
339
+ } finally {
340
+
341
+ renderTarget.viewport.copy( currentViewport );
342
+ renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel );
343
+ renderer.autoClear = currentAutoClear;
344
+ renderer.xr.enabled = currentXrEnabled;
345
+ renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
346
+
347
+ if ( replacedSunLights !== null ) restoreSunLights( scene, replacedSunLights );
348
+
349
+ scene.matrixWorldAutoUpdate = currentMatrixWorldAutoUpdate;
350
+ this.visible = currentVisible;
351
+ this.texture = currentTexture;
352
+
353
+ }
354
+
355
+ }
356
+
357
+ /**
358
+ * Selects the atlas to sample during capture, snapshotting each indirect pass
359
+ * before its first range overwrites the live atlas.
360
+ *
361
+ * @private
362
+ * @param {WebGLRenderer} renderer - The renderer.
363
+ * @param {number} pass - The bounce pass.
364
+ * @param {number} start - The first probe index.
365
+ */
366
+ _updateBakeTexture( renderer, pass, start ) {
367
+
368
+ if ( pass === 0 ) {
369
+
370
+ this.texture = _emptyAtlas;
371
+ if ( start === 0 ) this._bouncePass = - 1;
372
+ return;
373
+
374
+ }
375
+
376
+ if ( start === 0 ) {
377
+
378
+ const renderTarget = this._renderTarget;
379
+
380
+ if ( this._bounceTarget === null ) this._bounceTarget = renderTarget.clone();
381
+
382
+ renderer.initRenderTarget( renderTarget );
383
+ renderer.initRenderTarget( this._bounceTarget );
384
+ _copyRegion.min.set( 0, 0, 0 );
385
+ _copyRegion.max.set( renderTarget.width, renderTarget.height, renderTarget.depth );
386
+ renderer.copyTextureToTexture( renderTarget.texture, this._bounceTarget.texture, _copyRegion );
387
+ this._bouncePass = pass;
388
+
389
+ }
390
+
391
+ this.texture = this._bounceTarget.texture;
392
+
393
+ }
394
+
395
+ /**
396
+ * Captures cubemaps and projects their SH coefficients into the batch target.
397
+ *
398
+ * @private
399
+ * @param {WebGLRenderer} renderer - The renderer.
400
+ * @param {Scene} scene - The scene to capture.
401
+ * @param {number} start - The first probe index.
402
+ * @param {number} end - The exclusive end probe index.
403
+ */
404
+ _captureProbes( renderer, scene, start, end ) {
405
+
406
+ const { x: nx, y: ny, z: nz } = this.resolution;
407
+ const probesPerLayer = nx * nz;
408
+
409
+ _mesh.material = _shMaterial;
410
+ _shMaterial.uniforms.envMap.value = _cubeRenderTarget.texture;
411
+
412
+ for ( let probeIndex = start; probeIndex < end; probeIndex ++ ) {
413
+
414
+ const ix = probeIndex % nx;
415
+ const iy = Math.floor( probeIndex / probesPerLayer );
416
+ const iz = Math.floor( probeIndex / nx ) % nz;
417
+
418
+ this.getProbePosition( ix, iy, iz, _position );
419
+ _cubeCamera.position.copy( _position );
420
+
421
+ // The cube faces must be cleared per face.
422
+ renderer.autoClear = true;
423
+ _cubeCamera.update( renderer, scene );
424
+
425
+ // Keep batch rows in texture order (X, Y, Z).
426
+ const batchRow = ix + iy * nx + iz * nx * ny;
427
+
428
+ renderer.autoClear = false;
429
+ _batchTarget.viewport.set( 0, batchRow, 9, 1 );
430
+ renderer.setRenderTarget( _batchTarget );
431
+ renderer.render( _scene, _camera );
432
+
433
+ }
434
+
435
+ }
436
+
437
+ /**
438
+ * Packs a probe range into the live atlas, including its boundary padding.
439
+ *
440
+ * @private
441
+ * @param {WebGLRenderer} renderer - The renderer.
442
+ * @param {number} start - The first probe index.
443
+ * @param {number} end - The exclusive end probe index.
444
+ */
445
+ _repackProbes( renderer, start, end ) {
446
+
447
+ const { x: nx, y: ny, z: nz } = this.resolution;
448
+ const probesPerLayer = nx * nz;
449
+ const startY = Math.floor( start / probesPerLayer );
450
+ const endY = Math.floor( end / probesPerLayer );
451
+ const paddedSlices = nz + 2 * ATLAS_PADDING;
452
+ const renderTarget = this._renderTarget;
453
+
454
+ for ( const material of _repackMaterials ) {
455
+
456
+ material.uniforms.batchTexture.value = _batchTarget.texture;
457
+ material.uniforms.resolution.value.copy( this.resolution );
458
+
459
+ }
460
+
461
+ // Map the horizontal bake range to contiguous rows in each Z slice.
462
+ for ( let iz = 0; iz < nz; iz ++ ) {
463
+
464
+ const sliceStart = startY * nx + MathUtils.clamp( start % probesPerLayer - iz * nx, 0, nx );
465
+ const sliceEnd = endY * nx + MathUtils.clamp( end % probesPerLayer - iz * nx, 0, nx );
466
+
467
+ for ( let probeIndex = sliceStart; probeIndex < sliceEnd; ) {
468
+
469
+ const ix = probeIndex % nx;
470
+ const iy = Math.floor( probeIndex / nx );
471
+
472
+ // Coalesce complete rows within a slice into one rectangle.
473
+ const width = Math.min( nx - ix, sliceEnd - probeIndex );
474
+ let height = 1;
475
+
476
+ if ( width === nx ) {
477
+
478
+ height = Math.min( ny - iy, Math.floor( ( sliceEnd - probeIndex ) / nx ) );
479
+
480
+ }
481
+
482
+ renderTarget.viewport.set( ix, iy, width, height );
483
+
484
+ for ( let t = 0; t < 7; t ++ ) {
485
+
486
+ _mesh.material = _repackMaterials[ t ];
487
+ _mesh.material.uniforms.sliceZ.value = iz;
488
+ const base = t * paddedSlices;
489
+
490
+ renderer.setRenderTarget( renderTarget, base + ATLAS_PADDING + iz );
491
+ renderer.render( _scene, _camera );
492
+
493
+ if ( iz === 0 ) {
494
+
495
+ renderer.setRenderTarget( renderTarget, base );
496
+ renderer.render( _scene, _camera );
497
+
498
+ }
499
+
500
+ if ( iz === nz - 1 ) {
501
+
502
+ renderer.setRenderTarget( renderTarget, base + ATLAS_PADDING + nz );
503
+ renderer.render( _scene, _camera );
504
+
505
+ }
506
+
507
+ }
508
+
509
+ probeIndex += width * height;
510
+
511
+ }
512
+
513
+ }
514
+
515
+ }
516
+
517
+ /**
518
+ * Ensures the atlas 3D render target exists with the correct dimensions.
519
+ *
520
+ * @private
521
+ */
522
+ _ensureTextures() {
523
+
524
+ if ( this._renderTarget !== null ) return;
525
+
526
+ const res = this.resolution;
527
+ const nx = res.x, ny = res.y, nz = res.z;
528
+
529
+ // Atlas depth: 7 sub-volumes, each with ATLAS_PADDING slices at both ends
530
+ const atlasDepth = 7 * ( nz + 2 * ATLAS_PADDING );
531
+
532
+ const rt = new WebGL3DRenderTarget( nx, ny, atlasDepth, {
533
+ format: RGBAFormat,
534
+ type: FloatType,
535
+ minFilter: LinearFilter,
536
+ magFilter: LinearFilter,
537
+ generateMipmaps: false,
538
+ depthBuffer: false
539
+ } );
540
+
541
+ this._renderTarget = rt;
542
+ this.texture = rt.texture;
543
+
544
+ }
545
+
546
+ /**
547
+ * Frees GPU resources.
548
+ */
549
+ dispose() {
550
+
551
+ if ( this._bounceTarget !== null ) {
552
+
553
+ this._bounceTarget.dispose();
554
+ this._bounceTarget = null;
555
+ this._bouncePass = - 1;
556
+
557
+ }
558
+
559
+ if ( this._renderTarget !== null ) {
560
+
561
+ this._renderTarget.dispose();
562
+ this._renderTarget = null;
563
+ this.texture = null;
564
+
565
+ }
566
+
567
+ }
568
+
569
+ }
570
+
571
+ // Internal: Ensure the shared fullscreen-quad scene exists
572
+ function _ensureScene() {
573
+
574
+ if ( _scene === null ) {
575
+
576
+ _camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
577
+ _mesh = new Mesh( new PlaneGeometry( 2, 2 ) );
578
+ _scene = new Scene();
579
+ _scene.add( _mesh );
580
+
581
+ }
582
+
583
+ }
584
+
585
+ // Internal: Ensure GPU resources for SH projection are created
586
+ function _ensureGPUResources( cubemapSize ) {
587
+
588
+ _ensureScene();
589
+
590
+ // Recreate material when cubemap size changes
591
+ if ( cubemapSize !== _lastCubemapSize ) {
592
+
593
+ if ( _shMaterial !== null ) _shMaterial.dispose();
594
+
595
+ _shMaterial = new ShaderMaterial( {
596
+ precision: 'highp',
597
+ defines: {
598
+ CUBEMAP_SIZE: cubemapSize
599
+ },
600
+ uniforms: {
601
+ envMap: { value: null }
602
+ },
603
+ vertexShader: /* glsl */`
604
+ void main() {
605
+ gl_Position = vec4( position.xy, 0.0, 1.0 );
606
+ }
607
+ `,
608
+ fragmentShader: /* glsl */`
609
+ #include <common>
610
+
611
+ uniform samplerCube envMap;
612
+
613
+ void main() {
614
+
615
+ int coefIndex = int( gl_FragCoord.x );
616
+
617
+ vec3 accum0 = vec3( 0.0 );
618
+ vec3 accum1 = vec3( 0.0 );
619
+ vec3 accum2 = vec3( 0.0 );
620
+ vec3 accum3 = vec3( 0.0 );
621
+ vec3 accum4 = vec3( 0.0 );
622
+ vec3 accum5 = vec3( 0.0 );
623
+ vec3 accum6 = vec3( 0.0 );
624
+ vec3 accum7 = vec3( 0.0 );
625
+ vec3 accum8 = vec3( 0.0 );
626
+ float totalWeight = 0.0;
627
+ float pixelSize = 2.0 / float( CUBEMAP_SIZE );
628
+
629
+ for ( int face = 0; face < 6; face ++ ) {
630
+
631
+ for ( int iy = 0; iy < CUBEMAP_SIZE; iy ++ ) {
632
+
633
+ for ( int ix = 0; ix < CUBEMAP_SIZE; ix ++ ) {
634
+
635
+ // WebGL cubemaps have a left-handed orientation (flip = -1)
636
+ float col = ( float( ix ) + 0.5 ) * pixelSize - 1.0;
637
+ float row = 1.0 - ( float( iy ) + 0.5 ) * pixelSize;
638
+
639
+ vec3 coord;
640
+
641
+ if ( face == 0 ) coord = vec3( 1.0, row, -col );
642
+ else if ( face == 1 ) coord = vec3( -1.0, row, col );
643
+ else if ( face == 2 ) coord = vec3( col, 1.0, -row );
644
+ else if ( face == 3 ) coord = vec3( col, -1.0, row );
645
+ else if ( face == 4 ) coord = vec3( col, row, 1.0 );
646
+ else coord = vec3( -col, row, -1.0 );
647
+
648
+ float lengthSq = dot( coord, coord );
649
+ float weight = 4.0 / ( sqrt( lengthSq ) * lengthSq );
650
+ totalWeight += weight;
651
+
652
+ vec3 dir = normalize( coord );
653
+ vec3 cw = textureCube( envMap, coord ).rgb * weight;
654
+
655
+ // band 0
656
+ accum0 += cw * 0.282095;
657
+
658
+ // band 1
659
+ accum1 += cw * ( 0.488603 * dir.y );
660
+ accum2 += cw * ( 0.488603 * dir.z );
661
+ accum3 += cw * ( 0.488603 * dir.x );
662
+
663
+ // band 2
664
+ accum4 += cw * ( 1.092548 * ( dir.x * dir.y ) );
665
+ accum5 += cw * ( 1.092548 * ( dir.y * dir.z ) );
666
+ accum6 += cw * ( 0.315392 * ( 3.0 * dir.z * dir.z - 1.0 ) );
667
+ accum7 += cw * ( 1.092548 * ( dir.x * dir.z ) );
668
+ accum8 += cw * ( 0.546274 * ( dir.x * dir.x - dir.y * dir.y ) );
669
+
670
+ }
671
+
672
+ }
673
+
674
+ }
675
+
676
+ float norm = 4.0 * PI / totalWeight;
677
+
678
+ vec3 accum;
679
+ if ( coefIndex == 0 ) accum = accum0;
680
+ else if ( coefIndex == 1 ) accum = accum1;
681
+ else if ( coefIndex == 2 ) accum = accum2;
682
+ else if ( coefIndex == 3 ) accum = accum3;
683
+ else if ( coefIndex == 4 ) accum = accum4;
684
+ else if ( coefIndex == 5 ) accum = accum5;
685
+ else if ( coefIndex == 6 ) accum = accum6;
686
+ else if ( coefIndex == 7 ) accum = accum7;
687
+ else accum = accum8;
688
+
689
+ gl_FragColor = vec4( accum * norm, 1.0 );
690
+
691
+ }
692
+ `
693
+ } );
694
+
695
+ _lastCubemapSize = cubemapSize;
696
+
697
+ }
698
+
699
+ }
700
+
701
+ // Internal: Ensure GPU resources for repacking SH into the atlas 3D texture
702
+ function _ensureRepackResources() {
703
+
704
+ if ( _repackMaterials !== null ) return;
705
+
706
+ _ensureScene();
707
+
708
+ // Create 7 materials, one per output texture packing
709
+ // Texture 0: (c0.r, c0.g, c0.b, c1.r)
710
+ // Texture 1: (c1.g, c1.b, c2.r, c2.g)
711
+ // Texture 2: (c2.b, c3.r, c3.g, c3.b)
712
+ // Texture 3: (c4.r, c4.g, c4.b, c5.r)
713
+ // Texture 4: (c5.g, c5.b, c6.r, c6.g)
714
+ // Texture 5: (c6.b, c7.r, c7.g, c7.b)
715
+ // Texture 6: (c8.r, c8.g, c8.b, 0.0)
716
+
717
+ const repackVertexShader = /* glsl */`
718
+ void main() {
719
+ gl_Position = vec4( position.xy, 0.0, 1.0 );
720
+ }
721
+ `;
722
+
723
+ _repackMaterials = [];
724
+
725
+ for ( let t = 0; t < 7; t ++ ) {
726
+
727
+ _repackMaterials[ t ] = new ShaderMaterial( {
728
+ precision: 'highp',
729
+ defines: {
730
+ TEXTURE_INDEX: t
731
+ },
732
+ uniforms: {
733
+ batchTexture: { value: null },
734
+ resolution: { value: new Vector3() },
735
+ sliceZ: { value: 0 }
736
+ },
737
+ vertexShader: repackVertexShader,
738
+ fragmentShader: /* glsl */`
739
+ uniform sampler2D batchTexture;
740
+ uniform vec3 resolution;
741
+ uniform int sliceZ;
742
+
743
+ void main() {
744
+
745
+ int ix = int( gl_FragCoord.x );
746
+ int iy = int( gl_FragCoord.y );
747
+ int iz = sliceZ;
748
+
749
+ int probeIndex = ix + iy * int( resolution.x ) + iz * int( resolution.x ) * int( resolution.y );
750
+
751
+ // Read 9 SH coefficients from the batch texture row
752
+ vec4 c0 = texelFetch( batchTexture, ivec2( 0, probeIndex ), 0 );
753
+ vec4 c1 = texelFetch( batchTexture, ivec2( 1, probeIndex ), 0 );
754
+ vec4 c2 = texelFetch( batchTexture, ivec2( 2, probeIndex ), 0 );
755
+ vec4 c3 = texelFetch( batchTexture, ivec2( 3, probeIndex ), 0 );
756
+ vec4 c4 = texelFetch( batchTexture, ivec2( 4, probeIndex ), 0 );
757
+ vec4 c5 = texelFetch( batchTexture, ivec2( 5, probeIndex ), 0 );
758
+ vec4 c6 = texelFetch( batchTexture, ivec2( 6, probeIndex ), 0 );
759
+ vec4 c7 = texelFetch( batchTexture, ivec2( 7, probeIndex ), 0 );
760
+ vec4 c8 = texelFetch( batchTexture, ivec2( 8, probeIndex ), 0 );
761
+
762
+ // Pack into the output format for this texture index
763
+ #if TEXTURE_INDEX == 0
764
+ gl_FragColor = vec4( c0.rgb, c1.r );
765
+ #elif TEXTURE_INDEX == 1
766
+ gl_FragColor = vec4( c1.gb, c2.rg );
767
+ #elif TEXTURE_INDEX == 2
768
+ gl_FragColor = vec4( c2.b, c3.rgb );
769
+ #elif TEXTURE_INDEX == 3
770
+ gl_FragColor = vec4( c4.rgb, c5.r );
771
+ #elif TEXTURE_INDEX == 4
772
+ gl_FragColor = vec4( c5.gb, c6.rg );
773
+ #elif TEXTURE_INDEX == 5
774
+ gl_FragColor = vec4( c6.b, c7.rgb );
775
+ #else
776
+ gl_FragColor = vec4( c8.rgb, 0.0 );
777
+ #endif
778
+
779
+ }
780
+ `
781
+ } );
782
+
783
+ }
784
+
785
+ }
786
+
787
+ // Internal: Ensure cube render target and camera exist with the right parameters
788
+ function _ensureBakeResources( options ) {
789
+
790
+ if ( _emptyAtlas === null ) {
791
+
792
+ _emptyAtlas = new Data3DTexture( new Uint16Array( 4 ), 1, 1, 1 );
793
+ _emptyAtlas.type = HalfFloatType;
794
+ _emptyAtlas.minFilter = LinearFilter;
795
+ _emptyAtlas.magFilter = LinearFilter;
796
+ _emptyAtlas.needsUpdate = true;
797
+
798
+ }
799
+
800
+ const {
801
+ cubemapSize = 8,
802
+ near = 0.1,
803
+ far = 100
804
+ } = options;
805
+
806
+ if ( _cubeRenderTarget === null || cubemapSize !== _cachedCubemapSize || near !== _cachedNear || far !== _cachedFar ) {
807
+
808
+ if ( _cubeRenderTarget !== null ) _cubeRenderTarget.dispose();
809
+
810
+ _cubeRenderTarget = new WebGLCubeRenderTarget( cubemapSize, { type: HalfFloatType } );
811
+ _cubeCamera = new CubeCamera( near, far, _cubeRenderTarget );
812
+ _cachedCubemapSize = cubemapSize;
813
+ _cachedNear = near;
814
+ _cachedFar = far;
815
+
816
+ }
817
+
818
+ _ensureGPUResources( cubemapSize );
819
+
820
+ }
821
+
822
+ function _ensureBatchTarget( totalProbes ) {
823
+
824
+ if ( _batchTarget === null || _batchTargetProbes !== totalProbes ) {
825
+
826
+ if ( _batchTarget !== null ) _batchTarget.dispose();
827
+
828
+ _batchTarget = new WebGLRenderTarget( 9, totalProbes, {
829
+ type: FloatType,
830
+ minFilter: NearestFilter,
831
+ magFilter: NearestFilter,
832
+ depthBuffer: false
833
+ } );
834
+
835
+ _batchTargetProbes = totalProbes;
836
+
837
+ }
838
+
839
+ }
840
+
841
+ export { LightProbeGridWebGL };