@codexo/exojs 0.8.4 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/README.md +34 -13
  3. package/dist/esm/animation/Tween.d.ts +20 -3
  4. package/dist/esm/animation/Tween.js +16 -8
  5. package/dist/esm/animation/Tween.js.map +1 -1
  6. package/dist/esm/animation/TweenManager.d.ts +16 -1
  7. package/dist/esm/animation/TweenManager.js +27 -2
  8. package/dist/esm/animation/TweenManager.js.map +1 -1
  9. package/dist/esm/audio/AudioAnalyser.d.ts +2 -0
  10. package/dist/esm/audio/AudioAnalyser.js +24 -9
  11. package/dist/esm/audio/AudioAnalyser.js.map +1 -1
  12. package/dist/esm/audio/AudioBus.d.ts +1 -0
  13. package/dist/esm/audio/AudioBus.js +8 -4
  14. package/dist/esm/audio/AudioBus.js.map +1 -1
  15. package/dist/esm/audio/AudioListener.d.ts +1 -0
  16. package/dist/esm/audio/AudioListener.js +7 -5
  17. package/dist/esm/audio/AudioListener.js.map +1 -1
  18. package/dist/esm/audio/AudioManager.d.ts +8 -2
  19. package/dist/esm/audio/AudioManager.js +14 -1
  20. package/dist/esm/audio/AudioManager.js.map +1 -1
  21. package/dist/esm/audio/BeatDetector.d.ts +2 -0
  22. package/dist/esm/audio/BeatDetector.js +27 -661
  23. package/dist/esm/audio/BeatDetector.js.map +1 -1
  24. package/dist/esm/audio/Music.d.ts +1 -0
  25. package/dist/esm/audio/Music.js +7 -3
  26. package/dist/esm/audio/Music.js.map +1 -1
  27. package/dist/esm/audio/OscillatorSound.d.ts +1 -0
  28. package/dist/esm/audio/OscillatorSound.js +7 -3
  29. package/dist/esm/audio/OscillatorSound.js.map +1 -1
  30. package/dist/esm/audio/Sound.d.ts +1 -0
  31. package/dist/esm/audio/Sound.js +7 -3
  32. package/dist/esm/audio/Sound.js.map +1 -1
  33. package/dist/esm/audio/audio-context.d.ts +2 -2
  34. package/dist/esm/audio/audio-context.js +4 -4
  35. package/dist/esm/audio/audio-context.js.map +1 -1
  36. package/dist/esm/audio/filters/ChorusFilter.d.ts +1 -0
  37. package/dist/esm/audio/filters/ChorusFilter.js +7 -3
  38. package/dist/esm/audio/filters/ChorusFilter.js.map +1 -1
  39. package/dist/esm/audio/filters/CompressorFilter.d.ts +1 -0
  40. package/dist/esm/audio/filters/CompressorFilter.js +7 -3
  41. package/dist/esm/audio/filters/CompressorFilter.js.map +1 -1
  42. package/dist/esm/audio/filters/DelayFilter.d.ts +1 -0
  43. package/dist/esm/audio/filters/DelayFilter.js +7 -3
  44. package/dist/esm/audio/filters/DelayFilter.js.map +1 -1
  45. package/dist/esm/audio/filters/EqualizerFilter.d.ts +1 -0
  46. package/dist/esm/audio/filters/EqualizerFilter.js +7 -3
  47. package/dist/esm/audio/filters/EqualizerFilter.js.map +1 -1
  48. package/dist/esm/audio/filters/GranularFilter.js +1 -86
  49. package/dist/esm/audio/filters/GranularFilter.js.map +1 -1
  50. package/dist/esm/audio/filters/HighpassFilter.d.ts +1 -0
  51. package/dist/esm/audio/filters/HighpassFilter.js +7 -3
  52. package/dist/esm/audio/filters/HighpassFilter.js.map +1 -1
  53. package/dist/esm/audio/filters/LowpassFilter.d.ts +1 -0
  54. package/dist/esm/audio/filters/LowpassFilter.js +7 -3
  55. package/dist/esm/audio/filters/LowpassFilter.js.map +1 -1
  56. package/dist/esm/audio/filters/PitchShiftFilter.js +1 -71
  57. package/dist/esm/audio/filters/PitchShiftFilter.js.map +1 -1
  58. package/dist/esm/audio/filters/ReverbFilter.d.ts +1 -0
  59. package/dist/esm/audio/filters/ReverbFilter.js +7 -3
  60. package/dist/esm/audio/filters/ReverbFilter.js.map +1 -1
  61. package/dist/esm/audio/filters/VocoderFilter.js +1 -89
  62. package/dist/esm/audio/filters/VocoderFilter.js.map +1 -1
  63. package/dist/esm/audio/filters/WorkletFilter.d.ts +2 -0
  64. package/dist/esm/audio/filters/WorkletFilter.js +10 -5
  65. package/dist/esm/audio/filters/WorkletFilter.js.map +1 -1
  66. package/dist/esm/audio/index.d.ts +15 -10
  67. package/dist/esm/audio/worklet/registerWorklet.d.ts +1 -1
  68. package/dist/esm/audio/worklet/registerWorklet.js +2 -2
  69. package/dist/esm/audio/worklet/registerWorklet.js.map +1 -1
  70. package/dist/esm/audio/worklets/beat-detector.worklet.d.ts +1 -0
  71. package/dist/esm/audio/worklets/beat-detector.worklet.js +647 -0
  72. package/dist/esm/audio/worklets/beat-detector.worklet.js.map +1 -0
  73. package/dist/esm/audio/worklets/granular.worklet.d.ts +1 -0
  74. package/dist/esm/audio/worklets/granular.worklet.js +89 -0
  75. package/dist/esm/audio/worklets/granular.worklet.js.map +1 -0
  76. package/dist/esm/audio/worklets/pitch-shift.worklet.d.ts +1 -0
  77. package/dist/esm/audio/worklets/pitch-shift.worklet.js +74 -0
  78. package/dist/esm/audio/worklets/pitch-shift.worklet.js.map +1 -0
  79. package/dist/esm/audio/worklets/vocoder.worklet.d.ts +1 -0
  80. package/dist/esm/audio/worklets/vocoder.worklet.js +92 -0
  81. package/dist/esm/audio/worklets/vocoder.worklet.js.map +1 -0
  82. package/dist/esm/core/Application.d.ts +86 -29
  83. package/dist/esm/core/Application.js +157 -47
  84. package/dist/esm/core/Application.js.map +1 -1
  85. package/dist/esm/core/Color.d.ts +0 -8
  86. package/dist/esm/core/Color.js +0 -24
  87. package/dist/esm/core/Color.js.map +1 -1
  88. package/dist/esm/core/Perf.d.ts +23 -0
  89. package/dist/esm/core/Perf.js +49 -0
  90. package/dist/esm/core/Perf.js.map +1 -0
  91. package/dist/esm/core/Scene.d.ts +40 -80
  92. package/dist/esm/core/Scene.js +63 -43
  93. package/dist/esm/core/Scene.js.map +1 -1
  94. package/dist/esm/core/SceneManager.d.ts +11 -25
  95. package/dist/esm/core/SceneManager.js +37 -100
  96. package/dist/esm/core/SceneManager.js.map +1 -1
  97. package/dist/esm/core/SceneNode.d.ts +28 -17
  98. package/dist/esm/core/SceneNode.js +66 -42
  99. package/dist/esm/core/SceneNode.js.map +1 -1
  100. package/dist/esm/core/Signal.d.ts +24 -28
  101. package/dist/esm/core/Signal.js +64 -50
  102. package/dist/esm/core/Signal.js.map +1 -1
  103. package/dist/esm/core/Timer.d.ts +1 -0
  104. package/dist/esm/core/Timer.js +3 -0
  105. package/dist/esm/core/Timer.js.map +1 -1
  106. package/dist/esm/core/capabilities.d.ts +2 -0
  107. package/dist/esm/core/capabilities.js +15 -0
  108. package/dist/esm/core/capabilities.js.map +1 -1
  109. package/dist/esm/core/index.d.ts +1 -0
  110. package/dist/esm/core/types.d.ts +1 -1
  111. package/dist/esm/core/utils.d.ts +12 -0
  112. package/dist/esm/core/utils.js +18 -1
  113. package/dist/esm/core/utils.js.map +1 -1
  114. package/dist/esm/debug/BoundingBoxesLayer.js +1 -1
  115. package/dist/esm/debug/BoundingBoxesLayer.js.map +1 -1
  116. package/dist/esm/debug/HitTestLayer.js +1 -1
  117. package/dist/esm/debug/HitTestLayer.js.map +1 -1
  118. package/dist/esm/debug/PerformanceLayer.js +1 -2
  119. package/dist/esm/debug/PerformanceLayer.js.map +1 -1
  120. package/dist/esm/debug/PointerStackLayer.js +1 -2
  121. package/dist/esm/debug/PointerStackLayer.js.map +1 -1
  122. package/dist/esm/debug/RenderPassInspectorLayer.js +1 -2
  123. package/dist/esm/debug/RenderPassInspectorLayer.js.map +1 -1
  124. package/dist/esm/index.js +37 -10
  125. package/dist/esm/index.js.map +1 -1
  126. package/dist/esm/input/InputManager.d.ts +1 -0
  127. package/dist/esm/input/InputManager.js +30 -3
  128. package/dist/esm/input/InputManager.js.map +1 -1
  129. package/dist/esm/input/InteractionManager.d.ts +5 -2
  130. package/dist/esm/input/InteractionManager.js +29 -18
  131. package/dist/esm/input/InteractionManager.js.map +1 -1
  132. package/dist/esm/input/Pointer.js +3 -2
  133. package/dist/esm/input/Pointer.js.map +1 -1
  134. package/dist/esm/input/internal/interactionManagerRegistry.d.ts +9 -0
  135. package/dist/esm/input/internal/interactionManagerRegistry.js +10 -0
  136. package/dist/esm/input/internal/interactionManagerRegistry.js.map +1 -0
  137. package/dist/esm/math/AbstractVector.d.ts +1 -7
  138. package/dist/esm/math/AbstractVector.js +6 -20
  139. package/dist/esm/math/AbstractVector.js.map +1 -1
  140. package/dist/esm/math/Circle.js +0 -2
  141. package/dist/esm/math/Circle.js.map +1 -1
  142. package/dist/esm/math/Collision.d.ts +9 -3
  143. package/dist/esm/math/Ellipse.d.ts +2 -5
  144. package/dist/esm/math/Ellipse.js +10 -7
  145. package/dist/esm/math/Ellipse.js.map +1 -1
  146. package/dist/esm/math/ObservableVector.d.ts +1 -1
  147. package/dist/esm/math/ObservableVector.js +3 -3
  148. package/dist/esm/math/ObservableVector.js.map +1 -1
  149. package/dist/esm/math/Polygon.d.ts +0 -2
  150. package/dist/esm/math/Polygon.js +1 -9
  151. package/dist/esm/math/Polygon.js.map +1 -1
  152. package/dist/esm/math/Rectangle.js +0 -2
  153. package/dist/esm/math/Rectangle.js.map +1 -1
  154. package/dist/esm/math/collision-detection.d.ts +19 -4
  155. package/dist/esm/math/collision-detection.js +61 -4
  156. package/dist/esm/math/collision-detection.js.map +1 -1
  157. package/dist/esm/math/swept-collision.d.ts +16 -12
  158. package/dist/esm/math/swept-collision.js +109 -19
  159. package/dist/esm/math/swept-collision.js.map +1 -1
  160. package/dist/esm/particles/ParticleSystem.d.ts +8 -5
  161. package/dist/esm/particles/ParticleSystem.js +10 -6
  162. package/dist/esm/particles/ParticleSystem.js.map +1 -1
  163. package/dist/esm/particles/distributions/{Gradient.d.ts → ColorGradient.d.ts} +5 -5
  164. package/dist/esm/particles/distributions/{Gradient.js → ColorGradient.js} +5 -5
  165. package/dist/esm/particles/distributions/ColorGradient.js.map +1 -0
  166. package/dist/esm/particles/distributions/Distribution.d.ts +2 -2
  167. package/dist/esm/particles/distributions/index.d.ts +2 -2
  168. package/dist/esm/particles/gpu/ParticleGpuState.js +1 -1
  169. package/dist/esm/particles/index.d.ts +1 -0
  170. package/dist/esm/particles/modules/ColorOverLifetime.d.ts +3 -3
  171. package/dist/esm/particles/modules/ColorOverLifetime.js.map +1 -1
  172. package/dist/esm/particles/modules/ColorOverSpeed.d.ts +3 -3
  173. package/dist/esm/particles/modules/ColorOverSpeed.js.map +1 -1
  174. package/dist/esm/particles/modules/UpdateModule.d.ts +2 -2
  175. package/dist/esm/particles/modules/UpdateModule.js +1 -1
  176. package/dist/esm/particles/modules/WgslContribution.d.ts +2 -2
  177. package/dist/esm/rendering/CallbackRenderPass.d.ts +1 -0
  178. package/dist/esm/rendering/CallbackRenderPass.js +1 -0
  179. package/dist/esm/rendering/CallbackRenderPass.js.map +1 -1
  180. package/dist/esm/rendering/Camera.d.ts +33 -0
  181. package/dist/esm/rendering/Camera.js +38 -0
  182. package/dist/esm/rendering/Camera.js.map +1 -0
  183. package/dist/esm/rendering/Container.d.ts +7 -25
  184. package/dist/esm/rendering/Container.js +25 -87
  185. package/dist/esm/rendering/Container.js.map +1 -1
  186. package/dist/esm/rendering/Drawable.d.ts +8 -10
  187. package/dist/esm/rendering/Drawable.js +12 -20
  188. package/dist/esm/rendering/Drawable.js.map +1 -1
  189. package/dist/esm/rendering/RenderBackend.d.ts +19 -0
  190. package/dist/esm/rendering/RenderNode.d.ts +82 -11
  191. package/dist/esm/rendering/RenderNode.js +133 -163
  192. package/dist/esm/rendering/RenderNode.js.map +1 -1
  193. package/dist/esm/rendering/RenderPass.d.ts +1 -0
  194. package/dist/esm/rendering/RenderStats.d.ts +9 -0
  195. package/dist/esm/rendering/RenderStats.js +2 -0
  196. package/dist/esm/rendering/RenderStats.js.map +1 -1
  197. package/dist/esm/rendering/RenderTarget.d.ts +13 -0
  198. package/dist/esm/rendering/RenderTarget.js +13 -0
  199. package/dist/esm/rendering/RenderTarget.js.map +1 -1
  200. package/dist/esm/rendering/RenderTargetPass.js +17 -0
  201. package/dist/esm/rendering/RenderTargetPass.js.map +1 -1
  202. package/dist/esm/rendering/RendererRegistry.d.ts +1 -0
  203. package/dist/esm/rendering/RendererRegistry.js +1 -0
  204. package/dist/esm/rendering/RendererRegistry.js.map +1 -1
  205. package/dist/esm/rendering/RenderingContext.d.ts +87 -0
  206. package/dist/esm/rendering/RenderingContext.js +157 -0
  207. package/dist/esm/rendering/RenderingContext.js.map +1 -0
  208. package/dist/esm/rendering/TransformBuffer.d.ts +38 -0
  209. package/dist/esm/rendering/TransformBuffer.js +116 -0
  210. package/dist/esm/rendering/TransformBuffer.js.map +1 -0
  211. package/dist/esm/rendering/View.d.ts +23 -0
  212. package/dist/esm/rendering/View.js +42 -0
  213. package/dist/esm/rendering/View.js.map +1 -1
  214. package/dist/esm/rendering/filters/WebGpuShaderFilter.js +5 -12
  215. package/dist/esm/rendering/filters/WebGpuShaderFilter.js.map +1 -1
  216. package/dist/esm/rendering/geometry/Geometry.d.ts +40 -0
  217. package/dist/esm/rendering/geometry/Geometry.js +228 -0
  218. package/dist/esm/rendering/geometry/Geometry.js.map +1 -0
  219. package/dist/esm/rendering/geometry/GeometryAttribute.d.ts +32 -0
  220. package/dist/esm/rendering/geometry/QuadGeometry.d.ts +5 -0
  221. package/dist/esm/rendering/gradient/Gradient.d.ts +34 -0
  222. package/dist/esm/rendering/gradient/Gradient.js +114 -0
  223. package/dist/esm/rendering/gradient/Gradient.js.map +1 -0
  224. package/dist/esm/rendering/gradient/LinearGradient.d.ts +10 -0
  225. package/dist/esm/rendering/gradient/LinearGradient.js +26 -0
  226. package/dist/esm/rendering/gradient/LinearGradient.js.map +1 -0
  227. package/dist/esm/rendering/gradient/RadialGradient.d.ts +10 -0
  228. package/dist/esm/rendering/gradient/RadialGradient.js +25 -0
  229. package/dist/esm/rendering/gradient/RadialGradient.js.map +1 -0
  230. package/dist/esm/rendering/index.d.ts +103 -59
  231. package/dist/esm/rendering/material/Material.d.ts +114 -0
  232. package/dist/esm/rendering/material/Material.js +111 -0
  233. package/dist/esm/rendering/material/Material.js.map +1 -0
  234. package/dist/esm/rendering/material/MaterialKey.d.ts +18 -0
  235. package/dist/esm/rendering/material/MaterialKey.js +82 -0
  236. package/dist/esm/rendering/material/MaterialKey.js.map +1 -0
  237. package/dist/esm/rendering/material/MeshMaterial.d.ts +16 -0
  238. package/dist/esm/rendering/material/MeshMaterial.js +21 -0
  239. package/dist/esm/rendering/material/MeshMaterial.js.map +1 -0
  240. package/dist/esm/rendering/{mesh/MeshShader.d.ts → material/ShaderSource.d.ts} +30 -62
  241. package/dist/esm/rendering/{mesh/MeshShader.js → material/ShaderSource.js} +36 -62
  242. package/dist/esm/rendering/material/ShaderSource.js.map +1 -0
  243. package/dist/esm/rendering/material/SpriteMaterial.d.ts +15 -0
  244. package/dist/esm/rendering/material/SpriteMaterial.js +20 -0
  245. package/dist/esm/rendering/material/SpriteMaterial.js.map +1 -0
  246. package/dist/esm/rendering/mesh/Mesh.d.ts +29 -12
  247. package/dist/esm/rendering/mesh/Mesh.js +123 -4
  248. package/dist/esm/rendering/mesh/Mesh.js.map +1 -1
  249. package/dist/esm/rendering/pass/RenderPassCoordinator.d.ts +63 -0
  250. package/dist/esm/rendering/pass/RenderPassDescriptor.d.ts +48 -0
  251. package/dist/esm/rendering/pass/RenderPassDescriptor.js +16 -0
  252. package/dist/esm/rendering/pass/RenderPassDescriptor.js.map +1 -0
  253. package/dist/esm/rendering/plan/RenderCommand.d.ts +67 -0
  254. package/dist/esm/rendering/plan/RenderCommand.js +94 -0
  255. package/dist/esm/rendering/plan/RenderCommand.js.map +1 -0
  256. package/dist/esm/rendering/plan/RenderEffectExecutor.d.ts +10 -0
  257. package/dist/esm/rendering/plan/RenderEffectExecutor.js +159 -0
  258. package/dist/esm/rendering/plan/RenderEffectExecutor.js.map +1 -0
  259. package/dist/esm/rendering/plan/RenderPlan.d.ts +23 -0
  260. package/dist/esm/rendering/plan/RenderPlan.js +12 -0
  261. package/dist/esm/rendering/plan/RenderPlan.js.map +1 -0
  262. package/dist/esm/rendering/plan/RenderPlanBuilder.d.ts +31 -0
  263. package/dist/esm/rendering/plan/RenderPlanBuilder.js +242 -0
  264. package/dist/esm/rendering/plan/RenderPlanBuilder.js.map +1 -0
  265. package/dist/esm/rendering/plan/RenderPlanOptimizer.d.ts +10 -0
  266. package/dist/esm/rendering/plan/RenderPlanOptimizer.js +180 -0
  267. package/dist/esm/rendering/plan/RenderPlanOptimizer.js.map +1 -0
  268. package/dist/esm/rendering/plan/RenderPlanPlayer.d.ts +9 -0
  269. package/dist/esm/rendering/plan/RenderPlanPlayer.js +56 -0
  270. package/dist/esm/rendering/plan/RenderPlanPlayer.js.map +1 -0
  271. package/dist/esm/rendering/plan/RenderScope.d.ts +70 -0
  272. package/dist/esm/rendering/plan/RenderScope.js +16 -0
  273. package/dist/esm/rendering/plan/RenderScope.js.map +1 -0
  274. package/dist/esm/rendering/plan/playRenderTree.d.ts +4 -0
  275. package/dist/esm/rendering/plan/playRenderTree.js +19 -0
  276. package/dist/esm/rendering/plan/playRenderTree.js.map +1 -0
  277. package/dist/esm/rendering/shader/Shader.d.ts +1 -0
  278. package/dist/esm/rendering/shader/Shader.js +1 -0
  279. package/dist/esm/rendering/shader/Shader.js.map +1 -1
  280. package/dist/esm/rendering/shader/ShaderUniform.d.ts +1 -0
  281. package/dist/esm/rendering/shader/ShaderUniform.js +1 -0
  282. package/dist/esm/rendering/shader/ShaderUniform.js.map +1 -1
  283. package/dist/esm/rendering/sprite/Sprite.d.ts +25 -3
  284. package/dist/esm/rendering/sprite/Sprite.js +48 -15
  285. package/dist/esm/rendering/sprite/Sprite.js.map +1 -1
  286. package/dist/esm/rendering/sprite/spriteMaterialSources.d.ts +36 -0
  287. package/dist/esm/rendering/sprite/spriteMaterialSources.js +128 -0
  288. package/dist/esm/rendering/sprite/spriteMaterialSources.js.map +1 -0
  289. package/dist/esm/rendering/text/AbstractText.d.ts +36 -0
  290. package/dist/esm/rendering/text/AbstractText.js +49 -0
  291. package/dist/esm/rendering/text/AbstractText.js.map +1 -0
  292. package/dist/esm/rendering/text/BitmapText.d.ts +97 -0
  293. package/dist/esm/rendering/text/BitmapText.js +220 -0
  294. package/dist/esm/rendering/text/BitmapText.js.map +1 -0
  295. package/dist/esm/rendering/text/BmFont.d.ts +50 -0
  296. package/dist/esm/rendering/text/BmFont.js +24 -0
  297. package/dist/esm/rendering/text/BmFont.js.map +1 -0
  298. package/dist/esm/rendering/text/GlyphAtlas.d.ts +104 -0
  299. package/dist/esm/rendering/text/GlyphAtlas.js +347 -0
  300. package/dist/esm/rendering/text/GlyphAtlas.js.map +1 -0
  301. package/dist/esm/rendering/text/GlyphAtlasPool.d.ts +40 -0
  302. package/dist/esm/rendering/text/GlyphAtlasPool.js +67 -0
  303. package/dist/esm/rendering/text/GlyphAtlasPool.js.map +1 -0
  304. package/dist/esm/rendering/text/GlyphSdf.d.ts +92 -0
  305. package/dist/esm/rendering/text/GlyphSdf.js +220 -0
  306. package/dist/esm/rendering/text/GlyphSdf.js.map +1 -0
  307. package/dist/esm/rendering/text/HTMLText.d.ts +107 -0
  308. package/dist/esm/rendering/text/HTMLText.js +284 -0
  309. package/dist/esm/rendering/text/HTMLText.js.map +1 -0
  310. package/dist/esm/rendering/text/LayoutOptions.d.ts +30 -0
  311. package/dist/esm/rendering/text/Text.d.ts +89 -20
  312. package/dist/esm/rendering/text/Text.js +176 -101
  313. package/dist/esm/rendering/text/Text.js.map +1 -1
  314. package/dist/esm/rendering/text/TextLayout.d.ts +20 -8
  315. package/dist/esm/rendering/text/TextLayout.js +234 -25
  316. package/dist/esm/rendering/text/TextLayout.js.map +1 -1
  317. package/dist/esm/rendering/text/TextStyle.d.ts +154 -87
  318. package/dist/esm/rendering/text/TextStyle.js +257 -203
  319. package/dist/esm/rendering/text/TextStyle.js.map +1 -1
  320. package/dist/esm/rendering/text/types.d.ts +73 -13
  321. package/dist/esm/rendering/texture/DataTexture.d.ts +5 -0
  322. package/dist/esm/rendering/texture/DataTexture.js +7 -0
  323. package/dist/esm/rendering/texture/DataTexture.js.map +1 -1
  324. package/dist/esm/rendering/texture/Texture.d.ts +1 -0
  325. package/dist/esm/rendering/texture/Texture.js +1 -0
  326. package/dist/esm/rendering/texture/Texture.js.map +1 -1
  327. package/dist/esm/rendering/types.d.ts +3 -1
  328. package/dist/esm/rendering/types.js +2 -0
  329. package/dist/esm/rendering/types.js.map +1 -1
  330. package/dist/esm/rendering/video/Video.d.ts +5 -8
  331. package/dist/esm/rendering/video/Video.js +12 -13
  332. package/dist/esm/rendering/video/Video.js.map +1 -1
  333. package/dist/esm/rendering/webgl2/WebGl2Backend.d.ts +40 -0
  334. package/dist/esm/rendering/webgl2/WebGl2Backend.js +344 -27
  335. package/dist/esm/rendering/webgl2/WebGl2Backend.js.map +1 -1
  336. package/dist/esm/rendering/webgl2/WebGl2MeshRenderer.d.ts +22 -2
  337. package/dist/esm/rendering/webgl2/WebGl2MeshRenderer.js +404 -112
  338. package/dist/esm/rendering/webgl2/WebGl2MeshRenderer.js.map +1 -1
  339. package/dist/esm/rendering/webgl2/WebGl2PassCoordinator.d.ts +57 -0
  340. package/dist/esm/rendering/webgl2/WebGl2PassCoordinator.js +79 -0
  341. package/dist/esm/rendering/webgl2/WebGl2PassCoordinator.js.map +1 -0
  342. package/dist/esm/rendering/webgl2/WebGl2SpriteRenderer.d.ts +12 -0
  343. package/dist/esm/rendering/webgl2/WebGl2SpriteRenderer.js +214 -58
  344. package/dist/esm/rendering/webgl2/WebGl2SpriteRenderer.js.map +1 -1
  345. package/dist/esm/rendering/webgl2/WebGl2StencilClipper.d.ts +34 -0
  346. package/dist/esm/rendering/webgl2/WebGl2StencilClipper.js +169 -0
  347. package/dist/esm/rendering/webgl2/WebGl2StencilClipper.js.map +1 -0
  348. package/dist/esm/rendering/webgl2/WebGl2TextRenderer.d.ts +56 -0
  349. package/dist/esm/rendering/webgl2/WebGl2TextRenderer.js +486 -0
  350. package/dist/esm/rendering/webgl2/WebGl2TextRenderer.js.map +1 -0
  351. package/dist/esm/rendering/webgl2/glsl/mesh.frag.js +1 -1
  352. package/dist/esm/rendering/webgl2/glsl/mesh.vert.js +1 -1
  353. package/dist/esm/rendering/webgl2/glsl/stencil-clip.frag.js +4 -0
  354. package/dist/esm/rendering/webgl2/glsl/stencil-clip.frag.js.map +1 -0
  355. package/dist/esm/rendering/webgl2/glsl/stencil-clip.vert.js +4 -0
  356. package/dist/esm/rendering/webgl2/glsl/stencil-clip.vert.js.map +1 -0
  357. package/dist/esm/rendering/webgl2/glsl/text-color.frag.js +4 -0
  358. package/dist/esm/rendering/webgl2/glsl/text-color.frag.js.map +1 -0
  359. package/dist/esm/rendering/webgl2/glsl/text-msdf.frag.js +4 -0
  360. package/dist/esm/rendering/webgl2/glsl/text-msdf.frag.js.map +1 -0
  361. package/dist/esm/rendering/webgl2/glsl/text-sdf.frag.js +4 -0
  362. package/dist/esm/rendering/webgl2/glsl/text-sdf.frag.js.map +1 -0
  363. package/dist/esm/rendering/webgl2/glsl/text.vert.js +4 -0
  364. package/dist/esm/rendering/webgl2/glsl/text.vert.js.map +1 -0
  365. package/dist/esm/rendering/webgpu/WebGpuBackend.d.ts +50 -0
  366. package/dist/esm/rendering/webgpu/WebGpuBackend.js +151 -27
  367. package/dist/esm/rendering/webgpu/WebGpuBackend.js.map +1 -1
  368. package/dist/esm/rendering/webgpu/WebGpuBlendState.js +26 -0
  369. package/dist/esm/rendering/webgpu/WebGpuBlendState.js.map +1 -1
  370. package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js +22 -17
  371. package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js.map +1 -1
  372. package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.d.ts +26 -2
  373. package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js +511 -89
  374. package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js.map +1 -1
  375. package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js +13 -17
  376. package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js.map +1 -1
  377. package/dist/esm/rendering/webgpu/WebGpuPassCoordinator.d.ts +141 -0
  378. package/dist/esm/rendering/webgpu/WebGpuPassCoordinator.js +270 -0
  379. package/dist/esm/rendering/webgpu/WebGpuPassCoordinator.js.map +1 -0
  380. package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.d.ts +16 -0
  381. package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.js +344 -27
  382. package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.js.map +1 -1
  383. package/dist/esm/rendering/webgpu/WebGpuStencilClipper.d.ts +57 -0
  384. package/dist/esm/rendering/webgpu/WebGpuStencilClipper.js +257 -0
  385. package/dist/esm/rendering/webgpu/WebGpuStencilClipper.js.map +1 -0
  386. package/dist/esm/rendering/webgpu/WebGpuStencilState.d.ts +14 -0
  387. package/dist/esm/rendering/webgpu/WebGpuStencilState.js +36 -0
  388. package/dist/esm/rendering/webgpu/WebGpuStencilState.js.map +1 -0
  389. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.d.ts +70 -0
  390. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.js +775 -0
  391. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.js.map +1 -0
  392. package/dist/esm/rendering/webgpu/WebGpuTransformStorage.d.ts +16 -0
  393. package/dist/esm/rendering/webgpu/WebGpuTransformStorage.js +57 -0
  394. package/dist/esm/rendering/webgpu/WebGpuTransformStorage.js.map +1 -0
  395. package/dist/esm/rendering/webgpu/compute/WebGpuComputePipeline.js +96 -0
  396. package/dist/esm/rendering/webgpu/compute/WebGpuComputePipeline.js.map +1 -0
  397. package/dist/esm/rendering/webgpu/compute/WebGpuStorageBuffer.js +68 -0
  398. package/dist/esm/rendering/webgpu/compute/WebGpuStorageBuffer.js.map +1 -0
  399. package/dist/esm/resources/Asset.d.ts +23 -0
  400. package/dist/esm/resources/Asset.js +23 -0
  401. package/dist/esm/resources/Asset.js.map +1 -0
  402. package/dist/esm/resources/AssetDefinitions.d.ts +137 -0
  403. package/dist/esm/resources/Assets.d.ts +35 -0
  404. package/dist/esm/resources/Assets.js +32 -0
  405. package/dist/esm/resources/Assets.js.map +1 -0
  406. package/dist/esm/resources/IndexedDbDatabase.js +17 -1
  407. package/dist/esm/resources/IndexedDbDatabase.js.map +1 -1
  408. package/dist/esm/resources/IndexedDbStore.js +17 -1
  409. package/dist/esm/resources/IndexedDbStore.js.map +1 -1
  410. package/dist/esm/resources/JsonStore.d.ts +18 -0
  411. package/dist/esm/resources/JsonStore.js +62 -0
  412. package/dist/esm/resources/JsonStore.js.map +1 -0
  413. package/dist/esm/resources/Loader.d.ts +244 -18
  414. package/dist/esm/resources/Loader.js +456 -50
  415. package/dist/esm/resources/Loader.js.map +1 -1
  416. package/dist/esm/resources/LoadingQueue.d.ts +28 -0
  417. package/dist/esm/resources/LoadingQueue.js +59 -0
  418. package/dist/esm/resources/LoadingQueue.js.map +1 -0
  419. package/dist/esm/resources/factories/BmFontFactory.d.ts +25 -0
  420. package/dist/esm/resources/factories/BmFontFactory.js +96 -0
  421. package/dist/esm/resources/factories/BmFontFactory.js.map +1 -0
  422. package/dist/esm/resources/factories/CsvFactory.d.ts +35 -0
  423. package/dist/esm/resources/factories/CsvFactory.js +87 -0
  424. package/dist/esm/resources/factories/CsvFactory.js.map +1 -0
  425. package/dist/esm/resources/factories/ImageFactory.d.ts +14 -8
  426. package/dist/esm/resources/factories/ImageFactory.js +13 -6
  427. package/dist/esm/resources/factories/ImageFactory.js.map +1 -1
  428. package/dist/esm/resources/factories/MusicFactory.d.ts +8 -2
  429. package/dist/esm/resources/factories/MusicFactory.js +25 -14
  430. package/dist/esm/resources/factories/MusicFactory.js.map +1 -1
  431. package/dist/esm/resources/factories/SoundFactory.d.ts +2 -2
  432. package/dist/esm/resources/factories/SoundFactory.js.map +1 -1
  433. package/dist/esm/resources/factories/SubtitleFactory.d.ts +28 -0
  434. package/dist/esm/resources/factories/SubtitleFactory.js +203 -0
  435. package/dist/esm/resources/factories/SubtitleFactory.js.map +1 -0
  436. package/dist/esm/resources/factories/SvgFactory.d.ts +18 -1
  437. package/dist/esm/resources/factories/SvgFactory.js +21 -2
  438. package/dist/esm/resources/factories/SvgFactory.js.map +1 -1
  439. package/dist/esm/resources/factories/TextureFactory.d.ts +4 -4
  440. package/dist/esm/resources/factories/TextureFactory.js +8 -4
  441. package/dist/esm/resources/factories/TextureFactory.js.map +1 -1
  442. package/dist/esm/resources/factories/VideoFactory.d.ts +8 -2
  443. package/dist/esm/resources/factories/VideoFactory.js +27 -20
  444. package/dist/esm/resources/factories/VideoFactory.js.map +1 -1
  445. package/dist/esm/resources/factories/XmlFactory.d.ts +24 -0
  446. package/dist/esm/resources/factories/XmlFactory.js +37 -0
  447. package/dist/esm/resources/factories/XmlFactory.js.map +1 -0
  448. package/dist/esm/resources/index.d.ts +9 -1
  449. package/dist/esm/resources/tokens.d.ts +49 -3
  450. package/dist/esm/resources/tokens.js +50 -4
  451. package/dist/esm/resources/tokens.js.map +1 -1
  452. package/dist/exo.esm.js +15382 -8078
  453. package/dist/exo.esm.js.map +1 -1
  454. package/package.json +34 -16
  455. package/dist/esm/input/interaction-hooks.d.ts +0 -34
  456. package/dist/esm/input/interaction-hooks.js +0 -35
  457. package/dist/esm/input/interaction-hooks.js.map +0 -1
  458. package/dist/esm/particles/distributions/Gradient.js.map +0 -1
  459. package/dist/esm/rendering/mesh/MeshShader.js.map +0 -1
  460. package/dist/esm/rendering/text/DynamicGlyphAtlas.d.ts +0 -33
  461. package/dist/esm/rendering/text/DynamicGlyphAtlas.js +0 -134
  462. package/dist/esm/rendering/text/DynamicGlyphAtlas.js.map +0 -1
  463. package/dist/esm/rendering/text/atlas-singleton.d.ts +0 -7
  464. package/dist/esm/rendering/text/atlas-singleton.js +0 -17
  465. package/dist/esm/rendering/text/atlas-singleton.js.map +0 -1
  466. package/dist/esm/resources/factories/VttFactory.d.ts +0 -24
  467. package/dist/esm/resources/factories/VttFactory.js +0 -158
  468. package/dist/esm/resources/factories/VttFactory.js.map +0 -1
  469. package/dist/esm/vendor/webgl-debug.js +0 -1160
  470. package/dist/esm/vendor/webgl-debug.js.map +0 -1
@@ -1,7 +1,8 @@
1
- import { RenderingPrimitives, BufferTypes, BufferUsage } from '../types.js';
1
+ import { RenderEntryKind } from '../plan/RenderCommand.js';
2
2
  import { Shader } from '../shader/Shader.js';
3
3
  import { RenderTexture } from '../texture/RenderTexture.js';
4
4
  import { Texture } from '../texture/Texture.js';
5
+ import { BlendModes, BufferTypes, BufferUsage, RenderingPrimitives } from '../types.js';
5
6
  import { AbstractWebGl2Renderer } from './AbstractWebGl2Renderer.js';
6
7
  import fragmentSource from './glsl/mesh.frag.js';
7
8
  import vertexSource from './glsl/mesh.vert.js';
@@ -17,22 +18,29 @@ const vertexStrideBytes = 20;
17
18
  const vertexStrideWords = vertexStrideBytes / 4;
18
19
  const initialVertexCapacity = 64;
19
20
  const initialIndexCapacity = 192;
21
+ const initialNodeIndexCapacity = 64;
20
22
  const defaultVertexColor = 0xffffffff; // white, full alpha
21
23
  const maxCustomTextureSlots = 8;
24
+ const transformTextureUnit = 8;
22
25
  class WebGl2MeshRenderer extends AbstractWebGl2Renderer {
23
26
  _defaultShader = new Shader(vertexSource, fragmentSource);
24
27
  _customShaders = new Map();
25
- _tintScratch = new Float32Array(4);
28
+ _compatibilityCache = new Map();
26
29
  _textureUnitScratch = new Int32Array([0]);
30
+ _transformUnitScratch = new Int32Array([transformTextureUnit]);
27
31
  // Pre-built texture-unit indices used for custom-shader sampler bindings;
28
32
  // pre-allocated so the per-frame uniform path stays allocation-free.
29
- _slotScratches = Array.from({ length: maxCustomTextureSlots }, (_, i) => new Int32Array([i]));
33
+ _slotScratches = Array.from({ length: Math.max(transformTextureUnit + 1, maxCustomTextureSlots + 1) }, (_, i) => new Int32Array([i]));
30
34
  _vertexCapacity = initialVertexCapacity;
31
35
  _indexCapacity = initialIndexCapacity;
36
+ _nodeIndexCapacity = initialNodeIndexCapacity;
32
37
  _vertexData = new ArrayBuffer(initialVertexCapacity * vertexStrideBytes);
33
38
  _float32View = new Float32Array(this._vertexData);
34
39
  _uint32View = new Uint32Array(this._vertexData);
35
40
  _indexData = new Uint16Array(initialIndexCapacity);
41
+ _nodeIndexData = new Uint32Array(initialNodeIndexCapacity);
42
+ _pendingDraws = [];
43
+ _staticGeometryCache = new Map();
36
44
  _connection = null;
37
45
  _currentBlendMode = null;
38
46
  render(mesh) {
@@ -40,85 +48,52 @@ class WebGl2MeshRenderer extends AbstractWebGl2Renderer {
40
48
  if (!connection) {
41
49
  throw new Error('WebGl2MeshRenderer is not connected to a backend.');
42
50
  }
43
- const vertexCount = mesh.vertexCount;
44
- if (vertexCount === 0) {
51
+ if (mesh.vertexCount === 0) {
45
52
  return;
46
53
  }
47
54
  const backend = this.getBackend();
48
- const blendMode = mesh.blendMode;
49
- if (blendMode !== this._currentBlendMode) {
50
- this._currentBlendMode = blendMode;
51
- backend.setBlendMode(blendMode);
52
- }
53
- const shader = mesh.shader === null ? this._defaultShader : this._getOrCreateCustomShader(mesh.shader, connection.gl);
54
- const view = backend.view;
55
- // Auto-bound uniforms are set unconditionally if the (possibly custom)
56
- // shader declares them. Custom shaders that ignore one of these still
57
- // see the cycles from has(), but the GL call is skipped.
58
- if (shader.uniforms.has('u_projection')) {
59
- shader.getUniform('u_projection').setValue(view.getTransform().toArray(false));
60
- }
61
- if (shader.uniforms.has('u_translation')) {
62
- shader.getUniform('u_translation').setValue(mesh.getGlobalTransform().toArray(false));
63
- }
64
- if (shader.uniforms.has('u_tint')) {
65
- const tint = mesh.tint;
66
- this._tintScratch[0] = tint.red;
67
- this._tintScratch[1] = tint.green;
68
- this._tintScratch[2] = tint.blue;
69
- this._tintScratch[3] = tint.alpha;
70
- shader.getUniform('u_tint').setValue(this._tintScratch);
71
- }
72
- // The default fragment shader samples u_texture branchlessly; meshes
73
- // without an explicit texture get the engine's 1×1 white default. Only
74
- // bind+set if the active shader actually consumes u_texture.
75
- if (shader.uniforms.has('u_texture')) {
76
- const meshTexture = mesh.texture ?? Texture.white;
77
- shader.getUniform('u_texture').setValue(this._textureUnitScratch);
78
- backend.bindTexture(meshTexture, 0);
79
- }
80
- if (mesh.shader?.uniforms !== undefined) {
81
- this._bindCustomUniforms(shader, mesh.shader.uniforms, backend);
82
- }
83
- this._ensureVertexCapacity(vertexCount);
84
- const positions = mesh.vertices;
85
- const uvs = mesh.uvs;
86
- const colors = mesh.colors;
87
- for (let i = 0; i < vertexCount; i++) {
88
- const word = i * vertexStrideWords;
89
- const pair = i * 2;
90
- this._float32View[word] = positions[pair];
91
- this._float32View[word + 1] = positions[pair + 1];
92
- if (uvs !== null) {
93
- this._float32View[word + 2] = uvs[pair];
94
- this._float32View[word + 3] = uvs[pair + 1];
95
- }
96
- else {
97
- this._float32View[word + 2] = 0;
98
- this._float32View[word + 3] = 0;
99
- }
100
- this._uint32View[word + 4] = colors !== null ? colors[i] : defaultVertexColor;
101
- }
102
- const indexCount = mesh.indexCount;
103
- this._ensureIndexCapacity(indexCount);
104
- if (mesh.indices !== null) {
105
- this._indexData.set(mesh.indices, 0);
55
+ const material = mesh.material;
56
+ const shader = material === null ? this._defaultShader : this._getOrCreateCustomShader(material, connection.gl);
57
+ // The material owns its blend mode; the mesh's own blendMode overrides it
58
+ // when set away from the default (Normal). Default-path meshes keep their
59
+ // own blendMode verbatim.
60
+ const blendMode = material !== null && mesh.blendMode === BlendModes.Normal ? material.blendMode : mesh.blendMode;
61
+ const texture = mesh.texture ?? Texture.white;
62
+ const command = backend.activeDrawCommand;
63
+ const supportsInstancing = material === null ? true : this._isInstancingCompatible(shader);
64
+ this._pendingDraws.push({
65
+ mesh,
66
+ command,
67
+ material,
68
+ shader,
69
+ blendMode,
70
+ texture,
71
+ supportsInstancing,
72
+ });
73
+ }
74
+ flush() {
75
+ const backend = this.getBackendOrNull();
76
+ const connection = this._connection;
77
+ if (backend === null || connection === null || this._pendingDraws.length === 0) {
78
+ this._pendingDraws.length = 0;
79
+ return;
106
80
  }
107
- else {
108
- for (let i = 0; i < indexCount; i++) {
109
- this._indexData[i] = i;
81
+ for (let i = 0; i < this._pendingDraws.length; i++) {
82
+ const draw = this._pendingDraws[i];
83
+ if (this._canBatchStatic(draw)) {
84
+ let end = i + 1;
85
+ while (end < this._pendingDraws.length && this._isSameBatch(this._pendingDraws[end - 1], this._pendingDraws[end])) {
86
+ end++;
87
+ }
88
+ if (end - i >= 2) {
89
+ this._drawStaticBatch(this._pendingDraws.slice(i, end), backend, connection);
90
+ i = end - 1;
91
+ continue;
92
+ }
110
93
  }
94
+ this._drawSingle(draw, backend, connection);
111
95
  }
112
- shader.sync();
113
- backend.bindVertexArrayObject(connection.vao);
114
- connection.vertexBuffer.upload(this._float32View.subarray(0, vertexCount * vertexStrideWords));
115
- connection.indexBuffer.upload(this._indexData.subarray(0, indexCount));
116
- connection.vao.draw(indexCount, 0, RenderingPrimitives.Triangles);
117
- backend.stats.batches++;
118
- backend.stats.drawCalls++;
119
- }
120
- flush() {
121
- // Mesh draws are immediate per-mesh; nothing to batch.
96
+ this._pendingDraws.length = 0;
122
97
  }
123
98
  destroy() {
124
99
  this.disconnect();
@@ -127,34 +102,40 @@ class WebGl2MeshRenderer extends AbstractWebGl2Renderer {
127
102
  shader.destroy();
128
103
  }
129
104
  this._customShaders.clear();
130
- this._currentBlendMode = null;
105
+ this._compatibilityCache.clear();
131
106
  }
132
107
  onConnect(backend) {
133
108
  const gl = backend.context;
134
- const vaoHandle = gl.createVertexArray();
135
- if (vaoHandle === null) {
136
- throw new Error('Could not create vertex array object.');
137
- }
138
109
  this._defaultShader.connect(createWebGl2ShaderProgram(gl));
139
- const buffers = new Map();
140
- const indexBuffer = new WebGl2RenderBuffer(BufferTypes.ElementArrayBuffer, this._indexData, BufferUsage.DynamicDraw).connect(this._createBufferRuntime(gl, buffers));
141
- const vertexBuffer = new WebGl2RenderBuffer(BufferTypes.ArrayBuffer, this._vertexData, BufferUsage.DynamicDraw).connect(this._createBufferRuntime(gl, buffers));
142
- // Force the shader's first finalize so attribute locations are
143
- // available immediately (the async-compile path defers extraction
144
- // to first sync(), but we need attributes here for VAO setup).
145
110
  this._defaultShader.sync();
146
111
  // Custom shaders compiled before connect() get connected here too.
147
112
  for (const customShader of this._customShaders.values()) {
148
113
  customShader.connect(createWebGl2ShaderProgram(gl));
149
114
  customShader.sync();
150
115
  }
151
- const vao = new WebGl2VertexArrayObject()
152
- .addIndex(indexBuffer)
153
- .addAttribute(vertexBuffer, this._defaultShader.getAttribute('a_position'), gl.FLOAT, false, vertexStrideBytes, 0)
154
- .addAttribute(vertexBuffer, this._defaultShader.getAttribute('a_texcoord'), gl.FLOAT, false, vertexStrideBytes, 8)
155
- .addAttribute(vertexBuffer, this._defaultShader.getAttribute('a_color'), gl.UNSIGNED_BYTE, true, vertexStrideBytes, 16)
156
- .connect(this._createVaoRuntime(gl, vaoHandle));
157
- this._connection = { gl, vao, vertexBuffer, indexBuffer };
116
+ const buffers = new Map();
117
+ const dynamicIndexBuffer = new WebGl2RenderBuffer(BufferTypes.ElementArrayBuffer, this._indexData, BufferUsage.DynamicDraw).connect(this._createBufferRuntime(gl, buffers));
118
+ const dynamicVertexBuffer = new WebGl2RenderBuffer(BufferTypes.ArrayBuffer, this._vertexData, BufferUsage.DynamicDraw).connect(this._createBufferRuntime(gl, buffers));
119
+ const dynamicNodeIndexBuffer = new WebGl2RenderBuffer(BufferTypes.ArrayBuffer, this._nodeIndexData, BufferUsage.DynamicDraw).connect(this._createBufferRuntime(gl, buffers));
120
+ const dynamicVaoHandle = gl.createVertexArray();
121
+ if (dynamicVaoHandle === null) {
122
+ throw new Error('Could not create vertex array object.');
123
+ }
124
+ const dynamicVao = new WebGl2VertexArrayObject()
125
+ .addIndex(dynamicIndexBuffer)
126
+ .addAttribute(dynamicVertexBuffer, this._defaultShader.getAttribute('a_position'), gl.FLOAT, false, vertexStrideBytes, 0)
127
+ .addAttribute(dynamicVertexBuffer, this._defaultShader.getAttribute('a_texcoord'), gl.FLOAT, false, vertexStrideBytes, 8)
128
+ .addAttribute(dynamicVertexBuffer, this._defaultShader.getAttribute('a_color'), gl.UNSIGNED_BYTE, true, vertexStrideBytes, 16)
129
+ .addAttribute(dynamicNodeIndexBuffer, this._defaultShader.getAttribute('a_nodeIndex'), gl.UNSIGNED_INT, false, Uint32Array.BYTES_PER_ELEMENT, 0, true, 1)
130
+ .connect(this._createVaoRuntime(gl, dynamicVaoHandle));
131
+ this._connection = {
132
+ gl,
133
+ buffers,
134
+ dynamicVao,
135
+ dynamicVertexBuffer,
136
+ dynamicIndexBuffer,
137
+ dynamicNodeIndexBuffer,
138
+ };
158
139
  }
159
140
  onDisconnect() {
160
141
  const connection = this._connection;
@@ -165,11 +146,262 @@ class WebGl2MeshRenderer extends AbstractWebGl2Renderer {
165
146
  for (const customShader of this._customShaders.values()) {
166
147
  customShader.disconnect();
167
148
  }
168
- connection.indexBuffer.destroy();
169
- connection.vertexBuffer.destroy();
170
- connection.vao.destroy();
149
+ for (const entry of this._staticGeometryCache.values()) {
150
+ for (const vao of entry.vaos.values()) {
151
+ vao.destroy();
152
+ }
153
+ entry.vaos.clear();
154
+ entry.indexBuffer.destroy();
155
+ entry.vertexBuffer.destroy();
156
+ }
157
+ this._staticGeometryCache.clear();
158
+ connection.dynamicNodeIndexBuffer.destroy();
159
+ connection.dynamicIndexBuffer.destroy();
160
+ connection.dynamicVertexBuffer.destroy();
161
+ connection.dynamicVao.destroy();
171
162
  this._connection = null;
172
163
  this._currentBlendMode = null;
164
+ this._pendingDraws.length = 0;
165
+ }
166
+ _drawSingle(draw, backend, connection) {
167
+ if (this._canBatchStatic(draw)) {
168
+ this._drawStaticBatch([draw], backend, connection);
169
+ return;
170
+ }
171
+ if (draw.supportsInstancing && draw.material === null) {
172
+ this._drawDynamicInstancedSingle(draw, backend, connection);
173
+ return;
174
+ }
175
+ this._drawLegacyImmediate(draw, backend, connection);
176
+ }
177
+ _drawDynamicInstancedSingle(draw, backend, connection) {
178
+ this._setBlendMode(draw.blendMode, backend);
179
+ this._bindInstancedShaderState(draw.shader, draw.texture, draw.material, backend, draw.command?.nodeIndex ?? 0);
180
+ this._ensureVertexCapacity(draw.mesh.vertexCount);
181
+ this._ensureIndexCapacity(draw.mesh.indexCount);
182
+ this._ensureNodeIndexCapacity(1);
183
+ this._packVertices(draw.mesh, 0);
184
+ this._packIndices(draw.mesh, 0);
185
+ const nodeIndex = draw.command?.nodeIndex ?? 0;
186
+ if (draw.command === null) {
187
+ backend._prepareDrawCommand({
188
+ ...this._createSyntheticCommand(draw.mesh, nodeIndex),
189
+ });
190
+ }
191
+ this._nodeIndexData[0] = nodeIndex >>> 0;
192
+ backend.bindVertexArrayObject(connection.dynamicVao);
193
+ connection.dynamicVertexBuffer.upload(this._float32View.subarray(0, draw.mesh.vertexCount * vertexStrideWords));
194
+ connection.dynamicIndexBuffer.upload(this._indexData.subarray(0, draw.mesh.indexCount));
195
+ connection.dynamicNodeIndexBuffer.upload(this._nodeIndexData.subarray(0, 1));
196
+ connection.dynamicVao.drawInstanced(draw.mesh.indexCount, 0, 1, RenderingPrimitives.Triangles);
197
+ backend.stats.batches++;
198
+ backend.stats.drawCalls++;
199
+ }
200
+ _drawStaticBatch(batch, backend, connection) {
201
+ const first = batch[0];
202
+ const geometry = first.mesh.geometry;
203
+ const cacheEntry = this._getOrCreateStaticGeometryEntry(geometry, first.mesh, connection);
204
+ const vao = this._getOrCreateStaticGeometryVao(cacheEntry, first.shader, connection.gl, connection.dynamicNodeIndexBuffer);
205
+ this._setBlendMode(first.blendMode, backend);
206
+ let maxNodeIndex = 0;
207
+ this._ensureNodeIndexCapacity(batch.length);
208
+ for (let i = 0; i < batch.length; i++) {
209
+ const command = batch[i].command;
210
+ const nodeIndex = command.nodeIndex >>> 0;
211
+ this._nodeIndexData[i] = nodeIndex;
212
+ if (nodeIndex > maxNodeIndex) {
213
+ maxNodeIndex = nodeIndex;
214
+ }
215
+ }
216
+ this._bindInstancedShaderState(first.shader, first.texture, first.material, backend, maxNodeIndex);
217
+ backend.bindVertexArrayObject(vao);
218
+ connection.dynamicNodeIndexBuffer.upload(this._nodeIndexData.subarray(0, batch.length));
219
+ vao.drawInstanced(cacheEntry.indexCount, 0, batch.length, RenderingPrimitives.Triangles);
220
+ backend.stats.batches++;
221
+ backend.stats.drawCalls++;
222
+ }
223
+ _drawLegacyImmediate(draw, backend, connection) {
224
+ const mesh = draw.mesh;
225
+ const shader = draw.shader;
226
+ this._setBlendMode(draw.blendMode, backend);
227
+ if (shader.uniforms.has('u_projection')) {
228
+ shader.getUniform('u_projection').setValue(backend.view.getTransform().toArray(false));
229
+ }
230
+ if (shader.uniforms.has('u_translation')) {
231
+ shader.getUniform('u_translation').setValue(mesh.getGlobalTransform().toArray(false));
232
+ }
233
+ if (shader.uniforms.has('u_tint')) {
234
+ shader.getUniform('u_tint').setValue(mesh.tint.toArray(false));
235
+ }
236
+ if (shader.uniforms.has('u_texture')) {
237
+ shader.getUniform('u_texture').setValue(this._textureUnitScratch);
238
+ backend.bindTexture(draw.texture, 0);
239
+ }
240
+ if (draw.material !== null) {
241
+ this._bindCustomUniforms(shader, draw.material, backend);
242
+ }
243
+ this._ensureVertexCapacity(mesh.vertexCount);
244
+ this._ensureIndexCapacity(mesh.indexCount);
245
+ this._packVertices(mesh, 0);
246
+ this._packIndices(mesh, 0);
247
+ shader.sync();
248
+ backend.bindVertexArrayObject(connection.dynamicVao);
249
+ connection.dynamicVertexBuffer.upload(this._float32View.subarray(0, mesh.vertexCount * vertexStrideWords));
250
+ connection.dynamicIndexBuffer.upload(this._indexData.subarray(0, mesh.indexCount));
251
+ connection.dynamicVao.draw(mesh.indexCount, 0, RenderingPrimitives.Triangles);
252
+ backend.stats.batches++;
253
+ backend.stats.drawCalls++;
254
+ }
255
+ _bindInstancedShaderState(shader, texture, material, backend, maxNodeIndex) {
256
+ if (shader.uniforms.has('u_projection')) {
257
+ shader.getUniform('u_projection').setValue(backend.view.getTransform().toArray(false));
258
+ }
259
+ if (shader.uniforms.has('u_transforms')) {
260
+ backend.bindTransformBufferTexture(transformTextureUnit, maxNodeIndex + 1);
261
+ shader.getUniform('u_transforms').setValue(this._transformUnitScratch);
262
+ }
263
+ if (shader.uniforms.has('u_texture')) {
264
+ shader.getUniform('u_texture').setValue(this._textureUnitScratch);
265
+ backend.bindTexture(texture, 0);
266
+ }
267
+ if (material !== null) {
268
+ this._bindCustomUniforms(shader, material, backend);
269
+ }
270
+ shader.sync();
271
+ }
272
+ _canBatchStatic(draw) {
273
+ if (!draw.supportsInstancing) {
274
+ return false;
275
+ }
276
+ if (draw.command?.groupIndex === undefined) {
277
+ return false;
278
+ }
279
+ const geometry = draw.mesh.geometry;
280
+ if (geometry?.usage !== 'static') {
281
+ return false;
282
+ }
283
+ return true;
284
+ }
285
+ _isSameBatch(left, right) {
286
+ if (!this._canBatchStatic(left) || !this._canBatchStatic(right)) {
287
+ return false;
288
+ }
289
+ return (left.command.groupIndex === right.command.groupIndex &&
290
+ left.mesh.geometry === right.mesh.geometry &&
291
+ left.shader === right.shader &&
292
+ left.material === right.material &&
293
+ left.blendMode === right.blendMode &&
294
+ left.texture === right.texture &&
295
+ left.command.material.pipelineKey === right.command.material.pipelineKey &&
296
+ left.command.material.bindKey === right.command.material.bindKey);
297
+ }
298
+ _isInstancingCompatible(shader) {
299
+ const cached = this._compatibilityCache.get(shader);
300
+ if (cached !== undefined) {
301
+ return cached;
302
+ }
303
+ const compatible = shader.attributes.has('a_nodeIndex') && shader.uniforms.has('u_transforms') && !shader.uniforms.has('u_translation') && !shader.uniforms.has('u_tint');
304
+ this._compatibilityCache.set(shader, compatible);
305
+ return compatible;
306
+ }
307
+ _getOrCreateStaticGeometryEntry(geometry, mesh, connection) {
308
+ const existing = this._staticGeometryCache.get(geometry);
309
+ if (existing !== undefined) {
310
+ return existing;
311
+ }
312
+ const vertexCount = mesh.vertexCount;
313
+ const indexCount = mesh.indexCount;
314
+ const interleaved = new ArrayBuffer(vertexCount * vertexStrideBytes);
315
+ const floatView = new Float32Array(interleaved);
316
+ const uintView = new Uint32Array(interleaved);
317
+ this._packVertices(mesh, 0, floatView, uintView);
318
+ const indexData = new Uint16Array(indexCount);
319
+ this._packIndices(mesh, 0, indexData);
320
+ const vertexBuffer = new WebGl2RenderBuffer(BufferTypes.ArrayBuffer, floatView, BufferUsage.StaticDraw).connect(this._createBufferRuntime(connection.gl, connection.buffers));
321
+ const indexBuffer = new WebGl2RenderBuffer(BufferTypes.ElementArrayBuffer, indexData, BufferUsage.StaticDraw).connect(this._createBufferRuntime(connection.gl, connection.buffers));
322
+ vertexBuffer.upload(floatView);
323
+ indexBuffer.upload(indexData);
324
+ const disposeListener = () => {
325
+ const entry = this._staticGeometryCache.get(geometry);
326
+ if (entry === undefined) {
327
+ return;
328
+ }
329
+ for (const vao of entry.vaos.values()) {
330
+ vao.destroy();
331
+ }
332
+ entry.vaos.clear();
333
+ entry.indexBuffer.destroy();
334
+ entry.vertexBuffer.destroy();
335
+ this._staticGeometryCache.delete(geometry);
336
+ };
337
+ geometry._onDispose(disposeListener);
338
+ const created = {
339
+ geometry,
340
+ vertexBuffer,
341
+ indexBuffer,
342
+ vaos: new Map(),
343
+ disposeListener,
344
+ indexCount,
345
+ };
346
+ this._staticGeometryCache.set(geometry, created);
347
+ return created;
348
+ }
349
+ _getOrCreateStaticGeometryVao(entry, shader, gl, nodeIndexBuffer) {
350
+ const existing = entry.vaos.get(shader);
351
+ if (existing !== undefined) {
352
+ return existing;
353
+ }
354
+ const vaoHandle = gl.createVertexArray();
355
+ if (vaoHandle === null) {
356
+ throw new Error('Could not create vertex array object.');
357
+ }
358
+ const nodeAttribute = shader.getAttribute('a_nodeIndex');
359
+ const vao = new WebGl2VertexArrayObject()
360
+ .addIndex(entry.indexBuffer)
361
+ .addAttribute(entry.vertexBuffer, shader.getAttribute('a_position'), gl.FLOAT, false, vertexStrideBytes, 0)
362
+ .addAttribute(entry.vertexBuffer, shader.getAttribute('a_texcoord'), gl.FLOAT, false, vertexStrideBytes, 8)
363
+ .addAttribute(entry.vertexBuffer, shader.getAttribute('a_color'), gl.UNSIGNED_BYTE, true, vertexStrideBytes, 16)
364
+ .addAttribute(nodeIndexBuffer, nodeAttribute, gl.UNSIGNED_INT, false, Uint32Array.BYTES_PER_ELEMENT, 0, true, 1)
365
+ .connect(this._createVaoRuntime(gl, vaoHandle));
366
+ entry.vaos.set(shader, vao);
367
+ return vao;
368
+ }
369
+ _setBlendMode(next, backend) {
370
+ if (this._currentBlendMode !== next) {
371
+ this._currentBlendMode = next;
372
+ backend.setBlendMode(next);
373
+ }
374
+ }
375
+ _packVertices(mesh, vertexStart, floatView = this._float32View, uintView = this._uint32View) {
376
+ const positions = mesh.vertices;
377
+ const uvs = mesh.uvs;
378
+ const colors = mesh.colors;
379
+ const vertexCount = mesh.vertexCount;
380
+ for (let i = 0; i < vertexCount; i++) {
381
+ const word = (vertexStart + i) * vertexStrideWords;
382
+ const pair = i * 2;
383
+ floatView[word] = positions[pair];
384
+ floatView[word + 1] = positions[pair + 1];
385
+ if (uvs !== null) {
386
+ floatView[word + 2] = uvs[pair];
387
+ floatView[word + 3] = uvs[pair + 1];
388
+ }
389
+ else {
390
+ floatView[word + 2] = 0;
391
+ floatView[word + 3] = 0;
392
+ }
393
+ uintView[word + 4] = colors !== null ? colors[i] : defaultVertexColor;
394
+ }
395
+ }
396
+ _packIndices(mesh, indexStart, target = this._indexData) {
397
+ const indexCount = mesh.indexCount;
398
+ if (mesh.indices !== null) {
399
+ target.set(mesh.indices, indexStart);
400
+ return;
401
+ }
402
+ for (let i = 0; i < indexCount; i++) {
403
+ target[indexStart + i] = i;
404
+ }
173
405
  }
174
406
  _ensureVertexCapacity(vertexCount) {
175
407
  if (vertexCount <= this._vertexCapacity) {
@@ -191,6 +423,15 @@ class WebGl2MeshRenderer extends AbstractWebGl2Renderer {
191
423
  }
192
424
  this._indexData = new Uint16Array(this._indexCapacity);
193
425
  }
426
+ _ensureNodeIndexCapacity(instanceCount) {
427
+ if (instanceCount <= this._nodeIndexCapacity) {
428
+ return;
429
+ }
430
+ while (this._nodeIndexCapacity < instanceCount) {
431
+ this._nodeIndexCapacity *= 2;
432
+ }
433
+ this._nodeIndexData = new Uint32Array(this._nodeIndexCapacity);
434
+ }
194
435
  _createBufferRuntime(gl, buffers) {
195
436
  const handle = gl.createBuffer();
196
437
  if (handle === null) {
@@ -232,8 +473,14 @@ class WebGl2MeshRenderer extends AbstractWebGl2Renderer {
232
473
  attribute.buffer.bind();
233
474
  lastBuffer = attribute.buffer;
234
475
  }
235
- gl.vertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, attribute.start);
476
+ if (attribute.integer) {
477
+ gl.vertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, attribute.start);
478
+ }
479
+ else {
480
+ gl.vertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, attribute.start);
481
+ }
236
482
  gl.enableVertexAttribArray(attribute.location);
483
+ gl.vertexAttribDivisor(attribute.location, attribute.divisor);
237
484
  }
238
485
  if (vao.indexBuffer) {
239
486
  vao.indexBuffer.bind();
@@ -252,39 +499,50 @@ class WebGl2MeshRenderer extends AbstractWebGl2Renderer {
252
499
  gl.drawArrays(type, start, size);
253
500
  }
254
501
  },
502
+ drawInstanced: (vao, count, start, instanceCount, type) => {
503
+ if (vao.indexBuffer) {
504
+ gl.drawElementsInstanced(type, count, gl.UNSIGNED_SHORT, start, instanceCount);
505
+ }
506
+ else {
507
+ gl.drawArraysInstanced(type, start, count, instanceCount);
508
+ }
509
+ },
255
510
  destroy: (vao) => {
256
511
  gl.deleteVertexArray(vaoHandle);
257
512
  vao.disconnect();
258
513
  },
259
514
  };
260
515
  }
261
- _getOrCreateCustomShader(config, gl) {
262
- const cached = this._customShaders.get(config);
516
+ _getOrCreateCustomShader(material, gl) {
517
+ const cached = this._customShaders.get(material);
263
518
  if (cached !== undefined) {
264
519
  return cached;
265
520
  }
266
- if (config.glsl === null) {
267
- throw new Error('MeshShader has no `glsl` source; cannot render through the WebGL2 backend.');
521
+ const glsl = material.shader.glsl;
522
+ if (glsl === null) {
523
+ throw new Error('Mesh material shader has no `glsl` source; cannot render through the WebGL2 backend.');
268
524
  }
269
- const shader = new Shader(config.glsl.vertex, config.glsl.fragment);
525
+ const shader = new Shader(glsl.vertex, glsl.fragment);
270
526
  shader.connect(createWebGl2ShaderProgram(gl));
271
527
  // Force first finalize so getUniform()/uniforms.has() are usable below.
272
528
  shader.sync();
273
- this._customShaders.set(config, shader);
274
- // Wire shader.destroy() through to evict + dispose the cached program.
275
- config._onDispose(() => {
276
- const stored = this._customShaders.get(config);
529
+ this._customShaders.set(material, shader);
530
+ // Wire material.destroy() through to evict + dispose the cached program.
531
+ material._onDispose(() => {
532
+ const stored = this._customShaders.get(material);
277
533
  if (stored !== undefined) {
278
534
  stored.destroy();
279
- this._customShaders.delete(config);
535
+ this._customShaders.delete(material);
280
536
  }
281
537
  });
282
538
  return shader;
283
539
  }
284
- _bindCustomUniforms(shader, uniforms, backend) {
285
- // Texture uniforms take consecutive slots starting at 1 (slot 0 belongs
286
- // to the mesh's own `u_texture` binding).
540
+ _bindCustomUniforms(shader, material, backend) {
541
+ // Texture bindings take consecutive slots starting at 1 (slot 0 belongs to
542
+ // the mesh's own `u_texture`). Texture-valued uniforms bind first, then the
543
+ // entries of the material's dedicated `textures` map.
287
544
  let textureSlot = 1;
545
+ const uniforms = material.uniforms;
288
546
  for (const name in uniforms) {
289
547
  if (!shader.uniforms.has(name)) {
290
548
  continue;
@@ -293,7 +551,7 @@ class WebGl2MeshRenderer extends AbstractWebGl2Renderer {
293
551
  const uniform = shader.getUniform(name);
294
552
  if (value instanceof Texture || value instanceof RenderTexture) {
295
553
  if (textureSlot >= maxCustomTextureSlots) {
296
- throw new Error(`Mesh custom shader requested more than ${maxCustomTextureSlots - 1} texture uniforms.`);
554
+ throw new Error(`Mesh material requested more than ${maxCustomTextureSlots - 1} texture bindings.`);
297
555
  }
298
556
  backend.bindTexture(value, textureSlot);
299
557
  uniform.setValue(this._slotScratches[textureSlot]);
@@ -303,6 +561,18 @@ class WebGl2MeshRenderer extends AbstractWebGl2Renderer {
303
561
  uniform.setValue(this._marshalUniformValue(value));
304
562
  }
305
563
  }
564
+ const textures = material.textures;
565
+ for (const name in textures) {
566
+ if (!shader.uniforms.has(name)) {
567
+ continue;
568
+ }
569
+ if (textureSlot >= maxCustomTextureSlots) {
570
+ throw new Error(`Mesh material requested more than ${maxCustomTextureSlots - 1} texture bindings.`);
571
+ }
572
+ backend.bindTexture(textures[name], textureSlot);
573
+ shader.getUniform(name).setValue(this._slotScratches[textureSlot]);
574
+ textureSlot++;
575
+ }
306
576
  }
307
577
  _marshalUniformValue(value) {
308
578
  if (value instanceof Float32Array || value instanceof Int32Array) {
@@ -314,6 +584,28 @@ class WebGl2MeshRenderer extends AbstractWebGl2Renderer {
314
584
  // readonly tuple [a, b], [a, b, c], [a, b, c, d]
315
585
  return new Float32Array(value);
316
586
  }
587
+ _createSyntheticCommand(mesh, nodeIndex) {
588
+ return {
589
+ kind: RenderEntryKind.Draw,
590
+ drawable: mesh,
591
+ nodeIndex,
592
+ seq: 0,
593
+ zIndex: mesh.zIndex,
594
+ material: {
595
+ rendererId: 0,
596
+ blendMode: mesh.blendMode,
597
+ textureId: -1,
598
+ shaderId: -1,
599
+ pipelineKey: 0,
600
+ bindKey: 0,
601
+ },
602
+ minX: 0,
603
+ minY: 0,
604
+ maxX: 0,
605
+ maxY: 0,
606
+ groupIndex: 0,
607
+ };
608
+ }
317
609
  }
318
610
 
319
611
  export { WebGl2MeshRenderer };