@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,528 @@
1
+ import { BUFFER_BINDING_BASE } from './bindings.js';
2
+ import { reportGpuError } from './diagnostics.js';
3
+ import { VERTEX_LAYOUT_2D } from './mesh.js';
4
+ /**
5
+ * Create a shader module and surface compile errors with file/line context. Compilation is
6
+ * async in the browser; errors are logged as soon as they are known.
7
+ */
8
+ export function createShaderModule(device, code, label) {
9
+ const module = device.createShaderModule({ code, label });
10
+ module.getCompilationInfo().then((info) => {
11
+ if (!info.messages.length)
12
+ return;
13
+ const lines = code.split('\n');
14
+ for (const m of info.messages) {
15
+ const src = lines[m.lineNum - 1] ?? '';
16
+ const caret = `${' '.repeat(Math.max(0, m.linePos - 1))}^`;
17
+ const text = `[wgsl] ${label}:${m.lineNum}:${m.linePos} ${m.type}: ${m.message}\n ${src}\n ${caret}`;
18
+ if (m.type === 'error')
19
+ reportGpuError(text);
20
+ else
21
+ console.warn(text);
22
+ }
23
+ });
24
+ return module;
25
+ }
26
+ /**
27
+ * Per-frame engine bindings for every material and drawable, in `@group(0)`:
28
+ *
29
+ * - `@binding(0) globals`: `logicalSize`, `targetSize` (scene target px), `time`, `dt`.
30
+ * - `@binding(1) camera` (the camera block): `view`, `proj`, `view_proj` (world → clip),
31
+ * `camera_pos` (world eye position, w = 1), `viewport` (target px: x, y, w, h),
32
+ * `view_index` (`camera.viewIndex`: 0, or the eye index of an XR view), `inv_view_proj`
33
+ * (clip → world, the inverse of `view_proj`; `camera.invViewProj` on the CPU side),
34
+ * `prev_view_proj` and `prev_view` (last frame's unjittered `view_proj` and `view`) and
35
+ * `jitter` (clip-space dx, dy; the pixel offset x, y).
36
+ */
37
+ export const WGSL_GLOBALS = /* wgsl */ `
38
+ struct EngineGlobals {
39
+ logicalSize: vec2f,
40
+ targetSize: vec2f,
41
+ time: f32,
42
+ dt: f32,
43
+ _pad: vec2f,
44
+ };
45
+ @group(0) @binding(0) var<uniform> globals: EngineGlobals;
46
+ struct EngineCamera {
47
+ view: mat4x4f,
48
+ proj: mat4x4f,
49
+ view_proj: mat4x4f,
50
+ camera_pos: vec4f,
51
+ viewport: vec4f,
52
+ view_index: u32,
53
+ _pad0: u32, _pad1: u32, _pad2: u32,
54
+ inv_view_proj: mat4x4f,
55
+ prev_view_proj: mat4x4f,
56
+ prev_view: mat4x4f,
57
+ jitter: vec4f,
58
+ };
59
+ @group(0) @binding(1) var<uniform> camera: EngineCamera;
60
+ `;
61
+ /**
62
+ * The Lambert BRDF for `wgslLightLoop`: `N·L` clamped at 0, the reflected fraction of a light's
63
+ * colour before the albedo (the light's colour × this is what `engine_lambert` returns per light).
64
+ */
65
+ export const WGSL_LAMBERT_BRDF = 'vec3f(max(dot(normal, l), 0.0))';
66
+ /**
67
+ * Generate the engine light loop as a WGSL function `name(world_pos: vec3f, normal: vec3f,
68
+ * layer_mask: u32${params}) -> vec3f`: the sum over the lights whose `layers` share a bit with
69
+ * `layer_mask` of the light's colour × its attenuation × `brdf`. The sun (× `engine_shadow`),
70
+ * the `(1 - d/radius)²` point falloff and the spot cone (`engine_spot_cone` × the same falloff)
71
+ * are the loop's; the BRDF is the material's.
72
+ *
73
+ * WGSL has no function pointers, so the material supplies `brdf` as a WGSL expression that the
74
+ * loop body inlines once per light kind. In it, `l` is the unit direction from the surface to
75
+ * the light, `normal` and `world_pos` are the function's parameters and `params` (`', v: vec3f,
76
+ * f0: vec3f'` and so on; leading comma) adds whatever else it needs to the signature. The
77
+ * expression must be finite for any `l` (it is multiplied by 0 for lights that do not reach).
78
+ * `WGSL_LIGHTS` instantiates it as `engine_light_accum` with `WGSL_LAMBERT_BRDF`; `WGSL_PBR` as
79
+ * `engine_pbr_accum` with `engine_brdf(...)`. Generate rather than copy: the loop then changes
80
+ * in one place when the block gains a light kind.
81
+ */
82
+ export function wgslLightLoop(name, brdf, params = '') {
83
+ return /* wgsl */ `fn ${name}(world_pos: vec3f, normal: vec3f, layer_mask: u32${params}) -> vec3f {
84
+ var sum = vec3f(0.0);
85
+ if ((lights.sun_layers & layer_mask) != 0u) {
86
+ let l = -lights.sun_dir;
87
+ sum += lights.sun_color * (${brdf}) * engine_shadow(world_pos);
88
+ }
89
+ for (var i = 0u; i < lights.point_count; i++) {
90
+ if ((lights.point_layers[i >> 2u][i & 3u] & layer_mask) == 0u) { continue; }
91
+ let light = lights.points[i];
92
+ let to = light.position - world_pos;
93
+ let d = length(to);
94
+ let falloff = saturate(1.0 - d / max(light.radius, 1e-4));
95
+ if (falloff <= 0.0) { continue; }
96
+ let l = to / max(d, 1e-4);
97
+ sum += light.color * (falloff * falloff * (${brdf}));
98
+ }
99
+ for (var i = 0u; i < lights.spot_count; i++) {
100
+ let light = lights.spots[i];
101
+ if ((light.layers & layer_mask) == 0u) { continue; }
102
+ let to = light.position - world_pos;
103
+ let d = length(to);
104
+ let l = to / max(d, 1e-4);
105
+ let falloff = saturate(1.0 - d / max(light.radius, 1e-4));
106
+ if (falloff <= 0.0) { continue; }
107
+ let cone = engine_spot_cone(dot(-l, light.direction), light.cos_outer, light.cos_inner);
108
+ sum += light.color * (falloff * falloff * cone * (${brdf}));
109
+ }
110
+ return sum;
111
+ }`;
112
+ }
113
+ /**
114
+ * The lighting block, `@group(0) @binding(2)` (see `Lights` / `lights.ts`), in every material
115
+ * and drawable prelude: `lights.ambient`, `lights.point_count`, `lights.sun_dir` (the way
116
+ * the light travels), `lights.sun_color`, `lights.points[i]` (`position`, `radius`, `color`),
117
+ * `lights.sun_view_proj` (world → sun clip), `lights.shadow_params` (bias, map texel size,
118
+ * enabled, pad), `lights.fog` (rgb, density), `lights.fog_range` (near, far, pad, pad),
119
+ * `lights.spot_count`, `lights.sun_layers` (the sun's layer mask), `lights.point_layers`
120
+ * (`array<vec4u, 4>`: the mask of point `i` is `point_layers[i >> 2u][i & 3u]`) and
121
+ * `lights.spots[i]` (`position`, `radius`, `direction`, `cos_outer`, `color`, `cos_inner`,
122
+ * `layers`). The sun's shadow map (`texture_depth_2d`) and its comparison sampler sit at
123
+ * `@binding(3)` and `@binding(4)`; with no shadow pass a 1×1 depth texture is bound there.
124
+ *
125
+ * Helpers a game may call or ignore: `engine_point_lights(normal, world_pos)` sums the point
126
+ * lights' diffuse (Lambert × a smooth falloff that reaches zero at `radius`), all layers;
127
+ * `engine_spot_cone(cos_theta, cos_outer, cos_inner)` is a spot's cone factor;
128
+ * `engine_instance_layers(flags)` is the instance's layer bits from `VSOut.flags`;
129
+ * `engine_light_accum(world_pos, normal, layer_mask)` sums the sun (× `engine_shadow`), point
130
+ * and spot Lambert terms of every light whose `layers` share a bit with `layer_mask`;
131
+ * `engine_shadow(world_pos)` is the sun's visibility, 0..1 (3×3 PCF over the shadow map; 1
132
+ * outside the map or when there is no shadow pass); `engine_fog(color, world_pos)` blends
133
+ * `color` toward the fog colour by the distance to the camera (linear over `fog_range` when
134
+ * `far > near`, else exponential past `near`; identity when density is 0);
135
+ * `engine_lambert(normal, world_pos)` is ambient + `engine_light_accum` over every layer, so
136
+ * with the default block it returns `vec3f(1.0)` and `albedo * engine_lambert(...)` is unlit;
137
+ * `engine_lambert_layers(normal, world_pos, layer_mask)` is the same against the instance's
138
+ * layers (`engine_instance_layers(in.flags)`), so masked lights skip it.
139
+ *
140
+ * `engine_light_accum` is `wgslLightLoop('engine_light_accum', WGSL_LAMBERT_BRDF)`: the one
141
+ * light loop, generated with a Lambert BRDF; `WGSL_PBR` generates the same loop with its GGX BRDF.
142
+ */
143
+ export const WGSL_LIGHTS = /* wgsl */ `
144
+ struct EnginePointLight {
145
+ position: vec3f,
146
+ radius: f32,
147
+ color: vec3f,
148
+ _pad: f32,
149
+ };
150
+ struct EngineSpotLight {
151
+ position: vec3f,
152
+ radius: f32,
153
+ direction: vec3f,
154
+ cos_outer: f32,
155
+ color: vec3f,
156
+ cos_inner: f32,
157
+ layers: u32,
158
+ _pad0: u32,
159
+ _pad1: u32,
160
+ _pad2: u32,
161
+ };
162
+ struct EngineLights {
163
+ ambient: vec3f,
164
+ point_count: u32,
165
+ sun_dir: vec3f,
166
+ _pad0: f32,
167
+ sun_color: vec3f,
168
+ _pad1: f32,
169
+ points: array<EnginePointLight, 16>,
170
+ sun_view_proj: mat4x4f,
171
+ shadow_params: vec4f,
172
+ fog: vec4f,
173
+ fog_range: vec4f,
174
+ spot_count: u32,
175
+ sun_layers: u32,
176
+ _pad2: vec2u,
177
+ point_layers: array<vec4u, 4>,
178
+ spots: array<EngineSpotLight, 8>,
179
+ };
180
+ @group(0) @binding(2) var<uniform> lights: EngineLights;
181
+ @group(0) @binding(3) var engine_shadow_map: texture_depth_2d;
182
+ @group(0) @binding(4) var engine_shadow_sampler: sampler_comparison;
183
+ fn engine_point_lights(normal: vec3f, world_pos: vec3f) -> vec3f {
184
+ var sum = vec3f(0.0);
185
+ for (var i = 0u; i < lights.point_count; i++) {
186
+ let l = lights.points[i];
187
+ let to = l.position - world_pos;
188
+ let d = length(to);
189
+ let falloff = saturate(1.0 - d / max(l.radius, 1e-4));
190
+ let diffuse = max(dot(normal, to / max(d, 1e-4)), 0.0);
191
+ sum += l.color * (falloff * falloff * diffuse);
192
+ }
193
+ return sum;
194
+ }
195
+ fn engine_shadow(world_pos: vec3f) -> f32 {
196
+ if (lights.shadow_params.z == 0.0) { return 1.0; }
197
+ let clip = lights.sun_view_proj * vec4f(world_pos, 1.0);
198
+ let ndc = clip.xyz / clip.w;
199
+ if (any(abs(ndc.xy) > vec2f(1.0)) || ndc.z < 0.0 || ndc.z > 1.0) { return 1.0; }
200
+ let uv = vec2f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5);
201
+ let depth = ndc.z - lights.shadow_params.x;
202
+ let texel = lights.shadow_params.y;
203
+ var lit = 0.0;
204
+ for (var y = -1; y <= 1; y++) {
205
+ for (var x = -1; x <= 1; x++) {
206
+ let o = vec2f(f32(x), f32(y)) * texel;
207
+ lit += textureSampleCompareLevel(engine_shadow_map, engine_shadow_sampler, uv + o, depth);
208
+ }
209
+ }
210
+ return lit / 9.0;
211
+ }
212
+ fn engine_fog(color: vec3f, world_pos: vec3f) -> vec3f {
213
+ let density = lights.fog.w;
214
+ if (density == 0.0) { return color; }
215
+ let d = distance(world_pos, camera.camera_pos.xyz);
216
+ let near = lights.fog_range.x;
217
+ let far = lights.fog_range.y;
218
+ let linear = saturate((d - near) / max(far - near, 1e-4)) * saturate(density);
219
+ let expo = 1.0 - exp(-density * max(d - near, 0.0));
220
+ let f = select(expo, linear, far > near);
221
+ return mix(color, lights.fog.rgb, f);
222
+ }
223
+ fn engine_spot_cone(cos_theta: f32, cos_outer: f32, cos_inner: f32) -> f32 {
224
+ let t = saturate((cos_theta - cos_outer) / max(cos_inner - cos_outer, 1e-4));
225
+ return t * t * (3.0 - 2.0 * t);
226
+ }
227
+ fn engine_instance_layers(flags: u32) -> u32 {
228
+ return flags >> 1u;
229
+ }
230
+ ${wgslLightLoop('engine_light_accum', WGSL_LAMBERT_BRDF)}
231
+ fn engine_lambert_layers(normal: vec3f, world_pos: vec3f, layer_mask: u32) -> vec3f {
232
+ return lights.ambient + engine_light_accum(world_pos, normal, layer_mask);
233
+ }
234
+ fn engine_lambert(normal: vec3f, world_pos: vec3f) -> vec3f {
235
+ return engine_lambert_layers(normal, world_pos, 0xffffffffu);
236
+ }
237
+ `;
238
+ /** Hash / value-noise / fbm helpers available to every material and fullscreen pass. */
239
+ export const WGSL_NOISE = /* wgsl */ `
240
+ fn engine_hash21(p: vec2f) -> f32 {
241
+ var p3 = fract(vec3f(p.x, p.y, p.x) * 0.1031);
242
+ p3 += dot(p3, p3.yzx + 33.33);
243
+ return fract((p3.x + p3.y) * p3.z);
244
+ }
245
+ fn engine_hash22(p: vec2f) -> vec2f {
246
+ var p3 = fract(vec3f(p.x, p.y, p.x) * vec3f(0.1031, 0.1030, 0.0973));
247
+ p3 += dot(p3, p3.yzx + 33.33);
248
+ return fract((p3.xx + p3.yz) * p3.zy);
249
+ }
250
+ fn engine_noise(p: vec2f) -> f32 {
251
+ let i = floor(p);
252
+ let f = fract(p);
253
+ let u = f * f * (3.0 - 2.0 * f);
254
+ let a = engine_hash21(i);
255
+ let b = engine_hash21(i + vec2f(1.0, 0.0));
256
+ let c = engine_hash21(i + vec2f(0.0, 1.0));
257
+ let d = engine_hash21(i + vec2f(1.0, 1.0));
258
+ return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
259
+ }
260
+ fn engine_fbm(p: vec2f, octaves: i32) -> f32 {
261
+ var v = 0.0;
262
+ var amp = 0.5;
263
+ var q = p;
264
+ for (var i = 0; i < octaves; i++) {
265
+ v += amp * engine_noise(q);
266
+ q = q * 2.03 + vec2f(17.1, 9.2);
267
+ amp *= 0.5;
268
+ }
269
+ return v;
270
+ }
271
+ fn engine_luma(c: vec3f) -> f32 {
272
+ return dot(c, vec3f(0.2126, 0.7152, 0.0722));
273
+ }
274
+ `;
275
+ /** The `SkinPalette` binding inside the material's group: `@group(1) @binding(16)`. */
276
+ export const SKIN_PALETTE_BINDING = BUFFER_BINDING_BASE;
277
+ /**
278
+ * GPU skinning, emitted by `materialPrelude` for a layout with `skinned: true` (after
279
+ * `VertexIn`, which it reads). The palette is the material's storage buffer slot 0
280
+ * (`SkinPalette.buffer` passed as `buffers: [palette.buffer]`): a header (`joints` per
281
+ * instance, `instances`, `history`) and `rows`, three `vec4f` rows per joint (row-major 3×4, the layout
282
+ * `anim`'s `skinMatrices` writes), instance after instance. `engine_skin(v, position, normal)`
283
+ * sums the four weighted joint matrices of the vertex (`v.joints`, `v.weights`) for the
284
+ * instance's palette slot `u32(v.params.w)` and applies them to an object-space position and
285
+ * normal, before the instance matrix. A weight of 0 skips the fetch.
286
+ */
287
+ export const WGSL_SKIN = /* wgsl */ `struct EngineSkinPalette {
288
+ joints: u32,
289
+ instances: u32,
290
+ history: u32,
291
+ _pad1: u32,
292
+ rows: array<vec4f>,
293
+ };
294
+ @group(1) @binding(${SKIN_PALETTE_BINDING}) var<storage, read> engine_skin_palette: EngineSkinPalette;
295
+ struct EngineSkinned {
296
+ position: vec3f,
297
+ normal: vec3f,
298
+ };
299
+ fn engine_skin(v: VertexIn, position: vec3f, normal: vec3f) -> EngineSkinned {
300
+ let base = u32(v.params.w) * engine_skin_palette.joints * 3u;
301
+ let p = vec4f(position, 1.0);
302
+ var skinned: EngineSkinned;
303
+ skinned.position = vec3f(0.0);
304
+ skinned.normal = vec3f(0.0);
305
+ for (var k = 0u; k < 4u; k++) {
306
+ let w = v.weights[k];
307
+ if (w == 0.0) { continue; }
308
+ let r = base + v.joints[k] * 3u;
309
+ let r0 = engine_skin_palette.rows[r];
310
+ let r1 = engine_skin_palette.rows[r + 1u];
311
+ let r2 = engine_skin_palette.rows[r + 2u];
312
+ skinned.position += w * vec3f(dot(r0, p), dot(r1, p), dot(r2, p));
313
+ skinned.normal += w * vec3f(dot(r0.xyz, normal), dot(r1.xyz, normal), dot(r2.xyz, normal));
314
+ }
315
+ return skinned;
316
+ }
317
+ // The previous frame's skinned position from the palette's history block (SkinPalette
318
+ // with history), w = 1; w = 0 when the palette keeps none (velocity reads zero).
319
+ fn engine_skin_previous(v: VertexIn, position: vec3f) -> vec4f {
320
+ if (engine_skin_palette.history == 0u) { return vec4f(0.0); }
321
+ let base = (engine_skin_palette.instances + u32(v.params.w)) * engine_skin_palette.joints * 3u;
322
+ let p = vec4f(position, 1.0);
323
+ var out = vec3f(0.0);
324
+ for (var k = 0u; k < 4u; k++) {
325
+ let w = v.weights[k];
326
+ if (w == 0.0) { continue; }
327
+ let r = base + v.joints[k] * 3u;
328
+ out += w * vec3f(dot(engine_skin_palette.rows[r], p), dot(engine_skin_palette.rows[r + 1u], p), dot(engine_skin_palette.rows[r + 2u], p));
329
+ }
330
+ return vec4f(out, 1.0);
331
+ }`;
332
+ /** The plain variant: what every material compiled with before aux targets. */
333
+ export const PLAIN_VARIANT = Object.freeze({});
334
+ /**
335
+ * Three vertex locations in 10..15 the layout's attributes leave free, for the previous-matrix
336
+ * lane (`prevLane`), as `[p0, p1, p2]`.
337
+ */
338
+ export function prevLaneLocations(layout) {
339
+ const used = new Set();
340
+ for (const a of layout.buffer.attributes)
341
+ used.add(a.shaderLocation);
342
+ const out = [];
343
+ for (let loc = 10; loc <= 15 && out.length < 3; loc++)
344
+ if (!used.has(loc))
345
+ out.push(loc);
346
+ if (out.length < 3)
347
+ throw new Error(`layout ${layout.name}: no free locations for a previous-matrix lane`);
348
+ return [out[0], out[1], out[2]];
349
+ }
350
+ /** The previous-matrix vertex buffer layout (slot 2) for `layout`: 48 bytes per instance. */
351
+ export function prevLaneBufferLayout(layout) {
352
+ let lane = laneLayouts.get(layout);
353
+ if (lane)
354
+ return lane;
355
+ const [a, b, c] = prevLaneLocations(layout);
356
+ lane = {
357
+ arrayStride: 48,
358
+ stepMode: 'instance',
359
+ attributes: [
360
+ { shaderLocation: a, offset: 0, format: 'float32x4' },
361
+ { shaderLocation: b, offset: 16, format: 'float32x4' },
362
+ { shaderLocation: c, offset: 32, format: 'float32x4' },
363
+ ],
364
+ };
365
+ laneLayouts.set(layout, lane);
366
+ return lane;
367
+ }
368
+ const laneLayouts = new WeakMap();
369
+ /**
370
+ * Prelude prepended to every material, generated per vertex layout (and `PreludeVariant`).
371
+ * Declares `VertexIn` (the layout's vertex fields plus the 28-float instance: 3×4 world matrix
372
+ * rows `m0..m2`, `uvRect`, `tint`, `params`, `misc` = emissive, flags, size.xy), the default
373
+ * vertex entry `vs_main`, the `VSOut` varyings (`flags` is the instance's flag bits: bit 0 set
374
+ * means `receiveShadow: false`, bits 1..23 are its layers; `tangent` the world-space file
375
+ * tangent, w = 0 without one; `uv1` the second uv set, `uv` without one) and the `FragOut` MRT
376
+ * struct.
377
+ *
378
+ * Helpers: `engine_local_position(v)` / `engine_local_normal(v)` / `engine_local_tangent(v)`
379
+ * (object space; skinned for a `skinned` layout), `engine_world_position(v)`,
380
+ * `engine_previous_world_position(v)` (last frame's, `vec4f`, w = 0 when unknown),
381
+ * `engine_vertex(v)`, `engine_velocity(in)` (screen-space uv motion since last frame, zero
382
+ * without a velocity target) and `engine_write_aux(&o, rough_metal, velocity)` (fills the
383
+ * target's aux outputs, a no-op without them); the lighting block and `engine_lambert` /
384
+ * `engine_point_lights` from `WGSL_LIGHTS`; `WGSL_SKIN` (`engine_skin`, the palette binding)
385
+ * for a skinned layout only. The text for the 2D and 3D layouts does not change with skinning
386
+ * (E-008).
387
+ */
388
+ export function materialPrelude(layout, variant = PLAIN_VARIANT) {
389
+ const velocity = variant.velocity === true;
390
+ const prevLane = variant.prevLane === true;
391
+ const roughMetal = variant.roughMetal === true;
392
+ let auxFields = '';
393
+ let auxLoc = 2;
394
+ if (roughMetal)
395
+ auxFields += `\n @location(${auxLoc++}) rough_metal: vec2f,`;
396
+ if (velocity)
397
+ auxFields += `\n @location(${auxLoc++}) velocity: vec2f,`;
398
+ let laneFields = '';
399
+ if (prevLane) {
400
+ const [a, b, c] = prevLaneLocations(layout);
401
+ laneFields = `\n @location(${a}) p0: vec4f,\n @location(${b}) p1: vec4f,\n @location(${c}) p2: vec4f,`;
402
+ }
403
+ const prevRows = prevLane ? 'v.p0, v.p1, v.p2' : 'v.m0, v.m1, v.m2';
404
+ const prevPos = layout.wgslPreviousPosition ?? 'vec4f(engine_local_position(v), 1.0)';
405
+ return /* wgsl */ `
406
+ ${WGSL_GLOBALS}
407
+ ${WGSL_LIGHTS}
408
+ ${WGSL_NOISE}
409
+ struct VertexIn {
410
+ ${layout.wgslFields}
411
+ @location(3) m0: vec4f,
412
+ @location(4) m1: vec4f,
413
+ @location(5) m2: vec4f,
414
+ @location(6) uvRect: vec4f,
415
+ @location(7) tint: vec4f,
416
+ @location(8) params: vec4f,
417
+ @location(9) misc: vec4f,${laneFields}
418
+ };
419
+
420
+ struct VSOut {
421
+ @builtin(position) clip: vec4f,
422
+ @location(0) uv: vec2f,
423
+ @location(1) local: vec2f,
424
+ @location(2) color: vec4f,
425
+ @location(3) params: vec4f,
426
+ @location(4) world: vec2f,
427
+ @location(5) emissive: f32,
428
+ @location(6) size: vec2f,
429
+ @location(7) normal: vec3f,
430
+ @location(8) worldPos: vec3f,
431
+ @location(9) @interpolate(flat) flags: u32,
432
+ @location(10) tangent: vec4f,
433
+ @location(12) uv1: vec2f,${velocity ? '\n @location(11) prev_clip: vec4f,' : ''}
434
+ };
435
+
436
+ struct FragOut {
437
+ @location(0) color: vec4f,
438
+ @location(1) emissive: vec4f,${auxFields}
439
+ };
440
+ ${layout.skinned ? `\n${WGSL_SKIN}\n` : ''}
441
+ fn engine_local_position(v: VertexIn) -> vec3f {
442
+ return ${layout.wgslPosition};
443
+ }
444
+
445
+ fn engine_local_normal(v: VertexIn) -> vec3f {
446
+ return ${layout.wgslNormal};
447
+ }
448
+
449
+ fn engine_local_tangent(v: VertexIn) -> vec4f {
450
+ return ${layout.wgslTangent ?? 'vec4f(0.0)'};
451
+ }
452
+
453
+ fn engine_world_position(v: VertexIn) -> vec3f {
454
+ let p = vec4f(engine_local_position(v), 1.0);
455
+ return vec3f(dot(v.m0, p), dot(v.m1, p), dot(v.m2, p));
456
+ }
457
+
458
+ fn engine_previous_world_position(v: VertexIn) -> vec4f {
459
+ let lp = ${prevPos};
460
+ let p = vec4f(lp.xyz, 1.0);
461
+ let rows = array<vec4f, 3>(${prevRows});
462
+ return vec4f(dot(rows[0], p), dot(rows[1], p), dot(rows[2], p), lp.w);
463
+ }
464
+
465
+ fn engine_vertex(v: VertexIn) -> VSOut {
466
+ let world3 = engine_world_position(v);
467
+ let world = world3.xy;
468
+ let n = engine_local_normal(v);
469
+ let t = engine_local_tangent(v);
470
+ var o: VSOut;
471
+ o.clip = camera.view_proj * vec4f(world3, 1.0);
472
+ o.uv = mix(v.uvRect.xy, v.uvRect.zw, v.uv);
473
+ o.local = v.uv;
474
+ o.color = v.color * v.tint;
475
+ o.params = v.params;
476
+ o.world = world;
477
+ o.emissive = v.misc.x;
478
+ o.size = v.misc.zw;
479
+ o.normal = normalize(vec3f(dot(v.m0.xyz, n), dot(v.m1.xyz, n), dot(v.m2.xyz, n)));
480
+ o.worldPos = world3;
481
+ o.flags = u32(v.misc.y);
482
+ o.tangent = vec4f(vec3f(dot(v.m0.xyz, t.xyz), dot(v.m1.xyz, t.xyz), dot(v.m2.xyz, t.xyz)), t.w);
483
+ o.uv1 = mix(v.uvRect.xy, v.uvRect.zw, ${layout.wgslUv1 ?? 'v.uv'});${velocity
484
+ ? `
485
+ let prev = engine_previous_world_position(v);
486
+ o.prev_clip = select(vec4f(0.0), camera.prev_view_proj * vec4f(prev.xyz, 1.0), prev.w != 0.0);`
487
+ : ''}
488
+ return o;
489
+ }
490
+
491
+ // Screen-space motion since the previous frame in uv units (+x right, +y down), jitter
492
+ // removed; zero when the target has no velocity attachment or the previous position is unknown.
493
+ fn engine_velocity(in: VSOut) -> vec2f {${velocity
494
+ ? `
495
+ if (in.prev_clip.w == 0.0) { return vec2f(0.0); }
496
+ let cur = (in.clip.xy - camera.viewport.xy) / camera.viewport.zw - camera.jitter.xy * vec2f(0.5, -0.5);
497
+ let pn = in.prev_clip.xy / in.prev_clip.w;
498
+ let prev = vec2f(pn.x * 0.5 + 0.5, 0.5 - pn.y * 0.5);
499
+ return cur - prev;`
500
+ : '\n return vec2f(0.0);'}
501
+ }
502
+
503
+ // Write the aux outputs the target has (roughness, metalness; velocity); nothing otherwise.
504
+ fn engine_write_aux(o: ptr<function, FragOut>, rough_metal: vec2f, velocity: vec2f) {${roughMetal ? '\n (*o).rough_metal = rough_metal;' : ''}${velocity ? '\n (*o).velocity = velocity;' : ''}
505
+ }
506
+
507
+ @vertex fn vs_main(v: VertexIn) -> VSOut {
508
+ return engine_vertex(v);
509
+ }
510
+ `;
511
+ }
512
+ /** The material prelude for the 2D vertex layout (what every 2D material compiles with). */
513
+ export const WGSL_MATERIAL_PRELUDE = materialPrelude(VERTEX_LAYOUT_2D);
514
+ /** Prelude for fullscreen passes: `vs_fullscreen` emits one triangle covering the target. */
515
+ export const WGSL_FULLSCREEN_PRELUDE = /* wgsl */ `
516
+ ${WGSL_NOISE}
517
+ struct FullscreenIn {
518
+ @builtin(position) pos: vec4f,
519
+ @location(0) uv: vec2f,
520
+ };
521
+ @vertex fn vs_fullscreen(@builtin(vertex_index) i: u32) -> FullscreenIn {
522
+ let p = vec2f(f32((i << 1u) & 2u), f32(i & 2u));
523
+ var o: FullscreenIn;
524
+ o.pos = vec4f(p * 2.0 - 1.0, 0.0, 1.0);
525
+ o.uv = vec2f(p.x, 1.0 - p.y);
526
+ return o;
527
+ }
528
+ `;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Save envelope, the typed-array JSON codec and the export/import string codec.
3
+ *
4
+ * Stored value: JSON `{ "v": <version>, "t": <savedAt ms>, "d": <data> }`.
5
+ * Export string: `TC1.<game>.<checksum>.<base64url(envelope JSON)>`. The checksum
6
+ * (FNV-1a, hex) catches truncated copy-paste; it is not tamper protection.
7
+ *
8
+ * Typed arrays inside the data are stored as `{ "$b": <base64url bytes>, "$t"?: <kind> }`
9
+ * (`$t` omitted for `Uint8Array`) by `saveReplacer` and turned back by `saveReviver`, so a
10
+ * tilemap or a voxel chunk never goes through a JSON number array. Bytes are in platform byte
11
+ * order (little-endian everywhere WebGPU runs). A plain object of the player's data that has
12
+ * its own `$b` key is escaped as `$$b` (one more `$` per level) and unescaped on load.
13
+ */
14
+ export interface Envelope {
15
+ v: number;
16
+ t: number;
17
+ d: unknown;
18
+ }
19
+ export declare function isEnvelope(x: unknown): x is Envelope;
20
+ /** 32-bit FNV-1a over UTF-16 code units, as 8 hex chars. */
21
+ export declare function fnv1a(text: string): string;
22
+ /** Element kinds a typed array can be tagged with in stored JSON. */
23
+ export type TypedKind = 'u8' | 'u16' | 'u32' | 'i8' | 'i16' | 'i32' | 'f32' | 'f64';
24
+ export type TypedArrayOf<K extends TypedKind> = K extends 'u8' ? Uint8Array : K extends 'u16' ? Uint16Array : K extends 'u32' ? Uint32Array : K extends 'i8' ? Int8Array : K extends 'i16' ? Int16Array : K extends 'i32' ? Int32Array : K extends 'f32' ? Float32Array : Float64Array;
25
+ type TypedCtor = {
26
+ new (buffer: ArrayBuffer, byteOffset?: number, length?: number): ArrayBufferView;
27
+ readonly BYTES_PER_ELEMENT: number;
28
+ };
29
+ /** Typed-array kind → constructor. Internal: `schema.ts` and the tests import it from here. */
30
+ export declare const TYPED_KIND_CTORS: Record<TypedKind, TypedCtor>;
31
+ /** The tag kind for `value` if it is one of the eight supported typed arrays, else null. */
32
+ export declare function typedKindOf(value: unknown): TypedKind | null;
33
+ /**
34
+ * `JSON.stringify` replacer: typed arrays become `{ $b, $t? }`; a plain object with a key
35
+ * matching `/^\$+b$/` gets that key prefixed with one more `$`.
36
+ */
37
+ export declare function saveReplacer(_key: string, value: unknown): unknown;
38
+ /** `JSON.parse` reviver undoing `saveReplacer`. Bad tags (damaged base64) are left as objects. */
39
+ export declare function saveReviver(_key: string, value: unknown): unknown;
40
+ export declare function encodeExport(game: string, env: Envelope): string;
41
+ export type DecodeResult = {
42
+ ok: true;
43
+ envelope: Envelope;
44
+ } | {
45
+ ok: false;
46
+ error: string;
47
+ };
48
+ export declare function decodeExport(game: string, text: string): DecodeResult;
49
+ export {};