@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,162 @@
1
+ import type { Material } from './material.js';
2
+ import type { Renderer } from './renderer.js';
3
+ import type { SkinPalette } from './skin.js';
4
+ import { type SamplerKind, type TextureLike } from './texture.js';
5
+ /**
6
+ * The standard physically based material (`createStandardMaterial`): base colour,
7
+ * metallic-roughness, normal, occlusion and emissive maps with factors, over every light of the
8
+ * engine's block (sun with its shadow, point and spot lights masked against the instance's
9
+ * layers, fog) through `engine_pbr_layers` (`WGSL_PBR`, the shared light loop). Every map is
10
+ * optional: a missing one is a 1×1 `defaultTextures` entry (white, white, flat normal, white,
11
+ * black), so any subset works.
12
+ * Texture conventions follow glTF: `metallicRoughness` has roughness in G and metallic in B,
13
+ * `occlusion` is in R, the normal map is +Y up (OpenGL / glTF), `baseColor` and `emissive` are
14
+ * sRGB and the data maps linear (`textureFromSource(src, label, { linear: true })`).
15
+ */
16
+ export interface StandardMaterialDesc {
17
+ /** Pipeline / bind group label. Default `name`, else `'standard'`. */
18
+ label?: string;
19
+ /** `Material.name` (a file's material name). Default: the label. */
20
+ name?: string;
21
+ /** `MaterialDesc.depthTest`: false draws over the scene on its layer (a panel in a room). */
22
+ depthTest?: boolean;
23
+ /** sRGB colour with alpha; multiplied by `baseColorFactor` and the instance colour × tint. */
24
+ baseColor?: TextureLike;
25
+ /** Linear RGBA, default `[1, 1, 1, 1]`. */
26
+ baseColorFactor?: ArrayLike<number>;
27
+ /** Linear; G = roughness, B = metallic, each multiplied by its factor. */
28
+ metallicRoughness?: TextureLike;
29
+ /** 0 (dielectric) .. 1 (metal). Default 0. */
30
+ metallic?: number;
31
+ /** 0 (mirror) .. 1 (matte). Default 0.5. */
32
+ roughness?: number;
33
+ /** Tangent-space normal map, linear, +Y up; applied without mesh tangents (derivatives). */
34
+ normal?: TextureLike;
35
+ /** Scales the normal map's xy. Default 1. */
36
+ normalScale?: number;
37
+ /** Linear; R darkens the ambient term only. */
38
+ occlusion?: TextureLike;
39
+ /** How much of the occlusion map applies: `ao = mix(1, R, strength)`. Default 1. */
40
+ occlusionStrength?: number;
41
+ /** sRGB; × `emissiveFactor`, written to the emissive target (bloom), not the colour. */
42
+ emissive?: TextureLike;
43
+ /** Linear RGB. Default `[1, 1, 1]` when `emissive` is given, else `[0, 0, 0]`. */
44
+ emissiveFactor?: ArrayLike<number>;
45
+ /**
46
+ * `opaque` (default): alpha is written as 1 and the draw is opaque (depth write, shadow
47
+ * caster). `mask`: opaque, and fragments with alpha below `alphaCutoff` are discarded, in
48
+ * the shadow pass too (ws/render-6: the material's `fs_shadow` entry, so the shadow has the
49
+ * same holes; an opaque material keeps the depth-only shadow pipeline). `blend`: the renderer's
50
+ * alpha-blended path (sorted back to front, no depth write, casts no shadow).
51
+ */
52
+ alphaMode?: 'opaque' | 'mask' | 'blend';
53
+ /** Alpha below this is discarded in `mask` mode. Default 0.5. */
54
+ alphaCutoff?: number;
55
+ /**
56
+ * Back faces are shaded with their normal flipped toward the viewer. Default false: back
57
+ * faces shade with the front normal, as every engine material does (the renderer never
58
+ * culls, so single-sided here means nothing is hidden, only that the normal is not flipped).
59
+ */
60
+ doubleSided?: boolean;
61
+ /**
62
+ * Skinned: bind this palette (or its storage buffer) as `buffers[0]` (`@binding(16)`), so the
63
+ * material draws `VERTEX_LAYOUT_SKINNED` meshes with the prelude's `engine_skin`: no custom
64
+ * WGSL. The same material still draws unskinned 3D meshes; a skinned mesh picks its palette
65
+ * slot with `InstanceParams.params[SKIN_PARAM]` (`params.w`). Swap the buffer later with
66
+ * `material.bindings.setBuffer(0, buffer)`.
67
+ */
68
+ skin?: SkinPalette | GPUBuffer;
69
+ /**
70
+ * Texture coordinate transform applied to every map, `[sx, sy, ox, oy, rot]`:
71
+ * `uv' = offset + R(rot) · (scale ⊙ uv)` (glTF's `KHR_texture_transform`, `T · R · S`, `rot`
72
+ * in radians). Default identity; the rotation's cosine and sine are packed on the CPU, so the
73
+ * shader does two multiply-adds per map whether or not one is given.
74
+ */
75
+ uvTransform?: ArrayLike<number>;
76
+ /**
77
+ * Per-map overrides (ws/render-4): a map's own `uvTransform` (else the material's) and the
78
+ * texture coordinate set it reads, `0` (`uv`, default) or `1` (`uv1`, a `VERTEX_LAYOUT_3D_UV2`
79
+ * mesh's second set; `uv` again on a layout without one).
80
+ */
81
+ maps?: Partial<Record<StandardMapSlot, StandardMapDesc>>;
82
+ /** The sampler every map is read with. Default `'linear-mip-repeat'`. */
83
+ sampler?: SamplerKind;
84
+ /**
85
+ * A noise-threshold dissolve (ws/render-5): fragments whose value noise is below `amount`
86
+ * are discarded, in the scene pass and in the sun's shadow pass alike, and a band
87
+ * `edgeWidth` wide above the threshold glows `edgeColor` (to the emissive target). Given at
88
+ * creation (even with `amount: 0`), the material builds its own shadow pipeline
89
+ * (`shadowFragmentEntry`); animate it with `setUniforms(packStandardUniforms(next))`.
90
+ */
91
+ dissolve?: StandardDissolve;
92
+ }
93
+ /** `StandardMaterialDesc.dissolve`. */
94
+ export interface StandardDissolve {
95
+ /** 0 (whole) .. 1 (gone): the noise threshold below which fragments are discarded. */
96
+ amount: number;
97
+ /** Linear RGB of the glowing band at the edge. Default `[1, 0.5, 0.1]`. */
98
+ edgeColor?: ArrayLike<number>;
99
+ /** Width of the band in noise units (0..1). Default 0.05; 0 draws no edge. */
100
+ edgeWidth?: number;
101
+ /**
102
+ * Noise scale: cells of value noise per uv unit of the mesh's own coordinates
103
+ * (`VSOut.local`). Default 6.
104
+ */
105
+ noise?: number;
106
+ }
107
+ /** A map's own settings (`StandardMaterialDesc.maps`). */
108
+ export interface StandardMapDesc {
109
+ uvTransform?: ArrayLike<number>;
110
+ texCoord?: 0 | 1;
111
+ }
112
+ /** The map names of `STANDARD_TEXTURE_SLOTS`. */
113
+ export type StandardMapSlot = keyof typeof STANDARD_TEXTURE_SLOTS;
114
+ /** Texture slots of a standard material (`material.setTexture(slot, tex)` swaps a map). */
115
+ export declare const STANDARD_TEXTURE_SLOTS: {
116
+ readonly baseColor: 0;
117
+ readonly metallicRoughness: 1;
118
+ readonly normal: 2;
119
+ readonly occlusion: 3;
120
+ readonly emissive: 4;
121
+ };
122
+ /** Float offset of the dissolve tail (`dissolve`, `dissolve_edge`) after the slots. */
123
+ export declare const STANDARD_DISSOLVE_OFFSET: number;
124
+ /** The standard material's uniform block, in floats (`setUniforms` takes the whole block). */
125
+ export declare const STANDARD_UNIFORM_FLOATS: number;
126
+ /**
127
+ * Pack a desc's factors into the standard material's uniform block:
128
+ * `base_color` (rgba), `factors` (metallic, roughness, normal_scale, alpha_cutoff),
129
+ * `emissive` (rgb, flags: bit 0 double-sided, bit 1 alpha mask, bit 2 alpha blend, bit 3
130
+ * dissolve),
131
+ * `uv_scale_offset` (sx, sy, ox, oy) and `uv_rot` (cos, sin, occlusion_strength, 0) from
132
+ * `uvTransform`, then one `StandardSlot` per map (`scale_offset`, `rot` = cos, sin, texCoord,
133
+ * 0) from `maps`, defaulting to the material's transform, then at `STANDARD_DISSOLVE_OFFSET`
134
+ * `dissolve` (amount, edge width, noise scale, 0) and `dissolve_edge` (rgb, 0). `out` must hold
135
+ * `STANDARD_UNIFORM_FLOATS`; returns it.
136
+ */
137
+ export declare function packStandardUniforms(desc: StandardMaterialDesc, out?: Float32Array<ArrayBuffer>): Float32Array<ArrayBuffer>;
138
+ /**
139
+ * The standard material's shader text, after the prelude and `WGSL_PBR`. Bindings follow the
140
+ * material convention: the block at `@group(1) @binding(0)`, the sampler at 1, the five maps at
141
+ * 2..6 in `STANDARD_TEXTURE_SLOTS` order. Every map is read through `standard_uv_slot`, its
142
+ * own transform and texture coordinate set (`maps`); `standard_uv` is the material-wide
143
+ * transform. The normal map perturbs along the mesh tangent (`VSOut.tangent`, a
144
+ * `VERTEX_LAYOUT_3D_TANGENT` mesh) or, without one, through `engine_perturb_normal`
145
+ * (screen-space derivatives), so the material draws any 3D layout. Roughness, metalness and
146
+ * the velocity go to the target's aux attachments through `engine_write_aux`.
147
+ */
148
+ export declare const STANDARD_WGSL = "\nstruct StandardSlot {\n scale_offset: vec4f,\n rot: vec4f,\n};\nstruct StandardParams {\n base_color: vec4f,\n factors: vec4f,\n emissive: vec4f,\n uv_scale_offset: vec4f,\n uv_rot: vec4f,\n slots: array<StandardSlot, 5>,\n dissolve: vec4f,\n dissolve_edge: vec4f,\n};\n@group(1) @binding(0) var<uniform> standard: StandardParams;\n@group(1) @binding(1) var standard_sampler: sampler;\n@group(1) @binding(2) var standard_base_color: texture_2d<f32>;\n@group(1) @binding(3) var standard_metallic_roughness: texture_2d<f32>;\n@group(1) @binding(4) var standard_normal: texture_2d<f32>;\n@group(1) @binding(5) var standard_occlusion: texture_2d<f32>;\n@group(1) @binding(6) var standard_emissive: texture_2d<f32>;\nfn standard_uv(uv: vec2f) -> vec2f {\n let s = uv * standard.uv_scale_offset.xy;\n let r = standard.uv_rot.xy;\n return vec2f(r.x * s.x - r.y * s.y, r.y * s.x + r.x * s.y) + standard.uv_scale_offset.zw;\n}\n// Map slot's coordinates: its texture coordinate set through its own transform.\nfn standard_uv_slot(in: VSOut, slot: u32) -> vec2f {\n let p = standard.slots[slot];\n let uv = select(in.uv, in.uv1, p.rot.z > 0.5);\n let s = uv * p.scale_offset.xy;\n return vec2f(p.rot.x * s.x - p.rot.y * s.y, p.rot.y * s.x + p.rot.x * s.y) + p.scale_offset.zw;\n}\n// Dissolve noise at a fragment, 0..1 (value-noise fbm over the mesh's own uv).\nfn standard_dissolve_noise(in: VSOut) -> f32 {\n return engine_fbm(in.local * standard.dissolve.z, 3) / 0.875;\n}\n// True when the dissolve discards this fragment (flag bit 3 and noise below the amount).\nfn standard_dissolved(in: VSOut) -> bool {\n if ((u32(standard.emissive.w) & 8u) == 0u) { return false; }\n let a = standard.dissolve.x;\n return a >= 1.0 || standard_dissolve_noise(in) < a;\n}\n// The shadow pass fragment (shadowFragmentEntry): the same holes as fs_main's alpha mask\n// (flag bit 1, base alpha below the cutoff) and dissolve. The sample comes first, in uniform\n// control flow.\n@fragment fn fs_shadow(in: VSOut) {\n let a = textureSample(standard_base_color, standard_sampler, standard_uv_slot(in, 0u)).a\n * standard.base_color.a * in.color.a;\n let masked = (u32(standard.emissive.w) & 2u) != 0u && a < standard.factors.w;\n if (masked || standard_dissolved(in)) { discard; }\n}\n\n@fragment fn fs_main(in: VSOut, @builtin(front_facing) front: bool) -> FragOut {\n let uv = standard_uv_slot(in, 2u);\n let base = textureSample(standard_base_color, standard_sampler, standard_uv_slot(in, 0u)) * standard.base_color * in.color;\n let mr = textureSample(standard_metallic_roughness, standard_sampler, standard_uv_slot(in, 1u));\n let nmap = textureSample(standard_normal, standard_sampler, uv).xyz;\n let ao_tex = textureSample(standard_occlusion, standard_sampler, standard_uv_slot(in, 3u)).r;\n let em = textureSample(standard_emissive, standard_sampler, standard_uv_slot(in, 4u)).rgb * standard.emissive.rgb;\n let ao = mix(1.0, ao_tex, standard.uv_rot.z);\n let flags = u32(standard.emissive.w);\n var n = normalize(in.normal);\n if ((flags & 1u) != 0u && !front) { n = -n; }\n let v = normalize(camera.camera_pos.xyz - in.worldPos);\n // Derivative path first (uniform control flow), then the tangent frame when the mesh has one.\n let nd = engine_perturb_normal(n, in.worldPos, uv, nmap, standard.factors.z);\n let tp = in.tangent.xyz - n * dot(n, in.tangent.xyz);\n let tl = length(tp);\n if (in.tangent.w != 0.0 && tl > 1e-6) {\n let t = tp / tl;\n let b = in.tangent.w * cross(n, t);\n let m = (nmap * 2.0 - 1.0) * vec3f(standard.factors.z, standard.factors.z, 1.0);\n n = normalize(t * m.x + b * m.y + n * m.z);\n } else {\n n = nd;\n }\n if ((flags & 2u) != 0u && base.a < standard.factors.w) { discard; }\n var edge = vec3f(0.0);\n if ((flags & 8u) != 0u) {\n let dn = standard_dissolve_noise(in);\n let da = standard.dissolve.x;\n if (da >= 1.0 || dn < da) { discard; }\n let w = standard.dissolve.y;\n if (da > 0.0 && w > 0.0) {\n edge = standard.dissolve_edge.rgb * (1.0 - smoothstep(da, da + w, dn));\n }\n }\n let metallic = mr.b * standard.factors.x;\n let roughness = mr.g * standard.factors.y;\n let lit = engine_pbr_layers(\n base.rgb, metallic, roughness, n, v, in.worldPos, ao, vec3f(0.0),\n engine_instance_layers(in.flags),\n );\n let glow = em + base.rgb * in.emissive + edge;\n // Fog attenuates the emissive without tinting it: fog(e) - fog(0) = e \u00D7 (1 - f).\n let fogged_glow = engine_fog(glow, in.worldPos) - engine_fog(vec3f(0.0), in.worldPos);\n let alpha = select(1.0, base.a, (flags & 4u) != 0u);\n var o: FragOut;\n o.color = vec4f(lit, alpha);\n o.emissive = vec4f(fogged_glow, alpha);\n engine_write_aux(&o, vec2f(roughness, metallic), engine_velocity(in));\n return o;\n}\n";
149
+ /**
150
+ * A standard PBR `Material` for `desc`: `createMaterial` with `STANDARD_WGSL`, a 272-byte block
151
+ * from `packStandardUniforms` and the five maps (the device's `defaultTextures` for the missing
152
+ * ones: `white` for the base colour, metallic-roughness and occlusion, since a 255 texel reads
153
+ * as 1.0 whether the view is sRGB or linear, `flatNormal` and `black`). The instance
154
+ * tint (and vertex colour) multiplies the base colour; `InstanceParams.emissive` adds
155
+ * `base × emissive` to the glow like the sprite material. Call `setTexture(slot, tex)` with a
156
+ * `STANDARD_TEXTURE_SLOTS` entry to swap a map, or `setUniforms(packStandardUniforms(next))`
157
+ * to change factors. The sampler is `desc.sampler`, default `linear-mip-repeat` (trilinear on
158
+ * maps with mips; level 0 otherwise).
159
+ * With `skin` (a `SkinPalette` or its buffer) the palette is bound as `buffers[0]` and the
160
+ * material skins `VERTEX_LAYOUT_SKINNED` meshes.
161
+ */
162
+ export declare function createStandardMaterial(renderer: Renderer, desc: StandardMaterialDesc): Material;
@@ -0,0 +1,263 @@
1
+ import { WGSL_PBR } from './pbr-wgsl.js';
2
+ import { defaultTextures } from './texture.js';
3
+ /** Texture slots of a standard material (`material.setTexture(slot, tex)` swaps a map). */
4
+ export const STANDARD_TEXTURE_SLOTS = {
5
+ baseColor: 0,
6
+ metallicRoughness: 1,
7
+ normal: 2,
8
+ occlusion: 3,
9
+ emissive: 4,
10
+ };
11
+ /** Floats of the shared head of the block, before the five per-map slots. */
12
+ const STANDARD_HEAD_FLOATS = 20;
13
+ /** Floats per map slot: `scale_offset` (4), `rot` (cos, sin, texCoord, 0). */
14
+ const STANDARD_SLOT_FLOATS = 8;
15
+ /** Float offset of the dissolve tail (`dissolve`, `dissolve_edge`) after the slots. */
16
+ export const STANDARD_DISSOLVE_OFFSET = STANDARD_HEAD_FLOATS + 5 * STANDARD_SLOT_FLOATS;
17
+ /** The standard material's uniform block, in floats (`setUniforms` takes the whole block). */
18
+ export const STANDARD_UNIFORM_FLOATS = STANDARD_DISSOLVE_OFFSET + 8;
19
+ const SLOT_NAMES = [
20
+ 'baseColor',
21
+ 'metallicRoughness',
22
+ 'normal',
23
+ 'occlusion',
24
+ 'emissive',
25
+ ];
26
+ /** Flag bits in `StandardParams.emissive.w`. */
27
+ const FLAG_DOUBLE_SIDED = 1;
28
+ const FLAG_MASK = 2;
29
+ const FLAG_BLEND = 4;
30
+ const FLAG_DISSOLVE = 8;
31
+ /**
32
+ * Pack a desc's factors into the standard material's uniform block:
33
+ * `base_color` (rgba), `factors` (metallic, roughness, normal_scale, alpha_cutoff),
34
+ * `emissive` (rgb, flags: bit 0 double-sided, bit 1 alpha mask, bit 2 alpha blend, bit 3
35
+ * dissolve),
36
+ * `uv_scale_offset` (sx, sy, ox, oy) and `uv_rot` (cos, sin, occlusion_strength, 0) from
37
+ * `uvTransform`, then one `StandardSlot` per map (`scale_offset`, `rot` = cos, sin, texCoord,
38
+ * 0) from `maps`, defaulting to the material's transform, then at `STANDARD_DISSOLVE_OFFSET`
39
+ * `dissolve` (amount, edge width, noise scale, 0) and `dissolve_edge` (rgb, 0). `out` must hold
40
+ * `STANDARD_UNIFORM_FLOATS`; returns it.
41
+ */
42
+ export function packStandardUniforms(desc, out = new Float32Array(STANDARD_UNIFORM_FLOATS)) {
43
+ if (out.length < STANDARD_UNIFORM_FLOATS) {
44
+ throw new Error(`packStandardUniforms: need ${STANDARD_UNIFORM_FLOATS} floats`);
45
+ }
46
+ const bc = desc.baseColorFactor;
47
+ out[0] = bc?.[0] ?? 1;
48
+ out[1] = bc?.[1] ?? 1;
49
+ out[2] = bc?.[2] ?? 1;
50
+ out[3] = bc?.[3] ?? 1;
51
+ out[4] = desc.metallic ?? 0;
52
+ out[5] = desc.roughness ?? 0.5;
53
+ out[6] = desc.normalScale ?? 1;
54
+ out[7] = desc.alphaCutoff ?? 0.5;
55
+ const ef = desc.emissiveFactor;
56
+ const e = desc.emissive ? 1 : 0;
57
+ out[8] = ef?.[0] ?? e;
58
+ out[9] = ef?.[1] ?? e;
59
+ out[10] = ef?.[2] ?? e;
60
+ let flags = 0;
61
+ if (desc.doubleSided)
62
+ flags |= FLAG_DOUBLE_SIDED;
63
+ if (desc.alphaMode === 'mask')
64
+ flags |= FLAG_MASK;
65
+ if (desc.alphaMode === 'blend')
66
+ flags |= FLAG_BLEND;
67
+ const dv = desc.dissolve;
68
+ if (dv)
69
+ flags |= FLAG_DISSOLVE;
70
+ out[11] = flags;
71
+ const t = desc.uvTransform;
72
+ out[12] = t?.[0] ?? 1;
73
+ out[13] = t?.[1] ?? 1;
74
+ out[14] = t?.[2] ?? 0;
75
+ out[15] = t?.[3] ?? 0;
76
+ const rot = t?.[4] ?? 0;
77
+ out[16] = Math.cos(rot);
78
+ out[17] = Math.sin(rot);
79
+ out[18] = desc.occlusionStrength ?? 1;
80
+ out[19] = 0;
81
+ for (let k = 0; k < 5; k++) {
82
+ const slot = desc.maps?.[SLOT_NAMES[k]];
83
+ const st = slot?.uvTransform ?? t;
84
+ const o = STANDARD_HEAD_FLOATS + k * STANDARD_SLOT_FLOATS;
85
+ out[o] = st?.[0] ?? 1;
86
+ out[o + 1] = st?.[1] ?? 1;
87
+ out[o + 2] = st?.[2] ?? 0;
88
+ out[o + 3] = st?.[3] ?? 0;
89
+ const sr = st?.[4] ?? 0;
90
+ out[o + 4] = Math.cos(sr);
91
+ out[o + 5] = Math.sin(sr);
92
+ out[o + 6] = slot?.texCoord === 1 ? 1 : 0;
93
+ out[o + 7] = 0;
94
+ }
95
+ const o = STANDARD_DISSOLVE_OFFSET;
96
+ const ec = dv?.edgeColor;
97
+ out[o] = dv ? dv.amount : 0;
98
+ out[o + 1] = dv ? (dv.edgeWidth ?? 0.05) : 0;
99
+ out[o + 2] = dv?.noise ?? 6;
100
+ out[o + 3] = 0;
101
+ out[o + 4] = ec?.[0] ?? 1;
102
+ out[o + 5] = ec?.[1] ?? 0.5;
103
+ out[o + 6] = ec?.[2] ?? 0.1;
104
+ out[o + 7] = 0;
105
+ return out;
106
+ }
107
+ /**
108
+ * The standard material's shader text, after the prelude and `WGSL_PBR`. Bindings follow the
109
+ * material convention: the block at `@group(1) @binding(0)`, the sampler at 1, the five maps at
110
+ * 2..6 in `STANDARD_TEXTURE_SLOTS` order. Every map is read through `standard_uv_slot`, its
111
+ * own transform and texture coordinate set (`maps`); `standard_uv` is the material-wide
112
+ * transform. The normal map perturbs along the mesh tangent (`VSOut.tangent`, a
113
+ * `VERTEX_LAYOUT_3D_TANGENT` mesh) or, without one, through `engine_perturb_normal`
114
+ * (screen-space derivatives), so the material draws any 3D layout. Roughness, metalness and
115
+ * the velocity go to the target's aux attachments through `engine_write_aux`.
116
+ */
117
+ export const STANDARD_WGSL = /* wgsl */ `
118
+ struct StandardSlot {
119
+ scale_offset: vec4f,
120
+ rot: vec4f,
121
+ };
122
+ struct StandardParams {
123
+ base_color: vec4f,
124
+ factors: vec4f,
125
+ emissive: vec4f,
126
+ uv_scale_offset: vec4f,
127
+ uv_rot: vec4f,
128
+ slots: array<StandardSlot, 5>,
129
+ dissolve: vec4f,
130
+ dissolve_edge: vec4f,
131
+ };
132
+ @group(1) @binding(0) var<uniform> standard: StandardParams;
133
+ @group(1) @binding(1) var standard_sampler: sampler;
134
+ @group(1) @binding(2) var standard_base_color: texture_2d<f32>;
135
+ @group(1) @binding(3) var standard_metallic_roughness: texture_2d<f32>;
136
+ @group(1) @binding(4) var standard_normal: texture_2d<f32>;
137
+ @group(1) @binding(5) var standard_occlusion: texture_2d<f32>;
138
+ @group(1) @binding(6) var standard_emissive: texture_2d<f32>;
139
+ fn standard_uv(uv: vec2f) -> vec2f {
140
+ let s = uv * standard.uv_scale_offset.xy;
141
+ let r = standard.uv_rot.xy;
142
+ return vec2f(r.x * s.x - r.y * s.y, r.y * s.x + r.x * s.y) + standard.uv_scale_offset.zw;
143
+ }
144
+ // Map slot's coordinates: its texture coordinate set through its own transform.
145
+ fn standard_uv_slot(in: VSOut, slot: u32) -> vec2f {
146
+ let p = standard.slots[slot];
147
+ let uv = select(in.uv, in.uv1, p.rot.z > 0.5);
148
+ let s = uv * p.scale_offset.xy;
149
+ return vec2f(p.rot.x * s.x - p.rot.y * s.y, p.rot.y * s.x + p.rot.x * s.y) + p.scale_offset.zw;
150
+ }
151
+ // Dissolve noise at a fragment, 0..1 (value-noise fbm over the mesh's own uv).
152
+ fn standard_dissolve_noise(in: VSOut) -> f32 {
153
+ return engine_fbm(in.local * standard.dissolve.z, 3) / 0.875;
154
+ }
155
+ // True when the dissolve discards this fragment (flag bit 3 and noise below the amount).
156
+ fn standard_dissolved(in: VSOut) -> bool {
157
+ if ((u32(standard.emissive.w) & 8u) == 0u) { return false; }
158
+ let a = standard.dissolve.x;
159
+ return a >= 1.0 || standard_dissolve_noise(in) < a;
160
+ }
161
+ // The shadow pass fragment (shadowFragmentEntry): the same holes as fs_main's alpha mask
162
+ // (flag bit 1, base alpha below the cutoff) and dissolve. The sample comes first, in uniform
163
+ // control flow.
164
+ @fragment fn fs_shadow(in: VSOut) {
165
+ let a = textureSample(standard_base_color, standard_sampler, standard_uv_slot(in, 0u)).a
166
+ * standard.base_color.a * in.color.a;
167
+ let masked = (u32(standard.emissive.w) & 2u) != 0u && a < standard.factors.w;
168
+ if (masked || standard_dissolved(in)) { discard; }
169
+ }
170
+
171
+ @fragment fn fs_main(in: VSOut, @builtin(front_facing) front: bool) -> FragOut {
172
+ let uv = standard_uv_slot(in, 2u);
173
+ let base = textureSample(standard_base_color, standard_sampler, standard_uv_slot(in, 0u)) * standard.base_color * in.color;
174
+ let mr = textureSample(standard_metallic_roughness, standard_sampler, standard_uv_slot(in, 1u));
175
+ let nmap = textureSample(standard_normal, standard_sampler, uv).xyz;
176
+ let ao_tex = textureSample(standard_occlusion, standard_sampler, standard_uv_slot(in, 3u)).r;
177
+ let em = textureSample(standard_emissive, standard_sampler, standard_uv_slot(in, 4u)).rgb * standard.emissive.rgb;
178
+ let ao = mix(1.0, ao_tex, standard.uv_rot.z);
179
+ let flags = u32(standard.emissive.w);
180
+ var n = normalize(in.normal);
181
+ if ((flags & 1u) != 0u && !front) { n = -n; }
182
+ let v = normalize(camera.camera_pos.xyz - in.worldPos);
183
+ // Derivative path first (uniform control flow), then the tangent frame when the mesh has one.
184
+ let nd = engine_perturb_normal(n, in.worldPos, uv, nmap, standard.factors.z);
185
+ let tp = in.tangent.xyz - n * dot(n, in.tangent.xyz);
186
+ let tl = length(tp);
187
+ if (in.tangent.w != 0.0 && tl > 1e-6) {
188
+ let t = tp / tl;
189
+ let b = in.tangent.w * cross(n, t);
190
+ let m = (nmap * 2.0 - 1.0) * vec3f(standard.factors.z, standard.factors.z, 1.0);
191
+ n = normalize(t * m.x + b * m.y + n * m.z);
192
+ } else {
193
+ n = nd;
194
+ }
195
+ if ((flags & 2u) != 0u && base.a < standard.factors.w) { discard; }
196
+ var edge = vec3f(0.0);
197
+ if ((flags & 8u) != 0u) {
198
+ let dn = standard_dissolve_noise(in);
199
+ let da = standard.dissolve.x;
200
+ if (da >= 1.0 || dn < da) { discard; }
201
+ let w = standard.dissolve.y;
202
+ if (da > 0.0 && w > 0.0) {
203
+ edge = standard.dissolve_edge.rgb * (1.0 - smoothstep(da, da + w, dn));
204
+ }
205
+ }
206
+ let metallic = mr.b * standard.factors.x;
207
+ let roughness = mr.g * standard.factors.y;
208
+ let lit = engine_pbr_layers(
209
+ base.rgb, metallic, roughness, n, v, in.worldPos, ao, vec3f(0.0),
210
+ engine_instance_layers(in.flags),
211
+ );
212
+ let glow = em + base.rgb * in.emissive + edge;
213
+ // Fog attenuates the emissive without tinting it: fog(e) - fog(0) = e × (1 - f).
214
+ let fogged_glow = engine_fog(glow, in.worldPos) - engine_fog(vec3f(0.0), in.worldPos);
215
+ let alpha = select(1.0, base.a, (flags & 4u) != 0u);
216
+ var o: FragOut;
217
+ o.color = vec4f(lit, alpha);
218
+ o.emissive = vec4f(fogged_glow, alpha);
219
+ engine_write_aux(&o, vec2f(roughness, metallic), engine_velocity(in));
220
+ return o;
221
+ }
222
+ `;
223
+ /**
224
+ * A standard PBR `Material` for `desc`: `createMaterial` with `STANDARD_WGSL`, a 272-byte block
225
+ * from `packStandardUniforms` and the five maps (the device's `defaultTextures` for the missing
226
+ * ones: `white` for the base colour, metallic-roughness and occlusion, since a 255 texel reads
227
+ * as 1.0 whether the view is sRGB or linear, `flatNormal` and `black`). The instance
228
+ * tint (and vertex colour) multiplies the base colour; `InstanceParams.emissive` adds
229
+ * `base × emissive` to the glow like the sprite material. Call `setTexture(slot, tex)` with a
230
+ * `STANDARD_TEXTURE_SLOTS` entry to swap a map, or `setUniforms(packStandardUniforms(next))`
231
+ * to change factors. The sampler is `desc.sampler`, default `linear-mip-repeat` (trilinear on
232
+ * maps with mips; level 0 otherwise).
233
+ * With `skin` (a `SkinPalette` or its buffer) the palette is bound as `buffers[0]` and the
234
+ * material skins `VERTEX_LAYOUT_SKINNED` meshes.
235
+ */
236
+ export function createStandardMaterial(renderer, desc) {
237
+ const d = defaultTextures(renderer.device);
238
+ const skin = desc.skin;
239
+ // A palette carries its `buffer`; a bare `GPUBuffer` has no such field (no `instanceof`: tests run without the global).
240
+ const buffers = skin ? ['buffer' in skin ? skin.buffer : skin] : undefined;
241
+ const m = renderer.createMaterial({
242
+ label: desc.label ?? desc.name ?? 'standard',
243
+ name: desc.name,
244
+ depthTest: desc.depthTest,
245
+ aux: true,
246
+ wgsl: `${WGSL_PBR}\n${STANDARD_WGSL}`,
247
+ blend: desc.alphaMode === 'blend' ? 'alpha' : 'opaque',
248
+ uniformBytes: STANDARD_UNIFORM_FLOATS * 4,
249
+ textures: 5,
250
+ sampler: desc.sampler ?? 'linear-mip-repeat',
251
+ buffers,
252
+ // A cutout's and a dissolve's holes show in the shadow too: the material's own shadow
253
+ // pipeline. Opaque and blended materials keep the depth-only one.
254
+ shadowFragmentEntry: desc.dissolve || desc.alphaMode === 'mask' ? 'fs_shadow' : undefined,
255
+ });
256
+ m.setUniforms(packStandardUniforms(desc));
257
+ m.setTexture(STANDARD_TEXTURE_SLOTS.baseColor, desc.baseColor ?? d.white);
258
+ m.setTexture(STANDARD_TEXTURE_SLOTS.metallicRoughness, desc.metallicRoughness ?? d.white);
259
+ m.setTexture(STANDARD_TEXTURE_SLOTS.normal, desc.normal ?? d.flatNormal);
260
+ m.setTexture(STANDARD_TEXTURE_SLOTS.occlusion, desc.occlusion ?? d.white);
261
+ m.setTexture(STANDARD_TEXTURE_SLOTS.emissive, desc.emissive ?? d.black);
262
+ return m;
263
+ }
@@ -0,0 +1,142 @@
1
+ import { type MipFilter } from './mipmap.js';
2
+ /** Anything with a sampleable view. */
3
+ export interface TextureLike {
4
+ readonly view: GPUTextureView;
5
+ readonly width: number;
6
+ readonly height: number;
7
+ }
8
+ export interface TextureDesc {
9
+ width: number;
10
+ height: number;
11
+ /**
12
+ * Array layers. When set (even to 1) the texture is a 2D array and its view is `'2d-array'`
13
+ * (WGSL `texture_2d_array<f32>`); left out, it is a plain 2D texture.
14
+ */
15
+ layers?: number;
16
+ /**
17
+ * Allocate the full mip chain (`mipLevelCount(width, height)` levels). Level 0 is what uploads
18
+ * write; `generateMipmaps(device, texture)` fills the rest.
19
+ */
20
+ mips?: boolean;
21
+ /** Allocate exactly this many mip levels (overrides `mips`): a file's own chain (KTX2). */
22
+ mipLevelCount?: number;
23
+ format?: GPUTextureFormat;
24
+ usage?: GPUTextureUsageFlags;
25
+ label?: string;
26
+ }
27
+ /** Levels of a full mip chain for a `width × height` texture (1 for 1×1). */
28
+ export declare function mipLevelCount(width: number, height: number): number;
29
+ /** Thin wrapper around a 2D (or 2D array) GPUTexture + default view. */
30
+ export declare class Texture implements TextureLike {
31
+ readonly texture: GPUTexture;
32
+ readonly view: GPUTextureView;
33
+ readonly width: number;
34
+ readonly height: number;
35
+ readonly format: GPUTextureFormat;
36
+ /** Array layers (1 for a plain 2D texture). */
37
+ readonly layers: number;
38
+ /** Mip levels allocated (1 unless created with `mips: true`). */
39
+ readonly mipLevels: number;
40
+ /** The default view's dimension: `'2d-array'` when created with `layers`, else `'2d'`. */
41
+ readonly viewDimension: '2d' | '2d-array';
42
+ constructor(device: GPUDevice, desc: TextureDesc);
43
+ destroy(): void;
44
+ }
45
+ /**
46
+ * Sampler presets. The `-mip` kinds blend between mip levels (`mipmapFilter: 'linear'`):
47
+ * `'linear-mip-repeat'` for tiling textures seen at a distance, `'nearest-mip-clamp'` for
48
+ * pixel-art faces (crisp up close, no shimmer far away), `'nearest-mip-repeat'` for pixel-art
49
+ * faces tiled across a quad (block faces whose uv spans whole cells). Without mips they act
50
+ * like their plain counterparts.
51
+ */
52
+ export type SamplerKind = 'linear-clamp' | 'linear-repeat' | 'nearest-clamp' | 'linear-mip-repeat' | 'nearest-mip-clamp' | 'nearest-mip-repeat';
53
+ export declare function createSamplers(device: GPUDevice): Record<SamplerKind, GPUSampler>;
54
+ export type TextureSource = ImageBitmap | ImageData | HTMLCanvasElement | OffscreenCanvas | HTMLImageElement;
55
+ /** Typed data accepted by `renderer.textureFromPixels` / `renderer.writePixels`. */
56
+ export type PixelData = Uint8Array<ArrayBuffer> | Uint8ClampedArray<ArrayBuffer> | Uint16Array<ArrayBuffer> | Float32Array<ArrayBuffer>;
57
+ /** Tightly packed texels of one image (`ImageData` is one). */
58
+ export interface PixelSource {
59
+ width: number;
60
+ height: number;
61
+ data: PixelData;
62
+ }
63
+ /** One layer of `loadTextureArray`: an image (copied on the GPU) or raw texels. */
64
+ export type TextureLayerSource = TextureSource | PixelSource;
65
+ /** A texture array whose layers the caller fills (`writeTexture` with `origin.z` = layer). */
66
+ export interface TextureArrayDesc {
67
+ width: number;
68
+ height: number;
69
+ layers: number;
70
+ /** Allocate the full mip chain (default false); fill it with `generateMipmaps`. */
71
+ mips?: boolean;
72
+ format?: GPUTextureFormat;
73
+ usage?: GPUTextureUsageFlags;
74
+ label?: string;
75
+ }
76
+ /** Create an empty `texture_2d_array` (`Texture.viewDimension === '2d-array'`). */
77
+ export declare function createTextureArray(device: GPUDevice, desc: TextureArrayDesc): Texture;
78
+ export interface LoadTextureArrayOptions {
79
+ /** Build the full mip chain on the GPU after upload (default true). */
80
+ mips?: boolean;
81
+ /** How each mip level is reduced from the one above (default `'linear'`, a 2×2 box). */
82
+ filter?: MipFilter;
83
+ /**
84
+ * Default `rgba8unorm-srgb` (colour). Image layers need an 8-bit RGBA/BGRA format; pixel
85
+ * layers any format `bytesPerTexel` lists.
86
+ */
87
+ format?: GPUTextureFormat;
88
+ label?: string;
89
+ }
90
+ /**
91
+ * Upload `sources` to the layers of one `texture_2d_array`, in order: images through
92
+ * `copyExternalImageToTexture`, pixel data (`ImageData` or `{ width, height, data }`) through
93
+ * `writeTexture`. Every source must have the size of the first. With `mips` (default) the full
94
+ * chain is allocated and generated on the GPU, layer by layer.
95
+ */
96
+ export declare function loadTextureArray(device: GPUDevice, sources: readonly TextureLayerSource[], opts?: LoadTextureArrayOptions): Texture;
97
+ export interface LoadTextureOptions {
98
+ /** Build the full mip chain on the GPU after upload (default true; a 1×1 source has one level). */
99
+ mips?: boolean;
100
+ /** How each mip level is reduced from the one above (default `'linear'`, a 2×2 box). */
101
+ filter?: MipFilter;
102
+ /**
103
+ * Default `rgba8unorm-srgb` (colour). An image source needs an 8-bit RGBA/BGRA format; a pixel
104
+ * source any format `bytesPerTexel` lists. Data such as normal maps wants `rgba8unorm`.
105
+ */
106
+ format?: GPUTextureFormat;
107
+ label?: string;
108
+ }
109
+ /**
110
+ * One call for a single 2D texture: create it, upload `source` (an image through
111
+ * `copyExternalImageToTexture`, `ImageData` or `{ width, height, data }` through `writeTexture`)
112
+ * as level 0 and, with `mips` (default), allocate the full chain and fill it with
113
+ * `generateMipmaps`. Non-power-of-two sizes get `mipLevelCount(width, height)` levels too.
114
+ * Allocates; call it at load time.
115
+ */
116
+ export declare function loadTexture(device: GPUDevice, source: TextureLayerSource, opts?: LoadTextureOptions): Texture;
117
+ /**
118
+ * Textures a material slot can read when the game sets nothing: one set per device, created on
119
+ * first use by `defaultTextures(device)` and alive as long as the device.
120
+ */
121
+ export interface DefaultTextures {
122
+ /** 1×1 `(255, 255, 255, 255)`, sRGB: a colour map that changes nothing. The unset-slot default. */
123
+ readonly white: Texture;
124
+ /** 1×1 `(0, 0, 0, 255)`, sRGB: no emissive, no light. */
125
+ readonly black: Texture;
126
+ /** 1×1 `(128, 128, 255, 255)`, linear: a tangent-space normal map that keeps the mesh normal. */
127
+ readonly flatNormal: Texture;
128
+ /**
129
+ * 1×1 `(255, 255, 0, 255)`, linear, in the glTF channel layout (G roughness, B metallic):
130
+ * a dielectric, fully rough surface (metallic 0, roughness 1).
131
+ */
132
+ readonly metalRough: Texture;
133
+ /**
134
+ * 8×8 sRGB checker of 2×2-texel magenta `(255, 0, 255)` and black squares, mipmapped: bind it
135
+ * where a texture failed to load so the gap is visible.
136
+ */
137
+ readonly checker: Texture;
138
+ }
139
+ /** The device's `DefaultTextures`, made on first call and cached (a `WeakMap` keyed by device). */
140
+ export declare function defaultTextures(device: GPUDevice): DefaultTextures;
141
+ /** Bytes per texel for the uncompressed formats `textureFromPixels` supports. */
142
+ export declare function bytesPerTexel(format: GPUTextureFormat): number;