@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
@@ -0,0 +1,775 @@
1
+ import '../../core/Color.js';
2
+ import { BlendModes } from '../types.js';
3
+ import '../../core/SceneNode.js';
4
+ import '../../core/Time.js';
5
+ import '../../math/Size.js';
6
+ import '../../math/Rectangle.js';
7
+ import '../plan/RenderCommand.js';
8
+ import '../plan/RenderScope.js';
9
+ import '../texture/RenderTexture.js';
10
+ import '../texture/Texture.js';
11
+ import '../pass/RenderPassDescriptor.js';
12
+ import '../View.js';
13
+ import { Text } from '../text/Text.js';
14
+ import { AbstractWebGpuRenderer } from './AbstractWebGpuRenderer.js';
15
+ import { getWebGpuBlendState } from './WebGpuBlendState.js';
16
+
17
+ /// <reference types="@webgpu/types" />
18
+ // ── Node data layout (identical to WebGl2TextRenderer) ───────────────────────
19
+ //
20
+ // Storage buffer: array<vec4<f32>> — 10 entries per node.
21
+ //
22
+ // [ni*10+0]: (a, c, 0, tx) transform col 0+2
23
+ // [ni*10+1]: (b, d, 0, ty) transform col 1+2
24
+ // [ni*10+2]: (r, g, b, a ) fillColor
25
+ // [ni*10+3]: (r, g, b, a ) outlineColor
26
+ // [ni*10+4]: (outlineMin, shadowAlpha, softness, gradientEnabled)
27
+ // [ni*10+5]: (r, g, b, a ) shadowColor
28
+ // [ni*10+6]: (shadowOffX_px, shadowOffY_px, gradientVertical, 0)
29
+ // [ni*10+7]: (r, g, b, a ) gradientTop
30
+ // [ni*10+8]: (r, g, b, a ) gradientBottom
31
+ // [ni*10+9]: (minX, minY, w, h) text block bounds
32
+ const nodeTexels = 10;
33
+ const nodeFloats = nodeTexels * 4;
34
+ // Per-vertex layout (20 bytes): pos f32x2 + uv f32x2 + nodeIndex f32
35
+ const vertexStrideBytes = 20;
36
+ const vertexStrideWords = vertexStrideBytes / 4;
37
+ const initialVertexCapacity = 256;
38
+ const initialIndexCapacity = 384;
39
+ const initialNodeCapacity = 32;
40
+ // FrameUniforms: 3 × vec4<f32> = 48 bytes (projection mat3x3 column-major)
41
+ const projectionBytes = 48;
42
+ // ── WGSL: shared vertex + three fragment entry points ────────────────────────
43
+ const textShaderSource = `
44
+ struct FrameUniforms {
45
+ projCol0 : vec4<f32>,
46
+ projCol1 : vec4<f32>,
47
+ projCol2 : vec4<f32>,
48
+ };
49
+
50
+ @group(0) @binding(0) var<uniform> frame : FrameUniforms;
51
+ @group(0) @binding(1) var<storage, read> nodes : array<vec4<f32>>;
52
+
53
+ @group(1) @binding(0) var atlasTexture : texture_2d<f32>;
54
+ @group(1) @binding(1) var atlasSampler : sampler;
55
+
56
+ struct VertexInput {
57
+ @location(0) position : vec2<f32>,
58
+ @location(1) texcoord : vec2<f32>,
59
+ @location(2) nodeIndex : f32,
60
+ };
61
+
62
+ struct VertexOutput {
63
+ @builtin(position) clipPos : vec4<f32>,
64
+ @location(0) texcoord : vec2<f32>,
65
+ @location(1) gradUV : vec2<f32>,
66
+ @location(2) @interpolate(flat) nodeIdx : u32,
67
+ };
68
+
69
+ @vertex
70
+ fn vertexMain(input: VertexInput) -> VertexOutput {
71
+ let ni = u32(input.nodeIndex);
72
+ let base = ni * 10u;
73
+
74
+ let t0 = nodes[base + 0u];
75
+ let t1 = nodes[base + 1u];
76
+ let t9 = nodes[base + 9u];
77
+
78
+ let proj = mat3x3<f32>(
79
+ frame.projCol0.xyz,
80
+ frame.projCol1.xyz,
81
+ frame.projCol2.xyz,
82
+ );
83
+ let xf = mat3x3<f32>(
84
+ vec3<f32>(t0.x, t0.y, 0.0),
85
+ vec3<f32>(t1.x, t1.y, 0.0),
86
+ vec3<f32>(t0.w, t1.w, 1.0),
87
+ );
88
+
89
+ let worldPos = proj * xf * vec3<f32>(input.position, 1.0);
90
+
91
+ let bSize = t9.zw;
92
+ var gradUV = vec2<f32>(0.0);
93
+ if (bSize.x > 0.0 && bSize.y > 0.0) {
94
+ gradUV = clamp((input.position - t9.xy) / bSize, vec2<f32>(0.0), vec2<f32>(1.0));
95
+ }
96
+
97
+ var out: VertexOutput;
98
+ out.clipPos = vec4<f32>(worldPos.xy, 0.0, 1.0);
99
+ out.texcoord = input.texcoord;
100
+ out.gradUV = gradUV;
101
+ out.nodeIdx = ni;
102
+ return out;
103
+ }
104
+
105
+ // ── SDF (R8 atlas) ────────────────────────────────────────────────────────────
106
+
107
+ @fragment
108
+ fn fragmentSdf(in: VertexOutput) -> @location(0) vec4<f32> {
109
+ let ni = in.nodeIdx;
110
+ let base = ni * 10u;
111
+
112
+ let tFill = nodes[base + 2u];
113
+ let tOutline = nodes[base + 3u];
114
+ let tParams = nodes[base + 4u];
115
+ let tShadow = nodes[base + 5u];
116
+ let tShadow2 = nodes[base + 6u];
117
+ let tGradTop = nodes[base + 7u];
118
+ let tGradBot = nodes[base + 8u];
119
+
120
+ let outlineMin = tParams.x;
121
+ let shadowAlpha = tParams.y;
122
+ let soft = max(tParams.z, 0.001);
123
+ let gradEnabled = tParams.w;
124
+ let pageSize = f32(textureDimensions(atlasTexture, 0).x);
125
+ let shadowOffset = tShadow2.xy / pageSize;
126
+ let gradVertical = tShadow2.z;
127
+
128
+ let sd = textureSample(atlasTexture, atlasSampler, in.texcoord).r;
129
+ let fill = smoothstep(0.5 - soft, 0.5 + soft, sd);
130
+
131
+ let shadowSd = textureSample(atlasTexture, atlasSampler, in.texcoord - shadowOffset).r;
132
+
133
+ let outline = select(0.0,
134
+ smoothstep(outlineMin - soft, outlineMin + soft, sd) * (1.0 - fill),
135
+ outlineMin < 0.5);
136
+
137
+ let shadow = smoothstep(0.5 - soft, 0.5 + soft, shadowSd)
138
+ * shadowAlpha * (1.0 - fill) * (1.0 - outline);
139
+
140
+ var fillColor : vec4<f32>;
141
+ if (gradEnabled > 0.5) {
142
+ let t = select(in.gradUV.x, in.gradUV.y, gradVertical > 0.5);
143
+ fillColor = mix(tGradBot, tGradTop, t);
144
+ } else {
145
+ fillColor = tFill;
146
+ }
147
+
148
+ return fillColor * fill + tOutline * outline + tShadow * shadow;
149
+ }
150
+
151
+ // ── MSDF (RGB atlas) ──────────────────────────────────────────────────────────
152
+
153
+ fn median3(r: f32, g: f32, b: f32) -> f32 {
154
+ return max(min(r, g), min(max(r, g), b));
155
+ }
156
+
157
+ @fragment
158
+ fn fragmentMsdf(in: VertexOutput) -> @location(0) vec4<f32> {
159
+ let ni = in.nodeIdx;
160
+ let base = ni * 10u;
161
+
162
+ let tFill = nodes[base + 2u];
163
+ let tOutline = nodes[base + 3u];
164
+ let tParams = nodes[base + 4u];
165
+ let tShadow = nodes[base + 5u];
166
+ let tShadow2 = nodes[base + 6u];
167
+ let tGradTop = nodes[base + 7u];
168
+ let tGradBot = nodes[base + 8u];
169
+
170
+ let outlineMin = tParams.x;
171
+ let shadowAlpha = tParams.y;
172
+ let soft = max(tParams.z, 0.001);
173
+ let gradEnabled = tParams.w;
174
+ let pageSize = f32(textureDimensions(atlasTexture, 0).x);
175
+ let shadowOffset = tShadow2.xy / pageSize;
176
+ let gradVertical = tShadow2.z;
177
+
178
+ let msd = textureSample(atlasTexture, atlasSampler, in.texcoord).rgb;
179
+ let sd = median3(msd.r, msd.g, msd.b);
180
+ let fill = smoothstep(0.5 - soft, 0.5 + soft, sd);
181
+
182
+ let shadowMsd = textureSample(atlasTexture, atlasSampler, in.texcoord - shadowOffset).rgb;
183
+ let shadowSd = median3(shadowMsd.r, shadowMsd.g, shadowMsd.b);
184
+
185
+ let outline = select(0.0,
186
+ smoothstep(outlineMin - soft, outlineMin + soft, sd) * (1.0 - fill),
187
+ outlineMin < 0.5);
188
+
189
+ let shadow = smoothstep(0.5 - soft, 0.5 + soft, shadowSd)
190
+ * shadowAlpha * (1.0 - fill) * (1.0 - outline);
191
+
192
+ var fillColor : vec4<f32>;
193
+ if (gradEnabled > 0.5) {
194
+ let t = select(in.gradUV.x, in.gradUV.y, gradVertical > 0.5);
195
+ fillColor = mix(tGradBot, tGradTop, t);
196
+ } else {
197
+ fillColor = tFill;
198
+ }
199
+
200
+ return fillColor * fill + tOutline * outline + tShadow * shadow;
201
+ }
202
+
203
+ // ── Color (RGBA atlas) ────────────────────────────────────────────────────────
204
+
205
+ @fragment
206
+ fn fragmentColor(in: VertexOutput) -> @location(0) vec4<f32> {
207
+ let ni = in.nodeIdx;
208
+ let base = ni * 10u;
209
+ let tint = nodes[base + 2u];
210
+ let sample = textureSample(atlasTexture, atlasSampler, in.texcoord);
211
+ return sample * tint;
212
+ }
213
+ `;
214
+ /**
215
+ * WebGPU renderer for {@link Text} and {@link BitmapText} nodes.
216
+ *
217
+ * Mirrors {@link WebGl2TextRenderer}: per-node style data is packed once per
218
+ * flush into a `var<storage, read>` buffer, three specialised WGSL fragment
219
+ * variants handle SDF / MSDF / colour-atlas glyphs, and quads are sorted and
220
+ * batched by (shaderType, atlasPage) to minimise draw calls within a single
221
+ * render pass.
222
+ */
223
+ class WebGpuTextRenderer extends AbstractWebGpuRenderer {
224
+ _device = null;
225
+ _shaderModule = null;
226
+ _frameBindGroupLayout = null;
227
+ _textureBindGroupLayout = null;
228
+ _pipelineLayout = null;
229
+ _pipelines = new Map();
230
+ // Weak cache: avoids retaining transient atlas textures via strong keys.
231
+ _texBindGroups = new WeakMap();
232
+ _projBuffer = null;
233
+ _nodeBuffer = null;
234
+ _vertexBuffer = null;
235
+ _indexBuffer = null;
236
+ _nodeBufferCapacity = 0;
237
+ _vertexBufferCapacity = 0;
238
+ _indexBufferCapacity = 0;
239
+ _frameBindGroup = null;
240
+ _frameBindGroupDirty = true;
241
+ // CPU-side working arrays
242
+ _vertexCapacity = initialVertexCapacity;
243
+ _indexCapacity = initialIndexCapacity;
244
+ _vertexData = new ArrayBuffer(initialVertexCapacity * vertexStrideBytes);
245
+ _float32View = new Float32Array(this._vertexData);
246
+ _indexData = new Uint16Array(initialIndexCapacity);
247
+ _projData = new Float32Array(projectionBytes / 4);
248
+ _nodeDataArray = new Float32Array(initialNodeCapacity * nodeFloats);
249
+ _nodeCapacity = initialNodeCapacity;
250
+ _nodeCount = 0;
251
+ _pendingQuads = [];
252
+ _nodeIndexMap = new Map();
253
+ _textureKeyMap = new Map();
254
+ _textureKeyCounter = 0;
255
+ // ── Public API ──────────────────────────────────────────────────────────────
256
+ render(node) {
257
+ if (!this._device)
258
+ throw new Error('WebGpuTextRenderer is not connected to a backend.');
259
+ if (this.getBackend()._passCoordinator.stencilActive) {
260
+ // MVP boundary: stencil clipping supports default-material Sprites, Meshes,
261
+ // and Graphics — not Text. Throw at collection time (inside the clip scope's
262
+ // try) so the push/pop balances.
263
+ throw new Error('WebGPU geometry stencil clipping currently supports default-material Sprites, Meshes, and Graphics. Text content under a Geometry clip (RenderNode.clip with a Geometry clipShape) is not supported yet. Use a Rectangle clipShape (scissor) or the WebGL2 backend instead.');
264
+ }
265
+ if (node instanceof Text) {
266
+ this._collectText(node);
267
+ }
268
+ else {
269
+ this._collectBitmapText(node);
270
+ }
271
+ }
272
+ flush() {
273
+ if (this._pendingQuads.length === 0) {
274
+ this._resetFrameState();
275
+ return;
276
+ }
277
+ const backend = this.getBackend();
278
+ const device = this._device;
279
+ // Assign stable sort keys to atlas textures seen this flush
280
+ for (const pq of this._pendingQuads) {
281
+ if (!this._textureKeyMap.has(pq.atlasTexture)) {
282
+ this._textureKeyMap.set(pq.atlasTexture, this._textureKeyCounter++);
283
+ }
284
+ }
285
+ // Sort by (shaderType, atlasTexture) so equal-key quads are contiguous
286
+ this._pendingQuads.sort((a, b) => {
287
+ const sc = a.shaderType.localeCompare(b.shaderType);
288
+ if (sc !== 0)
289
+ return sc;
290
+ return (this._textureKeyMap.get(a.atlasTexture) ?? 0) - (this._textureKeyMap.get(b.atlasTexture) ?? 0);
291
+ });
292
+ // Upload projection (3 × vec4<f32> = column-major mat3x3)
293
+ const m = backend.view.getTransform().toArray(false);
294
+ this._projData[0] = m[0];
295
+ this._projData[1] = m[1];
296
+ this._projData[2] = m[2];
297
+ this._projData[3] = 0;
298
+ this._projData[4] = m[3];
299
+ this._projData[5] = m[4];
300
+ this._projData[6] = m[5];
301
+ this._projData[7] = 0;
302
+ this._projData[8] = m[6];
303
+ this._projData[9] = m[7];
304
+ this._projData[10] = m[8];
305
+ this._projData[11] = 0;
306
+ device.queue.writeBuffer(this._projBuffer, 0, this._projData.buffer, 0, projectionBytes);
307
+ // Upload per-node style data (may reallocate the storage buffer)
308
+ this._uploadNodeBuffer(device);
309
+ // Build interleaved vertex/index data for all batches in one pass
310
+ const quads = this._pendingQuads;
311
+ const batches = [];
312
+ let totalV = 0, totalI = 0;
313
+ for (const pq of quads) {
314
+ totalV += pq.quads.quadCount * 4;
315
+ totalI += pq.quads.indices.length;
316
+ }
317
+ this._ensureVertexCapacity(totalV);
318
+ this._ensureIndexCapacity(totalI);
319
+ let packedV = 0, packedI = 0, qi = 0;
320
+ while (qi < quads.length) {
321
+ const first = quads[qi];
322
+ const firstTextureKey = this._textureKeyMap.get(first.atlasTexture);
323
+ let qj = qi + 1;
324
+ while (qj < quads.length) {
325
+ const pq = quads[qj];
326
+ if (pq.shaderType !== first.shaderType || this._textureKeyMap.get(pq.atlasTexture) !== firstTextureKey)
327
+ break;
328
+ qj++;
329
+ }
330
+ const batchFirstIndex = packedI;
331
+ let batchIndexCount = 0;
332
+ for (let k = qi; k < qj; k++) {
333
+ const { quads: batch, nodeIndex } = quads[k];
334
+ const qVerts = batch.quadCount * 4;
335
+ const { vertices, uvs, indices } = batch;
336
+ for (let v = 0; v < qVerts; v++) {
337
+ const w = (packedV + v) * vertexStrideWords;
338
+ const vp = v * 2;
339
+ this._float32View[w + 0] = vertices[vp];
340
+ this._float32View[w + 1] = vertices[vp + 1];
341
+ this._float32View[w + 2] = uvs[vp];
342
+ this._float32View[w + 3] = uvs[vp + 1];
343
+ this._float32View[w + 4] = nodeIndex;
344
+ }
345
+ for (let x = 0; x < indices.length; x++) {
346
+ this._indexData[packedI + x] = indices[x] + packedV;
347
+ }
348
+ packedV += qVerts;
349
+ packedI += indices.length;
350
+ batchIndexCount += indices.length;
351
+ }
352
+ batches.push({
353
+ shaderType: first.shaderType,
354
+ atlasTexture: first.atlasTexture,
355
+ firstIndex: batchFirstIndex,
356
+ indexCount: batchIndexCount,
357
+ });
358
+ qi = qj;
359
+ }
360
+ // Upload vertex/index buffers (reallocate GPU side when needed)
361
+ this._ensureGpuVertexBuffer(device, packedV);
362
+ this._ensureGpuIndexBuffer(device, packedI);
363
+ device.queue.writeBuffer(this._vertexBuffer, 0, this._vertexData, 0, packedV * vertexStrideBytes);
364
+ device.queue.writeBuffer(this._indexBuffer, 0, this._indexData.buffer, 0, packedI * 2);
365
+ const format = backend.renderTargetFormat;
366
+ const frameBindGroup = this._getFrameBindGroup(device);
367
+ // The coordinator owns the GPU pass (load/clear resolution, pass count and
368
+ // scissor are applied there) and ends + submits it below.
369
+ const pass = backend._passCoordinator.acquirePass().pass;
370
+ pass.setVertexBuffer(0, this._vertexBuffer);
371
+ pass.setIndexBuffer(this._indexBuffer, 'uint16');
372
+ let lastShaderType = null;
373
+ let lastTexture = null;
374
+ for (const batch of batches) {
375
+ if (batch.shaderType !== lastShaderType) {
376
+ pass.setPipeline(this._getPipeline(batch.shaderType, format));
377
+ pass.setBindGroup(0, frameBindGroup);
378
+ lastShaderType = batch.shaderType;
379
+ }
380
+ if (batch.atlasTexture !== lastTexture) {
381
+ pass.setBindGroup(1, this._getTexBindGroup(device, backend, batch.atlasTexture));
382
+ lastTexture = batch.atlasTexture;
383
+ }
384
+ pass.drawIndexed(batch.indexCount, 1, batch.firstIndex, 0, 0);
385
+ backend.stats.batches++;
386
+ backend.stats.drawCalls++;
387
+ }
388
+ backend._passCoordinator.endPass();
389
+ this._resetFrameState();
390
+ }
391
+ destroy() {
392
+ this.disconnect();
393
+ }
394
+ /**
395
+ * Pre-create render pipelines for every (shaderType × targetFormat) pair
396
+ * asynchronously. Called from the backend init path so first-frame draws
397
+ * do not block on synchronous pipeline compilation.
398
+ */
399
+ async prewarmPipelines(formats) {
400
+ const device = this._device;
401
+ if (!device || !this._shaderModule || !this._pipelineLayout)
402
+ return;
403
+ if (typeof device.createRenderPipelineAsync !== 'function')
404
+ return;
405
+ const shaderTypes = ['sdf', 'msdf', 'color'];
406
+ const promises = [];
407
+ for (const shaderType of shaderTypes) {
408
+ for (const format of formats) {
409
+ const key = `${shaderType}:${format}`;
410
+ if (this._pipelines.has(key))
411
+ continue;
412
+ promises.push(device.createRenderPipelineAsync(this._buildPipelineDescriptor(shaderType, format)).then(pipeline => {
413
+ this._pipelines.set(key, pipeline);
414
+ }));
415
+ }
416
+ }
417
+ await Promise.all(promises);
418
+ }
419
+ // ── Connection lifecycle ─────────────────────────────────────────────────
420
+ onConnect(backend) {
421
+ const device = backend.device;
422
+ this._device = device;
423
+ this._shaderModule = device.createShaderModule({
424
+ label: 'WebGpuTextRenderer',
425
+ code: textShaderSource,
426
+ });
427
+ this._frameBindGroupLayout = device.createBindGroupLayout({
428
+ label: 'WebGpuTextRenderer/frame',
429
+ entries: [
430
+ {
431
+ binding: 0,
432
+ visibility: GPUShaderStage.VERTEX,
433
+ buffer: { type: 'uniform' },
434
+ },
435
+ {
436
+ binding: 1,
437
+ visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
438
+ buffer: { type: 'read-only-storage' },
439
+ },
440
+ ],
441
+ });
442
+ this._textureBindGroupLayout = device.createBindGroupLayout({
443
+ label: 'WebGpuTextRenderer/texture',
444
+ entries: [
445
+ {
446
+ binding: 0,
447
+ visibility: GPUShaderStage.FRAGMENT,
448
+ texture: { sampleType: 'float' },
449
+ },
450
+ {
451
+ binding: 1,
452
+ visibility: GPUShaderStage.FRAGMENT,
453
+ sampler: { type: 'filtering' },
454
+ },
455
+ ],
456
+ });
457
+ this._pipelineLayout = device.createPipelineLayout({
458
+ label: 'WebGpuTextRenderer',
459
+ bindGroupLayouts: [this._frameBindGroupLayout, this._textureBindGroupLayout],
460
+ });
461
+ this._projBuffer = device.createBuffer({
462
+ label: 'WebGpuTextRenderer/proj',
463
+ size: projectionBytes,
464
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
465
+ });
466
+ const nodeBytes = initialNodeCapacity * nodeFloats * 4;
467
+ this._nodeBuffer = device.createBuffer({
468
+ label: 'WebGpuTextRenderer/nodes',
469
+ size: nodeBytes,
470
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
471
+ });
472
+ this._nodeBufferCapacity = nodeBytes;
473
+ const vertexBytes = initialVertexCapacity * vertexStrideBytes;
474
+ this._vertexBuffer = device.createBuffer({
475
+ label: 'WebGpuTextRenderer/vertices',
476
+ size: vertexBytes,
477
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
478
+ });
479
+ this._vertexBufferCapacity = vertexBytes;
480
+ const indexBytes = initialIndexCapacity * 2;
481
+ this._indexBuffer = device.createBuffer({
482
+ label: 'WebGpuTextRenderer/indices',
483
+ size: indexBytes,
484
+ usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
485
+ });
486
+ this._indexBufferCapacity = indexBytes;
487
+ this._frameBindGroupDirty = true;
488
+ }
489
+ onDisconnect() {
490
+ this._projBuffer?.destroy();
491
+ this._nodeBuffer?.destroy();
492
+ this._vertexBuffer?.destroy();
493
+ this._indexBuffer?.destroy();
494
+ this._projBuffer = null;
495
+ this._nodeBuffer = null;
496
+ this._vertexBuffer = null;
497
+ this._indexBuffer = null;
498
+ this._nodeBufferCapacity = 0;
499
+ this._vertexBufferCapacity = 0;
500
+ this._indexBufferCapacity = 0;
501
+ this._frameBindGroup = null;
502
+ this._frameBindGroupDirty = true;
503
+ this._pipelines.clear();
504
+ this._texBindGroups = new WeakMap();
505
+ this._pipelineLayout = null;
506
+ this._textureBindGroupLayout = null;
507
+ this._frameBindGroupLayout = null;
508
+ this._shaderModule = null;
509
+ this._device = null;
510
+ this._resetFrameState();
511
+ }
512
+ // ── Collection ───────────────────────────────────────────────────────────
513
+ _collectText(node) {
514
+ node.syncDirty();
515
+ const { pageQuads, atlas } = node;
516
+ if (pageQuads.length === 0 || atlas === null)
517
+ return;
518
+ const nodeIndex = this._assignNodeIndex(node);
519
+ const shaderType = node.colorGlyphs ? 'color' : 'sdf';
520
+ const pages = atlas.pages;
521
+ for (const batch of pageQuads) {
522
+ const page = pages[batch.pageIndex];
523
+ if (page === undefined)
524
+ continue;
525
+ this._pendingQuads.push({ quads: batch, nodeIndex, shaderType, atlasTexture: page.texture });
526
+ }
527
+ }
528
+ _collectBitmapText(node) {
529
+ const { pageQuads, textures, msdf } = node;
530
+ if (pageQuads.length === 0)
531
+ return;
532
+ const nodeIndex = this._assignNodeIndex(node);
533
+ const shaderType = msdf ? 'msdf' : 'color';
534
+ for (const batch of pageQuads) {
535
+ const tex = textures[batch.pageIndex];
536
+ if (tex === undefined)
537
+ continue;
538
+ this._pendingQuads.push({ quads: batch, nodeIndex, shaderType, atlasTexture: tex });
539
+ }
540
+ }
541
+ _assignNodeIndex(node) {
542
+ const existing = this._nodeIndexMap.get(node);
543
+ if (existing !== undefined)
544
+ return existing;
545
+ const idx = this._nodeCount++;
546
+ this._nodeIndexMap.set(node, idx);
547
+ this._ensureNodeCapacity(idx + 1);
548
+ this._packNodeData(idx, node);
549
+ return idx;
550
+ }
551
+ // ── Node data packing (identical to WebGl2TextRenderer) ──────────────────
552
+ _packNodeData(ni, node) {
553
+ const arr = this._nodeDataArray;
554
+ const base = ni * nodeFloats;
555
+ const style = node.style;
556
+ const m = node.getGlobalTransform().toArray(false);
557
+ arr[base + 0] = m[0];
558
+ arr[base + 1] = m[1];
559
+ arr[base + 2] = m[2];
560
+ arr[base + 3] = m[6];
561
+ arr[base + 4] = m[3];
562
+ arr[base + 5] = m[4];
563
+ arr[base + 6] = m[5];
564
+ arr[base + 7] = m[7];
565
+ const fc = style.fillColor;
566
+ arr[base + 8] = fc.r / 255;
567
+ arr[base + 9] = fc.g / 255;
568
+ arr[base + 10] = fc.b / 255;
569
+ arr[base + 11] = fc.a;
570
+ const oc = style.outlineColor;
571
+ arr[base + 12] = oc.r / 255;
572
+ arr[base + 13] = oc.g / 255;
573
+ arr[base + 14] = oc.b / 255;
574
+ arr[base + 15] = oc.a;
575
+ const outlineMin = style.outlineWidth > 0 ? Math.max(0, 0.5 - style.outlineWidth) : 0.5;
576
+ arr[base + 16] = outlineMin;
577
+ arr[base + 17] = style.shadowAlpha;
578
+ arr[base + 18] = Math.max(0.03, style.shadowBlur * 0.1);
579
+ arr[base + 19] = style.gradientColors !== null ? 1 : 0;
580
+ const sc = style.shadowColor;
581
+ arr[base + 20] = sc.r / 255;
582
+ arr[base + 21] = sc.g / 255;
583
+ arr[base + 22] = sc.b / 255;
584
+ arr[base + 23] = sc.a;
585
+ arr[base + 24] = style.shadowOffsetX;
586
+ arr[base + 25] = style.shadowOffsetY;
587
+ arr[base + 26] = style.gradientAxis === 'vertical' ? 1 : 0;
588
+ arr[base + 27] = 0;
589
+ const gc = style.gradientColors;
590
+ if (gc !== null) {
591
+ arr[base + 28] = gc[0].r / 255;
592
+ arr[base + 29] = gc[0].g / 255;
593
+ arr[base + 30] = gc[0].b / 255;
594
+ arr[base + 31] = gc[0].a;
595
+ arr[base + 32] = gc[1].r / 255;
596
+ arr[base + 33] = gc[1].g / 255;
597
+ arr[base + 34] = gc[1].b / 255;
598
+ arr[base + 35] = gc[1].a;
599
+ }
600
+ else {
601
+ arr[base + 28] = arr[base + 29] = arr[base + 30] = arr[base + 31] = 0;
602
+ arr[base + 32] = arr[base + 33] = arr[base + 34] = arr[base + 35] = 0;
603
+ }
604
+ const bounds = node.textBounds;
605
+ arr[base + 36] = 0;
606
+ arr[base + 37] = 0;
607
+ arr[base + 38] = bounds.width;
608
+ arr[base + 39] = bounds.height;
609
+ }
610
+ // ── GPU resource helpers ─────────────────────────────────────────────────
611
+ _uploadNodeBuffer(device) {
612
+ const requiredBytes = this._nodeCount * nodeFloats * 4;
613
+ if (requiredBytes > this._nodeBufferCapacity) {
614
+ let newCap = this._nodeBufferCapacity;
615
+ while (newCap < requiredBytes)
616
+ newCap *= 2;
617
+ this._nodeBuffer?.destroy();
618
+ this._nodeBuffer = device.createBuffer({
619
+ label: 'WebGpuTextRenderer/nodes',
620
+ size: newCap,
621
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
622
+ });
623
+ this._nodeBufferCapacity = newCap;
624
+ this._frameBindGroupDirty = true;
625
+ }
626
+ device.queue.writeBuffer(this._nodeBuffer, 0, this._nodeDataArray.buffer, 0, requiredBytes);
627
+ }
628
+ _ensureGpuVertexBuffer(device, vertexCount) {
629
+ const required = vertexCount * vertexStrideBytes;
630
+ if (required <= this._vertexBufferCapacity)
631
+ return;
632
+ let newCap = this._vertexBufferCapacity;
633
+ while (newCap < required)
634
+ newCap *= 2;
635
+ this._vertexBuffer?.destroy();
636
+ this._vertexBuffer = device.createBuffer({
637
+ label: 'WebGpuTextRenderer/vertices',
638
+ size: newCap,
639
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
640
+ });
641
+ this._vertexBufferCapacity = newCap;
642
+ }
643
+ _ensureGpuIndexBuffer(device, indexCount) {
644
+ const required = indexCount * 2;
645
+ if (required <= this._indexBufferCapacity)
646
+ return;
647
+ let newCap = this._indexBufferCapacity;
648
+ while (newCap < required)
649
+ newCap *= 2;
650
+ this._indexBuffer?.destroy();
651
+ this._indexBuffer = device.createBuffer({
652
+ label: 'WebGpuTextRenderer/indices',
653
+ size: newCap,
654
+ usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
655
+ });
656
+ this._indexBufferCapacity = newCap;
657
+ }
658
+ _getFrameBindGroup(device) {
659
+ if (!this._frameBindGroupDirty && this._frameBindGroup !== null) {
660
+ return this._frameBindGroup;
661
+ }
662
+ this._frameBindGroup = device.createBindGroup({
663
+ layout: this._frameBindGroupLayout,
664
+ entries: [
665
+ { binding: 0, resource: { buffer: this._projBuffer } },
666
+ { binding: 1, resource: { buffer: this._nodeBuffer } },
667
+ ],
668
+ });
669
+ this._frameBindGroupDirty = false;
670
+ return this._frameBindGroup;
671
+ }
672
+ _getTexBindGroup(device, backend, texture) {
673
+ const existing = this._texBindGroups.get(texture);
674
+ if (existing !== undefined)
675
+ return existing;
676
+ const { view, sampler } = backend.getTextureBinding(texture);
677
+ const group = device.createBindGroup({
678
+ layout: this._textureBindGroupLayout,
679
+ entries: [
680
+ { binding: 0, resource: view },
681
+ { binding: 1, resource: sampler },
682
+ ],
683
+ });
684
+ this._texBindGroups.set(texture, group);
685
+ return group;
686
+ }
687
+ // ── Pipeline helpers ─────────────────────────────────────────────────────
688
+ _getPipeline(shaderType, format) {
689
+ const key = `${shaderType}:${format}`;
690
+ const existing = this._pipelines.get(key);
691
+ if (existing)
692
+ return existing;
693
+ const pipeline = this._device.createRenderPipeline(this._buildPipelineDescriptor(shaderType, format));
694
+ this._pipelines.set(key, pipeline);
695
+ return pipeline;
696
+ }
697
+ _buildPipelineDescriptor(shaderType, format) {
698
+ let fragEntry;
699
+ if (shaderType === 'sdf') {
700
+ fragEntry = 'fragmentSdf';
701
+ }
702
+ else if (shaderType === 'msdf') {
703
+ fragEntry = 'fragmentMsdf';
704
+ }
705
+ else {
706
+ fragEntry = 'fragmentColor';
707
+ }
708
+ return {
709
+ label: `WebGpuTextRenderer/${shaderType}`,
710
+ layout: this._pipelineLayout,
711
+ vertex: {
712
+ module: this._shaderModule,
713
+ entryPoint: 'vertexMain',
714
+ buffers: [
715
+ {
716
+ arrayStride: vertexStrideBytes,
717
+ stepMode: 'vertex',
718
+ attributes: [
719
+ { shaderLocation: 0, offset: 0, format: 'float32x2' },
720
+ { shaderLocation: 1, offset: 8, format: 'float32x2' },
721
+ { shaderLocation: 2, offset: 16, format: 'float32' },
722
+ ],
723
+ },
724
+ ],
725
+ },
726
+ fragment: {
727
+ module: this._shaderModule,
728
+ entryPoint: fragEntry,
729
+ targets: [
730
+ {
731
+ format,
732
+ blend: getWebGpuBlendState(BlendModes.Normal),
733
+ writeMask: GPUColorWrite.ALL,
734
+ },
735
+ ],
736
+ },
737
+ primitive: { topology: 'triangle-list' },
738
+ };
739
+ }
740
+ // ── Capacity helpers ─────────────────────────────────────────────────────
741
+ _ensureVertexCapacity(vertexCount) {
742
+ if (vertexCount <= this._vertexCapacity)
743
+ return;
744
+ while (this._vertexCapacity < vertexCount)
745
+ this._vertexCapacity *= 2;
746
+ this._vertexData = new ArrayBuffer(this._vertexCapacity * vertexStrideBytes);
747
+ this._float32View = new Float32Array(this._vertexData);
748
+ }
749
+ _ensureIndexCapacity(indexCount) {
750
+ if (indexCount <= this._indexCapacity)
751
+ return;
752
+ while (this._indexCapacity < indexCount)
753
+ this._indexCapacity *= 2;
754
+ this._indexData = new Uint16Array(this._indexCapacity);
755
+ }
756
+ _ensureNodeCapacity(nodeCount) {
757
+ if (nodeCount <= this._nodeCapacity)
758
+ return;
759
+ while (this._nodeCapacity < nodeCount)
760
+ this._nodeCapacity *= 2;
761
+ const next = new Float32Array(this._nodeCapacity * nodeFloats);
762
+ next.set(this._nodeDataArray);
763
+ this._nodeDataArray = next;
764
+ }
765
+ _resetFrameState() {
766
+ this._pendingQuads.length = 0;
767
+ this._nodeIndexMap.clear();
768
+ this._textureKeyMap.clear();
769
+ this._textureKeyCounter = 0;
770
+ this._nodeCount = 0;
771
+ }
772
+ }
773
+
774
+ export { WebGpuTextRenderer };
775
+ //# sourceMappingURL=WebGpuTextRenderer.js.map