@onerjs/core 8.55.8 → 8.56.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 (423) hide show
  1. package/Animations/animation.pure.js +2 -2
  2. package/Animations/animation.pure.js.map +1 -1
  3. package/Animations/runtimeAnimation.js +4 -0
  4. package/Animations/runtimeAnimation.js.map +1 -1
  5. package/AudioV2/webAudio/webAudioEngine.d.ts +7 -0
  6. package/AudioV2/webAudio/webAudioEngine.js +6 -5
  7. package/AudioV2/webAudio/webAudioEngine.js.map +1 -1
  8. package/Behaviors/Cameras/autoRotationBehavior.js +1 -1
  9. package/Behaviors/Cameras/autoRotationBehavior.js.map +1 -1
  10. package/Behaviors/Meshes/followBehavior.js +1 -0
  11. package/Behaviors/Meshes/followBehavior.js.map +1 -1
  12. package/Behaviors/Meshes/surfaceMagnetismBehavior.js +1 -0
  13. package/Behaviors/Meshes/surfaceMagnetismBehavior.js.map +1 -1
  14. package/Cameras/Inputs/followCameraMouseWheelInput.js +2 -2
  15. package/Cameras/Inputs/followCameraMouseWheelInput.js.map +1 -1
  16. package/Cameras/Inputs/followCameraPointersInput.d.ts +15 -0
  17. package/Cameras/Inputs/followCameraPointersInput.js +18 -3
  18. package/Cameras/Inputs/followCameraPointersInput.js.map +1 -1
  19. package/Cameras/Stereoscopic/stereoscopicScreenUniversalCamera.js +1 -1
  20. package/Cameras/Stereoscopic/stereoscopicScreenUniversalCamera.js.map +1 -1
  21. package/Cameras/Stereoscopic/stereoscopicUniversalCamera.pure.js +1 -1
  22. package/Cameras/Stereoscopic/stereoscopicUniversalCamera.pure.js.map +1 -1
  23. package/Cameras/arcRotateCamera.pure.js +1 -1
  24. package/Cameras/arcRotateCamera.pure.js.map +1 -1
  25. package/Collisions/gpuPicker.d.ts +1 -0
  26. package/Collisions/gpuPicker.js +5 -4
  27. package/Collisions/gpuPicker.js.map +1 -1
  28. package/Culling/Helper/boundingInfoHelper.js +9 -5
  29. package/Culling/Helper/boundingInfoHelper.js.map +1 -1
  30. package/Culling/boundingSphere.js +7 -4
  31. package/Culling/boundingSphere.js.map +1 -1
  32. package/Engines/AbstractEngine/abstractEngine.textureLoaders.d.ts +5 -1
  33. package/Engines/AbstractEngine/abstractEngine.textureLoaders.js +7 -3
  34. package/Engines/AbstractEngine/abstractEngine.textureLoaders.js.map +1 -1
  35. package/Engines/AbstractEngine/abstractEngine.textureLoaders.pure.d.ts +6 -0
  36. package/Engines/AbstractEngine/abstractEngine.textureLoaders.pure.js +16 -0
  37. package/Engines/AbstractEngine/abstractEngine.textureLoaders.pure.js.map +1 -0
  38. package/Engines/AbstractEngine/pure.d.ts +1 -0
  39. package/Engines/AbstractEngine/pure.js +1 -0
  40. package/Engines/AbstractEngine/pure.js.map +1 -1
  41. package/Engines/Extensions/engine.prefilteredCubeTexture.pure.js +1 -1
  42. package/Engines/Extensions/engine.prefilteredCubeTexture.pure.js.map +1 -1
  43. package/Engines/IDrawContext.d.ts +2 -0
  44. package/Engines/IDrawContext.js.map +1 -1
  45. package/Engines/Native/Extensions/nativeEngine.cubeTexture.pure.js +48 -6
  46. package/Engines/Native/Extensions/nativeEngine.cubeTexture.pure.js.map +1 -1
  47. package/Engines/Native/nativeInterfaces.d.ts +1 -1
  48. package/Engines/Native/nativeInterfaces.js.map +1 -1
  49. package/Engines/WebGPU/webgpuDrawContext.d.ts +8 -0
  50. package/Engines/WebGPU/webgpuDrawContext.js +15 -0
  51. package/Engines/WebGPU/webgpuDrawContext.js.map +1 -1
  52. package/Engines/abstractEngine.pure.js +2 -2
  53. package/Engines/abstractEngine.pure.js.map +1 -1
  54. package/Engines/engine.d.ts +21 -4
  55. package/Engines/thinNativeEngine.pure.d.ts +6 -1
  56. package/Engines/thinNativeEngine.pure.js +29 -2
  57. package/Engines/thinNativeEngine.pure.js.map +1 -1
  58. package/Engines/webgpuEngine.d.ts +1 -0
  59. package/Engines/webgpuEngine.js +1 -0
  60. package/Engines/webgpuEngine.js.map +1 -1
  61. package/Engines/webgpuEngine.pure.d.ts +10 -0
  62. package/Engines/webgpuEngine.pure.js +15 -1
  63. package/Engines/webgpuEngine.pure.js.map +1 -1
  64. package/FlowGraph/Blocks/Data/flowGraphIsKeyPressedBlock.d.ts +3 -63
  65. package/FlowGraph/Blocks/Data/flowGraphIsKeyPressedBlock.js +5 -71
  66. package/FlowGraph/Blocks/Data/flowGraphIsKeyPressedBlock.js.map +1 -1
  67. package/FlowGraph/Blocks/Data/flowGraphIsKeyPressedBlock.pure.d.ts +71 -0
  68. package/FlowGraph/Blocks/Data/flowGraphIsKeyPressedBlock.pure.js +86 -0
  69. package/FlowGraph/Blocks/Data/flowGraphIsKeyPressedBlock.pure.js.map +1 -0
  70. package/FlowGraph/Blocks/Data/pure.d.ts +1 -0
  71. package/FlowGraph/Blocks/Data/pure.js +1 -0
  72. package/FlowGraph/Blocks/Data/pure.js.map +1 -1
  73. package/FlowGraph/Blocks/Event/flowGraphKeyDownEventBlock.d.ts +3 -37
  74. package/FlowGraph/Blocks/Event/flowGraphKeyDownEventBlock.js +5 -39
  75. package/FlowGraph/Blocks/Event/flowGraphKeyDownEventBlock.js.map +1 -1
  76. package/FlowGraph/Blocks/Event/flowGraphKeyDownEventBlock.pure.d.ts +45 -0
  77. package/FlowGraph/Blocks/Event/flowGraphKeyDownEventBlock.pure.js +54 -0
  78. package/FlowGraph/Blocks/Event/flowGraphKeyDownEventBlock.pure.js.map +1 -0
  79. package/FlowGraph/Blocks/Event/flowGraphKeyUpEventBlock.d.ts +3 -17
  80. package/FlowGraph/Blocks/Event/flowGraphKeyUpEventBlock.js +5 -22
  81. package/FlowGraph/Blocks/Event/flowGraphKeyUpEventBlock.js.map +1 -1
  82. package/FlowGraph/Blocks/Event/flowGraphKeyUpEventBlock.pure.d.ts +25 -0
  83. package/FlowGraph/Blocks/Event/flowGraphKeyUpEventBlock.pure.js +37 -0
  84. package/FlowGraph/Blocks/Event/flowGraphKeyUpEventBlock.pure.js.map +1 -0
  85. package/FlowGraph/Blocks/Event/pure.d.ts +2 -0
  86. package/FlowGraph/Blocks/Event/pure.js +2 -0
  87. package/FlowGraph/Blocks/Event/pure.js.map +1 -1
  88. package/FlowGraph/Blocks/flowGraphBlockFactory.d.ts +1 -1
  89. package/FlowGraph/Blocks/flowGraphBlockFactory.js +198 -172
  90. package/FlowGraph/Blocks/flowGraphBlockFactory.js.map +1 -1
  91. package/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.pure.js +2 -5
  92. package/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.pure.js.map +1 -1
  93. package/FrameGraph/frameGraph.js +10 -1
  94. package/FrameGraph/frameGraph.js.map +1 -1
  95. package/Gamepads/gamepadManager.d.ts +1 -0
  96. package/Gamepads/gamepadManager.js +5 -2
  97. package/Gamepads/gamepadManager.js.map +1 -1
  98. package/Gizmos/scaleGizmo.js +1 -0
  99. package/Gizmos/scaleGizmo.js.map +1 -1
  100. package/Lights/IES/iesLoader.js +6 -8
  101. package/Lights/IES/iesLoader.js.map +1 -1
  102. package/Lights/Shadows/cascadedShadowGenerator.pure.js +4 -6
  103. package/Lights/Shadows/cascadedShadowGenerator.pure.js.map +1 -1
  104. package/Lights/Shadows/shadowGenerator.js +2 -2
  105. package/Lights/Shadows/shadowGenerator.js.map +1 -1
  106. package/Lights/light.js +3 -5
  107. package/Lights/light.js.map +1 -1
  108. package/Lights/spotLight.pure.js +1 -1
  109. package/Lights/spotLight.pure.js.map +1 -1
  110. package/Materials/Background/backgroundMaterial.pure.d.ts +1 -1
  111. package/Materials/Background/backgroundMaterial.pure.js +3 -12
  112. package/Materials/Background/backgroundMaterial.pure.js.map +1 -1
  113. package/Materials/GaussianSplatting/gaussianSplattingMaterial.pure.js +2 -0
  114. package/Materials/GaussianSplatting/gaussianSplattingMaterial.pure.js.map +1 -1
  115. package/Materials/Node/Blocks/Fragment/TBNBlock.pure.js +1 -1
  116. package/Materials/Node/Blocks/Fragment/TBNBlock.pure.js.map +1 -1
  117. package/Materials/Node/Blocks/Fragment/imageProcessingBlock.pure.js +2 -0
  118. package/Materials/Node/Blocks/Fragment/imageProcessingBlock.pure.js.map +1 -1
  119. package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.pure.js +1 -0
  120. package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.pure.js.map +1 -1
  121. package/Materials/Node/Blocks/powBlock.pure.js +2 -1
  122. package/Materials/Node/Blocks/powBlock.pure.js.map +1 -1
  123. package/Materials/Node/Blocks/triPlanarBlock.pure.js +14 -12
  124. package/Materials/Node/Blocks/triPlanarBlock.pure.js.map +1 -1
  125. package/Materials/Node/nodeMaterial.pure.d.ts +1 -0
  126. package/Materials/Node/nodeMaterialBuildState.d.ts +3 -3
  127. package/Materials/PBR/openpbrMaterial.pure.d.ts +2 -1
  128. package/Materials/PBR/openpbrMaterial.pure.js +3 -12
  129. package/Materials/PBR/openpbrMaterial.pure.js.map +1 -1
  130. package/Materials/PBR/pbrBaseMaterial.pure.d.ts +2 -1
  131. package/Materials/PBR/pbrBaseMaterial.pure.js +3 -12
  132. package/Materials/PBR/pbrBaseMaterial.pure.js.map +1 -1
  133. package/Materials/Textures/index.d.ts +1 -0
  134. package/Materials/Textures/index.js +1 -0
  135. package/Materials/Textures/index.js.map +1 -1
  136. package/Materials/Textures/renderTargetTexture.pure.js +1 -1
  137. package/Materials/Textures/renderTargetTexture.pure.js.map +1 -1
  138. package/Materials/drawWrapper.js +3 -0
  139. package/Materials/drawWrapper.js.map +1 -1
  140. package/Materials/imageProcessingConfiguration.defines.d.ts +3 -0
  141. package/Materials/imageProcessingConfiguration.defines.js +2 -0
  142. package/Materials/imageProcessingConfiguration.defines.js.map +1 -1
  143. package/Materials/imageProcessingConfiguration.functions.js +3 -0
  144. package/Materials/imageProcessingConfiguration.functions.js.map +1 -1
  145. package/Materials/imageProcessingConfiguration.pure.d.ts +58 -0
  146. package/Materials/imageProcessingConfiguration.pure.js +123 -2
  147. package/Materials/imageProcessingConfiguration.pure.js.map +1 -1
  148. package/Materials/material.pure.js +2 -2
  149. package/Materials/material.pure.js.map +1 -1
  150. package/Materials/standardMaterial.pure.d.ts +2 -1
  151. package/Materials/standardMaterial.pure.js +4 -13
  152. package/Materials/standardMaterial.pure.js.map +1 -1
  153. package/Materials/uniformBuffer.d.ts +29 -0
  154. package/Materials/uniformBuffer.js +146 -0
  155. package/Materials/uniformBuffer.js.map +1 -1
  156. package/Maths/colorTemperature.functions.d.ts +29 -0
  157. package/Maths/colorTemperature.functions.js +196 -0
  158. package/Maths/colorTemperature.functions.js.map +1 -0
  159. package/Maths/index.d.ts +1 -0
  160. package/Maths/index.js +1 -0
  161. package/Maths/index.js.map +1 -1
  162. package/Maths/math.path.js +1 -1
  163. package/Maths/math.path.js.map +1 -1
  164. package/Maths/math.polar.js +1 -1
  165. package/Maths/math.polar.js.map +1 -1
  166. package/Maths/math.vector.pure.js +4 -3
  167. package/Maths/math.vector.pure.js.map +1 -1
  168. package/Maths/pure.d.ts +1 -0
  169. package/Maths/pure.js +1 -0
  170. package/Maths/pure.js.map +1 -1
  171. package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.d.ts +72 -0
  172. package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.js +164 -1
  173. package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.js.map +1 -1
  174. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.d.ts +2 -1
  175. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js +36 -18
  176. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js.map +1 -1
  177. package/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh.pure.d.ts +5 -4
  178. package/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh.pure.js +25 -8
  179. package/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh.pure.js.map +1 -1
  180. package/Meshes/GreasedLine/greasedLineRibbonMesh.pure.js +3 -3
  181. package/Meshes/GreasedLine/greasedLineRibbonMesh.pure.js.map +1 -1
  182. package/Meshes/Node/Blocks/Instances/instantiateOnVolumeBlock.pure.js +1 -1
  183. package/Meshes/Node/Blocks/Instances/instantiateOnVolumeBlock.pure.js.map +1 -1
  184. package/Meshes/Node/Blocks/geometryOptimizeBlock.pure.js +2 -2
  185. package/Meshes/Node/Blocks/geometryOptimizeBlock.pure.js.map +1 -1
  186. package/Meshes/Node/Blocks/mappingBlock.pure.js +2 -2
  187. package/Meshes/Node/Blocks/mappingBlock.pure.js.map +1 -1
  188. package/Meshes/csg.js +5 -5
  189. package/Meshes/csg.js.map +1 -1
  190. package/Meshes/groundMesh.pure.js +1 -1
  191. package/Meshes/groundMesh.pure.js.map +1 -1
  192. package/Meshes/mesh.pure.js +2 -2
  193. package/Meshes/mesh.pure.js.map +1 -1
  194. package/Misc/deepMerger.js +1 -1
  195. package/Misc/deepMerger.js.map +1 -1
  196. package/Misc/dumpTools.pure.js +1 -1
  197. package/Misc/dumpTools.pure.js.map +1 -1
  198. package/Misc/index.d.ts +1 -0
  199. package/Misc/index.js +1 -0
  200. package/Misc/index.js.map +1 -1
  201. package/Misc/observable.pure.js +1 -3
  202. package/Misc/observable.pure.js.map +1 -1
  203. package/Misc/pure.d.ts +1 -0
  204. package/Misc/pure.js +1 -0
  205. package/Misc/pure.js.map +1 -1
  206. package/Misc/shaderImportLoader.d.ts +25 -0
  207. package/Misc/shaderImportLoader.js +54 -0
  208. package/Misc/shaderImportLoader.js.map +1 -0
  209. package/Misc/tools.pure.js +1 -1
  210. package/Misc/tools.pure.js.map +1 -1
  211. package/Particles/Node/Blocks/particleClampBlock.pure.d.ts +0 -1
  212. package/Particles/Node/Blocks/particleClampBlock.pure.js +1 -6
  213. package/Particles/Node/Blocks/particleClampBlock.pure.js.map +1 -1
  214. package/Particles/Node/Blocks/particleMathBlock.pure.js +1 -1
  215. package/Particles/Node/Blocks/particleMathBlock.pure.js.map +1 -1
  216. package/Particles/Node/Blocks/particleNLerpBlock.pure.js +8 -3
  217. package/Particles/Node/Blocks/particleNLerpBlock.pure.js.map +1 -1
  218. package/Particles/Node/Blocks/particleSmoothStepBlock.pure.js +3 -2
  219. package/Particles/Node/Blocks/particleSmoothStepBlock.pure.js.map +1 -1
  220. package/Particles/Node/Blocks/particleStepBlock.pure.js +3 -2
  221. package/Particles/Node/Blocks/particleStepBlock.pure.js.map +1 -1
  222. package/PostProcesses/RenderPipeline/Pipelines/defaultRenderingPipeline.pure.js +1 -1
  223. package/PostProcesses/RenderPipeline/Pipelines/defaultRenderingPipeline.pure.js.map +1 -1
  224. package/PostProcesses/depthOfFieldEffect.js +1 -1
  225. package/PostProcesses/depthOfFieldEffect.js.map +1 -1
  226. package/PostProcesses/imageProcessingPostProcess.d.ts +41 -1
  227. package/PostProcesses/imageProcessingPostProcess.js +41 -1
  228. package/PostProcesses/imageProcessingPostProcess.js.map +1 -1
  229. package/PostProcesses/screenSpaceCurvaturePostProcess.pure.js +1 -1
  230. package/PostProcesses/screenSpaceCurvaturePostProcess.pure.js.map +1 -1
  231. package/PostProcesses/sharpenPostProcess.pure.js +1 -1
  232. package/PostProcesses/sharpenPostProcess.pure.js.map +1 -1
  233. package/PostProcesses/thinImageProcessingPostProcess.d.ts +50 -0
  234. package/PostProcesses/thinImageProcessingPostProcess.js +65 -0
  235. package/PostProcesses/thinImageProcessingPostProcess.js.map +1 -1
  236. package/Rendering/IBLShadows/iblShadowsMaterialCompatibility.pure.d.ts +12 -0
  237. package/Rendering/IBLShadows/iblShadowsMaterialCompatibility.pure.js +22 -0
  238. package/Rendering/IBLShadows/iblShadowsMaterialCompatibility.pure.js.map +1 -0
  239. package/Rendering/IBLShadows/iblShadowsPluginMaterial.pure.d.ts +1 -0
  240. package/Rendering/IBLShadows/iblShadowsPluginMaterial.pure.js +39 -0
  241. package/Rendering/IBLShadows/iblShadowsPluginMaterial.pure.js.map +1 -1
  242. package/Rendering/IBLShadows/iblShadowsRenderPipeline.pure.d.ts +12 -0
  243. package/Rendering/IBLShadows/iblShadowsRenderPipeline.pure.js +17 -5
  244. package/Rendering/IBLShadows/iblShadowsRenderPipeline.pure.js.map +1 -1
  245. package/Rendering/IBLShadows/iblShadowsVoxelRenderer.pure.d.ts +14 -0
  246. package/Rendering/IBLShadows/iblShadowsVoxelRenderer.pure.js +122 -6
  247. package/Rendering/IBLShadows/iblShadowsVoxelRenderer.pure.js.map +1 -1
  248. package/Rendering/IBLShadows/iblShadowsVoxelTracingPass.d.ts +7 -0
  249. package/Rendering/IBLShadows/iblShadowsVoxelTracingPass.js +17 -0
  250. package/Rendering/IBLShadows/iblShadowsVoxelTracingPass.js.map +1 -1
  251. package/Rendering/IBLShadows/pure.d.ts +1 -0
  252. package/Rendering/IBLShadows/pure.js +1 -0
  253. package/Rendering/IBLShadows/pure.js.map +1 -1
  254. package/Rendering/boundingBoxRenderer.pure.js +3 -3
  255. package/Rendering/boundingBoxRenderer.pure.js.map +1 -1
  256. package/Rendering/fluidRenderer/fluidRenderingObject.d.ts +11 -0
  257. package/Rendering/fluidRenderer/fluidRenderingObject.js +36 -14
  258. package/Rendering/fluidRenderer/fluidRenderingObject.js.map +1 -1
  259. package/Rendering/fluidRenderer/fluidRenderingObjectCustomParticles.d.ts +5 -0
  260. package/Rendering/fluidRenderer/fluidRenderingObjectCustomParticles.js +16 -3
  261. package/Rendering/fluidRenderer/fluidRenderingObjectCustomParticles.js.map +1 -1
  262. package/Rendering/fluidRenderer/fluidRenderingObjectParticleSystem.d.ts +5 -0
  263. package/Rendering/fluidRenderer/fluidRenderingObjectParticleSystem.js +12 -0
  264. package/Rendering/fluidRenderer/fluidRenderingObjectParticleSystem.js.map +1 -1
  265. package/Rendering/iblCdfGenerator.js +10 -1
  266. package/Rendering/iblCdfGenerator.js.map +1 -1
  267. package/Rendering/outlineRenderer.pure.js +1 -0
  268. package/Rendering/outlineRenderer.pure.js.map +1 -1
  269. package/Rendering/subSurfaceConfiguration.js +1 -1
  270. package/Rendering/subSurfaceConfiguration.js.map +1 -1
  271. package/Rendering/subSurfaceSceneComponent.pure.d.ts +1 -1
  272. package/Rendering/subSurfaceSceneComponent.pure.js +1 -1
  273. package/Rendering/subSurfaceSceneComponent.pure.js.map +1 -1
  274. package/Rendering/utilityLayerRenderer.js +1 -1
  275. package/Rendering/utilityLayerRenderer.js.map +1 -1
  276. package/Shaders/ShadersInclude/hdrFilteringFunctions.js +1 -1
  277. package/Shaders/ShadersInclude/hdrFilteringFunctions.js.map +1 -1
  278. package/Shaders/ShadersInclude/helperFunctions.js +2 -2
  279. package/Shaders/ShadersInclude/helperFunctions.js.map +1 -1
  280. package/Shaders/ShadersInclude/imageProcessingDeclaration.js +3 -0
  281. package/Shaders/ShadersInclude/imageProcessingDeclaration.js.map +1 -1
  282. package/Shaders/ShadersInclude/imageProcessingFunctions.js +3 -0
  283. package/Shaders/ShadersInclude/imageProcessingFunctions.js.map +1 -1
  284. package/Shaders/ShadersInclude/openpbrDirectLighting.js +34 -4
  285. package/Shaders/ShadersInclude/openpbrDirectLighting.js.map +1 -1
  286. package/Shaders/ShadersInclude/openpbrIblFunctions.js +8 -2
  287. package/Shaders/ShadersInclude/openpbrIblFunctions.js.map +1 -1
  288. package/Shaders/ShadersInclude/pbrDirectLightingFunctions.js +5 -0
  289. package/Shaders/ShadersInclude/pbrDirectLightingFunctions.js.map +1 -1
  290. package/Shaders/fluidRenderingParticleDepth.vertex.js +7 -1
  291. package/Shaders/fluidRenderingParticleDepth.vertex.js.map +1 -1
  292. package/Shaders/fluidRenderingParticleDiffuse.vertex.js +7 -1
  293. package/Shaders/fluidRenderingParticleDiffuse.vertex.js.map +1 -1
  294. package/Shaders/fluidRenderingParticleThickness.vertex.js +7 -1
  295. package/Shaders/fluidRenderingParticleThickness.vertex.js.map +1 -1
  296. package/Shaders/gaussianSplattingVoxel.fragment.js +4 -10
  297. package/Shaders/gaussianSplattingVoxel.fragment.js.map +1 -1
  298. package/Shaders/iblCombineVoxelGrids.fragment.js +1 -1
  299. package/Shaders/iblCombineVoxelGrids.fragment.js.map +1 -1
  300. package/Shaders/iblShadowVoxelTracing.fragment.js +24 -7
  301. package/Shaders/iblShadowVoxelTracing.fragment.js.map +1 -1
  302. package/ShadersWGSL/ShadersInclude/iblVoxelOpacityAtomicMax.d.ts +5 -0
  303. package/ShadersWGSL/ShadersInclude/iblVoxelOpacityAtomicMax.js +13 -0
  304. package/ShadersWGSL/ShadersInclude/iblVoxelOpacityAtomicMax.js.map +1 -0
  305. package/ShadersWGSL/ShadersInclude/imageProcessingDeclaration.js +3 -0
  306. package/ShadersWGSL/ShadersInclude/imageProcessingDeclaration.js.map +1 -1
  307. package/ShadersWGSL/ShadersInclude/imageProcessingFunctions.js +3 -0
  308. package/ShadersWGSL/ShadersInclude/imageProcessingFunctions.js.map +1 -1
  309. package/ShadersWGSL/ShadersInclude/openpbrDirectLighting.js +35 -5
  310. package/ShadersWGSL/ShadersInclude/openpbrDirectLighting.js.map +1 -1
  311. package/ShadersWGSL/ShadersInclude/openpbrDirectLightingInit.js +1 -1
  312. package/ShadersWGSL/ShadersInclude/openpbrDirectLightingInit.js.map +1 -1
  313. package/ShadersWGSL/ShadersInclude/openpbrIblFunctions.js +8 -2
  314. package/ShadersWGSL/ShadersInclude/openpbrIblFunctions.js.map +1 -1
  315. package/ShadersWGSL/ShadersInclude/pbrDirectLightingFunctions.js +5 -0
  316. package/ShadersWGSL/ShadersInclude/pbrDirectLightingFunctions.js.map +1 -1
  317. package/ShadersWGSL/fluidRenderingParticleDepth.vertex.js +16 -4
  318. package/ShadersWGSL/fluidRenderingParticleDepth.vertex.js.map +1 -1
  319. package/ShadersWGSL/fluidRenderingParticleDiffuse.vertex.js +15 -3
  320. package/ShadersWGSL/fluidRenderingParticleDiffuse.vertex.js.map +1 -1
  321. package/ShadersWGSL/fluidRenderingParticleThickness.vertex.js +15 -3
  322. package/ShadersWGSL/fluidRenderingParticleThickness.vertex.js.map +1 -1
  323. package/ShadersWGSL/gaussianSplattingVoxel.fragment.js +15 -9
  324. package/ShadersWGSL/gaussianSplattingVoxel.fragment.js.map +1 -1
  325. package/ShadersWGSL/iblCombineVoxelGrids.fragment.js +1 -1
  326. package/ShadersWGSL/iblCombineVoxelGrids.fragment.js.map +1 -1
  327. package/ShadersWGSL/iblCopyVoxelBufferToGrid.compute.d.ts +5 -0
  328. package/ShadersWGSL/iblCopyVoxelBufferToGrid.compute.js +14 -0
  329. package/ShadersWGSL/iblCopyVoxelBufferToGrid.compute.js.map +1 -0
  330. package/ShadersWGSL/iblShadowVoxelTracing.fragment.js +24 -7
  331. package/ShadersWGSL/iblShadowVoxelTracing.fragment.js.map +1 -1
  332. package/ShadersWGSL/iblVoxelGrid.fragment.js +26 -6
  333. package/ShadersWGSL/iblVoxelGrid.fragment.js.map +1 -1
  334. package/SmartAssets/smartAssetManager.pure.js +1 -1
  335. package/SmartAssets/smartAssetManager.pure.js.map +1 -1
  336. package/Sprites/thinSprite.js +1 -1
  337. package/Sprites/thinSprite.js.map +1 -1
  338. package/XR/features/Layers/WebXRCompositionLayer.d.ts +182 -12
  339. package/XR/features/Layers/WebXRCompositionLayer.js +272 -3
  340. package/XR/features/Layers/WebXRCompositionLayer.js.map +1 -1
  341. package/XR/features/Layers/WebXRFallbackLayer.d.ts +84 -0
  342. package/XR/features/Layers/WebXRFallbackLayer.js +137 -0
  343. package/XR/features/Layers/WebXRFallbackLayer.js.map +1 -0
  344. package/XR/features/Layers/WebXRWebGPUCompositionLayer.d.ts +4 -4
  345. package/XR/features/Layers/WebXRWebGPUCompositionLayer.js.map +1 -1
  346. package/XR/features/WebXRAnchorSystem.pure.d.ts +45 -0
  347. package/XR/features/WebXRAnchorSystem.pure.js +153 -13
  348. package/XR/features/WebXRAnchorSystem.pure.js.map +1 -1
  349. package/XR/features/WebXRControllerPointerSelection.pure.js +2 -1
  350. package/XR/features/WebXRControllerPointerSelection.pure.js.map +1 -1
  351. package/XR/features/WebXRControllerTeleportation.pure.js +2 -1
  352. package/XR/features/WebXRControllerTeleportation.pure.js.map +1 -1
  353. package/XR/features/WebXRDepthSensing.pure.d.ts +21 -0
  354. package/XR/features/WebXRDepthSensing.pure.js +42 -0
  355. package/XR/features/WebXRDepthSensing.pure.js.map +1 -1
  356. package/XR/features/WebXRHandTracking.pure.js +2 -0
  357. package/XR/features/WebXRHandTracking.pure.js.map +1 -1
  358. package/XR/features/WebXRLayers.pure.d.ts +183 -8
  359. package/XR/features/WebXRLayers.pure.js +531 -99
  360. package/XR/features/WebXRLayers.pure.js.map +1 -1
  361. package/XR/features/WebXRLayersFallback.d.ts +5 -0
  362. package/XR/features/WebXRLayersFallback.js +8 -0
  363. package/XR/features/WebXRLayersFallback.js.map +1 -0
  364. package/XR/features/WebXRLayersFallback.pure.d.ts +6 -0
  365. package/XR/features/WebXRLayersFallback.pure.js +44 -0
  366. package/XR/features/WebXRLayersFallback.pure.js.map +1 -0
  367. package/XR/features/WebXRLightEstimation.pure.d.ts +3 -4
  368. package/XR/features/WebXRLightEstimation.pure.js +22 -21
  369. package/XR/features/WebXRLightEstimation.pure.js.map +1 -1
  370. package/XR/features/WebXRMeshDetector.pure.d.ts +5 -0
  371. package/XR/features/WebXRMeshDetector.pure.js +1 -0
  372. package/XR/features/WebXRMeshDetector.pure.js.map +1 -1
  373. package/XR/features/WebXRNearInteraction.pure.js +3 -3
  374. package/XR/features/WebXRNearInteraction.pure.js.map +1 -1
  375. package/XR/features/WebXRPlaneDetector.pure.d.ts +9 -5
  376. package/XR/features/WebXRPlaneDetector.pure.js +12 -8
  377. package/XR/features/WebXRPlaneDetector.pure.js.map +1 -1
  378. package/XR/features/WebXRTrackedSources.d.ts +5 -0
  379. package/XR/features/WebXRTrackedSources.js +8 -0
  380. package/XR/features/WebXRTrackedSources.js.map +1 -0
  381. package/XR/features/WebXRTrackedSources.pure.d.ts +70 -0
  382. package/XR/features/WebXRTrackedSources.pure.js +153 -0
  383. package/XR/features/WebXRTrackedSources.pure.js.map +1 -0
  384. package/XR/features/index.d.ts +1 -0
  385. package/XR/features/index.js +1 -0
  386. package/XR/features/index.js.map +1 -1
  387. package/XR/features/pure.d.ts +2 -0
  388. package/XR/features/pure.js +2 -0
  389. package/XR/features/pure.js.map +1 -1
  390. package/XR/motionController/webXRAbstractMotionController.d.ts +53 -1
  391. package/XR/motionController/webXRAbstractMotionController.js +61 -0
  392. package/XR/motionController/webXRAbstractMotionController.js.map +1 -1
  393. package/XR/webXRCamera.d.ts +2 -0
  394. package/XR/webXRCamera.js +8 -2
  395. package/XR/webXRCamera.js.map +1 -1
  396. package/XR/webXRDefaultExperience.js +8 -4
  397. package/XR/webXRDefaultExperience.js.map +1 -1
  398. package/XR/webXRExperienceHelper.js +86 -44
  399. package/XR/webXRExperienceHelper.js.map +1 -1
  400. package/XR/webXRFeaturesManager.d.ts +9 -0
  401. package/XR/webXRFeaturesManager.js +4 -0
  402. package/XR/webXRFeaturesManager.js.map +1 -1
  403. package/XR/webXRGraphicsBinding.d.ts +29 -0
  404. package/XR/webXRGraphicsBinding.js +40 -0
  405. package/XR/webXRGraphicsBinding.js.map +1 -1
  406. package/XR/webXRInputSource.js +1 -1
  407. package/XR/webXRInputSource.js.map +1 -1
  408. package/XR/webXRLayerWrapper.d.ts +26 -10
  409. package/XR/webXRLayerWrapper.js +19 -7
  410. package/XR/webXRLayerWrapper.js.map +1 -1
  411. package/XR/webXRRenderTargetTextureProvider.d.ts +4 -4
  412. package/XR/webXRRenderTargetTextureProvider.js.map +1 -1
  413. package/XR/webXRSessionManager.d.ts +45 -0
  414. package/XR/webXRSessionManager.js +174 -29
  415. package/XR/webXRSessionManager.js.map +1 -1
  416. package/XR/webXRWebGLRenderTargetTextureProvider.d.ts +2 -1
  417. package/XR/webXRWebGLRenderTargetTextureProvider.js.map +1 -1
  418. package/XR/webXRWebGPURenderTargetTextureProvider.d.ts +3 -3
  419. package/XR/webXRWebGPURenderTargetTextureProvider.js.map +1 -1
  420. package/package.json +1 -1
  421. package/scene.pure.d.ts +5 -0
  422. package/scene.pure.js +25 -0
  423. package/scene.pure.js.map +1 -1
@@ -3,14 +3,27 @@ import { WebXRFeatureName, WebXRFeaturesManager } from "../webXRFeaturesManager.
3
3
  import { WebXRAbstractFeature } from "./WebXRAbstractFeature.js";
4
4
  import { WebXRWebGLLayerWrapper } from "../webXRWebGLLayer.js";
5
5
  import { WebXRProjectionLayerWrapper, DefaultXRProjectionLayerInit } from "./Layers/WebXRProjectionLayer.js";
6
- import { WebXRCompositionLayerRenderTargetTextureProvider, WebXRCompositionLayerWrapper } from "./Layers/WebXRCompositionLayer.js";
6
+ import { WebXRCompositionLayerRenderTargetTextureProvider, WebXRCompositionLayerWrapper, WebXRCubeLayerWrapper, WebXRMediaLayerWrapper, WebXRSpatialLayerWrapper, } from "./Layers/WebXRCompositionLayer.js";
7
7
  import { WebXRWebGPUProjectionLayerWrapper, CreateDefaultXRGPUProjectionLayerInit } from "./Layers/WebXRWebGPUProjectionLayer.js";
8
- import { WebXRWebGPUCompositionLayerRenderTargetTextureProvider, WebXRWebGPUCompositionLayerWrapper } from "./Layers/WebXRWebGPUCompositionLayer.js";
8
+ import { WebXRWebGPUCompositionLayerRenderTargetTextureProvider } from "./Layers/WebXRWebGPUCompositionLayer.js";
9
+ import { IsWebGPUXRSupported } from "../webXRGraphicsBinding.js";
9
10
  import { Color4 } from "../../Maths/math.color.pure.js";
10
11
  import { Logger } from "../../Misc/logger.js";
12
+ import { TransformNode } from "../../Meshes/transformNode.pure.js";
13
+ import { Quaternion } from "../../Maths/math.vector.pure.js";
14
+ export { WebXRCompositionLayerWrapper, WebXRCubeLayerWrapper, WebXRMediaLayerWrapper, WebXRSpatialLayerWrapper } from "./Layers/WebXRCompositionLayer.js";
11
15
  const DefaultXRWebGLLayerInit = {};
12
16
  const WebGPUQuadLayerCreateWarning = "WebGPU XR quad layers are unavailable because XRGPUBinding.createQuadLayer is not supported; the requested quad layer was skipped and projection rendering remains active.";
13
17
  const WebGPUQuadLayerSubImageWarning = "WebGPU XR quad layers are unavailable because XRGPUBinding.getSubImage is not supported; the requested quad layer was skipped and projection rendering remains active.";
18
+ let _FallbackLayerFactory = null;
19
+ /**
20
+ * Registers the optional mesh-fallback implementation without making its rendering dependencies part of projection-only bundles.
21
+ * @param factory creates a fallback wrapper
22
+ * @internal
23
+ */
24
+ export function _RegisterWebXRFallbackLayerFactory(factory) {
25
+ _FallbackLayerFactory = factory;
26
+ }
14
27
  /**
15
28
  * Exposes the WebXR Layers API.
16
29
  */
@@ -22,13 +35,31 @@ export class WebXRLayers extends WebXRAbstractFeature {
22
35
  * Already-created layers
23
36
  */
24
37
  this._existingLayers = [];
38
+ this._fallbackLayers = [];
25
39
  this._isWebGPU = false;
26
40
  this._isMultiviewEnabled = false;
27
41
  this._projectionLayerInitialized = false;
28
42
  this._compositionLayerTextureMapping = new WeakMap();
29
43
  this._layerToRTTProviderMapping = new WeakMap();
44
+ this._layerCleanupFunctions = new WeakMap();
30
45
  this.xrNativeFeatureName = "layers";
31
46
  }
47
+ /**
48
+ * Whether the active XR session exposes its compositor layer limit.
49
+ */
50
+ get isMaxRenderLayersSupported() {
51
+ return this.maxRenderLayers !== null;
52
+ }
53
+ /**
54
+ * Gets the maximum number of native layers accepted in the active session's render-state `layers` array.
55
+ * The projection layer counts toward this limit. Fallback mesh layers do not.
56
+ * @returns The native layer limit, or `null` when the runtime does not expose it.
57
+ * @see https://playground.babylonjs.com/#TODARD#0
58
+ */
59
+ get maxRenderLayers() {
60
+ const maxRenderLayers = this._xrSessionManager.session?.maxRenderLayers;
61
+ return typeof maxRenderLayers === "number" ? maxRenderLayers : null;
62
+ }
32
63
  /**
33
64
  * Attach this feature.
34
65
  * Will usually be called by the features manager.
@@ -64,6 +95,13 @@ export class WebXRLayers extends WebXRAbstractFeature {
64
95
  this.createProjectionLayer(projectionLayerInit /*, projectionLayerMultiview*/);
65
96
  }
66
97
  this._projectionLayerInitialized = true;
98
+ this._addNewAttachObserver(this._xrSessionManager.onXRReferenceSpaceChanged, (referenceSpace) => {
99
+ for (const layer of this._existingLayers) {
100
+ if (layer instanceof WebXRSpatialLayerWrapper && layer.usesSessionReferenceSpace) {
101
+ layer.layer.space = referenceSpace;
102
+ }
103
+ }
104
+ });
67
105
  return true;
68
106
  }
69
107
  detach() {
@@ -71,9 +109,15 @@ export class WebXRLayers extends WebXRAbstractFeature {
71
109
  return false;
72
110
  }
73
111
  for (const layer of this._existingLayers) {
112
+ this._layerCleanupFunctions.get(layer)?.();
74
113
  layer.dispose();
75
114
  }
76
115
  this._existingLayers.length = 0;
116
+ for (const layer of this._fallbackLayers) {
117
+ layer.dispose();
118
+ }
119
+ this._fallbackLayers.length = 0;
120
+ this._xrMediaBinding = undefined;
77
121
  this._projectionLayerInitialized = false;
78
122
  return true;
79
123
  }
@@ -86,7 +130,7 @@ export class WebXRLayers extends WebXRAbstractFeature {
86
130
  const layer = new XRWebGLLayer(this._xrSessionManager.session, this._glContext, params);
87
131
  return new WebXRWebGLLayerWrapper(layer);
88
132
  }
89
- _validateLayerInit(params, multiview = this._isMultiviewEnabled) {
133
+ _validateLayerInit(params, multiview = this._isMultiviewEnabled, allowTextureArrayWithoutMultiview = false) {
90
134
  // check if we are in session
91
135
  if (!this._xrSessionManager.inXRSession) {
92
136
  throw new Error("Cannot create a layer outside of a WebXR session. Make sure the session has started before creating layers.");
@@ -95,7 +139,7 @@ export class WebXRLayers extends WebXRAbstractFeature {
95
139
  throw new Error("Projection layers can only be made multiview if they use texture arrays. Set the textureType parameter to 'texture-array'.");
96
140
  }
97
141
  // TODO (rgerd): Support RTT's that are bound to sub-images in the texture array.
98
- if (!multiview && params.textureType === "texture-array") {
142
+ if (!multiview && params.textureType === "texture-array" && !allowTextureArrayWithoutMultiview) {
99
143
  throw new Error("We currently only support multiview rendering when the textureType parameter is set to 'texture-array'.");
100
144
  }
101
145
  }
@@ -105,6 +149,177 @@ export class WebXRLayers extends WebXRAbstractFeature {
105
149
  }
106
150
  return params;
107
151
  }
152
+ _getProjectionLayerDimensions() {
153
+ const projectionLayer = this._existingLayers.find((layer) => layer.layerType === "XRProjectionLayer");
154
+ if (!projectionLayer) {
155
+ throw new Error("A projection layer must be created before adding WebXR composition layers.");
156
+ }
157
+ return {
158
+ width: projectionLayer.getWidth(),
159
+ height: projectionLayer.getHeight(),
160
+ };
161
+ }
162
+ _createTransformNode(layerType, transformNode, transform, orientation) {
163
+ if (transformNode) {
164
+ return { node: transformNode, ownsNode: false };
165
+ }
166
+ const node = new TransformNode(`WebXR ${layerType}`, this._xrSessionManager.scene);
167
+ node.rotationQuaternion = new Quaternion();
168
+ const sourcePosition = transform?.position;
169
+ const sourceOrientation = transform?.orientation ?? orientation;
170
+ if (sourcePosition) {
171
+ const worldScalingFactor = this._xrSessionManager.worldScalingFactor;
172
+ node.position.set(sourcePosition.x * worldScalingFactor, sourcePosition.y * worldScalingFactor, sourcePosition.z * worldScalingFactor);
173
+ }
174
+ if (sourceOrientation) {
175
+ node.rotationQuaternion.set(sourceOrientation.x, sourceOrientation.y, sourceOrientation.z, sourceOrientation.w);
176
+ }
177
+ if (!this._xrSessionManager.scene.useRightHandedSystem) {
178
+ node.position.z *= -1;
179
+ node.rotationQuaternion.z *= -1;
180
+ node.rotationQuaternion.w *= -1;
181
+ }
182
+ return { node, ownsNode: true };
183
+ }
184
+ _createFallbackLayer(layerType, transformNode, transform, orientation, dimensions, texture, video) {
185
+ if (!_FallbackLayerFactory) {
186
+ Logger.Warn("WebXR mesh fallbacks require importing `@babylonjs/core/XR/features/WebXRLayersFallback`.");
187
+ return null;
188
+ }
189
+ const transformInfo = this._createTransformNode(layerType, transformNode, transform, orientation);
190
+ const wrapper = _FallbackLayerFactory({
191
+ scene: this._xrSessionManager.scene,
192
+ isWebGPU: this._isWebGPU,
193
+ layerType,
194
+ transformNode: transformInfo.node,
195
+ ownsTransformNode: transformInfo.ownsNode,
196
+ dimensions,
197
+ worldScalingFactor: this._xrSessionManager.worldScalingFactor,
198
+ texture,
199
+ video,
200
+ });
201
+ if (wrapper) {
202
+ this._fallbackLayers.push(wrapper);
203
+ }
204
+ else if (transformInfo.ownsNode) {
205
+ transformInfo.node.dispose();
206
+ }
207
+ return wrapper;
208
+ }
209
+ _createGraphicsLayer(layerType, factoryName, factorySupported, options, createWebGLLayer, createWebGPULayer, copyWebGPUSpecificInit) {
210
+ if (!this._xrSessionManager.inXRSession) {
211
+ throw new Error("Cannot create a layer outside of a WebXR session. Make sure the session has started before creating layers.");
212
+ }
213
+ if (!factorySupported) {
214
+ if (options.fallbackMode !== "mesh") {
215
+ Logger.Warn(`${layerType} is unavailable because ${factoryName} is not supported; the requested layer was skipped and projection rendering remains active.`);
216
+ }
217
+ return null;
218
+ }
219
+ if (this._isWebGPU && typeof this._xrGPUBinding?.getSubImage !== "function") {
220
+ if (options.fallbackMode !== "mesh") {
221
+ Logger.Warn(`${layerType} is unavailable because XRGPUBinding.getSubImage is not supported; the requested layer was skipped and projection rendering remains active.`);
222
+ }
223
+ return null;
224
+ }
225
+ this._validateLayerCount(this._existingLayers.length + 1);
226
+ const dimensions = this._getProjectionLayerDimensions();
227
+ const defaultViewPixelWidth = layerType === "XRCubeLayer" ? Math.min(dimensions.width, dimensions.height) : dimensions.width;
228
+ const defaultViewPixelHeight = layerType === "XRCubeLayer" ? defaultViewPixelWidth : dimensions.height;
229
+ const populatedParams = {
230
+ space: this._xrSessionManager.referenceSpace,
231
+ viewPixelWidth: defaultViewPixelWidth,
232
+ viewPixelHeight: defaultViewPixelHeight,
233
+ clearOnAccess: true,
234
+ textureType: "texture",
235
+ layout: "mono",
236
+ ...options.layerInit,
237
+ };
238
+ if (layerType === "XRCubeLayer" && populatedParams.viewPixelWidth !== populatedParams.viewPixelHeight) {
239
+ throw new Error("WebXR cube layer faces must have equal pixel width and height.");
240
+ }
241
+ this._validateLayerInit(populatedParams, false, layerType === "XRCubeLayer");
242
+ let layer;
243
+ let effectiveParams = populatedParams;
244
+ let depthStencilFormat;
245
+ if (this._isWebGPU) {
246
+ const binding = this._xrGPUBinding;
247
+ const gpuParams = {
248
+ colorFormat: binding.getPreferredColorFormat(),
249
+ textureUsage: 0x10,
250
+ space: populatedParams.space,
251
+ viewPixelWidth: populatedParams.viewPixelWidth,
252
+ viewPixelHeight: populatedParams.viewPixelHeight,
253
+ layout: populatedParams.layout,
254
+ mipLevels: populatedParams.mipLevels,
255
+ isStatic: populatedParams.isStatic,
256
+ };
257
+ copyWebGPUSpecificInit(populatedParams, gpuParams);
258
+ Object.assign(gpuParams, options.gpuLayerInit);
259
+ if (layerType === "XRCubeLayer" && gpuParams.viewPixelWidth !== gpuParams.viewPixelHeight) {
260
+ throw new Error("WebXR cube layer faces must have equal pixel width and height.");
261
+ }
262
+ effectiveParams = gpuParams;
263
+ depthStencilFormat = gpuParams.depthStencilFormat;
264
+ layer = createWebGPULayer(binding, gpuParams);
265
+ }
266
+ else {
267
+ layer = createWebGLLayer(this._xrWebGLBinding, populatedParams);
268
+ }
269
+ const transform = "transform" in effectiveParams ? effectiveParams.transform : undefined;
270
+ const orientation = "orientation" in effectiveParams ? effectiveParams.orientation : undefined;
271
+ const usesSessionReferenceSpace = options.layerInit?.space === undefined && (!this._isWebGPU || options.gpuLayerInit?.space === undefined);
272
+ const transformInfo = this._createTransformNode(layerType, options.transformNode, transform, orientation);
273
+ let wrapper;
274
+ if (layerType === "XRCubeLayer") {
275
+ wrapper = new WebXRCubeLayerWrapper(() => effectiveParams.viewPixelWidth, () => effectiveParams.viewPixelHeight, layer, !!effectiveParams.isStatic, usesSessionReferenceSpace, this._isWebGPU ? this._xrGPUBinding : this._xrWebGLBinding, transformInfo.node, transformInfo.ownsNode);
276
+ }
277
+ else if (this._isWebGPU) {
278
+ const binding = this._xrGPUBinding;
279
+ wrapper = new WebXRSpatialLayerWrapper(() => effectiveParams.viewPixelWidth, () => effectiveParams.viewPixelHeight, layer, layerType, false, !!effectiveParams.isStatic, usesSessionReferenceSpace, (sessionManager) => new WebXRWebGPUCompositionLayerRenderTargetTextureProvider(sessionManager, binding, wrapper, depthStencilFormat), transformInfo.node, transformInfo.ownsNode);
280
+ }
281
+ else {
282
+ wrapper = new WebXRSpatialLayerWrapper(() => effectiveParams.viewPixelWidth, () => effectiveParams.viewPixelHeight, layer, layerType, false, !!effectiveParams.isStatic, usesSessionReferenceSpace, (sessionManager) => new WebXRCompositionLayerRenderTargetTextureProvider(sessionManager, this._xrWebGLBinding, wrapper), transformInfo.node, transformInfo.ownsNode);
283
+ }
284
+ if (wrapper.usesRenderTargetProvider) {
285
+ const rttProvider = wrapper.createRenderTargetTextureProvider(this._xrSessionManager);
286
+ this._layerToRTTProviderMapping.set(layer, rttProvider);
287
+ }
288
+ this.addXRSessionLayer(wrapper);
289
+ return wrapper;
290
+ }
291
+ _createMediaLayer(layerType, factoryName, video, options, createLayer) {
292
+ if (!this._xrSessionManager.inXRSession) {
293
+ throw new Error("Cannot create a layer outside of a WebXR session. Make sure the session has started before creating layers.");
294
+ }
295
+ if (typeof XRMediaBinding === "undefined") {
296
+ if (options.fallbackMode !== "mesh") {
297
+ Logger.Warn(`${layerType} media layers are unavailable because XRMediaBinding is not supported; the requested layer was skipped.`);
298
+ }
299
+ return null;
300
+ }
301
+ this._xrMediaBinding ?? (this._xrMediaBinding = new XRMediaBinding(this._xrSessionManager.session));
302
+ const mediaBinding = this._xrMediaBinding;
303
+ const factory = mediaBinding[factoryName];
304
+ if (typeof factory !== "function") {
305
+ if (options.fallbackMode !== "mesh") {
306
+ Logger.Warn(`${layerType} media layers are unavailable because XRMediaBinding.${factoryName} is not supported; the requested layer was skipped.`);
307
+ }
308
+ return null;
309
+ }
310
+ this._validateLayerCount(this._existingLayers.length + 1);
311
+ const populatedParams = {
312
+ space: this._xrSessionManager.referenceSpace,
313
+ layout: "mono",
314
+ ...options.layerInit,
315
+ };
316
+ const layer = createLayer(mediaBinding, video, populatedParams);
317
+ const transform = "transform" in populatedParams ? populatedParams.transform : undefined;
318
+ const transformInfo = this._createTransformNode(layerType, options.transformNode, transform);
319
+ const wrapper = new WebXRMediaLayerWrapper(() => video.videoWidth, () => video.videoHeight, layer, layerType, transformInfo.node, transformInfo.ownsNode, options.layerInit?.space === undefined);
320
+ this.addXRSessionLayer(wrapper);
321
+ return wrapper;
322
+ }
108
323
  /**
109
324
  * Creates a new XRProjectionLayer.
110
325
  * @param params an object providing configuration options for the new XRProjectionLayer.
@@ -112,9 +327,10 @@ export class WebXRLayers extends WebXRAbstractFeature {
112
327
  * @returns the projection layer
113
328
  */
114
329
  createProjectionLayer(params = DefaultXRProjectionLayerInit, multiview = this._isMultiviewEnabled) {
115
- this._extendXRLayerInit(params, multiview);
116
- this._validateLayerInit(params, multiview);
117
- const projLayer = this._xrWebGLBinding.createProjectionLayer(params);
330
+ const extendedParams = this._extendXRLayerInit(params, multiview);
331
+ this._validateLayerInit(extendedParams, multiview);
332
+ this._validateLayerCount(this._existingLayers.length + 1);
333
+ const projLayer = this._xrWebGLBinding.createProjectionLayer(extendedParams);
118
334
  const layer = new WebXRProjectionLayerWrapper(projLayer, multiview, this._xrWebGLBinding);
119
335
  this.addXRSessionLayer(layer);
120
336
  return layer;
@@ -128,6 +344,7 @@ export class WebXRLayers extends WebXRAbstractFeature {
128
344
  if (!this._xrSessionManager.inXRSession) {
129
345
  throw new Error("Cannot create a layer outside of a WebXR session. Make sure the session has started before creating layers.");
130
346
  }
347
+ this._validateLayerCount(this._existingLayers.length + 1);
131
348
  const binding = this._xrGPUBinding;
132
349
  const init = CreateDefaultXRGPUProjectionLayerInit(binding.getPreferredColorFormat());
133
350
  const projLayer = binding.createProjectionLayer(init);
@@ -136,25 +353,138 @@ export class WebXRLayers extends WebXRAbstractFeature {
136
353
  return layer;
137
354
  }
138
355
  /**
139
- * Note about making it private - this function will be exposed once I decide on a proper API to support all of the XR layers' options
140
- * @param options an object providing configuration options for the new XRQuadLayer.
141
- * @param babylonTexture the texture to display in the layer
142
- * @returns the quad layer, or null when the WebGPU binding lacks quad-layer support
356
+ * Creates a graphics-backed quad layer and adds it to the current XR session.
357
+ * @param options initialization and transform-node options for the layer
358
+ * @returns the created layer wrapper, or `null` when the active graphics binding does not support quad layers
143
359
  */
360
+ createQuadLayer(options = {}) {
361
+ const factorySupported = this._isWebGPU ? typeof this._xrGPUBinding?.createQuadLayer === "function" : typeof this._xrWebGLBinding.createQuadLayer === "function";
362
+ const factoryName = this._isWebGPU ? "XRGPUBinding.createQuadLayer" : "XRWebGLBinding.createQuadLayer";
363
+ const nativeLayer = this._createGraphicsLayer("XRQuadLayer", factoryName, factorySupported, options, (binding, init) => binding.createQuadLayer(init), (binding, init) => binding.createQuadLayer(init), (webGLInit, webGPUInit) => {
364
+ webGPUInit.transform = webGLInit.transform;
365
+ webGPUInit.width = webGLInit.width;
366
+ webGPUInit.height = webGLInit.height;
367
+ });
368
+ if (nativeLayer || options.fallbackMode !== "mesh") {
369
+ return nativeLayer;
370
+ }
371
+ return this._createFallbackLayer("XRQuadLayer", options.transformNode, options.layerInit?.transform, undefined, { width: options.layerInit?.width, height: options.layerInit?.height }, options.fallbackTexture);
372
+ }
373
+ /**
374
+ * Creates a graphics-backed cylinder layer and adds it to the current XR session.
375
+ * @param options initialization and transform-node options for the layer
376
+ * @returns the created layer wrapper, or `null` when the active graphics binding does not support cylinder layers
377
+ */
378
+ createCylinderLayer(options = {}) {
379
+ const factorySupported = this._isWebGPU ? typeof this._xrGPUBinding?.createCylinderLayer === "function" : typeof this._xrWebGLBinding.createCylinderLayer === "function";
380
+ const factoryName = this._isWebGPU ? "XRGPUBinding.createCylinderLayer" : "XRWebGLBinding.createCylinderLayer";
381
+ const nativeLayer = this._createGraphicsLayer("XRCylinderLayer", factoryName, factorySupported, options, (binding, init) => binding.createCylinderLayer(init), (binding, init) => binding.createCylinderLayer(init), (webGLInit, webGPUInit) => {
382
+ webGPUInit.transform = webGLInit.transform;
383
+ webGPUInit.radius = webGLInit.radius;
384
+ webGPUInit.centralAngle = webGLInit.centralAngle;
385
+ webGPUInit.aspectRatio = webGLInit.aspectRatio;
386
+ });
387
+ if (nativeLayer || options.fallbackMode !== "mesh") {
388
+ return nativeLayer;
389
+ }
390
+ return this._createFallbackLayer("XRCylinderLayer", options.transformNode, options.layerInit?.transform, undefined, {
391
+ radius: options.layerInit?.radius,
392
+ centralAngle: options.layerInit?.centralAngle,
393
+ aspectRatio: options.layerInit?.aspectRatio,
394
+ }, options.fallbackTexture);
395
+ }
396
+ /**
397
+ * Creates a graphics-backed equirectangular layer and adds it to the current XR session.
398
+ * @param options initialization and transform-node options for the layer
399
+ * @returns the created layer wrapper, or `null` when the active graphics binding does not support equirectangular layers
400
+ */
401
+ createEquirectLayer(options = {}) {
402
+ const factorySupported = this._isWebGPU ? typeof this._xrGPUBinding?.createEquirectLayer === "function" : typeof this._xrWebGLBinding.createEquirectLayer === "function";
403
+ const factoryName = this._isWebGPU ? "XRGPUBinding.createEquirectLayer" : "XRWebGLBinding.createEquirectLayer";
404
+ const nativeLayer = this._createGraphicsLayer("XREquirectLayer", factoryName, factorySupported, options, (binding, init) => binding.createEquirectLayer(init), (binding, init) => binding.createEquirectLayer(init), (webGLInit, webGPUInit) => {
405
+ webGPUInit.transform = webGLInit.transform;
406
+ webGPUInit.radius = webGLInit.radius;
407
+ webGPUInit.centralHorizontalAngle = webGLInit.centralHorizontalAngle;
408
+ webGPUInit.upperVerticalAngle = webGLInit.upperVerticalAngle;
409
+ webGPUInit.lowerVerticalAngle = webGLInit.lowerVerticalAngle;
410
+ });
411
+ if (nativeLayer || options.fallbackMode !== "mesh") {
412
+ return nativeLayer;
413
+ }
414
+ return this._createFallbackLayer("XREquirectLayer", options.transformNode, options.layerInit?.transform, undefined, {
415
+ radius: options.layerInit?.radius,
416
+ centralHorizontalAngle: options.layerInit?.centralHorizontalAngle,
417
+ upperVerticalAngle: options.layerInit?.upperVerticalAngle,
418
+ lowerVerticalAngle: options.layerInit?.lowerVerticalAngle,
419
+ }, options.fallbackTexture);
420
+ }
421
+ /**
422
+ * Creates a graphics-backed cube layer and adds it to the current XR session.
423
+ * Cube layers synchronize only the rotation of their transform node because the WebXR API does not support cube-layer translation.
424
+ * @param options initialization and transform-node options for the layer
425
+ * @returns the created layer wrapper, or `null` when the active graphics binding does not support cube layers
426
+ */
427
+ createCubeLayer(options = {}) {
428
+ const factorySupported = this._isWebGPU ? typeof this._xrGPUBinding?.createCubeLayer === "function" : typeof this._xrWebGLBinding.createCubeLayer === "function";
429
+ const factoryName = this._isWebGPU ? "XRGPUBinding.createCubeLayer" : "XRWebGLBinding.createCubeLayer";
430
+ const nativeLayer = this._createGraphicsLayer("XRCubeLayer", factoryName, factorySupported, options, (binding, init) => binding.createCubeLayer(init), (binding, init) => binding.createCubeLayer(init), (webGLInit, webGPUInit) => {
431
+ webGPUInit.orientation = webGLInit.orientation;
432
+ });
433
+ if (nativeLayer || options.fallbackMode !== "mesh") {
434
+ return nativeLayer;
435
+ }
436
+ return this._createFallbackLayer("XRCubeLayer", options.transformNode, undefined, options.layerInit?.orientation, {}, options.fallbackTexture);
437
+ }
438
+ /**
439
+ * Creates a video-backed quad layer and adds it to the current XR session.
440
+ * @see https://playground.babylonjs.com/#D35HOL#0
441
+ * @param video the video element presented by the XR compositor
442
+ * @param options initialization and transform-node options for the layer
443
+ * @returns the created media layer wrapper, or `null` when XRMediaBinding is unavailable
444
+ */
445
+ createMediaQuadLayer(video, options = {}) {
446
+ const nativeLayer = this._createMediaLayer("XRQuadLayer", "createQuadLayer", video, options, (binding, media, init) => binding.createQuadLayer(media, init));
447
+ if (nativeLayer || options.fallbackMode !== "mesh") {
448
+ return nativeLayer;
449
+ }
450
+ return this._createFallbackLayer("XRQuadLayer", options.transformNode, options.layerInit?.transform, undefined, { width: options.layerInit?.width, height: options.layerInit?.height }, undefined, video);
451
+ }
452
+ /**
453
+ * Creates a video-backed cylinder layer and adds it to the current XR session.
454
+ * @param video the video element presented by the XR compositor
455
+ * @param options initialization and transform-node options for the layer
456
+ * @returns the created media layer wrapper, or `null` when XRMediaBinding is unavailable
457
+ */
458
+ createMediaCylinderLayer(video, options = {}) {
459
+ const nativeLayer = this._createMediaLayer("XRCylinderLayer", "createCylinderLayer", video, options, (binding, media, init) => binding.createCylinderLayer(media, init));
460
+ if (nativeLayer || options.fallbackMode !== "mesh") {
461
+ return nativeLayer;
462
+ }
463
+ return this._createFallbackLayer("XRCylinderLayer", options.transformNode, options.layerInit?.transform, undefined, {
464
+ radius: options.layerInit?.radius,
465
+ centralAngle: options.layerInit?.centralAngle,
466
+ aspectRatio: options.layerInit?.aspectRatio,
467
+ }, undefined, video);
468
+ }
469
+ /**
470
+ * Creates a video-backed equirectangular layer and adds it to the current XR session.
471
+ * @param video the video element presented by the XR compositor
472
+ * @param options initialization and transform-node options for the layer
473
+ * @returns the created media layer wrapper, or `null` when XRMediaBinding is unavailable
474
+ */
475
+ createMediaEquirectLayer(video, options = {}) {
476
+ const nativeLayer = this._createMediaLayer("XREquirectLayer", "createEquirectLayer", video, options, (binding, media, init) => binding.createEquirectLayer(media, init));
477
+ if (nativeLayer || options.fallbackMode !== "mesh") {
478
+ return nativeLayer;
479
+ }
480
+ return this._createFallbackLayer("XREquirectLayer", options.transformNode, options.layerInit?.transform, undefined, {
481
+ radius: options.layerInit?.radius,
482
+ centralHorizontalAngle: options.layerInit?.centralHorizontalAngle,
483
+ upperVerticalAngle: options.layerInit?.upperVerticalAngle,
484
+ lowerVerticalAngle: options.layerInit?.lowerVerticalAngle,
485
+ }, undefined, video);
486
+ }
144
487
  _createQuadLayer(options = { params: {} }, babylonTexture) {
145
- this._extendXRLayerInit(options.params, false);
146
- const width = this._existingLayers[0].layer.textureWidth;
147
- const height = this._existingLayers[0].layer.textureHeight;
148
- const populatedParams = {
149
- space: this._xrSessionManager.referenceSpace,
150
- viewPixelWidth: width,
151
- viewPixelHeight: height,
152
- clearOnAccess: true,
153
- ...options.params,
154
- };
155
- this._validateLayerInit(populatedParams, false);
156
- let quadLayer;
157
- let wrapper;
158
488
  if (this._isWebGPU) {
159
489
  const binding = this._xrGPUBinding;
160
490
  if (typeof binding.createQuadLayer !== "function") {
@@ -165,48 +495,17 @@ export class WebXRLayers extends WebXRAbstractFeature {
165
495
  Logger.Warn(WebGPUQuadLayerSubImageWarning);
166
496
  return null;
167
497
  }
168
- const gpuParams = {
169
- colorFormat: binding.getPreferredColorFormat(),
170
- // GPUTextureUsage.RENDER_ATTACHMENT (0x10) is requested explicitly. The usage of a
171
- // compositor-owned sub-image texture is not a valid source for layer creation flags.
172
- textureUsage: 0x10,
173
- space: populatedParams.space,
174
- viewPixelWidth: populatedParams.viewPixelWidth,
175
- viewPixelHeight: populatedParams.viewPixelHeight,
176
- };
177
- if (populatedParams.layout !== undefined) {
178
- gpuParams.layout = populatedParams.layout;
179
- }
180
- if (populatedParams.mipLevels !== undefined) {
181
- gpuParams.mipLevels = populatedParams.mipLevels;
182
- }
183
- if (populatedParams.isStatic !== undefined) {
184
- gpuParams.isStatic = populatedParams.isStatic;
185
- }
186
- if (populatedParams.transform !== undefined) {
187
- gpuParams.transform = populatedParams.transform;
188
- }
189
- if (populatedParams.width !== undefined) {
190
- gpuParams.width = populatedParams.width;
191
- }
192
- if (populatedParams.height !== undefined) {
193
- gpuParams.height = populatedParams.height;
194
- }
195
- quadLayer = binding.createQuadLayer(gpuParams);
196
- wrapper = new WebXRWebGPUCompositionLayerWrapper(() => quadLayer.width, () => quadLayer.height, quadLayer, "XRQuadLayer", false, (sessionManager) => new WebXRWebGPUCompositionLayerRenderTargetTextureProvider(sessionManager, binding, wrapper));
197
498
  }
198
- else {
199
- quadLayer = this._xrWebGLBinding.createQuadLayer(populatedParams);
200
- wrapper = new WebXRCompositionLayerWrapper(() => quadLayer.width, () => quadLayer.height, quadLayer, "XRQuadLayer", false, (sessionManager) => new WebXRCompositionLayerRenderTargetTextureProvider(sessionManager, this._xrWebGLBinding, wrapper));
499
+ const wrapper = this.createQuadLayer({ layerInit: options.params });
500
+ if (!wrapper || wrapper.layer === null) {
501
+ return null;
201
502
  }
503
+ const quadLayer = wrapper.layer;
202
504
  quadLayer.width = this._isMultiviewEnabled ? 1 : 2;
203
505
  quadLayer.height = 1;
204
506
  if (babylonTexture) {
205
507
  this._compositionLayerTextureMapping.set(quadLayer, babylonTexture);
206
508
  }
207
- const rtt = wrapper.createRenderTargetTextureProvider(this._xrSessionManager);
208
- this._layerToRTTProviderMapping.set(quadLayer, rtt);
209
- this.addXRSessionLayer(wrapper);
210
509
  return wrapper;
211
510
  }
212
511
  /**
@@ -228,13 +527,12 @@ export class WebXRLayers extends WebXRAbstractFeature {
228
527
  if (!wrapper) {
229
528
  return null;
230
529
  }
231
- const layer = wrapper.layer;
232
530
  const distance = Math.max(0.1, options.distanceFromHeadset);
233
- const pos = { x: 0, y: 0, z: -distance };
234
- const orient = { x: 0, y: 0, z: 0, w: 1 };
235
- layer.transform = new XRRigidTransform(pos, orient);
236
- const rttProvider = this._layerToRTTProviderMapping.get(layer);
237
- if (!rttProvider) {
531
+ const z = this._xrSessionManager.scene.useRightHandedSystem ? -distance : distance;
532
+ wrapper.transformNode.position.set(0, 0, z * this._xrSessionManager.worldScalingFactor);
533
+ const rttProvider = this._layerToRTTProviderMapping.get(wrapper.layer);
534
+ if (!rttProvider ||
535
+ (!(rttProvider instanceof WebXRCompositionLayerRenderTargetTextureProvider) && !(rttProvider instanceof WebXRWebGPUCompositionLayerRenderTargetTextureProvider))) {
238
536
  throw new Error("Could not find the RTT provider for the layer");
239
537
  }
240
538
  const babylonLayer = this._xrSessionManager.scene.layers.find((babylonLayer) => {
@@ -243,25 +541,43 @@ export class WebXRLayers extends WebXRAbstractFeature {
243
541
  if (!babylonLayer) {
244
542
  throw new Error("Could not find the babylon layer for the texture");
245
543
  }
246
- rttProvider.onRenderTargetTextureCreatedObservable.add((data) => {
544
+ const renderTargetTextures = new Set();
545
+ const beforeRenderObservers = [];
546
+ const previousRenderOnlyInRenderTargetTextures = babylonLayer.renderOnlyInRenderTargetTextures;
547
+ let cleanedUp = false;
548
+ const renderTargetCreatedObserver = rttProvider.onRenderTargetTextureCreatedObservable.add((data) => {
247
549
  if (data.eye && data.eye === "right") {
248
550
  return;
249
551
  }
250
552
  data.texture.clearColor = new Color4(0, 0, 0, 0);
251
553
  babylonLayer.renderTargetTextures.push(data.texture);
554
+ renderTargetTextures.add(data.texture);
252
555
  babylonLayer.renderOnlyInRenderTargetTextures = true;
253
556
  // for stereo (not for gui) it should be onBeforeCameraRenderObservable
254
- this._xrSessionManager.scene.onBeforeRenderObservable.add(() => {
557
+ beforeRenderObservers.push(this._xrSessionManager.scene.onBeforeRenderObservable.add(() => {
255
558
  data.texture.render();
256
- });
257
- babylonLayer.renderTargetTextures.push(data.texture);
258
- babylonLayer.renderOnlyInRenderTargetTextures = true;
259
- // add it back when the session ends
260
- this._xrSessionManager.onXRSessionEnded.addOnce(() => {
261
- babylonLayer.renderTargetTextures.splice(babylonLayer.renderTargetTextures.indexOf(data.texture), 1);
262
- babylonLayer.renderOnlyInRenderTargetTextures = false;
263
- });
559
+ }));
264
560
  });
561
+ const cleanup = () => {
562
+ if (cleanedUp) {
563
+ return;
564
+ }
565
+ cleanedUp = true;
566
+ rttProvider.onRenderTargetTextureCreatedObservable.remove(renderTargetCreatedObserver);
567
+ for (const observer of beforeRenderObservers) {
568
+ this._xrSessionManager.scene.onBeforeRenderObservable.remove(observer);
569
+ }
570
+ for (const renderTargetTexture of renderTargetTextures) {
571
+ const index = babylonLayer.renderTargetTextures.indexOf(renderTargetTexture);
572
+ if (index !== -1) {
573
+ babylonLayer.renderTargetTextures.splice(index, 1);
574
+ }
575
+ }
576
+ babylonLayer.renderOnlyInRenderTargetTextures = previousRenderOnlyInRenderTargetTextures;
577
+ this._layerCleanupFunctions.delete(wrapper);
578
+ };
579
+ this._layerCleanupFunctions.set(wrapper, cleanup);
580
+ this._xrSessionManager.onXRSessionEnded.addOnce(cleanup);
265
581
  return wrapper;
266
582
  }
267
583
  /**
@@ -287,12 +603,12 @@ export class WebXRLayers extends WebXRAbstractFeature {
287
603
  layer.width = 2;
288
604
  layer.height = 1;
289
605
  const distance = 10;
290
- const pos = { x: 0, y: 0, z: -distance };
291
- const orient = { x: 0, y: 0, z: 0, w: 1 };
292
- layer.transform = new XRRigidTransform(pos, orient);
606
+ const z = this._xrSessionManager.scene.useRightHandedSystem ? -distance : distance;
607
+ wrapper.transformNode.position.set(0, 0, z * this._xrSessionManager.worldScalingFactor);
293
608
  // get the rtt wrapper
294
609
  const rttProvider = this._layerToRTTProviderMapping.get(layer);
295
- if (!rttProvider) {
610
+ if (!rttProvider ||
611
+ (!(rttProvider instanceof WebXRCompositionLayerRenderTargetTextureProvider) && !(rttProvider instanceof WebXRWebGPUCompositionLayerRenderTargetTextureProvider))) {
296
612
  throw new Error("Could not find the RTT provider for the layer");
297
613
  }
298
614
  // render the flare system to the rtt
@@ -321,9 +637,57 @@ export class WebXRLayers extends WebXRAbstractFeature {
321
637
  * @param wrappedLayer the new layer to add to the existing ones
322
638
  */
323
639
  addXRSessionLayer(wrappedLayer) {
640
+ this._validateLayerCount(this._existingLayers.length + 1);
324
641
  this._existingLayers.push(wrappedLayer);
325
642
  this.setXRSessionLayers(this._existingLayers);
326
643
  }
644
+ /**
645
+ * Removes a non-projection layer from the current XR session.
646
+ * @param wrappedLayer the layer wrapper to remove
647
+ * @param dispose whether to dispose the wrapper and destroy its native composition layer
648
+ * @returns whether the layer was present and removed
649
+ */
650
+ removeXRSessionLayer(wrappedLayer, dispose = true) {
651
+ const index = this._existingLayers.indexOf(wrappedLayer);
652
+ if (index === -1) {
653
+ return false;
654
+ }
655
+ if (wrappedLayer.layerType === "XRProjectionLayer") {
656
+ Logger.Warn("The active projection layer cannot be removed from WebXRLayers.");
657
+ return false;
658
+ }
659
+ this._existingLayers.splice(index, 1);
660
+ this._layerCleanupFunctions.get(wrappedLayer)?.();
661
+ if (wrappedLayer instanceof WebXRCompositionLayerWrapper) {
662
+ this._layerToRTTProviderMapping.delete(wrappedLayer.layer);
663
+ this._compositionLayerTextureMapping.delete(wrappedLayer.layer);
664
+ }
665
+ this.setXRSessionLayers(this._existingLayers);
666
+ if (dispose) {
667
+ wrappedLayer.dispose();
668
+ }
669
+ return true;
670
+ }
671
+ /**
672
+ * Removes either a native spatial layer or a fallback layer created by this feature.
673
+ * @param wrappedLayer the native or fallback layer wrapper to remove
674
+ * @param dispose whether to dispose resources owned by the wrapper
675
+ * @returns whether the wrapper was present and removed
676
+ */
677
+ removeLayer(wrappedLayer, dispose = true) {
678
+ if (wrappedLayer.layer === null) {
679
+ const index = this._fallbackLayers.indexOf(wrappedLayer);
680
+ if (index === -1) {
681
+ return false;
682
+ }
683
+ this._fallbackLayers.splice(index, 1);
684
+ if (dispose) {
685
+ wrappedLayer.dispose();
686
+ }
687
+ return true;
688
+ }
689
+ return this.removeXRSessionLayer(wrappedLayer, dispose);
690
+ }
327
691
  /**
328
692
  * Sets the layers to be used by the XR session.
329
693
  * Note that you must call this function with any layers you wish to render to
@@ -334,6 +698,7 @@ export class WebXRLayers extends WebXRAbstractFeature {
334
698
  * @param wrappedLayers An array of WebXRLayerWrapper, usually returned from the WebXRLayers createLayer functions.
335
699
  */
336
700
  setXRSessionLayers(wrappedLayers = this._existingLayers) {
701
+ this._validateLayerCount(wrappedLayers.length);
337
702
  // this._existingLayers = wrappedLayers;
338
703
  const renderStateInit = { ...this._xrSessionManager.session.renderState };
339
704
  // Clear out the layer-related fields.
@@ -344,9 +709,70 @@ export class WebXRLayers extends WebXRAbstractFeature {
344
709
  this._xrSessionManager._setBaseLayerWrapper(wrappedLayers.length > 0 ? wrappedLayers.at(0) : null);
345
710
  }
346
711
  }
712
+ _validateLayerCount(layerCount) {
713
+ const maxRenderLayers = this.maxRenderLayers;
714
+ if (maxRenderLayers !== null && layerCount > maxRenderLayers) {
715
+ const layerLabel = maxRenderLayers === 1 ? "layer" : "layers";
716
+ throw new Error(`The XR session supports at most ${maxRenderLayers} render ${layerLabel}, but ${layerCount} were provided.`);
717
+ }
718
+ }
719
+ /**
720
+ * Checks whether the active runtime exposes the factory needed for a layer type.
721
+ * This is a capability check only; creation can still fail when an initialization dictionary is invalid.
722
+ * @param layerType the concrete WebXR layer type
723
+ * @param source whether to check a graphics-backed or media-backed layer
724
+ * @returns whether the requested factory is available
725
+ */
726
+ isLayerTypeSupported(layerType, source = "graphics") {
727
+ if (source === "media") {
728
+ if (layerType === "XRProjectionLayer" || layerType === "XRCubeLayer" || typeof XRMediaBinding === "undefined") {
729
+ return false;
730
+ }
731
+ switch (layerType) {
732
+ case "XRQuadLayer":
733
+ return typeof XRMediaBinding.prototype.createQuadLayer === "function";
734
+ case "XRCylinderLayer":
735
+ return typeof XRMediaBinding.prototype.createCylinderLayer === "function";
736
+ case "XREquirectLayer":
737
+ return typeof XRMediaBinding.prototype.createEquirectLayer === "function";
738
+ }
739
+ }
740
+ if (this._xrSessionManager.scene.getEngine().isWebGPU) {
741
+ if (typeof XRGPUBinding === "undefined") {
742
+ return false;
743
+ }
744
+ switch (layerType) {
745
+ case "XRProjectionLayer":
746
+ return typeof XRGPUBinding.prototype.createProjectionLayer === "function";
747
+ case "XRQuadLayer":
748
+ return typeof XRGPUBinding.prototype.createQuadLayer === "function";
749
+ case "XRCylinderLayer":
750
+ return typeof XRGPUBinding.prototype.createCylinderLayer === "function";
751
+ case "XREquirectLayer":
752
+ return typeof XRGPUBinding.prototype.createEquirectLayer === "function";
753
+ case "XRCubeLayer":
754
+ return typeof XRGPUBinding.prototype.createCubeLayer === "function";
755
+ }
756
+ }
757
+ if (typeof XRWebGLBinding === "undefined") {
758
+ return false;
759
+ }
760
+ switch (layerType) {
761
+ case "XRProjectionLayer":
762
+ return typeof XRWebGLBinding.prototype.createProjectionLayer === "function";
763
+ case "XRQuadLayer":
764
+ return typeof XRWebGLBinding.prototype.createQuadLayer === "function";
765
+ case "XRCylinderLayer":
766
+ return typeof XRWebGLBinding.prototype.createCylinderLayer === "function";
767
+ case "XREquirectLayer":
768
+ return typeof XRWebGLBinding.prototype.createEquirectLayer === "function";
769
+ case "XRCubeLayer":
770
+ return typeof XRWebGLBinding.prototype.createCubeLayer === "function";
771
+ }
772
+ }
347
773
  isCompatible() {
348
774
  if (this._xrSessionManager.scene.getEngine().isWebGPU) {
349
- return typeof XRGPUBinding !== "undefined" && !!XRGPUBinding.prototype.createProjectionLayer;
775
+ return IsWebGPUXRSupported();
350
776
  }
351
777
  // Native WebGL continues to use NativeXRRenderTarget instead of WebXR Layers.
352
778
  if (this._xrSessionManager.isNative) {
@@ -361,30 +787,36 @@ export class WebXRLayers extends WebXRAbstractFeature {
361
787
  super.dispose();
362
788
  }
363
789
  _onXRFrame(_xrFrame) {
364
- // Replace once the mapped internal texture of each available composition layer, apart from the last one, which is the projection layer that needs an RTT
790
+ for (let i = 0; i < this._fallbackLayers.length; ++i) {
791
+ this._fallbackLayers[i].updateFromTransformNode(this._xrSessionManager.worldScalingFactor);
792
+ }
365
793
  const layers = this._existingLayers;
366
794
  for (let i = 0; i < layers.length; ++i) {
367
795
  const layer = layers[i];
368
- if (layer.layerType !== "XRProjectionLayer") {
369
- // get the rtt provider
370
- const rttProvider = this._layerToRTTProviderMapping.get(layer.layer);
371
- if (!rttProvider) {
372
- continue;
373
- }
374
- if (rttProvider.layerWrapper.isMultiview) {
375
- // get the views, if we are in multiview
376
- const pose = _xrFrame.getViewerPose(this._xrSessionManager.referenceSpace);
377
- if (pose) {
378
- const views = pose.views;
379
- for (let j = 0; j < views.length; ++j) {
380
- const view = views[j];
381
- rttProvider.getRenderTargetTextureForView(view);
382
- }
796
+ if (layer instanceof WebXRSpatialLayerWrapper) {
797
+ layer.updateFromTransformNode(this._xrSessionManager.scene.useRightHandedSystem, this._xrSessionManager.worldScalingFactor);
798
+ }
799
+ if (layer.layerType === "XRProjectionLayer" || !(layer instanceof WebXRCompositionLayerWrapper) || !layer.usesRenderTargetProvider) {
800
+ continue;
801
+ }
802
+ if (layer.isStatic && !layer.layer.needsRedraw) {
803
+ continue;
804
+ }
805
+ const rttProvider = this._layerToRTTProviderMapping.get(layer.layer);
806
+ if (!rttProvider) {
807
+ continue;
808
+ }
809
+ if (layer.layer.layout === "mono") {
810
+ rttProvider.getRenderTargetTextureForEye("none");
811
+ }
812
+ else {
813
+ const pose = _xrFrame.getViewerPose(this._xrSessionManager.referenceSpace);
814
+ if (pose) {
815
+ const views = pose.views;
816
+ for (let j = 0; j < views.length; ++j) {
817
+ rttProvider.getRenderTargetTextureForView(views[j]);
383
818
  }
384
819
  }
385
- else {
386
- rttProvider.getRenderTargetTextureForView();
387
- }
388
820
  }
389
821
  }
390
822
  }