@gnsx/three 0.185.16 → 0.186.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (417) hide show
  1. package/build/three.cjs +10 -82600
  2. package/build/three.core.js +1303 -728
  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/build/three.core.min.js +0 -6
  411. package/build/three.module.min.js +0 -6
  412. package/build/three.tsl.min.js +0 -6
  413. package/build/three.webgpu.min.js +0 -6
  414. package/build/three.webgpu.nodes.min.js +0 -6
  415. package/examples/jsm/libs/ecsy.module.js +0 -1792
  416. package/examples/jsm/loaders/LottieLoader.js +0 -130
  417. package/src/nodes/functions/BSDF/BRDF_GGX_Multiscatter.js +0 -52
@@ -4,11 +4,15 @@ import { Item } from '../ui/Item.js';
4
4
  import { splitPath, splitCamelCase } from '../ui/utils.js';
5
5
  import { getItem, setItem } from '../Inspector.js';
6
6
 
7
- import { RendererUtils, NoToneMapping, LinearSRGBColorSpace, QuadMesh, NodeMaterial, CanvasTarget, Vector2 } from '@gnsx/three/webgpu';
7
+ import { RendererUtils, NoToneMapping, LinearSRGBColorSpace, QuadMesh, NodeMaterial, CanvasTarget, Vector2, Color } from '@gnsx/three/webgpu';
8
8
  import { renderOutput, vec2, vec3, vec4, Fn, screenUV, step, OnMaterialUpdate, uniform, float } from '@gnsx/three/tsl';
9
9
 
10
10
  const _size = /*@__PURE__*/ new Vector2();
11
11
 
12
+ const splitIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="1" x2="12" y2="23"></line><polyline points="5 8 1 12 5 16"></polyline><polyline points="19 8 23 12 19 16"></polyline></svg>';
13
+ const fullscreenIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/></svg>';
14
+ const backIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
15
+
12
16
  const aspectRatioUV = /*@__PURE__*/ Fn( ( [ uv, textureNode, canvasAspect ] ) => {
13
17
 
14
18
  const textureAspect = uniform( 0 );
@@ -55,7 +59,7 @@ class Viewer extends Tab {
55
59
  const backBtn = document.createElement( 'button' );
56
60
  backBtn.className = 'viewer-back-btn';
57
61
  backBtn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>';
58
- backBtn.title = 'Back to list';
62
+ backBtn.title = 'Back';
59
63
  backBtn.style.display = 'none';
60
64
  toolbar.appendChild( backBtn );
61
65
 
@@ -73,11 +77,13 @@ class Viewer extends Tab {
73
77
  select.appendChild( defaultOption );
74
78
 
75
79
  toolbar.appendChild( select );
76
- this.content.appendChild( toolbar );
77
80
 
78
81
  const nodeList = new List( 'Viewer', 'Name' );
79
82
  nodeList.setGridStyle( '150px minmax(200px, 2fr)' );
80
83
  nodeList.domElement.style.minWidth = '400px';
84
+ this.nodeList = nodeList;
85
+
86
+ this.content.appendChild( toolbar );
81
87
 
82
88
  const scrollWrapper = document.createElement( 'div' );
83
89
  scrollWrapper.className = 'list-scroll-wrapper';
@@ -103,7 +109,6 @@ class Viewer extends Tab {
103
109
  this.folderLibrary = new Map();
104
110
  this.canvasNodes = new Map();
105
111
  this.currentDataList = [];
106
- this.nodeList = nodeList;
107
112
  this.nodes = nodes;
108
113
  this.scrollWrapper = scrollWrapper;
109
114
  this.fullViewerContainer = fullViewerContainer;
@@ -112,8 +117,24 @@ class Viewer extends Tab {
112
117
  this.activeFullNodeId = null;
113
118
  this.pendingRestoreView = true;
114
119
 
120
+ this.splitActive = false;
121
+ this.splitCanvasData = null;
122
+ this.splitOverlay = null;
123
+ this.splitLine = null;
124
+ this.splitQuad = null;
125
+ this.splitMaterial = null;
126
+ this.splitUniforms = null;
127
+ this.splitCanvas = null;
128
+ this.splitCanvasTarget = null;
129
+
115
130
  backBtn.addEventListener( 'click', () => {
116
131
 
132
+ if ( this.splitActive ) {
133
+
134
+ this.stopSplitMode();
135
+
136
+ }
137
+
117
138
  select.value = 'list';
118
139
  this.showListView();
119
140
 
@@ -162,8 +183,6 @@ class Viewer extends Tab {
162
183
 
163
184
  const renderer = this.inspector.getRenderer();
164
185
 
165
- if ( ! renderer || ! renderer.domElement ) return;
166
-
167
186
  if ( e.isForwarded ) return;
168
187
 
169
188
  // Block native event from reaching other document-level listeners (OrbitControls)
@@ -220,6 +239,12 @@ class Viewer extends Tab {
220
239
  this.activeSourceCanvas = null;
221
240
  this.activePointerIds.clear();
222
241
 
242
+ if ( this.splitActive ) {
243
+
244
+ this.stopSplitMode();
245
+
246
+ }
247
+
223
248
  }
224
249
 
225
250
  addNodeItem( canvasData ) {
@@ -249,6 +274,13 @@ class Viewer extends Tab {
249
274
  viewBtn.onclick = ( e ) => {
250
275
 
251
276
  e.stopPropagation();
277
+
278
+ if ( this.splitActive ) {
279
+
280
+ this.stopSplitMode();
281
+
282
+ }
283
+
252
284
  this.select.value = canvasData.id;
253
285
  this.showNodeView( canvasData.id );
254
286
  this.saveLastView();
@@ -259,45 +291,60 @@ class Viewer extends Tab {
259
291
  const fullscreenBtn = document.createElement( 'button' );
260
292
  fullscreenBtn.className = 'node-canvas-fullscreen-btn';
261
293
  fullscreenBtn.title = 'Fullscreen view';
262
- fullscreenBtn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/></svg>';
294
+ fullscreenBtn.innerHTML = fullscreenIcon;
263
295
 
264
296
  fullscreenBtn.onclick = ( e ) => {
265
297
 
266
298
  e.stopPropagation();
267
- this.select.value = canvasData.id;
268
- this.showNodeView( canvasData.id );
269
299
 
270
- if ( this.profiler && ! this.profiler.panel.classList.contains( 'maximized' ) ) {
300
+ if ( this.splitActive && this.splitCanvasData === canvasData && this.splitFullscreen ) {
271
301
 
272
- this.profiler.toggleMaximize();
273
- this.maximizedByFullscreenButton = true;
302
+ this.stopSplitMode();
274
303
 
275
- if ( ! this._maximizeListenerAdded && this.profiler.maximizeBtn ) {
304
+ } else {
276
305
 
277
- this.profiler.maximizeBtn.addEventListener( 'click', () => {
306
+ this.splitFullscreen = true;
307
+ this.startSplitMode( canvasData );
278
308
 
279
- this.maximizedByFullscreenButton = false;
309
+ }
280
310
 
281
- } );
282
- this._maximizeListenerAdded = true;
311
+ };
283
312
 
284
- }
313
+ // Split screen button
314
+ const splitBtn = document.createElement( 'button' );
315
+ splitBtn.className = 'node-canvas-split-btn';
316
+ splitBtn.title = 'Interactive split screen';
317
+ splitBtn.innerHTML = splitIcon;
285
318
 
286
- }
319
+ splitBtn.onclick = ( e ) => {
287
320
 
288
- this.saveLastView();
321
+ e.stopPropagation();
322
+
323
+ if ( this.splitActive && this.splitCanvasData === canvasData && ! this.splitFullscreen ) {
324
+
325
+ this.stopSplitMode();
326
+
327
+ } else {
328
+
329
+ this.splitFullscreen = false;
330
+ this.startSplitMode( canvasData );
331
+
332
+ }
289
333
 
290
334
  };
291
335
 
292
336
  wrapper.appendChild( domElement );
293
337
  wrapper.appendChild( viewBtn );
294
338
  wrapper.appendChild( fullscreenBtn );
339
+ wrapper.appendChild( splitBtn );
295
340
 
296
341
  this.setupEventForwarding( domElement );
297
342
 
298
343
  // Store elements in canvasData for access
299
344
  canvasData.domElement = domElement;
300
345
  canvasData.wrapperElement = wrapper;
346
+ canvasData.splitBtn = splitBtn;
347
+ canvasData.fullscreenBtn = fullscreenBtn;
301
348
 
302
349
  item = new Item( wrapper, name );
303
350
  item.itemRow.children[ 1 ].style[ 'justify-content' ] = 'flex-start';
@@ -441,6 +488,45 @@ class Viewer extends Tab {
441
488
 
442
489
  }
443
490
 
491
+ init( inspector ) {
492
+
493
+ super.init( inspector );
494
+
495
+ const updateLayoutFromPosition = () => {
496
+
497
+ const position = inspector.profiler.position;
498
+ const isHorizontal = position === 'top' || position === 'bottom';
499
+ this.setViewMode( isHorizontal ? 'grid' : 'list' );
500
+
501
+ };
502
+
503
+ inspector.profiler.addEventListener( 'resize', updateLayoutFromPosition );
504
+
505
+ // Run initially once
506
+ updateLayoutFromPosition();
507
+
508
+ }
509
+
510
+ setViewMode( mode ) {
511
+
512
+ if ( this.nodeList ) {
513
+
514
+ if ( mode === 'grid' ) {
515
+
516
+ this.nodeList.domElement.style.minWidth = '0';
517
+
518
+ } else {
519
+
520
+ this.nodeList.domElement.style.minWidth = '400px';
521
+
522
+ }
523
+
524
+ this.nodeList.setViewMode( mode );
525
+
526
+ }
527
+
528
+ }
529
+
444
530
  showListView() {
445
531
 
446
532
  if ( this.activeFullNodeId ) {
@@ -514,6 +600,288 @@ class Viewer extends Tab {
514
600
 
515
601
  }
516
602
 
603
+ get isActive() {
604
+
605
+ if ( this.splitActive ) return true;
606
+
607
+ return super.isActive;
608
+
609
+ }
610
+
611
+ set isActive( value ) {
612
+
613
+ super.isActive = value;
614
+
615
+ }
616
+
617
+ startSplitMode( canvasData ) {
618
+
619
+ if ( this.profiler && this.profiler.panel.classList.contains( 'visible' ) ) {
620
+
621
+ this.profiler.togglePanel();
622
+
623
+ }
624
+
625
+ this.splitActive = true;
626
+ this.splitCanvasData = canvasData;
627
+ this.splitX = 0.5;
628
+
629
+ const renderer = this.inspector.getRenderer();
630
+ const mainCanvas = renderer.domElement;
631
+ const rect = mainCanvas.getBoundingClientRect();
632
+ const targetParent = document.fullscreenElement || this.profiler.domElement;
633
+ const parentRect = targetParent.getBoundingClientRect();
634
+ const localLeft = rect.left - parentRect.left;
635
+ const localTop = rect.top - parentRect.top;
636
+
637
+ // Position target canvas on top of main canvas
638
+ if ( ! this.splitCanvas ) {
639
+
640
+ this.splitCanvas = document.createElement( 'canvas' );
641
+ this.splitCanvas.style.position = 'absolute';
642
+ this.splitCanvas.style.pointerEvents = 'none';
643
+ this.splitCanvas.style.zIndex = '998';
644
+
645
+ this.splitCanvasTarget = new CanvasTarget( this.splitCanvas );
646
+ this.splitCanvasTarget.setPixelRatio( window.devicePixelRatio );
647
+
648
+ }
649
+
650
+ this.splitCanvas.style.left = `${ localLeft }px`;
651
+ this.splitCanvas.style.top = `${ localTop }px`;
652
+ this.splitCanvas.style.width = `${ rect.width }px`;
653
+ this.splitCanvas.style.height = `${ rect.height }px`;
654
+
655
+ this.splitCanvasTarget.setSize( rect.width, rect.height );
656
+ renderer.backend.delete( this.splitCanvasTarget );
657
+
658
+ targetParent.appendChild( this.splitCanvas );
659
+
660
+ // Overlay divider line (only in split/non-fullscreen mode)
661
+ if ( ! this.splitFullscreen ) {
662
+
663
+ if ( ! this.splitOverlay ) {
664
+
665
+ const overlay = document.createElement( 'div' );
666
+ overlay.className = 'split-screen-overlay three-inspector';
667
+
668
+ const line = document.createElement( 'div' );
669
+ line.className = 'split-screen-line';
670
+
671
+ overlay.appendChild( line );
672
+
673
+ let isDragging = false;
674
+
675
+ const onPointerDown = ( e ) => {
676
+
677
+ isDragging = true;
678
+ line.classList.add( 'active' );
679
+ e.preventDefault();
680
+
681
+ };
682
+
683
+ const onPointerMove = ( e ) => {
684
+
685
+ if ( ! isDragging ) return;
686
+
687
+ const r = mainCanvas.getBoundingClientRect();
688
+ const localX = e.clientX - r.left;
689
+ const pct = Math.max( 0, Math.min( 1, localX / r.width ) );
690
+ this.splitX = pct;
691
+ line.style.left = `${ pct * 100 }%`;
692
+
693
+ if ( this.splitUniforms && this.splitUniforms.splitX ) {
694
+
695
+ this.splitUniforms.splitX.value = pct;
696
+
697
+ }
698
+
699
+ };
700
+
701
+ const onPointerUp = () => {
702
+
703
+ isDragging = false;
704
+ line.classList.remove( 'active' );
705
+
706
+ };
707
+
708
+ line.addEventListener( 'pointerdown', onPointerDown );
709
+ window.addEventListener( 'pointermove', onPointerMove );
710
+ window.addEventListener( 'pointerup', onPointerUp );
711
+
712
+ this.splitOverlay = overlay;
713
+ this.splitLine = line;
714
+
715
+ }
716
+
717
+ this.splitOverlay.style.left = `${ localLeft }px`;
718
+ this.splitOverlay.style.top = `${ localTop }px`;
719
+ this.splitOverlay.style.width = `${ rect.width }px`;
720
+ this.splitOverlay.style.height = `${ rect.height }px`;
721
+ this.splitLine.style.left = '50%';
722
+
723
+ targetParent.appendChild( this.splitOverlay );
724
+
725
+ } else {
726
+
727
+ // If we transitioned from split to fullscreen, remove the overlay slider
728
+ if ( this.splitOverlay && this.splitOverlay.parentElement ) {
729
+
730
+ this.splitOverlay.parentElement.removeChild( this.splitOverlay );
731
+
732
+ }
733
+
734
+ }
735
+
736
+ if ( ! this.splitUniforms ) {
737
+
738
+ this.splitUniforms = {
739
+ splitX: uniform( 0.5 ),
740
+ viewportWidth: uniform( rect.width )
741
+ };
742
+
743
+ }
744
+
745
+ this.splitUniforms.splitX.value = 0.5;
746
+ this.splitUniforms.viewportWidth.value = rect.width;
747
+
748
+ // Recreate or setup material for split screen comparison
749
+ const node = canvasData.node;
750
+ const target = node.context( { getUV: () => screenUV } );
751
+ const targetColor = renderOutput( vec4( vec3( target ), 1 ), NoToneMapping, renderer.outputColorSpace );
752
+ const targetColorCtx = targetColor.context( { inspector: true } );
753
+
754
+ let finalColor;
755
+
756
+ if ( this.splitFullscreen ) {
757
+
758
+ finalColor = targetColorCtx;
759
+
760
+ } else {
761
+
762
+ finalColor = Fn( () => {
763
+
764
+ screenUV.x.lessThan( this.splitUniforms.splitX ).discard();
765
+
766
+ return targetColorCtx;
767
+
768
+ } )();
769
+
770
+ }
771
+
772
+ if ( this.splitMaterial ) {
773
+
774
+ this.splitMaterial.dispose();
775
+
776
+ }
777
+
778
+ this.splitMaterial = new NodeMaterial();
779
+ this.splitMaterial.outputNode = finalColor;
780
+ this.splitMaterial.depthTest = false;
781
+ this.splitMaterial.depthWrite = false;
782
+
783
+ if ( this.splitQuad ) {
784
+
785
+ this.splitQuad.material = this.splitMaterial;
786
+
787
+ } else {
788
+
789
+ this.splitQuad = new QuadMesh( this.splitMaterial );
790
+
791
+ }
792
+
793
+ this.updateSplitButtonsState();
794
+
795
+ }
796
+
797
+ stopSplitMode() {
798
+
799
+ this.splitActive = false;
800
+ this.splitCanvasData = null;
801
+ this.splitFullscreen = false;
802
+
803
+ if ( this.splitOverlay && this.splitOverlay.parentElement ) {
804
+
805
+ this.splitOverlay.parentElement.removeChild( this.splitOverlay );
806
+
807
+ }
808
+
809
+ if ( this.splitCanvas && this.splitCanvas.parentElement ) {
810
+
811
+ this.splitCanvas.parentElement.removeChild( this.splitCanvas );
812
+
813
+ }
814
+
815
+ this.updateSplitButtonsState();
816
+
817
+ }
818
+
819
+ updateSplitButtonsState() {
820
+
821
+ if ( this.splitActive ) {
822
+
823
+ this.backBtn.style.display = '';
824
+
825
+ } else {
826
+
827
+ if ( this.select.value === 'list' ) {
828
+
829
+ this.backBtn.style.display = 'none';
830
+
831
+ } else {
832
+
833
+ this.backBtn.style.display = '';
834
+
835
+ }
836
+
837
+ }
838
+
839
+ for ( const canvasData of this.canvasNodes.values() ) {
840
+
841
+ if ( ! canvasData.splitBtn || ! canvasData.fullscreenBtn ) continue;
842
+
843
+ const isSelected = this.splitActive && this.splitCanvasData === canvasData;
844
+
845
+ if ( isSelected ) {
846
+
847
+ if ( this.splitFullscreen ) {
848
+
849
+ canvasData.fullscreenBtn.classList.add( 'active' );
850
+ canvasData.fullscreenBtn.innerHTML = backIcon;
851
+ canvasData.fullscreenBtn.title = 'Exit Fullscreen';
852
+
853
+ canvasData.splitBtn.classList.remove( 'active' );
854
+ canvasData.splitBtn.innerHTML = splitIcon;
855
+ canvasData.splitBtn.title = 'Interactive split screen';
856
+
857
+ } else {
858
+
859
+ canvasData.splitBtn.classList.add( 'active' );
860
+ canvasData.splitBtn.innerHTML = backIcon;
861
+ canvasData.splitBtn.title = 'Exit Split Screen';
862
+
863
+ canvasData.fullscreenBtn.classList.remove( 'active' );
864
+ canvasData.fullscreenBtn.innerHTML = fullscreenIcon;
865
+ canvasData.fullscreenBtn.title = 'Fullscreen view';
866
+
867
+ }
868
+
869
+ } else {
870
+
871
+ canvasData.splitBtn.classList.remove( 'active' );
872
+ canvasData.splitBtn.innerHTML = splitIcon;
873
+ canvasData.splitBtn.title = 'Interactive split screen';
874
+
875
+ canvasData.fullscreenBtn.classList.remove( 'active' );
876
+ canvasData.fullscreenBtn.innerHTML = fullscreenIcon;
877
+ canvasData.fullscreenBtn.title = 'Fullscreen view';
878
+
879
+ }
880
+
881
+ }
882
+
883
+ }
884
+
517
885
  getCanvasDataByNode( renderer, node ) {
518
886
 
519
887
  let canvasData = this.canvasNodes.get( node );
@@ -575,13 +943,92 @@ class Viewer extends Tab {
575
943
  update( inspector ) {
576
944
 
577
945
  const renderer = inspector.getRenderer();
946
+
947
+ if ( this.splitActive ) {
948
+
949
+ const mainCanvas = renderer.domElement;
950
+ const rect = mainCanvas.getBoundingClientRect();
951
+
952
+ if ( rect.width <= 0 || rect.height <= 0 ) {
953
+
954
+ return;
955
+
956
+ }
957
+
958
+ const targetParent = document.fullscreenElement || this.profiler.domElement;
959
+ const parentRect = targetParent.getBoundingClientRect();
960
+ const localLeft = rect.left - parentRect.left;
961
+ const localTop = rect.top - parentRect.top;
962
+
963
+ if ( this.splitCanvas.parentElement !== targetParent ) {
964
+
965
+ targetParent.appendChild( this.splitCanvas );
966
+
967
+ }
968
+
969
+ if ( this.splitOverlay && ! this.splitFullscreen && this.splitOverlay.parentElement !== targetParent ) {
970
+
971
+ targetParent.appendChild( this.splitOverlay );
972
+
973
+ }
974
+
975
+ this.splitCanvas.style.left = `${ localLeft }px`;
976
+ this.splitCanvas.style.top = `${ localTop }px`;
977
+ this.splitCanvas.style.width = `${ rect.width }px`;
978
+ this.splitCanvas.style.height = `${ rect.height }px`;
979
+
980
+ if ( this.splitOverlay && ! this.splitFullscreen ) {
981
+
982
+ this.splitOverlay.style.left = `${ localLeft }px`;
983
+ this.splitOverlay.style.top = `${ localTop }px`;
984
+ this.splitOverlay.style.width = `${ rect.width }px`;
985
+ this.splitOverlay.style.height = `${ rect.height }px`;
986
+
987
+ }
988
+
989
+ if ( this.splitCanvasTarget.width !== rect.width || this.splitCanvasTarget.height !== rect.height ) {
990
+
991
+ this.splitCanvasTarget.setSize( rect.width, rect.height );
992
+
993
+ if ( this.splitUniforms && this.splitUniforms.viewportWidth ) {
994
+
995
+ this.splitUniforms.viewportWidth.value = rect.width;
996
+
997
+ }
998
+
999
+ renderer.backend.delete( this.splitCanvasTarget );
1000
+
1001
+ }
1002
+
1003
+ // Render the split quad to the splitCanvasTarget
1004
+ const previousCanvasTarget = renderer.getCanvasTarget();
1005
+ const previousClearColor = renderer.getClearColor( new Color() );
1006
+ const previousClearAlpha = renderer.getClearAlpha();
1007
+
1008
+ const state = RendererUtils.resetRendererState( renderer );
1009
+
1010
+ renderer.toneMapping = NoToneMapping;
1011
+ renderer.outputColorSpace = LinearSRGBColorSpace;
1012
+
1013
+ renderer.setCanvasTarget( this.splitCanvasTarget );
1014
+ renderer.setClearColor( 0x000000, 0 );
1015
+
1016
+ this.splitQuad.render( renderer );
1017
+
1018
+ renderer.setCanvasTarget( previousCanvasTarget );
1019
+ renderer.setClearColor( previousClearColor, previousClearAlpha );
1020
+
1021
+ RendererUtils.restoreRendererState( renderer, state );
1022
+
1023
+ }
1024
+
578
1025
  const nodes = inspector.getNodes();
579
1026
 
580
1027
  if ( nodes.length > 0 ) {
581
1028
 
582
1029
  if ( ! renderer.backend.isWebGPUBackend ) {
583
1030
 
584
- inspector.resolveConsoleOnce( 'warn', 'Inspector: Viewer is only available with WebGPU.' );
1031
+ // Viewer is only available with WebGPU.
585
1032
 
586
1033
  return;
587
1034
 
@@ -875,6 +1322,53 @@ class Viewer extends Tab {
875
1322
 
876
1323
  }
877
1324
 
1325
+ dispose() {
1326
+
1327
+ if ( this.splitActive ) {
1328
+
1329
+ this.stopSplitMode();
1330
+
1331
+ }
1332
+
1333
+ if ( this.splitCanvas ) {
1334
+
1335
+ if ( this.splitCanvas.parentElement ) {
1336
+
1337
+ this.splitCanvas.parentElement.removeChild( this.splitCanvas );
1338
+
1339
+ }
1340
+
1341
+ this.splitCanvas = null;
1342
+
1343
+ }
1344
+
1345
+ if ( this.splitCanvasTarget ) {
1346
+
1347
+ this.splitCanvasTarget.dispose();
1348
+ this.splitCanvasTarget = null;
1349
+
1350
+ }
1351
+
1352
+ if ( this.splitMaterial ) {
1353
+
1354
+ this.splitMaterial.dispose();
1355
+ this.splitMaterial = null;
1356
+
1357
+ }
1358
+
1359
+ for ( const canvasData of this.canvasNodes.values() ) {
1360
+
1361
+ canvasData.canvasTarget.dispose();
1362
+ canvasData.material.dispose();
1363
+
1364
+ }
1365
+
1366
+ this.canvasNodes.clear();
1367
+
1368
+ super.dispose();
1369
+
1370
+ }
1371
+
878
1372
  }
879
1373
 
880
1374
  export { Viewer };
@@ -11,9 +11,6 @@ export class List {
11
11
  this.id = `list-${Math.random().toString( 36 ).slice( 2, 11 )}`;
12
12
  this.domElement.dataset.listId = this.id;
13
13
 
14
- this.gridStyleElement = document.createElement( 'style' );
15
- this.domElement.appendChild( this.gridStyleElement );
16
-
17
14
  const headerRow = document.createElement( 'div' );
18
15
  headerRow.className = 'list-header';
19
16
  this.headers.forEach( headerText => {
@@ -30,12 +27,21 @@ export class List {
30
27
 
31
28
  setGridStyle( gridTemplate ) {
32
29
 
33
- this.gridStyleElement.textContent = `
34
- [data-list-id="${this.id}"] > .list-header,
35
- [data-list-id="${this.id}"] .list-item-row {
36
- grid-template-columns: ${gridTemplate};
37
- }
38
- `;
30
+ this.domElement.style.setProperty( '--list-grid-template', gridTemplate );
31
+
32
+ }
33
+
34
+ setViewMode( mode ) {
35
+
36
+ if ( mode === 'grid' ) {
37
+
38
+ this.domElement.classList.add( 'grid-mode' );
39
+
40
+ } else {
41
+
42
+ this.domElement.classList.remove( 'grid-mode' );
43
+
44
+ }
39
45
 
40
46
  }
41
47