@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,1039 @@
1
+ import {
2
+ Box3,
3
+ BufferAttribute,
4
+ InstancedBufferGeometry,
5
+ Matrix3,
6
+ Matrix4,
7
+ Mesh,
8
+ NodeMaterial,
9
+ Ray,
10
+ Sphere,
11
+ StorageBufferAttribute,
12
+ Vector2,
13
+ Vector3
14
+ } from '@gnsx/three/webgpu';
15
+
16
+ import {
17
+ Discard,
18
+ Fn,
19
+ If,
20
+ atan,
21
+ cameraProjectionMatrix,
22
+ cameraViewport,
23
+ cos,
24
+ dot,
25
+ exp,
26
+ float,
27
+ highpModelViewMatrix,
28
+ instanceIndex,
29
+ max,
30
+ min,
31
+ normalize,
32
+ positionGeometry,
33
+ sin,
34
+ sqrt,
35
+ storage,
36
+ uint,
37
+ uniform,
38
+ unpackUnorm4x8,
39
+ varyingProperty,
40
+ vec2,
41
+ vec3,
42
+ vec4
43
+ } from '@gnsx/three/tsl';
44
+
45
+ import { CountingSort } from '../gpgpu/CountingSort.js';
46
+ import {
47
+ SH_BAND_COMPONENTS,
48
+ SH_BAND_WORDS,
49
+ getSphericalHarmonicsDegree
50
+ } from '../utils/GaussianSplatUtils.js';
51
+
52
+ const BIN_COUNT = 4096;
53
+ const WORKGROUP_SIZE = 256;
54
+ const SORT_DIRECTION_THRESHOLD = 0.9995;
55
+ const KERNEL_2D_SIZE = 0.3;
56
+ const SPLAT_KERNEL_CUTOFF = 2;
57
+ const COVARIANCE_FLATNESS = 1e-4;
58
+ const MIN_RAYCAST_OPACITY = 0.2;
59
+ const MAX_SCREEN_SPACE_SPLAT_SIZE = 1024;
60
+ const CLIP_XY = 1.4;
61
+
62
+ const _worldCenter = /*@__PURE__*/ new Vector3();
63
+ const _viewCenter = /*@__PURE__*/ new Vector3();
64
+ const _worldScale = /*@__PURE__*/ new Vector3();
65
+ const _sortDirection = /*@__PURE__*/ new Vector3();
66
+ const _sortDepthRange = /*@__PURE__*/ new Vector2();
67
+ const _worldMatrixInverse = /*@__PURE__*/ new Matrix4();
68
+ const _modelViewMatrix = /*@__PURE__*/ new Matrix4();
69
+ const _inverseMatrix = /*@__PURE__*/ new Matrix4();
70
+ const _ray = /*@__PURE__*/ new Ray();
71
+ const _sphere = /*@__PURE__*/ new Sphere();
72
+ const _covarianceMatrix = /*@__PURE__*/ new Matrix3();
73
+ const _originOffset = /*@__PURE__*/ new Vector3();
74
+ const _mDirection = /*@__PURE__*/ new Vector3();
75
+ const _mOriginOffset = /*@__PURE__*/ new Vector3();
76
+ const _vector = /*@__PURE__*/ new Vector3();
77
+
78
+ /**
79
+ * A minimal renderer for 3D Gaussian splat geometry.
80
+ *
81
+ * Note that this class can only be used with {@link WebGPURenderer}. The
82
+ * `forceWebGL` fallback of {@link WebGPURenderer} is supported, but
83
+ * {@link WebGLRenderer} is not. Import maps or package exports must resolve
84
+ * both `three/webgpu` and `three/tsl`.
85
+ *
86
+ * ```js
87
+ * const splats = new GaussianSplat( geometry );
88
+ * scene.add( splats );
89
+ * ```
90
+ *
91
+ * @augments Mesh
92
+ * @three_import import { GaussianSplat } from 'three/addons/objects/GaussianSplat.js';
93
+ */
94
+ class GaussianSplat extends Mesh {
95
+
96
+ /**
97
+ * Constructs a new Gaussian splat mesh.
98
+ *
99
+ * @param {BufferGeometry} splatGeometry - The splat geometry to render. Higher-order spherical harmonics attributes must use packed `Uint32Array` words from {@link createGaussianSplatGeometry} (`SH_BAND_WORDS[ degree ]` words per splat, four clamped-byte coefficients per word).
100
+ * @param {Object} [options] - Options.
101
+ * @param {boolean} [options.autoSort=true] - Whether to sort automatically in `onBeforeRender`.
102
+ */
103
+ constructor( splatGeometry, { autoSort = true } = {} ) {
104
+
105
+ const positionAttribute = splatGeometry.getAttribute( 'position' );
106
+ const covarianceAttribute = splatGeometry.getAttribute( 'covariance' );
107
+ const colorAttribute = splatGeometry.getAttribute( 'color' );
108
+ const sphericalHarmonicsDegree = getSphericalHarmonicsDegree( splatGeometry );
109
+ const count = positionAttribute.count;
110
+
111
+ if ( splatGeometry.boundingBox === null ) splatGeometry.computeBoundingBox();
112
+ if ( splatGeometry.boundingSphere === null ) splatGeometry.computeBoundingSphere();
113
+
114
+ const geometry = createGeometry( count );
115
+ const buffers = createStorageBuffers( count, positionAttribute.array, covarianceAttribute.array, colorAttribute.array, {
116
+ degree: sphericalHarmonicsDegree,
117
+ sh1: sphericalHarmonicsDegree >= 1 ? splatGeometry.getAttribute( 'sphericalHarmonics1' ).array : undefined,
118
+ sh2: sphericalHarmonicsDegree >= 2 ? splatGeometry.getAttribute( 'sphericalHarmonics2' ).array : undefined,
119
+ sh3: sphericalHarmonicsDegree >= 3 ? splatGeometry.getAttribute( 'sphericalHarmonics3' ).array : undefined
120
+ } );
121
+ const localCameraPosition = uniform( new Vector3() );
122
+ const sphericalHarmonicsComputeNode = createSphericalHarmonicsComputeNode( buffers, localCameraPosition );
123
+ const sort = new CountingSort( count, { binCount: BIN_COUNT, workgroupSize: WORKGROUP_SIZE } );
124
+ const materialNodes = createMaterialNodes( buffers, sort, localCameraPosition );
125
+ const material = createMaterial( materialNodes.vertexNode, materialNodes.fragmentNode );
126
+
127
+ super( geometry, material );
128
+
129
+ /**
130
+ * This flag can be used for type testing.
131
+ *
132
+ * @type {boolean}
133
+ * @readonly
134
+ * @default true
135
+ */
136
+ this.isGaussianSplat = true;
137
+
138
+ this.type = 'GaussianSplat';
139
+
140
+ /**
141
+ * The source splat geometry.
142
+ *
143
+ * @type {BufferGeometry}
144
+ */
145
+ this.splatGeometry = splatGeometry;
146
+
147
+ /**
148
+ * The bounding box of the splats. Can be computed via {@link GaussianSplat#computeBoundingBox}.
149
+ *
150
+ * @type {?Box3}
151
+ * @default null
152
+ */
153
+ this.boundingBox = null;
154
+
155
+ /**
156
+ * The bounding sphere of the splats. Can be computed via {@link GaussianSplat#computeBoundingSphere}.
157
+ *
158
+ * @type {?Sphere}
159
+ * @default null
160
+ */
161
+ this.boundingSphere = null;
162
+
163
+ /**
164
+ * Whether to sort automatically in `onBeforeRender`.
165
+ *
166
+ * @type {boolean}
167
+ */
168
+ this.autoSort = autoSort;
169
+
170
+ this._buffers = buffers;
171
+ this._sort = sort;
172
+ this._sortMatrix = uniform( new Matrix4() );
173
+ this._sortDepthRange = uniform( new Vector2( 0, 1 ) );
174
+ this._sortInitialized = false;
175
+ this._lastSortDirection = new Vector3();
176
+ this._localCameraPosition = localCameraPosition;
177
+ this._sphericalHarmonicsComputeNode = sphericalHarmonicsComputeNode;
178
+ this._sphericalHarmonicsInitialized = false;
179
+ this._lastSphericalHarmonicsCameraMatrix = new Matrix4();
180
+ this._lastSphericalHarmonicsWorldMatrix = new Matrix4();
181
+ this._sphericalHarmonicsVertexNode = materialNodes.sphericalHarmonicsVertexNode;
182
+ this._precomputedSphericalHarmonicsVertexNode = materialNodes.vertexNode;
183
+ this._positionAttribute = positionAttribute;
184
+
185
+ const centerRead = buffers.centerRead;
186
+ const sortMatrix = this._sortMatrix;
187
+ const sortDepthRange = this._sortDepthRange;
188
+
189
+ sort.setBinNode( () => {
190
+
191
+ const center = centerRead.element( instanceIndex ).xyz.toVar( 'center' );
192
+ const viewCenter = sortMatrix.mul( vec4( center, 1 ) ).xyz.toVar( 'viewCenter' );
193
+ const depth = viewCenter.z.negate().toVar( 'depth' );
194
+ const range = max( sortDepthRange.y.sub( sortDepthRange.x ), 0.0001 ).toVar( 'range' );
195
+ const normalized = depth.sub( sortDepthRange.x ).div( range ).clamp( 0, 1 ).toVar( 'normalized' );
196
+ const depthBin = uint( normalized.mul( BIN_COUNT - 1 ) ).toVar( 'depthBin' );
197
+
198
+ return uint( BIN_COUNT - 1 ).sub( depthBin );
199
+
200
+ } );
201
+
202
+ this.onBeforeRender = ( renderer, scene, camera ) => {
203
+
204
+ const vertexNode = renderer.backend && renderer.backend.isWebGLBackend === true ?
205
+ this._sphericalHarmonicsVertexNode :
206
+ this._precomputedSphericalHarmonicsVertexNode;
207
+
208
+ if ( vertexNode !== null && material.vertexNode !== vertexNode ) {
209
+
210
+ material.vertexNode = vertexNode;
211
+ material.needsUpdate = true;
212
+
213
+ }
214
+
215
+ this.updateSphericalHarmonics( renderer, camera );
216
+
217
+ if ( this.autoSort === true ) {
218
+
219
+ this.updateSort( renderer, camera );
220
+
221
+ }
222
+
223
+ };
224
+
225
+ }
226
+
227
+ /**
228
+ * Updates the view-dependent spherical harmonics colors if the camera or
229
+ * mesh transform has changed.
230
+ *
231
+ * @param {Renderer} renderer - The renderer.
232
+ * @param {Camera} camera - The camera used for rendering.
233
+ * @return {boolean} Whether a compute pass was dispatched this call.
234
+ */
235
+ updateSphericalHarmonics( renderer, camera ) {
236
+
237
+ if ( this._sphericalHarmonicsComputeNode === null ) return false;
238
+
239
+ const isWebGLBackend = renderer.backend && renderer.backend.isWebGLBackend === true;
240
+
241
+ if ( this._sphericalHarmonicsInitialized === true &&
242
+ camera.matrixWorld.equals( this._lastSphericalHarmonicsCameraMatrix ) &&
243
+ this.matrixWorld.equals( this._lastSphericalHarmonicsWorldMatrix ) &&
244
+ ( isWebGLBackend === true || this._buffers.sphericalHarmonicsContributionRead !== undefined ) ) {
245
+
246
+ return false;
247
+
248
+ }
249
+
250
+ if ( isWebGLBackend === true ) {
251
+
252
+ enableWebGLBuffers( this._buffers );
253
+
254
+ }
255
+
256
+ _worldMatrixInverse.copy( this.matrixWorld ).invert();
257
+ this._localCameraPosition.value.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4( _worldMatrixInverse );
258
+
259
+ this._lastSphericalHarmonicsCameraMatrix.copy( camera.matrixWorld );
260
+ this._lastSphericalHarmonicsWorldMatrix.copy( this.matrixWorld );
261
+ this._sphericalHarmonicsInitialized = true;
262
+
263
+ if ( isWebGLBackend === true ) return false;
264
+
265
+ ensureSphericalHarmonicsContributionBuffer( this._buffers );
266
+ renderer.compute( this._sphericalHarmonicsComputeNode );
267
+
268
+ return true;
269
+
270
+ }
271
+
272
+ /**
273
+ * Computes the bounding box of the splats, updating {@link GaussianSplat#boundingBox}.
274
+ *
275
+ * Each splat is expanded by its own extent rather than treated as a point, so the bounds cover
276
+ * what is drawn.
277
+ */
278
+ computeBoundingBox() {
279
+
280
+ if ( this.boundingBox === null ) this.boundingBox = new Box3();
281
+
282
+ this.boundingBox.makeEmpty();
283
+
284
+ const positionAttribute = this.splatGeometry.getAttribute( 'position' );
285
+ const covarianceAttribute = this.splatGeometry.getAttribute( 'covariance' );
286
+ const count = positionAttribute.count;
287
+
288
+ for ( let i = 0; i < count; i ++ ) {
289
+
290
+ const x = positionAttribute.getX( i );
291
+ const y = positionAttribute.getY( i );
292
+ const z = positionAttribute.getZ( i );
293
+
294
+ const c00 = covarianceAttribute.getComponent( i, 0 );
295
+ const c11 = covarianceAttribute.getComponent( i, 3 );
296
+ const c22 = covarianceAttribute.getComponent( i, 5 );
297
+
298
+ // the radius of the drawn largest extent
299
+ const radius = SPLAT_KERNEL_CUTOFF * Math.sqrt( Math.max( c00, c11, c22 ) );
300
+
301
+ this.boundingBox.expandByPoint( _vector.set( x - radius, y - radius, z - radius ) );
302
+ this.boundingBox.expandByPoint( _vector.set( x + radius, y + radius, z + radius ) );
303
+
304
+ }
305
+
306
+ }
307
+
308
+ /**
309
+ * Computes the bounding sphere of the splats, updating {@link GaussianSplat#boundingSphere}.
310
+ *
311
+ * Each splat is expanded by its own extent rather than treated as a point, so the bounds cover
312
+ * what is drawn.
313
+ */
314
+ computeBoundingSphere() {
315
+
316
+ if ( this.boundingSphere === null ) this.boundingSphere = new Sphere();
317
+
318
+ this.computeBoundingBox();
319
+ this.boundingBox.getBoundingSphere( this.boundingSphere );
320
+
321
+ const positionAttribute = this.splatGeometry.getAttribute( 'position' );
322
+ const covarianceAttribute = this.splatGeometry.getAttribute( 'covariance' );
323
+ const count = positionAttribute.count;
324
+ const center = this.boundingSphere.center;
325
+
326
+ let maxRadius = 0;
327
+
328
+ for ( let i = 0; i < count; i ++ ) {
329
+
330
+ const x = positionAttribute.getX( i );
331
+ const y = positionAttribute.getY( i );
332
+ const z = positionAttribute.getZ( i );
333
+
334
+ const c00 = covarianceAttribute.getComponent( i, 0 );
335
+ const c11 = covarianceAttribute.getComponent( i, 3 );
336
+ const c22 = covarianceAttribute.getComponent( i, 5 );
337
+
338
+ // the radius of the drawn largest extent
339
+ const radius = SPLAT_KERNEL_CUTOFF * Math.sqrt( Math.max( c00, c11, c22 ) );
340
+
341
+ maxRadius = Math.max( maxRadius, center.distanceTo( _vector.set( x, y, z ) ) + radius );
342
+
343
+ }
344
+
345
+ this.boundingSphere.radius = maxRadius;
346
+
347
+ }
348
+
349
+ /**
350
+ * Computes intersection points between a casted ray and the splats.
351
+ *
352
+ * @param {Raycaster} raycaster - The raycaster.
353
+ * @param {Array<Object>} intersects - The target array that holds the intersection points.
354
+ */
355
+ raycast( raycaster, intersects ) {
356
+
357
+ const matrixWorld = this.matrixWorld;
358
+
359
+ // Checking boundingSphere distance to ray
360
+
361
+ if ( this.boundingSphere === null ) this.computeBoundingSphere();
362
+
363
+ _sphere.copy( this.boundingSphere );
364
+ _sphere.applyMatrix4( matrixWorld );
365
+
366
+ if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
367
+
368
+ //
369
+
370
+ _inverseMatrix.copy( matrixWorld ).invert();
371
+ _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
372
+
373
+ // test with bounding box in local space
374
+
375
+ if ( this.boundingBox !== null ) {
376
+
377
+ if ( _ray.intersectsBox( this.boundingBox ) === false ) return;
378
+
379
+ }
380
+
381
+ const positionAttribute = this.splatGeometry.getAttribute( 'position' );
382
+ const covarianceAttribute = this.splatGeometry.getAttribute( 'covariance' );
383
+ const colorAttribute = this.splatGeometry.getAttribute( 'color' );
384
+ const count = positionAttribute.count;
385
+
386
+ for ( let i = 0; i < count; i ++ ) {
387
+
388
+ computeRayIntersection( positionAttribute, covarianceAttribute, colorAttribute, i, matrixWorld, raycaster, intersects, this );
389
+
390
+ }
391
+
392
+ }
393
+
394
+ /**
395
+ * Updates the draw order if the camera or mesh orientation has changed enough
396
+ * to need a new sort.
397
+ *
398
+ * @param {Renderer} renderer - The renderer.
399
+ * @param {Camera} camera - The camera used for rendering.
400
+ * @return {boolean} Whether a sort was dispatched this call.
401
+ */
402
+ updateSort( renderer, camera ) {
403
+
404
+ this.updateWorldMatrix( true, false );
405
+
406
+ const needsSort = this._needsSort( camera );
407
+
408
+ if ( this._sortInitialized === false || needsSort === true ) {
409
+
410
+ this._updateSortUniforms( camera );
411
+
412
+ if ( renderer.backend && renderer.backend.isWebGLBackend === true ) {
413
+
414
+ enableWebGLBuffers( this._buffers );
415
+ this._sort.enableWebGLBuffers();
416
+ this._sortCPU();
417
+
418
+ } else {
419
+
420
+ this._sort.compute( renderer );
421
+
422
+ }
423
+
424
+ this._sortInitialized = true;
425
+ this._lastSortDirection.copy( _sortDirection );
426
+
427
+ return true;
428
+
429
+ }
430
+
431
+ return false;
432
+
433
+ }
434
+
435
+ _needsSort( camera ) {
436
+
437
+ _modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, this.matrixWorld );
438
+
439
+ const e = _modelViewMatrix.elements;
440
+ _sortDirection.set( e[ 2 ], e[ 6 ], e[ 10 ] ).normalize();
441
+
442
+ return _sortDirection.dot( this._lastSortDirection ) < SORT_DIRECTION_THRESHOLD;
443
+
444
+ }
445
+
446
+ _updateSortUniforms( camera ) {
447
+
448
+ this._sortMatrix.value.multiplyMatrices( camera.matrixWorldInverse, this.matrixWorld );
449
+
450
+ if ( this.boundingSphere === null ) this.computeBoundingSphere();
451
+
452
+ _worldCenter.copy( this.boundingSphere.center ).applyMatrix4( this.matrixWorld );
453
+ _viewCenter.copy( _worldCenter ).applyMatrix4( camera.matrixWorldInverse );
454
+
455
+ _worldScale.setFromMatrixScale( this.matrixWorld );
456
+
457
+ const radius = this.boundingSphere.radius * Math.max( _worldScale.x, _worldScale.y, _worldScale.z );
458
+ const depth = - _viewCenter.z;
459
+ const nearDepth = Math.max( camera.near, depth - radius );
460
+ const farDepth = Math.max( nearDepth + 0.0001, depth + radius );
461
+
462
+ _sortDepthRange.set( nearDepth, farDepth );
463
+ this._sortDepthRange.value.copy( _sortDepthRange );
464
+
465
+ }
466
+
467
+ _sortCPU() {
468
+
469
+ const centers = this._positionAttribute.array;
470
+ const matrix = this._sortMatrix.value.elements;
471
+ const nearDepth = this._sortDepthRange.value.x;
472
+ const range = Math.max( this._sortDepthRange.value.y - nearDepth, 0.0001 );
473
+ const scale = ( BIN_COUNT - 1 ) / range;
474
+
475
+ this._sort.computeCPU( ( i ) => {
476
+
477
+ const i3 = i * 3;
478
+ const depth = - ( matrix[ 2 ] * centers[ i3 ] + matrix[ 6 ] * centers[ i3 + 1 ] + matrix[ 10 ] * centers[ i3 + 2 ] + matrix[ 14 ] );
479
+ const depthBin = Math.min( BIN_COUNT - 1, Math.max( 0, Math.floor( ( depth - nearDepth ) * scale ) ) );
480
+
481
+ return BIN_COUNT - 1 - depthBin;
482
+
483
+ } );
484
+
485
+ }
486
+
487
+ }
488
+
489
+ // Intersects the ray with the ellipsoid the splat's covariance describes, which reduces to a
490
+ // quadratic in t whose smaller root is the near surface.
491
+ function computeRayIntersection( positionAttribute, covarianceAttribute, colorAttribute, index, matrixWorld, raycaster, intersects, object ) {
492
+
493
+ // skip faint splats - cheapest possible rejection, a single attribute read
494
+ if ( colorAttribute.getW( index ) < MIN_RAYCAST_OPACITY ) {
495
+
496
+ return;
497
+
498
+ }
499
+
500
+ // the diagonal of the covariance bounds the splat's drawn extent (same radius used by
501
+ // computeBoundingBox/computeBoundingSphere); reject rays that don't pass near the splat
502
+ // at all before doing any of the more expensive matrix work below
503
+ const c00 = covarianceAttribute.getComponent( index, 0 );
504
+ const c11 = covarianceAttribute.getComponent( index, 3 );
505
+ const c22 = covarianceAttribute.getComponent( index, 5 );
506
+ const maxVariance = Math.max( c00, c11, c22 );
507
+
508
+ if ( maxVariance <= 0 ) {
509
+
510
+ return;
511
+
512
+ }
513
+
514
+ const center = _vector.fromBufferAttribute( positionAttribute, index );
515
+ const boundingRadius = SPLAT_KERNEL_CUTOFF * Math.sqrt( maxVariance );
516
+
517
+ if ( _ray.distanceSqToPoint( center ) > boundingRadius * boundingRadius ) {
518
+
519
+ return;
520
+
521
+ }
522
+
523
+ // the attribute holds the upper triangle of the symmetric covariance
524
+ const c01 = covarianceAttribute.getComponent( index, 1 );
525
+ const c02 = covarianceAttribute.getComponent( index, 2 );
526
+ const c12 = covarianceAttribute.getComponent( index, 4 );
527
+
528
+ // splats are often flat enough to make the covariance singular, so the thinnest axis is floored
529
+ // relative to the widest to keep the quadratic solvable
530
+ const minVariance = maxVariance * COVARIANCE_FLATNESS;
531
+
532
+ _covarianceMatrix.set(
533
+ c00 + minVariance, c01, c02,
534
+ c01, c11 + minVariance, c12,
535
+ c02, c12, c22 + minVariance
536
+ );
537
+
538
+ const determinant = _covarianceMatrix.determinant();
539
+
540
+ if ( determinant <= 0 ) {
541
+
542
+ return;
543
+
544
+ }
545
+
546
+ // inverse( covariance ), applied below to the ray direction and to the origin offset
547
+ _covarianceMatrix.invert();
548
+
549
+ _mDirection.copy( _ray.direction ).applyMatrix3( _covarianceMatrix );
550
+
551
+ // squared length of the ray direction in the ellipsoid's metric; must be positive for a valid covariance
552
+ const a = _ray.direction.dot( _mDirection );
553
+
554
+ if ( a <= 0 ) {
555
+
556
+ return;
557
+
558
+ }
559
+
560
+ _originOffset.copy( _ray.origin ).sub( center );
561
+ _mOriginOffset.copy( _originOffset ).applyMatrix3( _covarianceMatrix );
562
+
563
+ const b = 2 * _originOffset.dot( _mDirection );
564
+ const c = _originOffset.dot( _mOriginOffset ) - SPLAT_KERNEL_CUTOFF * SPLAT_KERNEL_CUTOFF;
565
+ const discriminant = b * b - 4 * a * c;
566
+
567
+ if ( discriminant < 0 ) {
568
+
569
+ return;
570
+
571
+ }
572
+
573
+ const sqrtDiscriminant = Math.sqrt( discriminant );
574
+ let t = ( - b - sqrtDiscriminant ) / ( 2 * a );
575
+
576
+ // the near surface is behind the origin when the ray starts inside the splat
577
+ if ( t < 0 ) {
578
+
579
+ t = ( - b + sqrtDiscriminant ) / ( 2 * a );
580
+
581
+ }
582
+
583
+ if ( t < 0 ) {
584
+
585
+ return;
586
+
587
+ }
588
+
589
+ const intersectPoint = new Vector3();
590
+ _ray.at( t, intersectPoint ).applyMatrix4( matrixWorld );
591
+
592
+ const distance = raycaster.ray.origin.distanceTo( intersectPoint );
593
+ if ( distance < raycaster.near || distance > raycaster.far ) {
594
+
595
+ return;
596
+
597
+ }
598
+
599
+ intersects.push( {
600
+
601
+ distance: distance,
602
+ point: intersectPoint,
603
+ index: index,
604
+ face: null,
605
+ faceIndex: null,
606
+ barycoord: null,
607
+ object: object
608
+
609
+ } );
610
+
611
+ }
612
+
613
+ function createGeometry( count ) {
614
+
615
+ const geometry = new InstancedBufferGeometry();
616
+ geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( [
617
+ - 2, - 2, 0,
618
+ 2, - 2, 0,
619
+ 2, 2, 0,
620
+ - 2, 2, 0
621
+ ] ), 3 ) );
622
+ geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );
623
+ geometry.instanceCount = count;
624
+
625
+ return geometry;
626
+
627
+ }
628
+
629
+ function createStorageBuffers( count, centers, covariances, colors, sphericalHarmonics ) {
630
+
631
+ const centerData = new Float32Array( count * 4 );
632
+ const covarianceAData = new Float32Array( count * 4 );
633
+ const covarianceBData = new Float32Array( count * 4 );
634
+ const colorData = new Uint32Array( count );
635
+ const sphericalHarmonicsDegree = sphericalHarmonics.degree;
636
+
637
+ for ( let i = 0; i < count; i ++ ) {
638
+
639
+ const i3 = i * 3;
640
+ const i4 = i * 4;
641
+ const i6 = i * 6;
642
+
643
+ centerData[ i4 ] = centers[ i3 ];
644
+ centerData[ i4 + 1 ] = centers[ i3 + 1 ];
645
+ centerData[ i4 + 2 ] = centers[ i3 + 2 ];
646
+
647
+ covarianceAData[ i4 ] = covariances[ i6 ];
648
+ covarianceAData[ i4 + 1 ] = covariances[ i6 + 1 ];
649
+ covarianceAData[ i4 + 2 ] = covariances[ i6 + 2 ];
650
+ covarianceAData[ i4 + 3 ] = covariances[ i6 + 3 ];
651
+
652
+ covarianceBData[ i4 ] = covariances[ i6 + 4 ];
653
+ covarianceBData[ i4 + 1 ] = covariances[ i6 + 5 ];
654
+
655
+ colorData[ i ] = ( colors[ i4 ] |
656
+ colors[ i4 + 1 ] << 8 |
657
+ colors[ i4 + 2 ] << 16 |
658
+ colors[ i4 + 3 ] << 24 ) >>> 0;
659
+
660
+ }
661
+
662
+ const centerAttribute = new StorageBufferAttribute( centerData, 4 );
663
+ const covarianceAAttribute = new StorageBufferAttribute( covarianceAData, 4 );
664
+ const covarianceBAttribute = new StorageBufferAttribute( covarianceBData, 4 );
665
+ const colorAttribute = new StorageBufferAttribute( colorData, 1 );
666
+
667
+ const buffers = {
668
+ count,
669
+ sphericalHarmonicsDegree,
670
+ webGLBuffersEnabled: false,
671
+ centerRead: storage( centerAttribute, 'vec4', count ).toReadOnly(),
672
+ covarianceARead: storage( covarianceAAttribute, 'vec4', count ).toReadOnly(),
673
+ covarianceBRead: storage( covarianceBAttribute, 'vec4', count ).toReadOnly(),
674
+ colorRead: storage( colorAttribute, 'uint', count ).toReadOnly()
675
+ };
676
+
677
+ for ( let degree = 1; degree <= sphericalHarmonicsDegree; degree ++ ) {
678
+
679
+ const words = SH_BAND_WORDS[ degree ];
680
+ const attribute = new StorageBufferAttribute( sphericalHarmonics[ `sh${ degree }` ], 1 );
681
+
682
+ buffers[ `sphericalHarmonics${ degree }Attribute` ] = attribute;
683
+ buffers[ `sphericalHarmonics${ degree }Read` ] = storage( attribute, 'uint', count * words ).toReadOnly();
684
+ buffers[ `sphericalHarmonics${ degree }Words` ] = words;
685
+
686
+ }
687
+
688
+ return buffers;
689
+
690
+ }
691
+
692
+ function ensureSphericalHarmonicsContributionBuffer( buffers ) {
693
+
694
+ if ( buffers.sphericalHarmonicsContributionRead !== undefined ) return;
695
+
696
+ // WebGPU stores one precomputed SH contribution per splat. The WebGL
697
+ // fallback evaluates SH in the vertex shader because its transform-feedback
698
+ // compute path cannot perform the packed buffer's indexed reads, so allocate
699
+ // this additional buffer lazily only when the WebGPU pre-pass runs.
700
+ const attribute = new StorageBufferAttribute( new Float32Array( buffers.count * 4 ), 4 );
701
+
702
+ buffers.sphericalHarmonicsContributionRead = storage( attribute, 'vec4', buffers.count ).toReadOnly();
703
+ buffers.sphericalHarmonicsContributionWrite = storage( attribute, 'vec4', buffers.count );
704
+
705
+ }
706
+
707
+ function enableWebGLBuffers( buffers ) {
708
+
709
+ if ( buffers.webGLBuffersEnabled === true ) return;
710
+
711
+ buffers.centerRead.setPBO( true );
712
+ buffers.covarianceARead.setPBO( true );
713
+ buffers.covarianceBRead.setPBO( true );
714
+ buffers.colorRead.setPBO( true );
715
+
716
+ for ( let degree = 1; degree <= buffers.sphericalHarmonicsDegree; degree ++ ) {
717
+
718
+ buffers[ `sphericalHarmonics${ degree }Read` ].setPBO( true );
719
+
720
+ }
721
+
722
+ buffers.webGLBuffersEnabled = true;
723
+
724
+ }
725
+
726
+ function unpackSphericalHarmonicsCoefficients( buffer, splatIndex, words, componentCount ) {
727
+
728
+ const coefficients = [];
729
+ let remaining = componentCount;
730
+
731
+ for ( let word = 0; word < words && remaining > 0; word ++ ) {
732
+
733
+ const packed = buffer.element( splatIndex.mul( words ).add( word ) ).toVar();
734
+ const bytesInWord = Math.min( 4, remaining );
735
+
736
+ for ( let byteIndex = 0; byteIndex < bytesInWord; byteIndex ++ ) {
737
+
738
+ const byte = packed.shiftRight( byteIndex * 8 ).bitAnd( 0xff );
739
+ coefficients.push( float( byte ).sub( 128 ).div( 128 ) );
740
+
741
+ }
742
+
743
+ remaining -= bytesInWord;
744
+
745
+ }
746
+
747
+ return coefficients;
748
+
749
+ }
750
+
751
+ function assembleSphericalHarmonicsVectors( coefficients, name ) {
752
+
753
+ const vectors = [];
754
+ const vectorCount = coefficients.length / 3;
755
+
756
+ for ( let i = 0; i < vectorCount; i ++ ) {
757
+
758
+ const offset = i * 3;
759
+ vectors.push( vec3(
760
+ coefficients[ offset ],
761
+ coefficients[ offset + 1 ],
762
+ coefficients[ offset + 2 ]
763
+ ).toVar( `${ name }${ i }` ) );
764
+
765
+ }
766
+
767
+ return vectors;
768
+
769
+ }
770
+
771
+ function accumulateSphericalHarmonics( vectors, weights ) {
772
+
773
+ let result = vectors[ 0 ].mul( weights[ 0 ] );
774
+
775
+ for ( let i = 1; i < vectors.length; i ++ ) {
776
+
777
+ result = result.add( vectors[ i ].mul( weights[ i ] ) );
778
+
779
+ }
780
+
781
+ return result;
782
+
783
+ }
784
+
785
+ function applySphericalHarmonicsBand( buffer, splatIndex, words, componentCount, name, weights ) {
786
+
787
+ const coefficients = unpackSphericalHarmonicsCoefficients( buffer, splatIndex, words, componentCount );
788
+ const vectors = assembleSphericalHarmonicsVectors( coefficients, name );
789
+
790
+ return accumulateSphericalHarmonics( vectors, weights );
791
+
792
+ }
793
+
794
+ function applySphericalHarmonics( rgb, center, localCameraPosition, splatIndex, buffers ) {
795
+
796
+ const viewDirection = normalize( center.sub( localCameraPosition ) ).toVar( 'sphericalHarmonicsViewDirection' );
797
+ const x = viewDirection.x;
798
+ const y = viewDirection.y;
799
+ const z = viewDirection.z;
800
+
801
+ rgb.addAssign( applySphericalHarmonicsBand(
802
+ buffers.sphericalHarmonics1Read,
803
+ splatIndex,
804
+ buffers.sphericalHarmonics1Words,
805
+ SH_BAND_COMPONENTS[ 1 ],
806
+ 'sh1_',
807
+ [
808
+ y.mul( - 0.4886025 ),
809
+ z.mul( 0.4886025 ),
810
+ x.mul( - 0.4886025 )
811
+ ]
812
+ ) );
813
+
814
+ if ( buffers.sphericalHarmonicsDegree >= 2 ) {
815
+
816
+ const xx = x.mul( x ).toVar( 'shXX' );
817
+ const yy = y.mul( y ).toVar( 'shYY' );
818
+ const zz = z.mul( z ).toVar( 'shZZ' );
819
+
820
+ rgb.addAssign( applySphericalHarmonicsBand(
821
+ buffers.sphericalHarmonics2Read,
822
+ splatIndex,
823
+ buffers.sphericalHarmonics2Words,
824
+ SH_BAND_COMPONENTS[ 2 ],
825
+ 'sh2_',
826
+ [
827
+ x.mul( y ).mul( 1.0925484 ),
828
+ y.mul( z ).mul( - 1.0925484 ),
829
+ zz.mul( 2 ).sub( xx ).sub( yy ).mul( 0.3153915 ),
830
+ x.mul( z ).mul( - 1.0925484 ),
831
+ xx.sub( yy ).mul( 0.5462742 )
832
+ ]
833
+ ) );
834
+
835
+ if ( buffers.sphericalHarmonicsDegree >= 3 ) {
836
+
837
+ const xy = x.mul( y ).toVar( 'shXY' );
838
+
839
+ rgb.addAssign( applySphericalHarmonicsBand(
840
+ buffers.sphericalHarmonics3Read,
841
+ splatIndex,
842
+ buffers.sphericalHarmonics3Words,
843
+ SH_BAND_COMPONENTS[ 3 ],
844
+ 'sh3_',
845
+ [
846
+ y.mul( xx.mul( 3 ).sub( yy ) ).mul( - 0.5900436 ),
847
+ xy.mul( z ).mul( 2.8906114 ),
848
+ y.mul( zz.mul( 4 ).sub( xx ).sub( yy ) ).mul( - 0.4570458 ),
849
+ z.mul( zz.mul( 2 ).sub( xx.mul( 3 ) ).sub( yy.mul( 3 ) ) ).mul( 0.3731763 ),
850
+ x.mul( zz.mul( 4 ).sub( xx ).sub( yy ) ).mul( - 0.4570458 ),
851
+ z.mul( xx.sub( yy ) ).mul( 1.4453057 ),
852
+ x.mul( xx.sub( yy.mul( 3 ) ) ).mul( - 0.5900436 )
853
+ ]
854
+ ) );
855
+
856
+ }
857
+
858
+ }
859
+
860
+ }
861
+
862
+ function createSphericalHarmonicsComputeNode( buffers, localCameraPosition ) {
863
+
864
+ if ( buffers.sphericalHarmonicsDegree === 0 ) return null;
865
+
866
+ return Fn( () => {
867
+
868
+ const splatIndex = instanceIndex;
869
+ const center = buffers.centerRead.element( splatIndex ).xyz.toVar( 'center' );
870
+ const rgb = vec3( 0 ).toVar( 'sphericalHarmonicsContribution' );
871
+
872
+ applySphericalHarmonics( rgb, center, localCameraPosition, splatIndex, buffers );
873
+ buffers.sphericalHarmonicsContributionWrite.element( splatIndex ).assign( vec4( rgb, 0 ) );
874
+
875
+ } )().compute( buffers.count, [ WORKGROUP_SIZE ] ).setName( 'GaussianSplatSphericalHarmonics' );
876
+
877
+ }
878
+
879
+ function createMaterialNodes( buffers, sort, localCameraPosition ) {
880
+
881
+ const splatUv = varyingProperty( 'vec2', 'vSplatUv' );
882
+ const splatColor = varyingProperty( 'vec4', 'vSplatColor' );
883
+
884
+ const createVertexNode = ( usePrecomputedSphericalHarmonics ) => Fn( () => {
885
+
886
+ const splatIndex = sort.orderRead.element( instanceIndex ).toVar( 'splatIndex' );
887
+ const center = buffers.centerRead.element( splatIndex ).xyz.toVar( 'center' );
888
+ const covA = buffers.covarianceARead.element( splatIndex ).toVar( 'covA' );
889
+ const covB = buffers.covarianceBRead.element( splatIndex ).toVar( 'covB' );
890
+ const color = unpackUnorm4x8( buffers.colorRead.element( splatIndex ) ).toVar( 'splatColor' );
891
+ const rgb = color.rgb.toVar( 'splatRgb' );
892
+
893
+ if ( buffers.sphericalHarmonicsDegree > 0 ) {
894
+
895
+ if ( usePrecomputedSphericalHarmonics === true ) {
896
+
897
+ rgb.addAssign( buffers.sphericalHarmonicsContributionRead.element( splatIndex ).rgb );
898
+
899
+ } else {
900
+
901
+ applySphericalHarmonics( rgb, center, localCameraPosition, splatIndex, buffers );
902
+
903
+ }
904
+
905
+ }
906
+
907
+ splatUv.assign( positionGeometry.xy );
908
+
909
+ const viewCenter4 = highpModelViewMatrix.mul( vec4( center, 1 ) ).toVar( 'viewCenter4' );
910
+ const viewCenter = viewCenter4.xyz.toVar( 'viewCenter' );
911
+ const centerClip = cameraProjectionMatrix.mul( viewCenter4 ).toVar( 'centerClip' );
912
+
913
+ const m = highpModelViewMatrix;
914
+ const r0 = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x ).toVar( 'r0' );
915
+ const r1 = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y ).toVar( 'r1' );
916
+ const r2 = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z ).toVar( 'r2' );
917
+
918
+ const cov0 = vec3( covA.x, covA.y, covA.z ).toVar( 'cov0' );
919
+ const cov1 = vec3( covA.y, covA.w, covB.x ).toVar( 'cov1' );
920
+ const cov2 = vec3( covA.z, covB.x, covB.y ).toVar( 'cov2' );
921
+
922
+ const vc0 = vec3( dot( r0, cov0 ), dot( r0, cov1 ), dot( r0, cov2 ) ).toVar( 'vc0' );
923
+ const vc1 = vec3( dot( r1, cov0 ), dot( r1, cov1 ), dot( r1, cov2 ) ).toVar( 'vc1' );
924
+ const vc2 = vec3( dot( r2, cov0 ), dot( r2, cov1 ), dot( r2, cov2 ) ).toVar( 'vc2' );
925
+
926
+ const c00 = dot( vc0, r0 ).toVar( 'c00' );
927
+ const c01 = dot( vc0, r1 ).toVar( 'c01' );
928
+ const c02 = dot( vc0, r2 ).toVar( 'c02' );
929
+ const c11 = dot( vc1, r1 ).toVar( 'c11' );
930
+ const c12 = dot( vc1, r2 ).toVar( 'c12' );
931
+ const c22 = dot( vc2, r2 ).toVar( 'c22' );
932
+
933
+ const z = min( viewCenter.z, - 0.01 ).toVar( 'z' );
934
+ const invZ = float( 1 ).div( z ).toVar( 'invZ' );
935
+ const invZ2 = invZ.mul( invZ ).toVar( 'invZ2' );
936
+ const focal = cameraViewport.zw.mul( 0.5 ).mul( vec2( cameraProjectionMatrix[ 0 ].x, cameraProjectionMatrix[ 1 ].y ) ).toVar( 'focal' );
937
+
938
+ const j00 = focal.x.negate().mul( invZ ).toVar( 'j00' );
939
+ const j11 = focal.y.negate().mul( invZ ).toVar( 'j11' );
940
+ const j02 = focal.x.mul( viewCenter.x ).mul( invZ2 ).toVar( 'j02' );
941
+ const j12 = focal.y.mul( viewCenter.y ).mul( invZ2 ).toVar( 'j12' );
942
+
943
+ const aBase = j00.mul( j00 ).mul( c00 )
944
+ .add( j00.mul( j02 ).mul( c02 ).mul( 2 ) )
945
+ .add( j02.mul( j02 ).mul( c22 ) )
946
+ .toVar( 'cov2dABase' );
947
+ const b = j00.mul( j11 ).mul( c01 )
948
+ .add( j00.mul( j12 ).mul( c02 ) )
949
+ .add( j02.mul( j11 ).mul( c12 ) )
950
+ .add( j02.mul( j12 ).mul( c22 ) )
951
+ .toVar( 'cov2dB' );
952
+ const cBase = j11.mul( j11 ).mul( c11 )
953
+ .add( j11.mul( j12 ).mul( c12 ).mul( 2 ) )
954
+ .add( j12.mul( j12 ).mul( c22 ) )
955
+ .toVar( 'cov2dCBase' );
956
+ const a = aBase.add( KERNEL_2D_SIZE ).toVar( 'cov2dA' );
957
+ const c = cBase.add( KERNEL_2D_SIZE ).toVar( 'cov2dC' );
958
+ const detBase = aBase.mul( cBase ).sub( b.mul( b ) ).toVar( 'detBase' );
959
+ const det = a.mul( c ).sub( b.mul( b ) ).toVar( 'det' );
960
+ const alphaScale = sqrt( max( detBase.div( max( det, 0.000001 ) ), 0 ) ).toVar( 'alphaScale' );
961
+
962
+ splatColor.assign( vec4( rgb.clamp( 0, 1 ), color.a.mul( alphaScale ) ) );
963
+
964
+ const halfTrace = a.add( c ).mul( 0.5 ).toVar( 'halfTrace' );
965
+ const radius = sqrt( max( a.sub( c ).mul( 0.5 ).pow2().add( b.mul( b ) ), 0.0000001 ) ).toVar( 'radius' );
966
+ const lambda1 = max( halfTrace.add( radius ), 0.0000001 ).toVar( 'lambda1' );
967
+ const lambda2 = max( halfTrace.sub( radius ), 0.0000001 ).toVar( 'lambda2' );
968
+ const axis1 = vec2( 1, 0 ).toVar( 'axis1' );
969
+
970
+ If( radius.greaterThan( 0.00001 ), () => {
971
+
972
+ const angle = atan( b.mul( 2 ), a.sub( c ) ).mul( 0.5 ).toVar( 'angle' );
973
+ axis1.assign( vec2( cos( angle ), sin( angle ) ) );
974
+
975
+ } );
976
+
977
+ const axis2 = vec2( axis1.y.negate(), axis1.x ).toVar( 'axis2' );
978
+
979
+ const scale1 = min( sqrt( lambda1 ), MAX_SCREEN_SPACE_SPLAT_SIZE ).toVar( 'scale1' );
980
+ const scale2 = min( sqrt( lambda2 ), MAX_SCREEN_SPACE_SPLAT_SIZE ).toVar( 'scale2' );
981
+ const offsetPixels = axis1.mul( positionGeometry.x ).mul( scale1 ).add( axis2.mul( positionGeometry.y ).mul( scale2 ) ).toVar( 'offsetPixels' );
982
+ const offsetNdc = offsetPixels.mul( 2 ).div( cameraViewport.zw ).toVar( 'offsetNdc' );
983
+ const clip = centerClip.add( vec4( offsetNdc.mul( centerClip.w ), 0, 0 ) ).toVar( 'clip' );
984
+
985
+ const clipLimit = centerClip.w.mul( CLIP_XY ).toVar( 'clipLimit' );
986
+
987
+ If( viewCenter.z.greaterThanEqual( - 0.01 )
988
+ .or( centerClip.z.lessThan( centerClip.w.negate() ) )
989
+ .or( centerClip.z.greaterThan( centerClip.w ) )
990
+ .or( centerClip.x.lessThan( clipLimit.negate() ) )
991
+ .or( centerClip.x.greaterThan( clipLimit ) )
992
+ .or( centerClip.y.lessThan( clipLimit.negate() ) )
993
+ .or( centerClip.y.greaterThan( clipLimit ) ), () => {
994
+
995
+ clip.assign( vec4( 2, 2, 2, 1 ) );
996
+
997
+ } );
998
+
999
+ return clip;
1000
+
1001
+ } )();
1002
+
1003
+ const vertexNode = createVertexNode( true );
1004
+ const sphericalHarmonicsVertexNode = buffers.sphericalHarmonicsDegree > 0 ? createVertexNode( false ) : null;
1005
+
1006
+ const fragmentNode = Fn( () => {
1007
+
1008
+ const r2 = dot( splatUv, splatUv ).toVar( 'r2' );
1009
+
1010
+ If( r2.greaterThan( 4 ), () => {
1011
+
1012
+ Discard();
1013
+
1014
+ } );
1015
+
1016
+ return vec4( splatColor.rgb, exp( r2.mul( - 0.5 ) ).mul( splatColor.a ) );
1017
+
1018
+ } )();
1019
+
1020
+ return { vertexNode, sphericalHarmonicsVertexNode, fragmentNode };
1021
+
1022
+ }
1023
+
1024
+ function createMaterial( vertexNode, fragmentNode ) {
1025
+
1026
+ const material = new NodeMaterial();
1027
+ material.vertexNode = vertexNode;
1028
+ material.colorNode = fragmentNode;
1029
+ material.transparent = true;
1030
+ material.depthWrite = false;
1031
+ material.depthTest = true;
1032
+ material.forceSinglePass = true;
1033
+ material.fog = false;
1034
+
1035
+ return material;
1036
+
1037
+ }
1038
+
1039
+ export { GaussianSplat };