@thunderclap-engine/engine 0.0.0-stage → 1.1.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 (566) hide show
  1. package/CHANGELOG.md +390 -0
  2. package/LICENSE +21 -0
  3. package/README.md +333 -2
  4. package/dist/analytics/analytics.d.ts +80 -0
  5. package/dist/analytics/analytics.js +129 -0
  6. package/dist/analytics/index.d.ts +1 -0
  7. package/dist/analytics/index.js +1 -0
  8. package/dist/anim/aim.d.ts +43 -0
  9. package/dist/anim/aim.js +157 -0
  10. package/dist/anim/clip.d.ts +98 -0
  11. package/dist/anim/clip.js +282 -0
  12. package/dist/anim/compress.d.ts +65 -0
  13. package/dist/anim/compress.js +339 -0
  14. package/dist/anim/foot-ik.d.ts +74 -0
  15. package/dist/anim/foot-ik.js +241 -0
  16. package/dist/anim/graph.d.ts +153 -0
  17. package/dist/anim/graph.js +532 -0
  18. package/dist/anim/ik.d.ts +105 -0
  19. package/dist/anim/ik.js +435 -0
  20. package/dist/anim/index.d.ts +36 -0
  21. package/dist/anim/index.js +21 -0
  22. package/dist/anim/match.d.ts +66 -0
  23. package/dist/anim/match.js +153 -0
  24. package/dist/anim/mixer.d.ts +113 -0
  25. package/dist/anim/mixer.js +314 -0
  26. package/dist/anim/morph.d.ts +41 -0
  27. package/dist/anim/morph.js +94 -0
  28. package/dist/anim/pose.d.ts +74 -0
  29. package/dist/anim/pose.js +254 -0
  30. package/dist/anim/quat.d.ts +44 -0
  31. package/dist/anim/quat.js +187 -0
  32. package/dist/anim/retarget.d.ts +97 -0
  33. package/dist/anim/retarget.js +366 -0
  34. package/dist/anim/root-motion.d.ts +44 -0
  35. package/dist/anim/root-motion.js +224 -0
  36. package/dist/anim/skin-pose.d.ts +39 -0
  37. package/dist/anim/skin-pose.js +53 -0
  38. package/dist/anim/socket.d.ts +47 -0
  39. package/dist/anim/socket.js +84 -0
  40. package/dist/anim/spring-chain.d.ts +73 -0
  41. package/dist/anim/spring-chain.js +294 -0
  42. package/dist/assets/atlas.d.ts +90 -0
  43. package/dist/assets/atlas.js +212 -0
  44. package/dist/assets/baked.d.ts +33 -0
  45. package/dist/assets/baked.js +38 -0
  46. package/dist/assets/bundle.d.ts +88 -0
  47. package/dist/assets/bundle.js +464 -0
  48. package/dist/assets/cache.d.ts +56 -0
  49. package/dist/assets/cache.js +123 -0
  50. package/dist/assets/gltf-load.d.ts +252 -0
  51. package/dist/assets/gltf-load.js +661 -0
  52. package/dist/assets/gltf-skin.d.ts +36 -0
  53. package/dist/assets/gltf-skin.js +109 -0
  54. package/dist/assets/gltf.d.ts +706 -0
  55. package/dist/assets/gltf.js +1376 -0
  56. package/dist/assets/index.d.ts +20 -0
  57. package/dist/assets/index.js +10 -0
  58. package/dist/assets/ktx2.d.ts +71 -0
  59. package/dist/assets/ktx2.js +213 -0
  60. package/dist/assets/manifest.d.ts +79 -0
  61. package/dist/assets/manifest.js +7 -0
  62. package/dist/assets/meshopt.d.ts +23 -0
  63. package/dist/assets/meshopt.js +403 -0
  64. package/dist/audio/audio.d.ts +733 -0
  65. package/dist/audio/audio.js +2013 -0
  66. package/dist/audio/dsp.d.ts +61 -0
  67. package/dist/audio/dsp.js +159 -0
  68. package/dist/audio/duck.d.ts +44 -0
  69. package/dist/audio/duck.js +101 -0
  70. package/dist/audio/envelope.d.ts +53 -0
  71. package/dist/audio/envelope.js +106 -0
  72. package/dist/audio/index.d.ts +13 -0
  73. package/dist/audio/index.js +14 -0
  74. package/dist/audio/music.d.ts +113 -0
  75. package/dist/audio/music.js +548 -0
  76. package/dist/audio/occlusion.d.ts +55 -0
  77. package/dist/audio/occlusion.js +61 -0
  78. package/dist/audio/persist.d.ts +23 -0
  79. package/dist/audio/persist.js +27 -0
  80. package/dist/audio/recipes.d.ts +55 -0
  81. package/dist/audio/recipes.js +227 -0
  82. package/dist/audio/send.d.ts +41 -0
  83. package/dist/audio/send.js +118 -0
  84. package/dist/audio/sprites.d.ts +59 -0
  85. package/dist/audio/sprites.js +43 -0
  86. package/dist/audio/synth.d.ts +103 -0
  87. package/dist/audio/synth.js +197 -0
  88. package/dist/audio/variations.d.ts +25 -0
  89. package/dist/audio/variations.js +55 -0
  90. package/dist/audio/zones.d.ts +100 -0
  91. package/dist/audio/zones.js +167 -0
  92. package/dist/core/detached-surface.d.ts +44 -0
  93. package/dist/core/detached-surface.js +104 -0
  94. package/dist/core/events.d.ts +24 -0
  95. package/dist/core/events.js +43 -0
  96. package/dist/core/game.d.ts +409 -0
  97. package/dist/core/game.js +530 -0
  98. package/dist/core/hash.d.ts +24 -0
  99. package/dist/core/hash.js +49 -0
  100. package/dist/core/index.d.ts +17 -0
  101. package/dist/core/index.js +9 -0
  102. package/dist/core/loop.d.ts +113 -0
  103. package/dist/core/loop.js +185 -0
  104. package/dist/core/math.d.ts +58 -0
  105. package/dist/core/math.js +210 -0
  106. package/dist/core/noise.d.ts +40 -0
  107. package/dist/core/noise.js +247 -0
  108. package/dist/core/pool.d.ts +42 -0
  109. package/dist/core/pool.js +85 -0
  110. package/dist/core/random.d.ts +61 -0
  111. package/dist/core/random.js +199 -0
  112. package/dist/core/scene.d.ts +79 -0
  113. package/dist/core/scene.js +195 -0
  114. package/dist/core/timer.d.ts +66 -0
  115. package/dist/core/timer.js +286 -0
  116. package/dist/fx/billboard-wgsl.d.ts +29 -0
  117. package/dist/fx/billboard-wgsl.js +158 -0
  118. package/dist/fx/billboard.d.ts +249 -0
  119. package/dist/fx/billboard.js +702 -0
  120. package/dist/fx/debug-draw.d.ts +127 -0
  121. package/dist/fx/debug-draw.js +523 -0
  122. package/dist/fx/debug-wgsl.d.ts +7 -0
  123. package/dist/fx/debug-wgsl.js +32 -0
  124. package/dist/fx/decals-wgsl.d.ts +15 -0
  125. package/dist/fx/decals-wgsl.js +173 -0
  126. package/dist/fx/decals.d.ts +216 -0
  127. package/dist/fx/decals.js +607 -0
  128. package/dist/fx/effect.d.ts +129 -0
  129. package/dist/fx/effect.js +349 -0
  130. package/dist/fx/effects/hit-spark.json +48 -0
  131. package/dist/fx/effects/index.d.ts +8 -0
  132. package/dist/fx/effects/index.js +9 -0
  133. package/dist/fx/effects/magic-aura.json +47 -0
  134. package/dist/fx/effects/smoke-puff.json +34 -0
  135. package/dist/fx/emit-surface.d.ts +40 -0
  136. package/dist/fx/emit-surface.js +124 -0
  137. package/dist/fx/flicker.d.ts +30 -0
  138. package/dist/fx/flicker.js +42 -0
  139. package/dist/fx/index.d.ts +31 -0
  140. package/dist/fx/index.js +20 -0
  141. package/dist/fx/particles-wgsl.d.ts +57 -0
  142. package/dist/fx/particles-wgsl.js +828 -0
  143. package/dist/fx/particles.d.ts +566 -0
  144. package/dist/fx/particles.js +1533 -0
  145. package/dist/fx/random.d.ts +15 -0
  146. package/dist/fx/random.js +20 -0
  147. package/dist/fx/sky-wgsl.d.ts +23 -0
  148. package/dist/fx/sky-wgsl.js +127 -0
  149. package/dist/fx/sky.d.ts +96 -0
  150. package/dist/fx/sky.js +175 -0
  151. package/dist/fx/text-atlas.d.ts +143 -0
  152. package/dist/fx/text-atlas.js +327 -0
  153. package/dist/fx/trail-wgsl.d.ts +11 -0
  154. package/dist/fx/trail-wgsl.js +42 -0
  155. package/dist/fx/trail.d.ts +194 -0
  156. package/dist/fx/trail.js +555 -0
  157. package/dist/fx/water-wgsl.d.ts +34 -0
  158. package/dist/fx/water-wgsl.js +197 -0
  159. package/dist/fx/water.d.ts +176 -0
  160. package/dist/fx/water.js +371 -0
  161. package/dist/geom/collide/bvh.d.ts +151 -0
  162. package/dist/geom/collide/bvh.js +493 -0
  163. package/dist/geom/collide/debug.d.ts +14 -0
  164. package/dist/geom/collide/debug.js +74 -0
  165. package/dist/geom/collide/grid.d.ts +26 -0
  166. package/dist/geom/collide/grid.js +91 -0
  167. package/dist/geom/collide/index.d.ts +8 -0
  168. package/dist/geom/collide/index.js +8 -0
  169. package/dist/geom/collide/queries.d.ts +70 -0
  170. package/dist/geom/collide/queries.js +583 -0
  171. package/dist/geom/collide/serialize.d.ts +14 -0
  172. package/dist/geom/collide/serialize.js +145 -0
  173. package/dist/geom/collide/shapes.d.ts +161 -0
  174. package/dist/geom/collide/shapes.js +686 -0
  175. package/dist/geom/collide/slide.d.ts +66 -0
  176. package/dist/geom/collide/slide.js +375 -0
  177. package/dist/geom/collide/tile-slide.d.ts +88 -0
  178. package/dist/geom/collide/tile-slide.js +255 -0
  179. package/dist/geom/geometry.d.ts +95 -0
  180. package/dist/geom/geometry.js +322 -0
  181. package/dist/geom/heightfield.d.ts +72 -0
  182. package/dist/geom/heightfield.js +295 -0
  183. package/dist/geom/hull.d.ts +27 -0
  184. package/dist/geom/hull.js +279 -0
  185. package/dist/geom/index.d.ts +35 -0
  186. package/dist/geom/index.js +23 -0
  187. package/dist/geom/iso.d.ts +74 -0
  188. package/dist/geom/iso.js +89 -0
  189. package/dist/geom/lod.d.ts +29 -0
  190. package/dist/geom/lod.js +27 -0
  191. package/dist/geom/ops.d.ts +47 -0
  192. package/dist/geom/ops.js +285 -0
  193. package/dist/geom/primitives.d.ts +97 -0
  194. package/dist/geom/primitives.js +359 -0
  195. package/dist/geom/shapes.d.ts +43 -0
  196. package/dist/geom/shapes.js +88 -0
  197. package/dist/geom/simplify.d.ts +38 -0
  198. package/dist/geom/simplify.js +519 -0
  199. package/dist/geom/split.d.ts +37 -0
  200. package/dist/geom/split.js +413 -0
  201. package/dist/geom/sweep.d.ts +83 -0
  202. package/dist/geom/sweep.js +534 -0
  203. package/dist/geom/tangents.d.ts +16 -0
  204. package/dist/geom/tangents.js +124 -0
  205. package/dist/geom/triangulate.d.ts +19 -0
  206. package/dist/geom/triangulate.js +147 -0
  207. package/dist/host/default.d.ts +10 -0
  208. package/dist/host/default.js +10 -0
  209. package/dist/host/index.d.ts +4 -0
  210. package/dist/host/index.js +3 -0
  211. package/dist/host/types.d.ts +144 -0
  212. package/dist/host/types.js +1 -0
  213. package/dist/host/web-links.d.ts +38 -0
  214. package/dist/host/web-links.js +110 -0
  215. package/dist/host/web.d.ts +30 -0
  216. package/dist/host/web.js +216 -0
  217. package/dist/host/xr.d.ts +24 -0
  218. package/dist/host/xr.js +59 -0
  219. package/dist/i18n/i18n.d.ts +59 -0
  220. package/dist/i18n/i18n.js +241 -0
  221. package/dist/i18n/index.d.ts +3 -0
  222. package/dist/i18n/index.js +3 -0
  223. package/dist/i18n/message.d.ts +72 -0
  224. package/dist/i18n/message.js +369 -0
  225. package/dist/i18n/negotiate.d.ts +17 -0
  226. package/dist/i18n/negotiate.js +58 -0
  227. package/dist/index.d.ts +7 -0
  228. package/dist/index.js +1 -0
  229. package/dist/input/bindings.d.ts +31 -0
  230. package/dist/input/bindings.js +141 -0
  231. package/dist/input/clock.d.ts +44 -0
  232. package/dist/input/clock.js +49 -0
  233. package/dist/input/follow.d.ts +133 -0
  234. package/dist/input/follow.js +218 -0
  235. package/dist/input/gestures.d.ts +281 -0
  236. package/dist/input/gestures.js +662 -0
  237. package/dist/input/glyphs.d.ts +35 -0
  238. package/dist/input/glyphs.js +216 -0
  239. package/dist/input/gyro.d.ts +85 -0
  240. package/dist/input/gyro.js +140 -0
  241. package/dist/input/index.d.ts +19 -0
  242. package/dist/input/index.js +16 -0
  243. package/dist/input/input.d.ts +543 -0
  244. package/dist/input/input.js +1492 -0
  245. package/dist/input/look.d.ts +327 -0
  246. package/dist/input/look.js +681 -0
  247. package/dist/input/magnify.d.ts +177 -0
  248. package/dist/input/magnify.js +131 -0
  249. package/dist/input/pointer-dispatch.d.ts +138 -0
  250. package/dist/input/pointer-dispatch.js +180 -0
  251. package/dist/input/pointer-router.d.ts +204 -0
  252. package/dist/input/pointer-router.js +533 -0
  253. package/dist/input/pointer-sources.d.ts +164 -0
  254. package/dist/input/pointer-sources.js +306 -0
  255. package/dist/input/rays.d.ts +138 -0
  256. package/dist/input/rays.js +615 -0
  257. package/dist/input/record.d.ts +209 -0
  258. package/dist/input/record.js +601 -0
  259. package/dist/input/touch-zones.d.ts +147 -0
  260. package/dist/input/touch-zones.js +300 -0
  261. package/dist/input/types.d.ts +158 -0
  262. package/dist/input/types.js +1 -0
  263. package/dist/input/xr-source.d.ts +53 -0
  264. package/dist/input/xr-source.js +164 -0
  265. package/dist/nav/astar.d.ts +45 -0
  266. package/dist/nav/astar.js +182 -0
  267. package/dist/nav/corridor.d.ts +40 -0
  268. package/dist/nav/corridor.js +95 -0
  269. package/dist/nav/crowd.d.ts +94 -0
  270. package/dist/nav/crowd.js +624 -0
  271. package/dist/nav/flow.d.ts +61 -0
  272. package/dist/nav/flow.js +193 -0
  273. package/dist/nav/grid.d.ts +108 -0
  274. package/dist/nav/grid.js +210 -0
  275. package/dist/nav/heap.d.ts +22 -0
  276. package/dist/nav/heap.js +92 -0
  277. package/dist/nav/index.d.ts +37 -0
  278. package/dist/nav/index.js +19 -0
  279. package/dist/nav/mesh/areas.d.ts +44 -0
  280. package/dist/nav/mesh/areas.js +98 -0
  281. package/dist/nav/mesh/bake-options.d.ts +33 -0
  282. package/dist/nav/mesh/bake-options.js +76 -0
  283. package/dist/nav/mesh/contour.d.ts +22 -0
  284. package/dist/nav/mesh/contour.js +323 -0
  285. package/dist/nav/mesh/flow3.d.ts +35 -0
  286. package/dist/nav/mesh/flow3.js +229 -0
  287. package/dist/nav/mesh/links.d.ts +38 -0
  288. package/dist/nav/mesh/links.js +72 -0
  289. package/dist/nav/mesh/mesh-path.d.ts +152 -0
  290. package/dist/nav/mesh/mesh-path.js +643 -0
  291. package/dist/nav/mesh/mesh-reach.d.ts +78 -0
  292. package/dist/nav/mesh/mesh-reach.js +450 -0
  293. package/dist/nav/mesh/navmesh.d.ts +117 -0
  294. package/dist/nav/mesh/navmesh.js +647 -0
  295. package/dist/nav/mesh/polymesh.d.ts +24 -0
  296. package/dist/nav/mesh/polymesh.js +384 -0
  297. package/dist/nav/mesh/regions.d.ts +12 -0
  298. package/dist/nav/mesh/regions.js +367 -0
  299. package/dist/nav/mesh/serialize.d.ts +13 -0
  300. package/dist/nav/mesh/serialize.js +197 -0
  301. package/dist/nav/mesh/voxelize.d.ts +111 -0
  302. package/dist/nav/mesh/voxelize.js +552 -0
  303. package/dist/nav/obstacles.d.ts +75 -0
  304. package/dist/nav/obstacles.js +294 -0
  305. package/dist/nav/path.d.ts +59 -0
  306. package/dist/nav/path.js +177 -0
  307. package/dist/nav/query-queue.d.ts +46 -0
  308. package/dist/nav/query-queue.js +308 -0
  309. package/dist/nav/reach.d.ts +53 -0
  310. package/dist/nav/reach.js +148 -0
  311. package/dist/nav/steer.d.ts +36 -0
  312. package/dist/nav/steer.js +78 -0
  313. package/dist/platform/boot.d.ts +28 -0
  314. package/dist/platform/boot.js +43 -0
  315. package/dist/platform/device-mode.d.ts +40 -0
  316. package/dist/platform/device-mode.js +104 -0
  317. package/dist/platform/device.d.ts +31 -0
  318. package/dist/platform/device.js +91 -0
  319. package/dist/platform/environment.d.ts +42 -0
  320. package/dist/platform/environment.js +82 -0
  321. package/dist/platform/gpu.d.ts +40 -0
  322. package/dist/platform/gpu.js +57 -0
  323. package/dist/platform/index.d.ts +18 -0
  324. package/dist/platform/index.js +10 -0
  325. package/dist/platform/letterbox.d.ts +43 -0
  326. package/dist/platform/letterbox.js +57 -0
  327. package/dist/platform/links.d.ts +20 -0
  328. package/dist/platform/links.js +43 -0
  329. package/dist/platform/screens.d.ts +36 -0
  330. package/dist/platform/screens.js +138 -0
  331. package/dist/platform/surface.d.ts +72 -0
  332. package/dist/platform/surface.js +157 -0
  333. package/dist/platform/xr-fake.d.ts +168 -0
  334. package/dist/platform/xr-fake.js +434 -0
  335. package/dist/platform/xr-surface.d.ts +120 -0
  336. package/dist/platform/xr-surface.js +214 -0
  337. package/dist/platform/xr-types.d.ts +262 -0
  338. package/dist/post/ao.d.ts +12 -0
  339. package/dist/post/ao.js +136 -0
  340. package/dist/post/blend.d.ts +27 -0
  341. package/dist/post/blend.js +129 -0
  342. package/dist/post/depth-pass.d.ts +43 -0
  343. package/dist/post/depth-pass.js +118 -0
  344. package/dist/post/dof.d.ts +1 -0
  345. package/dist/post/dof.js +66 -0
  346. package/dist/post/exposure.d.ts +80 -0
  347. package/dist/post/exposure.js +322 -0
  348. package/dist/post/index.d.ts +12 -0
  349. package/dist/post/index.js +11 -0
  350. package/dist/post/lens-dirt.d.ts +13 -0
  351. package/dist/post/lens-dirt.js +91 -0
  352. package/dist/post/lut.d.ts +19 -0
  353. package/dist/post/lut.js +50 -0
  354. package/dist/post/motion-blur.d.ts +9 -0
  355. package/dist/post/motion-blur.js +78 -0
  356. package/dist/post/post-stack.d.ts +302 -0
  357. package/dist/post/post-stack.js +1137 -0
  358. package/dist/post/settings.d.ts +485 -0
  359. package/dist/post/settings.js +416 -0
  360. package/dist/post/shaders.d.ts +25 -0
  361. package/dist/post/shaders.js +410 -0
  362. package/dist/post/ssr.d.ts +16 -0
  363. package/dist/post/ssr.js +155 -0
  364. package/dist/post/taa.d.ts +74 -0
  365. package/dist/post/taa.js +235 -0
  366. package/dist/post/white-balance.d.ts +25 -0
  367. package/dist/post/white-balance.js +98 -0
  368. package/dist/render/bindings.d.ts +98 -0
  369. package/dist/render/bindings.js +281 -0
  370. package/dist/render/blend.d.ts +13 -0
  371. package/dist/render/blend.js +26 -0
  372. package/dist/render/camera-2d.d.ts +72 -0
  373. package/dist/render/camera-2d.js +92 -0
  374. package/dist/render/camera.d.ts +302 -0
  375. package/dist/render/camera.js +671 -0
  376. package/dist/render/color.d.ts +16 -0
  377. package/dist/render/color.js +41 -0
  378. package/dist/render/compressed.d.ts +104 -0
  379. package/dist/render/compressed.js +248 -0
  380. package/dist/render/diagnostics.d.ts +15 -0
  381. package/dist/render/diagnostics.js +43 -0
  382. package/dist/render/dynamic-resolution.d.ts +70 -0
  383. package/dist/render/dynamic-resolution.js +126 -0
  384. package/dist/render/fake-gpu.d.ts +204 -0
  385. package/dist/render/fake-gpu.js +426 -0
  386. package/dist/render/flipbook.d.ts +56 -0
  387. package/dist/render/flipbook.js +87 -0
  388. package/dist/render/frame.d.ts +278 -0
  389. package/dist/render/frame.js +174 -0
  390. package/dist/render/fullscreen.d.ts +54 -0
  391. package/dist/render/fullscreen.js +91 -0
  392. package/dist/render/gpu-timer.d.ts +73 -0
  393. package/dist/render/gpu-timer.js +186 -0
  394. package/dist/render/index.d.ts +53 -0
  395. package/dist/render/index.js +29 -0
  396. package/dist/render/instance-list.d.ts +185 -0
  397. package/dist/render/instance-list.js +547 -0
  398. package/dist/render/lights.d.ts +181 -0
  399. package/dist/render/lights.js +233 -0
  400. package/dist/render/lod.d.ts +54 -0
  401. package/dist/render/lod.js +52 -0
  402. package/dist/render/material.d.ts +165 -0
  403. package/dist/render/material.js +292 -0
  404. package/dist/render/mesh.d.ts +284 -0
  405. package/dist/render/mesh.js +472 -0
  406. package/dist/render/mipmap.d.ts +16 -0
  407. package/dist/render/mipmap.js +121 -0
  408. package/dist/render/parallax.d.ts +50 -0
  409. package/dist/render/parallax.js +47 -0
  410. package/dist/render/pbr-wgsl.d.ts +31 -0
  411. package/dist/render/pbr-wgsl.js +119 -0
  412. package/dist/render/ping-pong.d.ts +42 -0
  413. package/dist/render/ping-pong.js +74 -0
  414. package/dist/render/renderer.d.ts +741 -0
  415. package/dist/render/renderer.js +2486 -0
  416. package/dist/render/scene-pipelines.d.ts +44 -0
  417. package/dist/render/scene-pipelines.js +92 -0
  418. package/dist/render/scene-target.d.ts +170 -0
  419. package/dist/render/scene-target.js +450 -0
  420. package/dist/render/shadow.d.ts +74 -0
  421. package/dist/render/shadow.js +208 -0
  422. package/dist/render/skin.d.ts +112 -0
  423. package/dist/render/skin.js +240 -0
  424. package/dist/render/snapshot.d.ts +36 -0
  425. package/dist/render/snapshot.js +34 -0
  426. package/dist/render/standard.d.ts +162 -0
  427. package/dist/render/standard.js +263 -0
  428. package/dist/render/texture.d.ts +142 -0
  429. package/dist/render/texture.js +228 -0
  430. package/dist/render/tile-layer.d.ts +110 -0
  431. package/dist/render/tile-layer.js +304 -0
  432. package/dist/render/transform.d.ts +115 -0
  433. package/dist/render/transform.js +318 -0
  434. package/dist/render/wgsl.d.ts +131 -0
  435. package/dist/render/wgsl.js +528 -0
  436. package/dist/save/codec.d.ts +49 -0
  437. package/dist/save/codec.js +169 -0
  438. package/dist/save/index.d.ts +8 -0
  439. package/dist/save/index.js +8 -0
  440. package/dist/save/journal.d.ts +24 -0
  441. package/dist/save/journal.js +102 -0
  442. package/dist/save/migrate.d.ts +15 -0
  443. package/dist/save/migrate.js +37 -0
  444. package/dist/save/schema.d.ts +72 -0
  445. package/dist/save/schema.js +154 -0
  446. package/dist/save/settings.d.ts +28 -0
  447. package/dist/save/settings.js +59 -0
  448. package/dist/save/slots.d.ts +56 -0
  449. package/dist/save/slots.js +200 -0
  450. package/dist/save/storage.d.ts +35 -0
  451. package/dist/save/storage.js +62 -0
  452. package/dist/save/store.d.ts +114 -0
  453. package/dist/save/store.js +269 -0
  454. package/dist/testing/fake-host.d.ts +103 -0
  455. package/dist/testing/fake-host.js +163 -0
  456. package/dist/testing/fixed-clock.d.ts +25 -0
  457. package/dist/testing/fixed-clock.js +30 -0
  458. package/dist/testing/index.d.ts +4 -0
  459. package/dist/testing/index.js +5 -0
  460. package/dist/testing/test-game.d.ts +76 -0
  461. package/dist/testing/test-game.js +92 -0
  462. package/dist/tween/ease.d.ts +77 -0
  463. package/dist/tween/ease.js +192 -0
  464. package/dist/tween/index.d.ts +8 -0
  465. package/dist/tween/index.js +7 -0
  466. package/dist/tween/timeline.d.ts +78 -0
  467. package/dist/tween/timeline.js +269 -0
  468. package/dist/tween/tween.d.ts +168 -0
  469. package/dist/tween/tween.js +320 -0
  470. package/dist/ui/anchor.d.ts +206 -0
  471. package/dist/ui/anchor.js +307 -0
  472. package/dist/ui/caption.d.ts +122 -0
  473. package/dist/ui/caption.js +286 -0
  474. package/dist/ui/cursor.d.ts +105 -0
  475. package/dist/ui/cursor.js +261 -0
  476. package/dist/ui/dom.d.ts +30 -0
  477. package/dist/ui/dom.js +92 -0
  478. package/dist/ui/floats.d.ts +86 -0
  479. package/dist/ui/floats.js +260 -0
  480. package/dist/ui/hud.d.ts +198 -0
  481. package/dist/ui/hud.js +431 -0
  482. package/dist/ui/index.d.ts +37 -0
  483. package/dist/ui/index.js +34 -0
  484. package/dist/ui/inventory-card.d.ts +52 -0
  485. package/dist/ui/inventory-card.js +173 -0
  486. package/dist/ui/inventory-context.d.ts +29 -0
  487. package/dist/ui/inventory-context.js +125 -0
  488. package/dist/ui/inventory-drag.d.ts +63 -0
  489. package/dist/ui/inventory-drag.js +394 -0
  490. package/dist/ui/inventory-grid.d.ts +66 -0
  491. package/dist/ui/inventory-grid.js +625 -0
  492. package/dist/ui/inventory-radial.d.ts +39 -0
  493. package/dist/ui/inventory-radial.js +168 -0
  494. package/dist/ui/inventory.d.ts +128 -0
  495. package/dist/ui/inventory.js +154 -0
  496. package/dist/ui/layout.d.ts +356 -0
  497. package/dist/ui/layout.js +856 -0
  498. package/dist/ui/link.d.ts +64 -0
  499. package/dist/ui/link.js +155 -0
  500. package/dist/ui/loading.d.ts +40 -0
  501. package/dist/ui/loading.js +157 -0
  502. package/dist/ui/loupe.d.ts +74 -0
  503. package/dist/ui/loupe.js +164 -0
  504. package/dist/ui/menu-nav.d.ts +33 -0
  505. package/dist/ui/menu-nav.js +28 -0
  506. package/dist/ui/minimap-canvas.d.ts +145 -0
  507. package/dist/ui/minimap-canvas.js +460 -0
  508. package/dist/ui/notify.d.ts +40 -0
  509. package/dist/ui/notify.js +141 -0
  510. package/dist/ui/orb.d.ts +53 -0
  511. package/dist/ui/orb.js +304 -0
  512. package/dist/ui/overlay.d.ts +213 -0
  513. package/dist/ui/overlay.js +394 -0
  514. package/dist/ui/padnav.d.ts +53 -0
  515. package/dist/ui/padnav.js +146 -0
  516. package/dist/ui/perf.d.ts +130 -0
  517. package/dist/ui/perf.js +329 -0
  518. package/dist/ui/rotate-card.d.ts +54 -0
  519. package/dist/ui/rotate-card.js +97 -0
  520. package/dist/ui/stack.d.ts +128 -0
  521. package/dist/ui/stack.js +312 -0
  522. package/dist/ui/styles.d.ts +13 -0
  523. package/dist/ui/styles.js +200 -0
  524. package/dist/ui/text-scale.d.ts +67 -0
  525. package/dist/ui/text-scale.js +102 -0
  526. package/dist/ui/theme.d.ts +70 -0
  527. package/dist/ui/theme.js +98 -0
  528. package/dist/ui/toast.d.ts +23 -0
  529. package/dist/ui/toast.js +46 -0
  530. package/dist/ui/tooltip.d.ts +89 -0
  531. package/dist/ui/tooltip.js +333 -0
  532. package/dist/ui/widgets-2.d.ts +134 -0
  533. package/dist/ui/widgets-2.js +399 -0
  534. package/dist/ui/widgets-3.d.ts +91 -0
  535. package/dist/ui/widgets-3.js +212 -0
  536. package/dist/ui/widgets.d.ts +34 -0
  537. package/dist/ui/widgets.js +50 -0
  538. package/dist/ui/world-panel/index.d.ts +5 -0
  539. package/dist/ui/world-panel/index.js +5 -0
  540. package/dist/ui/world-panel/layout.d.ts +38 -0
  541. package/dist/ui/world-panel/layout.js +68 -0
  542. package/dist/ui/world-panel/paint.d.ts +96 -0
  543. package/dist/ui/world-panel/paint.js +136 -0
  544. package/dist/ui/world-panel/panel.d.ts +235 -0
  545. package/dist/ui/world-panel/panel.js +762 -0
  546. package/dist/ui/world-panel/wgsl.d.ts +10 -0
  547. package/dist/ui/world-panel/wgsl.js +52 -0
  548. package/dist/ui/world-panel/widgets.d.ts +207 -0
  549. package/dist/ui/world-panel/widgets.js +569 -0
  550. package/dist/voxel/chunks.d.ts +77 -0
  551. package/dist/voxel/chunks.js +149 -0
  552. package/dist/voxel/grid.d.ts +84 -0
  553. package/dist/voxel/grid.js +223 -0
  554. package/dist/voxel/index.d.ts +22 -0
  555. package/dist/voxel/index.js +7 -0
  556. package/dist/voxel/mesher-worker.d.ts +14 -0
  557. package/dist/voxel/mesher-worker.js +47 -0
  558. package/dist/voxel/mesher.d.ts +73 -0
  559. package/dist/voxel/mesher.js +306 -0
  560. package/dist/voxel/ray.d.ts +32 -0
  561. package/dist/voxel/ray.js +73 -0
  562. package/dist/voxel/wgsl.d.ts +16 -0
  563. package/dist/voxel/wgsl.js +28 -0
  564. package/dist/voxel/worker-client.d.ts +79 -0
  565. package/dist/voxel/worker-client.js +122 -0
  566. package/package.json +177 -3
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The fx module's default randomness (ws/fx-4). Every random draw in `src/fx` goes through a
3
+ * core `Random`; an object built without one forks its own stream from one module default,
4
+ * seeded once with `FX_DEFAULT_SEED`. Forks are named by kind and creation index
5
+ * (`particles#0`, `decals#1`, …), so a page that builds the same objects in the same order gets
6
+ * the same numbers on every load. Pass `random` (`createRandom(seed)` or a fork of a game's
7
+ * own stream) to make an object independent of construction order.
8
+ */
9
+ import { type Random } from '../core/random.js';
10
+ /** The seed of the fx module's default stream. */
11
+ export declare const FX_DEFAULT_SEED = "thunderclap-fx";
12
+ /** Largest particle spawn seed (exactly representable in a `f32`). */
13
+ export declare const SPAWN_SEED_MAX = 16777214;
14
+ /** A fork of the module default (`FX_DEFAULT_SEED`) for one object of `kind`. */
15
+ export declare function defaultFxRandom(kind: string): Random;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The fx module's default randomness (ws/fx-4). Every random draw in `src/fx` goes through a
3
+ * core `Random`; an object built without one forks its own stream from one module default,
4
+ * seeded once with `FX_DEFAULT_SEED`. Forks are named by kind and creation index
5
+ * (`particles#0`, `decals#1`, …), so a page that builds the same objects in the same order gets
6
+ * the same numbers on every load. Pass `random` (`createRandom(seed)` or a fork of a game's
7
+ * own stream) to make an object independent of construction order.
8
+ */
9
+ import { createRandom } from '../core/random.js';
10
+ /** The seed of the fx module's default stream. */
11
+ export const FX_DEFAULT_SEED = 'thunderclap-fx';
12
+ /** Largest particle spawn seed (exactly representable in a `f32`). */
13
+ export const SPAWN_SEED_MAX = 16777214;
14
+ let root = null;
15
+ let forks = 0;
16
+ /** A fork of the module default (`FX_DEFAULT_SEED`) for one object of `kind`. */
17
+ export function defaultFxRandom(kind) {
18
+ root ??= createRandom(FX_DEFAULT_SEED);
19
+ return root.fork(`${kind}#${forks++}`);
20
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The sky shader: one fullscreen triangle at the far plane whose fragment reconstructs the view
3
+ * ray from the camera block and shades a procedural dome.
4
+ *
5
+ * View ray. The camera block carries `proj` and `view`, no inverse. A perspective projection
6
+ * (including an off-centre XR one) inverts analytically: with `vz = -1`,
7
+ * `ndc.x = (p00 * vx + p20 * vz) / (p23 * vz)` gives `vx = (p20 - p23 * ndc.x) / p00`, and y the
8
+ * same with `p11`, `p21`. The world direction is the view rotation's transpose applied to that
9
+ * (`dot(view[i].xyz, d)` per component, the view's columns). An orthographic projection
10
+ * (`p23 == 0`) has one view direction, the camera's forward (`-z`, or `+z` when `p22 > 0`, the
11
+ * 2D camera's convention). `skyRay` in `sky.ts` is the same
12
+ * math in TypeScript, tested against `Camera.screenToWorld`.
13
+ *
14
+ * Colour, all in linear space: zenith → horizon → ground by the ray's elevation; a band around
15
+ * the horizon mixes towards `lights.fog` (scaled by its density) so fogged geometry meets the
16
+ * sky; the sun disc (`sunSize` radians of angular radius, `sky.horizon.w`) and two glow lobes
17
+ * (`sunGlow`, `sky.ground.w`) tinted by `lights.sun_color` at `-lights.sun_dir`; when the sun
18
+ * is below the horizon the dome darkens and the stars (a hash of the direction on a grid of
19
+ * `density` cells per unit) appear. Without a sun (colour all zero) the dome is as set and the
20
+ * stars, if on, are full. The sun disc and the stars also go to the emissive target so bloom
21
+ * picks them up.
22
+ */
23
+ export declare const SKY_WGSL: string;
@@ -0,0 +1,127 @@
1
+ import { WGSL_GLOBALS, WGSL_LIGHTS, WGSL_NOISE } from '../render/wgsl.js';
2
+ /**
3
+ * The sky shader: one fullscreen triangle at the far plane whose fragment reconstructs the view
4
+ * ray from the camera block and shades a procedural dome.
5
+ *
6
+ * View ray. The camera block carries `proj` and `view`, no inverse. A perspective projection
7
+ * (including an off-centre XR one) inverts analytically: with `vz = -1`,
8
+ * `ndc.x = (p00 * vx + p20 * vz) / (p23 * vz)` gives `vx = (p20 - p23 * ndc.x) / p00`, and y the
9
+ * same with `p11`, `p21`. The world direction is the view rotation's transpose applied to that
10
+ * (`dot(view[i].xyz, d)` per component, the view's columns). An orthographic projection
11
+ * (`p23 == 0`) has one view direction, the camera's forward (`-z`, or `+z` when `p22 > 0`, the
12
+ * 2D camera's convention). `skyRay` in `sky.ts` is the same
13
+ * math in TypeScript, tested against `Camera.screenToWorld`.
14
+ *
15
+ * Colour, all in linear space: zenith → horizon → ground by the ray's elevation; a band around
16
+ * the horizon mixes towards `lights.fog` (scaled by its density) so fogged geometry meets the
17
+ * sky; the sun disc (`sunSize` radians of angular radius, `sky.horizon.w`) and two glow lobes
18
+ * (`sunGlow`, `sky.ground.w`) tinted by `lights.sun_color` at `-lights.sun_dir`; when the sun
19
+ * is below the horizon the dome darkens and the stars (a hash of the direction on a grid of
20
+ * `density` cells per unit) appear. Without a sun (colour all zero) the dome is as set and the
21
+ * stars, if on, are full. The sun disc and the stars also go to the emissive target so bloom
22
+ * picks them up.
23
+ */
24
+ export const SKY_WGSL = /* wgsl */ `
25
+ ${WGSL_GLOBALS}
26
+ ${WGSL_LIGHTS}
27
+ ${WGSL_NOISE}
28
+ struct SkyParams {
29
+ zenith: vec4f, // rgb, exposure
30
+ horizon: vec4f, // rgb, sun angular radius (radians)
31
+ ground: vec4f, // rgb, sun glow
32
+ stars: vec4f, // density, seed, enabled, night floor
33
+ };
34
+ @group(1) @binding(0) var<uniform> sky: SkyParams;
35
+
36
+ struct SkyOut {
37
+ @builtin(position) clip: vec4f,
38
+ @location(0) ndc: vec2f,
39
+ };
40
+
41
+ struct FragOut {
42
+ @location(0) color: vec4f,
43
+ @location(1) emissive: vec4f,
44
+ };
45
+
46
+ // One triangle covering clip space, at the far plane (z = 1): with depth compare less-equal
47
+ // and no depth write, geometry drawn before or after it always wins.
48
+ @vertex fn vs(@builtin(vertex_index) i: u32) -> SkyOut {
49
+ let x = f32(i32(i & 1u) * 4 - 1);
50
+ let y = f32(i32(i >> 1u) * 4 - 1);
51
+ var o: SkyOut;
52
+ o.clip = vec4f(x, y, 1.0, 1.0);
53
+ o.ndc = vec2f(x, y);
54
+ return o;
55
+ }
56
+
57
+ fn sky_ray(ndc: vec2f) -> vec3f {
58
+ let p = camera.proj;
59
+ var d = vec3f(0.0, 0.0, -1.0);
60
+ if (p[2][3] != 0.0) {
61
+ d.x = (p[2][0] - p[2][3] * ndc.x) / p[0][0];
62
+ d.y = (p[2][1] - p[2][3] * ndc.y) / p[1][1];
63
+ } else if (p[2][2] > 0.0) {
64
+ d.z = 1.0; // an orthographic view that looks down +z (the 2D camera)
65
+ }
66
+ let v = camera.view;
67
+ return normalize(vec3f(dot(v[0].xyz, d), dot(v[1].xyz, d), dot(v[2].xyz, d)));
68
+ }
69
+
70
+ fn sky_stars(d: vec3f, density: f32, seed: f32) -> f32 {
71
+ let p = d * density;
72
+ let cell = floor(p);
73
+ let key = cell.xy + vec2f(cell.z * 37.0 + seed, cell.z * 11.0 - seed);
74
+ let h = engine_hash22(key);
75
+ let hz = engine_hash21(key + 17.0);
76
+ let bright = engine_hash21(key + 41.0);
77
+ if (bright < 0.72) { return 0.0; }
78
+ let centre = normalize(cell + 0.5 + (vec3f(h, hz) - 0.5) * 0.8);
79
+ let r = 0.07 / density;
80
+ let c = dot(d, centre);
81
+ let edge = 1.0 - r * r * 0.5;
82
+ let s = smoothstep(edge, edge + r * r * 0.4, c);
83
+ return s * (0.4 + 0.6 * (bright - 0.72) / 0.28);
84
+ }
85
+
86
+ @fragment fn fs(in: SkyOut) -> FragOut {
87
+ let d = sky_ray(in.ndc);
88
+ let up = d.y;
89
+ let exposure = sky.zenith.w;
90
+
91
+ // The dome.
92
+ let above = mix(sky.horizon.rgb, sky.zenith.rgb, pow(saturate(up), 0.6));
93
+ let below = mix(sky.horizon.rgb, sky.ground.rgb, smoothstep(0.0, 0.25, -up));
94
+ var col = select(below, above, up >= 0.0);
95
+
96
+ // Horizon haze towards the fog colour, so fogged ground meets the sky.
97
+ let haze = saturate(lights.fog.w) * exp(-abs(up) * 6.0);
98
+ col = mix(col, lights.fog.rgb, haze);
99
+
100
+ // Day and night from the sun's elevation; no sun at all leaves the dome as set.
101
+ let to_sun = -lights.sun_dir;
102
+ let sun_color = lights.sun_color;
103
+ let has_sun = dot(sun_color, vec3f(1.0)) > 0.0;
104
+ let day = select(1.0, smoothstep(-0.12, 0.08, to_sun.y), has_sun);
105
+ col *= mix(sky.stars.w, 1.0, day);
106
+
107
+ // Sun disc and glow.
108
+ let cos_a = dot(d, to_sun);
109
+ let cos_disc = cos(sky.horizon.w);
110
+ let disc = smoothstep(cos_disc - 0.0004, cos_disc, cos_a) * smoothstep(-0.02, 0.0, up);
111
+ let glow = sky.ground.w * (0.3 * pow(saturate(cos_a), 16.0) + pow(saturate(cos_a), 256.0));
112
+ let sun = sun_color * (disc * 12.0 + glow);
113
+ col += sun;
114
+
115
+ // Stars at night.
116
+ var stars = 0.0;
117
+ if (sky.stars.z > 0.5) {
118
+ stars = sky_stars(d, sky.stars.x, sky.stars.y) * (1.0 - day) * smoothstep(-0.05, 0.05, up);
119
+ }
120
+ col += vec3f(stars * 2.0);
121
+
122
+ var o: FragOut;
123
+ o.color = vec4f(col * exposure, 1.0);
124
+ o.emissive = vec4f((sun_color * disc * 2.0 + vec3f(stars * 1.5)) * exposure, 1.0);
125
+ return o;
126
+ }
127
+ `;
@@ -0,0 +1,96 @@
1
+ import type { Camera } from '../render/camera.js';
2
+ import type { Drawable, Frame } from '../render/frame.js';
3
+ import type { Renderer } from '../render/renderer.js';
4
+ /** Floats in the sky's params block (4 × vec4f, 64 bytes). */
5
+ export declare const SKY_PARAMS_FLOATS = 16;
6
+ /** Starfield settings (`Sky.stars`). */
7
+ export interface SkyStars {
8
+ /** Grid cells per unit of direction; more cells, more and smaller stars. Default 24. */
9
+ density: number;
10
+ /** Shuffles the field. Default 0. */
11
+ seed: number;
12
+ }
13
+ export interface SkyOptions {
14
+ /** Linear RGB straight up. Default a clear blue. */
15
+ zenith?: ArrayLike<number>;
16
+ /** Linear RGB at the horizon. Default a pale haze. */
17
+ horizon?: ArrayLike<number>;
18
+ /** Linear RGB below the horizon (where no geometry covers the dome). Default a dark earth. */
19
+ ground?: ArrayLike<number>;
20
+ /** Angular radius of the sun disc, radians. Default 0.03. */
21
+ sunSize?: number;
22
+ /** Strength of the glow around the sun (0 for none). Default 1. */
23
+ sunGlow?: number;
24
+ /** Stars at night: `true` for the defaults, or `{ density, seed }`. Default off. */
25
+ stars?: boolean | Partial<SkyStars>;
26
+ /** Multiplier on the whole dome. Default 1. */
27
+ exposure?: number;
28
+ /**
29
+ * How dark the dome goes at night, as a fraction of its daytime colour (the floor of the
30
+ * day/night fade driven by the sun's elevation). Default 0.06. Raise it for brighter nights,
31
+ * lower it towards 0 for black skies behind the stars.
32
+ */
33
+ ambientFloor?: number;
34
+ }
35
+ /**
36
+ * A procedural sky: a gradient dome with a sun disc and glow that follow `frame.lights.sun`,
37
+ * horizon haze towards `frame.lights.fog.color`, and stars once the sun sets. One fullscreen
38
+ * triangle, no asset, no instance; `frame.drawable(sky)` draws it.
39
+ *
40
+ * It reads the sun and fog from the lights block the renderer uploads with every view, so its
41
+ * only upload is the 64-byte params block, written once per frame in `prepare`. The fields are
42
+ * live: mutate `zenith`, `sunSize`, `stars`... and the next frame shows it.
43
+ *
44
+ * Depth: under a depth camera the triangle sits at the far plane with depth compare
45
+ * `less-equal` and no depth write (the test-only state, `DepthMode` 1), so geometry drawn before
46
+ * or after it wins wherever it wrote depth and the sky fills the rest. Without depth (a 2D
47
+ * camera) it paints the whole view; give it the lowest `order` then. Nothing to cull.
48
+ */
49
+ export declare class Sky implements Drawable {
50
+ /** Linear RGB straight up. Live. */
51
+ readonly zenith: Float32Array<ArrayBuffer>;
52
+ /** Linear RGB at the horizon. Live. */
53
+ readonly horizon: Float32Array<ArrayBuffer>;
54
+ /** Linear RGB below the horizon. Live. */
55
+ readonly ground: Float32Array<ArrayBuffer>;
56
+ /** Angular radius of the sun disc, radians. Live. */
57
+ sunSize: number;
58
+ /** Glow strength around the sun. Live. */
59
+ sunGlow: number;
60
+ /** Starfield settings, or null for no stars. Live (replace or mutate). */
61
+ stars: SkyStars | null;
62
+ /** Multiplier on the whole dome. Live. */
63
+ exposure: number;
64
+ /** Night brightness as a fraction of day (`SkyOptions.ambientFloor`). Live. */
65
+ ambientFloor: number;
66
+ private readonly device;
67
+ private readonly params;
68
+ private readonly paramsBuffer;
69
+ private readonly group;
70
+ private readonly desc;
71
+ private readonly renderer;
72
+ /**
73
+ * Pipelines per depth format (null: none; a depth one tests without writing) × the view
74
+ * target's aux key, built on first use from `renderer.sceneTargets` (ws/render-10).
75
+ */
76
+ private readonly pipelines;
77
+ constructor(renderer: Renderer, opts?: SkyOptions);
78
+ /**
79
+ * Pack the live fields into the params block (`SKY_PARAMS_FLOATS` floats: zenith rgb +
80
+ * exposure, horizon rgb + sunSize, ground rgb + sunGlow, stars density, seed, enabled,
81
+ * ambientFloor) and
82
+ * upload it. Called by the renderer once per frame. No allocation.
83
+ */
84
+ prepare(_encoder: GPUCommandEncoder, _frame?: Frame): void;
85
+ /** Draw inside the scene pass: one 3-vertex draw, a depth pipeline when the frame has depth. */
86
+ draw(pass: GPURenderPassEncoder, frame?: Frame): void;
87
+ private pipelineFor;
88
+ destroy(): void;
89
+ }
90
+ /**
91
+ * The world-space view direction through clip point (`nx`, `ny`) (NDC, -1..1, y up) of
92
+ * `camera`, into `out` (normalised): the math the sky shader runs per pixel, from the camera's
93
+ * `projection` and `view` alone. A perspective projection is inverted analytically (its
94
+ * off-centre terms included); an orthographic one gives the camera's forward for every pixel.
95
+ */
96
+ export declare function skyRay(camera: Camera, nx: number, ny: number, out: Float32Array): Float32Array;
package/dist/fx/sky.js ADDED
@@ -0,0 +1,175 @@
1
+ import { auxSuffix, ScenePipelineCache, sceneVariant } from '../render/scene-pipelines.js';
2
+ import { createShaderModule } from '../render/wgsl.js';
3
+ import { SKY_WGSL } from './sky-wgsl.js';
4
+ /** Floats in the sky's params block (4 × vec4f, 64 bytes). */
5
+ export const SKY_PARAMS_FLOATS = 16;
6
+ const DEFAULT_ZENITH = [0.18, 0.38, 0.85];
7
+ const DEFAULT_HORIZON = [0.62, 0.72, 0.9];
8
+ const DEFAULT_GROUND = [0.22, 0.2, 0.18];
9
+ const DEFAULT_STARS = { density: 24, seed: 0 };
10
+ /**
11
+ * A procedural sky: a gradient dome with a sun disc and glow that follow `frame.lights.sun`,
12
+ * horizon haze towards `frame.lights.fog.color`, and stars once the sun sets. One fullscreen
13
+ * triangle, no asset, no instance; `frame.drawable(sky)` draws it.
14
+ *
15
+ * It reads the sun and fog from the lights block the renderer uploads with every view, so its
16
+ * only upload is the 64-byte params block, written once per frame in `prepare`. The fields are
17
+ * live: mutate `zenith`, `sunSize`, `stars`... and the next frame shows it.
18
+ *
19
+ * Depth: under a depth camera the triangle sits at the far plane with depth compare
20
+ * `less-equal` and no depth write (the test-only state, `DepthMode` 1), so geometry drawn before
21
+ * or after it wins wherever it wrote depth and the sky fills the rest. Without depth (a 2D
22
+ * camera) it paints the whole view; give it the lowest `order` then. Nothing to cull.
23
+ */
24
+ export class Sky {
25
+ /** Linear RGB straight up. Live. */
26
+ zenith = new Float32Array(3);
27
+ /** Linear RGB at the horizon. Live. */
28
+ horizon = new Float32Array(3);
29
+ /** Linear RGB below the horizon. Live. */
30
+ ground = new Float32Array(3);
31
+ /** Angular radius of the sun disc, radians. Live. */
32
+ sunSize;
33
+ /** Glow strength around the sun. Live. */
34
+ sunGlow;
35
+ /** Starfield settings, or null for no stars. Live (replace or mutate). */
36
+ stars;
37
+ /** Multiplier on the whole dome. Live. */
38
+ exposure;
39
+ /** Night brightness as a fraction of day (`SkyOptions.ambientFloor`). Live. */
40
+ ambientFloor;
41
+ device;
42
+ params;
43
+ paramsBuffer;
44
+ group;
45
+ desc;
46
+ renderer;
47
+ /**
48
+ * Pipelines per depth format (null: none; a depth one tests without writing) × the view
49
+ * target's aux key, built on first use from `renderer.sceneTargets` (ws/render-10).
50
+ */
51
+ pipelines = new ScenePipelineCache();
52
+ constructor(renderer, opts = {}) {
53
+ const device = renderer.device;
54
+ this.device = device;
55
+ this.renderer = renderer;
56
+ set3(this.zenith, opts.zenith ?? DEFAULT_ZENITH);
57
+ set3(this.horizon, opts.horizon ?? DEFAULT_HORIZON);
58
+ set3(this.ground, opts.ground ?? DEFAULT_GROUND);
59
+ this.sunSize = opts.sunSize ?? 0.03;
60
+ this.sunGlow = opts.sunGlow ?? 1;
61
+ this.exposure = opts.exposure ?? 1;
62
+ this.ambientFloor = opts.ambientFloor ?? 0.06;
63
+ const s = opts.stars;
64
+ this.stars = s
65
+ ? {
66
+ density: (s === true ? undefined : s.density) ?? DEFAULT_STARS.density,
67
+ seed: (s === true ? undefined : s.seed) ?? DEFAULT_STARS.seed,
68
+ }
69
+ : null;
70
+ this.params = new Float32Array(SKY_PARAMS_FLOATS);
71
+ this.paramsBuffer = device.createBuffer({
72
+ label: 'sky-params',
73
+ size: this.params.byteLength,
74
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
75
+ });
76
+ const layout = device.createBindGroupLayout({
77
+ label: 'sky-layout',
78
+ entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, buffer: {} }],
79
+ });
80
+ this.group = device.createBindGroup({
81
+ label: 'sky',
82
+ layout,
83
+ entries: [{ binding: 0, resource: { buffer: this.paramsBuffer } }],
84
+ });
85
+ const module = createShaderModule(device, SKY_WGSL, 'sky');
86
+ this.desc = {
87
+ label: 'sky',
88
+ layout: device.createPipelineLayout({ bindGroupLayouts: [renderer.globalsLayout, layout] }),
89
+ vertex: { module, entryPoint: 'vs' },
90
+ fragment: {
91
+ module,
92
+ entryPoint: 'fs',
93
+ targets: renderer.sceneTargets(),
94
+ },
95
+ primitive: { topology: 'triangle-list', cullMode: 'none' },
96
+ };
97
+ this.pipelines.set(null, renderer.target.auxKey, device.createRenderPipeline(this.desc));
98
+ }
99
+ /**
100
+ * Pack the live fields into the params block (`SKY_PARAMS_FLOATS` floats: zenith rgb +
101
+ * exposure, horizon rgb + sunSize, ground rgb + sunGlow, stars density, seed, enabled,
102
+ * ambientFloor) and
103
+ * upload it. Called by the renderer once per frame. No allocation.
104
+ */
105
+ prepare(_encoder, _frame) {
106
+ const p = this.params;
107
+ p[0] = this.zenith[0];
108
+ p[1] = this.zenith[1];
109
+ p[2] = this.zenith[2];
110
+ p[3] = this.exposure;
111
+ p[4] = this.horizon[0];
112
+ p[5] = this.horizon[1];
113
+ p[6] = this.horizon[2];
114
+ p[7] = this.sunSize;
115
+ p[8] = this.ground[0];
116
+ p[9] = this.ground[1];
117
+ p[10] = this.ground[2];
118
+ p[11] = this.sunGlow;
119
+ const s = this.stars;
120
+ p[12] = s ? s.density : 0;
121
+ p[13] = s ? s.seed : 0;
122
+ p[14] = s ? 1 : 0;
123
+ p[15] = this.ambientFloor;
124
+ this.device.queue.writeBuffer(this.paramsBuffer, 0, p);
125
+ }
126
+ /** Draw inside the scene pass: one 3-vertex draw, a depth pipeline when the frame has depth. */
127
+ draw(pass, frame) {
128
+ const fmt = frame?.depthFormat ?? null;
129
+ pass.setPipeline(this.pipelineFor(fmt, frame ? frame.auxKey : this.renderer.target.auxKey));
130
+ pass.setBindGroup(1, this.group);
131
+ pass.draw(3);
132
+ }
133
+ pipelineFor(format, aux) {
134
+ const p = this.pipelines.get(format, aux);
135
+ if (p)
136
+ return p;
137
+ return this.pipelines.set(format, aux, this.device.createRenderPipeline(sceneVariant(this.desc, this.renderer.sceneTargets(undefined, aux), `sky${format ? `:${format}` : ''}${auxSuffix(aux)}`, format ? { format, depthWriteEnabled: false, depthCompare: 'less-equal' } : undefined)));
138
+ }
139
+ destroy() {
140
+ this.paramsBuffer.destroy();
141
+ }
142
+ }
143
+ /**
144
+ * The world-space view direction through clip point (`nx`, `ny`) (NDC, -1..1, y up) of
145
+ * `camera`, into `out` (normalised): the math the sky shader runs per pixel, from the camera's
146
+ * `projection` and `view` alone. A perspective projection is inverted analytically (its
147
+ * off-centre terms included); an orthographic one gives the camera's forward for every pixel.
148
+ */
149
+ export function skyRay(camera, nx, ny, out) {
150
+ const p = camera.projection;
151
+ const v = camera.view;
152
+ // Column-major: p[c * 4 + r].
153
+ const p23 = p[11];
154
+ let dx = 0;
155
+ let dy = 0;
156
+ if (p23 !== 0) {
157
+ dx = (p[8] - p23 * nx) / p[0];
158
+ dy = (p[9] - p23 * ny) / p[5];
159
+ }
160
+ // Orthographic: every pixel looks along the camera's forward (+z for the 2D camera).
161
+ const dz = p23 === 0 && p[10] > 0 ? 1 : -1;
162
+ const wx = v[0] * dx + v[1] * dy + v[2] * dz;
163
+ const wy = v[4] * dx + v[5] * dy + v[6] * dz;
164
+ const wz = v[8] * dx + v[9] * dy + v[10] * dz;
165
+ const k = 1 / Math.hypot(wx, wy, wz);
166
+ out[0] = wx * k;
167
+ out[1] = wy * k;
168
+ out[2] = wz * k;
169
+ return out;
170
+ }
171
+ function set3(out, v) {
172
+ out[0] = v[0] ?? 0;
173
+ out[1] = v[1] ?? 0;
174
+ out[2] = v[2] ?? 0;
175
+ }
@@ -0,0 +1,143 @@
1
+ /**
2
+ * A canvas text atlas: strings rasterised once with `CanvasRenderingContext2D.fillText` into
3
+ * one square canvas, packed on shelves, cached by text and style, with least-recently-used
4
+ * eviction when the canvas is full. No GPU and no DOM beyond the canvas itself: the owner
5
+ * uploads `canvas` when `dirty` is set (`Billboards` does it once per frame at most).
6
+ */
7
+ /** How a string is drawn into the atlas. Colours are CSS colour strings (the canvas's). */
8
+ export interface TextStyle {
9
+ /** CSS font family (and weight), e.g. `'bold sans-serif'`. Default: the atlas's font. */
10
+ font?: string;
11
+ /** Font size in atlas px. Default 32. */
12
+ size?: number;
13
+ /** Fill colour. Default `'#fff'`. */
14
+ color?: string;
15
+ /** Outline colour; none when unset. */
16
+ stroke?: string;
17
+ /** Outline width in atlas px. Default 0 (none even with `stroke`). */
18
+ strokeWidth?: number;
19
+ /** Transparent px kept around the glyphs on every side. Default 2. */
20
+ padding?: number;
21
+ }
22
+ /**
23
+ * A rectangle of the atlas: the uv rect to sample (`u0, v0` top left, `u1, v1` bottom right, v
24
+ * down as in the canvas) and its size in atlas px, for a billboard's aspect ratio.
25
+ */
26
+ export interface AtlasRegion {
27
+ u0: number;
28
+ v0: number;
29
+ u1: number;
30
+ v1: number;
31
+ /** Size in atlas px. */
32
+ width: number;
33
+ height: number;
34
+ }
35
+ /** The subset of the canvas 2D context the atlas draws with (so tests can stub it). */
36
+ export interface AtlasContext2D {
37
+ font: string;
38
+ textBaseline: CanvasTextBaseline;
39
+ textAlign: CanvasTextAlign;
40
+ fillStyle: string | CanvasGradient | CanvasPattern;
41
+ strokeStyle: string | CanvasGradient | CanvasPattern;
42
+ lineWidth: number;
43
+ lineJoin: CanvasLineJoin;
44
+ measureText(text: string): {
45
+ width: number;
46
+ };
47
+ fillText(text: string, x: number, y: number): void;
48
+ strokeText(text: string, x: number, y: number): void;
49
+ clearRect(x: number, y: number, w: number, h: number): void;
50
+ }
51
+ /** The canvas the atlas draws into: an `OffscreenCanvas`, an `HTMLCanvasElement` or a stub. */
52
+ export interface AtlasCanvas {
53
+ width: number;
54
+ height: number;
55
+ getContext(kind: '2d'): AtlasContext2D | null;
56
+ }
57
+ export interface TextAtlasOptions {
58
+ /** Canvas side in px (square). Default 1024. */
59
+ size?: number;
60
+ /** Default font family for styles without one. Default `'sans-serif'`. */
61
+ font?: string;
62
+ /**
63
+ * The canvas to draw into. Default: an `OffscreenCanvas` when the platform has one, else a
64
+ * `document.createElement('canvas')`. Tests pass a stub with a fake 2D context.
65
+ */
66
+ canvas?: AtlasCanvas;
67
+ }
68
+ /**
69
+ * Text rendered once into a canvas and shared by every quad that shows it. `text(text, style)`
70
+ * returns the cached `AtlasRegion` or rasterises and packs a new one; when the canvas is full the
71
+ * least recently used shelf is cleared and reused. Read `dirty` and `canvas` to upload, then
72
+ * call `markUploaded()`.
73
+ */
74
+ export declare class TextAtlas {
75
+ readonly size: number;
76
+ readonly canvas: AtlasCanvas;
77
+ /** The canvas has text the GPU has not seen yet. */
78
+ dirty: boolean;
79
+ /** Strings currently cached. */
80
+ count: number;
81
+ /** Evictions so far (shelves cleared because the canvas was full). */
82
+ evictions: number;
83
+ private readonly ctx;
84
+ private readonly font;
85
+ private readonly cache;
86
+ private readonly shelves;
87
+ /** Next free y for a new shelf. */
88
+ private top;
89
+ private tick;
90
+ /** Owned cells made so far (their cache keys). */
91
+ private cells;
92
+ constructor(opts?: TextAtlasOptions);
93
+ /** Atlas px in use, as a share of the canvas (shelf area, 0..1). */
94
+ get used(): number;
95
+ /**
96
+ * The region for `text` in `style`: cached, or rasterised now. Returns `null` only when the
97
+ * string is wider or taller than the whole canvas.
98
+ */
99
+ text(text: string, style?: TextStyle): AtlasRegion | null;
100
+ /**
101
+ * An **owned** cell for text that changes (ws/fx-4): not shared through the cache, its width
102
+ * rounded up for headroom, the region covering the whole cell with `text` centred in it.
103
+ * Change its text with `rewrite`; `release` it when done. Evicted like any string when the
104
+ * canvas is full and it is the least recently used (`touch` keeps it). Returns `null` only
105
+ * when the text is larger than the whole canvas.
106
+ */
107
+ cell(text: string, style?: TextStyle): AtlasRegion | null;
108
+ /** The size in atlas px `cell(text, style)` would get, without placing anything. */
109
+ cellSize(text: string, style?: TextStyle): {
110
+ width: number;
111
+ height: number;
112
+ };
113
+ /**
114
+ * Redraw an owned cell with `text`, in place (the same region object, nothing allocated) when
115
+ * it fits the cell, else in a new wider cell (the old one released). Also a new cell when
116
+ * `cell` was evicted since. Returns `null` when the text is larger than the whole canvas.
117
+ */
118
+ rewrite(cell: AtlasRegion, text: string): AtlasRegion | null;
119
+ /** Give back an owned cell (a no-op for a cached string or one already released/evicted). */
120
+ release(cell: AtlasRegion): void;
121
+ /** Mark `region` as used now, so a live quad's text is not the first evicted. */
122
+ touch(region: AtlasRegion): void;
123
+ /** Is `region` still what it was made for (not evicted since)? */
124
+ has(region: AtlasRegion): boolean;
125
+ /** The owner uploaded `canvas`. */
126
+ markUploaded(): void;
127
+ /** Forget every string and clear the canvas. */
128
+ clear(): void;
129
+ private resolve;
130
+ private measure;
131
+ private lineHeight;
132
+ private makeCell;
133
+ /** Place, size and cache a `w × h` entry under `key`. */
134
+ private make;
135
+ /** Clear `e`'s rect and draw `text` centred in it. */
136
+ private draw;
137
+ /** Find or make room for a `w × h` rect: a fitting shelf, a new shelf, or an evicted one. */
138
+ private place;
139
+ private fit;
140
+ private alloc;
141
+ private evict;
142
+ private recycle;
143
+ }