@drawcall/lod 0.2.0 → 0.3.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 (364) hide show
  1. package/README.md +8 -6
  2. package/dist/bake.d.ts +22 -0
  3. package/dist/bake.js +88 -0
  4. package/dist/bake.js.map +1 -0
  5. package/dist/baked/codec.d.ts +3 -6
  6. package/dist/baked/codec.js +48 -154
  7. package/dist/baked/codec.js.map +1 -1
  8. package/dist/baked/coverage.d.ts +6 -3
  9. package/dist/baked/coverage.js +6 -3
  10. package/dist/baked/coverage.js.map +1 -1
  11. package/dist/baked/fields.d.ts +9 -0
  12. package/dist/baked/fields.js +22 -0
  13. package/dist/baked/fields.js.map +1 -0
  14. package/dist/baked/index.d.ts +12 -6
  15. package/dist/baked/index.js +22 -20
  16. package/dist/baked/index.js.map +1 -1
  17. package/dist/baked/interior/faces.d.ts +4 -3
  18. package/dist/baked/interior/faces.js +13 -10
  19. package/dist/baked/interior/faces.js.map +1 -1
  20. package/dist/baked/interior/material.d.ts +7 -10
  21. package/dist/baked/interior/material.js +29 -36
  22. package/dist/baked/interior/material.js.map +1 -1
  23. package/dist/baked/interior/rooms.js +1 -1
  24. package/dist/baked/interior/rooms.js.map +1 -1
  25. package/dist/baked/low.js +5 -4
  26. package/dist/baked/low.js.map +1 -1
  27. package/dist/baked/raster.js +6 -6
  28. package/dist/baked/raster.js.map +1 -1
  29. package/dist/baked/textures.d.ts +17 -0
  30. package/dist/baked/textures.js +95 -0
  31. package/dist/baked/textures.js.map +1 -0
  32. package/dist/baked/transfer.js +19 -18
  33. package/dist/baked/transfer.js.map +1 -1
  34. package/dist/baked/unwrap.js +4 -3
  35. package/dist/baked/unwrap.js.map +1 -1
  36. package/dist/baked/xatlas.js.map +1 -1
  37. package/dist/codec/container.d.ts +8 -0
  38. package/dist/codec/container.js +63 -0
  39. package/dist/codec/container.js.map +1 -0
  40. package/dist/codec/mesh.d.ts +8 -0
  41. package/dist/{mesh/codec.js → codec/mesh.js} +80 -52
  42. package/dist/codec/mesh.js.map +1 -0
  43. package/dist/dispose.d.ts +7 -4
  44. package/dist/dispose.js +20 -22
  45. package/dist/dispose.js.map +1 -1
  46. package/dist/gpu.d.ts +39 -0
  47. package/dist/gpu.js +41 -0
  48. package/dist/gpu.js.map +1 -0
  49. package/dist/impostor/bake/atlas.d.ts +4 -4
  50. package/dist/impostor/bake/atlas.js +12 -12
  51. package/dist/impostor/bake/atlas.js.map +1 -1
  52. package/dist/impostor/bake/fit.d.ts +8 -0
  53. package/dist/impostor/bake/fit.js +28 -0
  54. package/dist/impostor/bake/fit.js.map +1 -0
  55. package/dist/impostor/bake/index.d.ts +22 -14
  56. package/dist/impostor/bake/index.js +41 -134
  57. package/dist/impostor/bake/index.js.map +1 -1
  58. package/dist/impostor/bake/materials.d.ts +3 -3
  59. package/dist/impostor/bake/materials.js +51 -13
  60. package/dist/impostor/bake/materials.js.map +1 -1
  61. package/dist/impostor/bake/sheet.d.ts +8 -0
  62. package/dist/impostor/bake/sheet.js +90 -0
  63. package/dist/impostor/bake/sheet.js.map +1 -0
  64. package/dist/impostor/bake/source.d.ts +2 -2
  65. package/dist/impostor/bake/source.js +8 -19
  66. package/dist/impostor/bake/source.js.map +1 -1
  67. package/dist/impostor/codec.d.ts +4 -5
  68. package/dist/impostor/codec.js +36 -109
  69. package/dist/impostor/codec.js.map +1 -1
  70. package/dist/impostor/impostor.d.ts +31 -7
  71. package/dist/impostor/impostor.js +21 -6
  72. package/dist/impostor/impostor.js.map +1 -1
  73. package/dist/impostor/ktx2/encode.d.ts +26 -0
  74. package/dist/impostor/ktx2/encode.js +117 -0
  75. package/dist/impostor/ktx2/encode.js.map +1 -0
  76. package/dist/impostor/ktx2/transcode.d.ts +3 -0
  77. package/dist/impostor/ktx2/transcode.js +99 -0
  78. package/dist/impostor/ktx2/transcode.js.map +1 -0
  79. package/dist/impostor/ktx2/uastc.d.ts +7 -0
  80. package/dist/impostor/ktx2/uastc.js +64 -0
  81. package/dist/impostor/ktx2/uastc.js.map +1 -0
  82. package/dist/impostor/ktx2/wasm/encoder.d.ts +4 -0
  83. package/dist/impostor/ktx2/wasm/encoder.js +10 -0
  84. package/dist/impostor/ktx2/wasm/encoder.js.map +1 -0
  85. package/dist/impostor/ktx2/wasm/transcoder.d.ts +3 -0
  86. package/dist/impostor/ktx2/wasm/transcoder.js +9 -0
  87. package/dist/impostor/ktx2/wasm/transcoder.js.map +1 -0
  88. package/dist/impostor/ktx2/worker.d.ts +1 -0
  89. package/dist/impostor/ktx2/worker.js +12 -0
  90. package/dist/impostor/ktx2/worker.js.map +1 -0
  91. package/dist/impostor/mesh/card.d.ts +3 -3
  92. package/dist/impostor/mesh/card.js +7 -7
  93. package/dist/impostor/mesh/card.js.map +1 -1
  94. package/dist/impostor/mesh/index.d.ts +5 -4
  95. package/dist/impostor/mesh/index.js +8 -9
  96. package/dist/impostor/mesh/index.js.map +1 -1
  97. package/dist/impostor/mesh/material.d.ts +18 -9
  98. package/dist/impostor/mesh/material.js +40 -27
  99. package/dist/impostor/mesh/material.js.map +1 -1
  100. package/dist/impostor/mesh/surface.d.ts +1 -1
  101. package/dist/impostor/mesh/surface.js +13 -9
  102. package/dist/impostor/mesh/surface.js.map +1 -1
  103. package/dist/impostor/mesh/textures.d.ts +3 -3
  104. package/dist/impostor/mesh/textures.js +24 -34
  105. package/dist/impostor/mesh/textures.js.map +1 -1
  106. package/dist/index.d.ts +15 -10
  107. package/dist/index.js +13 -8
  108. package/dist/index.js.map +1 -1
  109. package/dist/instanced/camera.d.ts +46 -0
  110. package/dist/instanced/camera.js +70 -0
  111. package/dist/instanced/camera.js.map +1 -0
  112. package/dist/instanced/chunk.d.ts +97 -0
  113. package/dist/instanced/chunk.js +156 -0
  114. package/dist/instanced/chunk.js.map +1 -0
  115. package/dist/instanced/chunks.d.ts +60 -0
  116. package/dist/instanced/chunks.js +208 -0
  117. package/dist/instanced/chunks.js.map +1 -0
  118. package/dist/instanced/cull.d.ts +28 -0
  119. package/dist/instanced/cull.js +22 -0
  120. package/dist/instanced/cull.js.map +1 -0
  121. package/dist/instanced/index.d.ts +96 -66
  122. package/dist/instanced/index.js +229 -288
  123. package/dist/instanced/index.js.map +1 -1
  124. package/dist/instanced/key.d.ts +19 -0
  125. package/dist/instanced/key.js +45 -0
  126. package/dist/instanced/key.js.map +1 -0
  127. package/dist/instanced/levels.d.ts +60 -0
  128. package/dist/instanced/levels.js +130 -0
  129. package/dist/instanced/levels.js.map +1 -0
  130. package/dist/instanced/lists.d.ts +70 -0
  131. package/dist/instanced/lists.js +133 -0
  132. package/dist/instanced/lists.js.map +1 -0
  133. package/dist/instanced/measure.d.ts +28 -0
  134. package/dist/instanced/measure.js +203 -0
  135. package/dist/instanced/measure.js.map +1 -0
  136. package/dist/instanced/meshes.d.ts +42 -51
  137. package/dist/instanced/meshes.js +158 -180
  138. package/dist/instanced/meshes.js.map +1 -1
  139. package/dist/instanced/mirror.d.ts +20 -0
  140. package/dist/instanced/mirror.js +37 -0
  141. package/dist/instanced/mirror.js.map +1 -0
  142. package/dist/instanced/pages/buffers.d.ts +37 -0
  143. package/dist/instanced/pages/buffers.js +15 -0
  144. package/dist/instanced/pages/buffers.js.map +1 -0
  145. package/dist/instanced/pages/chunk.d.ts +51 -0
  146. package/dist/instanced/pages/chunk.js +81 -0
  147. package/dist/instanced/pages/chunk.js.map +1 -0
  148. package/dist/instanced/pages/index.d.ts +74 -0
  149. package/dist/instanced/pages/index.js +269 -0
  150. package/dist/instanced/pages/index.js.map +1 -0
  151. package/dist/instanced/pages/passes.d.ts +21 -0
  152. package/dist/instanced/pages/passes.js +52 -0
  153. package/dist/instanced/pages/passes.js.map +1 -0
  154. package/dist/instanced/pages/slots.d.ts +11 -0
  155. package/dist/instanced/pages/slots.js +90 -0
  156. package/dist/instanced/pages/slots.js.map +1 -0
  157. package/dist/instanced/pages/workgroup.d.ts +14 -0
  158. package/dist/instanced/pages/workgroup.js +38 -0
  159. package/dist/instanced/pages/workgroup.js.map +1 -0
  160. package/dist/instanced/raycast.d.ts +13 -11
  161. package/dist/instanced/raycast.js +33 -40
  162. package/dist/instanced/raycast.js.map +1 -1
  163. package/dist/instanced/rows.d.ts +108 -0
  164. package/dist/instanced/rows.js +209 -0
  165. package/dist/instanced/rows.js.map +1 -0
  166. package/dist/instanced/shape.d.ts +25 -0
  167. package/dist/instanced/shape.js +51 -0
  168. package/dist/instanced/shape.js.map +1 -0
  169. package/dist/instanced/sort.d.ts +63 -0
  170. package/dist/instanced/sort.js +162 -0
  171. package/dist/instanced/sort.js.map +1 -0
  172. package/dist/instanced/update.d.ts +30 -0
  173. package/dist/instanced/update.js +207 -0
  174. package/dist/instanced/update.js.map +1 -0
  175. package/dist/levels/bounds.d.ts +21 -0
  176. package/dist/levels/bounds.js +42 -0
  177. package/dist/levels/bounds.js.map +1 -0
  178. package/dist/levels/cameras.d.ts +48 -0
  179. package/dist/levels/cameras.js +122 -0
  180. package/dist/levels/cameras.js.map +1 -0
  181. package/dist/levels/compile/contexts.d.ts +30 -0
  182. package/dist/levels/compile/contexts.js +18 -0
  183. package/dist/levels/compile/contexts.js.map +1 -0
  184. package/dist/levels/compile/index.d.ts +39 -0
  185. package/dist/levels/compile/index.js +185 -0
  186. package/dist/levels/compile/index.js.map +1 -0
  187. package/dist/levels/compile/pipelines.d.ts +26 -0
  188. package/dist/levels/compile/pipelines.js +177 -0
  189. package/dist/levels/compile/pipelines.js.map +1 -0
  190. package/dist/levels/compiles.d.ts +29 -0
  191. package/dist/levels/compiles.js +50 -0
  192. package/dist/levels/compiles.js.map +1 -0
  193. package/dist/levels/draw.d.ts +102 -0
  194. package/dist/levels/draw.js +401 -0
  195. package/dist/levels/draw.js.map +1 -0
  196. package/dist/levels/fade.d.ts +69 -0
  197. package/dist/levels/fade.js +150 -0
  198. package/dist/levels/fade.js.map +1 -0
  199. package/dist/levels/index.d.ts +99 -0
  200. package/dist/levels/index.js +155 -0
  201. package/dist/levels/index.js.map +1 -0
  202. package/dist/levels/item.d.ts +38 -0
  203. package/dist/levels/item.js +97 -0
  204. package/dist/levels/item.js.map +1 -0
  205. package/dist/levels/load.d.ts +31 -0
  206. package/dist/levels/load.js +142 -0
  207. package/dist/levels/load.js.map +1 -0
  208. package/dist/levels/manager.d.ts +159 -0
  209. package/dist/levels/manager.js +339 -0
  210. package/dist/levels/manager.js.map +1 -0
  211. package/dist/{material.js → levels/material.js} +4 -3
  212. package/dist/levels/material.js.map +1 -0
  213. package/dist/levels/renderer.d.ts +29 -0
  214. package/dist/levels/renderer.js +41 -0
  215. package/dist/levels/renderer.js.map +1 -0
  216. package/dist/levels/requests.d.ts +49 -0
  217. package/dist/levels/requests.js +95 -0
  218. package/dist/levels/requests.js.map +1 -0
  219. package/dist/levels/screen.d.ts +14 -0
  220. package/dist/levels/screen.js +21 -0
  221. package/dist/levels/screen.js.map +1 -0
  222. package/dist/levels/wait.d.ts +27 -0
  223. package/dist/levels/wait.js +61 -0
  224. package/dist/levels/wait.js.map +1 -0
  225. package/dist/loader/build.d.ts +10 -0
  226. package/dist/loader/build.js +28 -0
  227. package/dist/loader/build.js.map +1 -0
  228. package/dist/loader/cache.d.ts +6 -9
  229. package/dist/loader/cache.js +17 -24
  230. package/dist/loader/cache.js.map +1 -1
  231. package/dist/loader/context.d.ts +46 -0
  232. package/dist/loader/context.js +91 -0
  233. package/dist/loader/context.js.map +1 -0
  234. package/dist/loader/{provenance.d.ts → dependencies.d.ts} +5 -3
  235. package/dist/loader/{provenance.js → dependencies.js} +12 -4
  236. package/dist/loader/dependencies.js.map +1 -0
  237. package/dist/loader/index.d.ts +62 -0
  238. package/dist/loader/index.js +284 -0
  239. package/dist/loader/index.js.map +1 -0
  240. package/dist/loader/level.d.ts +41 -0
  241. package/dist/loader/level.js +140 -0
  242. package/dist/loader/level.js.map +1 -0
  243. package/dist/loader/request.d.ts +87 -0
  244. package/dist/loader/request.js +59 -0
  245. package/dist/loader/request.js.map +1 -0
  246. package/dist/loader/url.d.ts +5 -2
  247. package/dist/loader/url.js +10 -6
  248. package/dist/loader/url.js.map +1 -1
  249. package/dist/lod.d.ts +81 -40
  250. package/dist/lod.js +196 -149
  251. package/dist/lod.js.map +1 -1
  252. package/dist/meshopt.d.ts +6 -0
  253. package/dist/meshopt.js +19 -0
  254. package/dist/meshopt.js.map +1 -0
  255. package/dist/simplify/cards.d.ts +14 -0
  256. package/dist/simplify/cards.js +128 -0
  257. package/dist/simplify/cards.js.map +1 -0
  258. package/dist/{simplify.d.ts → simplify/index.d.ts} +7 -4
  259. package/dist/{simplify.js → simplify/index.js} +41 -23
  260. package/dist/simplify/index.js.map +1 -0
  261. package/dist/{bounds.d.ts → source/detail.d.ts} +4 -23
  262. package/dist/{bounds.js → source/detail.js} +19 -51
  263. package/dist/source/detail.js.map +1 -0
  264. package/dist/source/deviation.js +6 -6
  265. package/dist/source/deviation.js.map +1 -1
  266. package/dist/source/{shading.d.ts → evaluator.d.ts} +10 -10
  267. package/dist/source/{shading.js → evaluator.js} +5 -5
  268. package/dist/source/evaluator.js.map +1 -0
  269. package/dist/source/{trace.d.ts → raycaster.d.ts} +6 -6
  270. package/dist/source/{trace.js → raycaster.js} +8 -8
  271. package/dist/source/raycaster.js.map +1 -0
  272. package/dist/source/{texels.d.ts → sampler.d.ts} +1 -1
  273. package/dist/source/{texels.js → sampler.js} +3 -3
  274. package/dist/source/sampler.js.map +1 -0
  275. package/dist/source/source.d.ts +1 -1
  276. package/dist/source/source.js +1 -1
  277. package/dist/source/source.js.map +1 -1
  278. package/dist/source/surface.js +1 -1
  279. package/dist/source/surface.js.map +1 -1
  280. package/dist/task.d.ts +6 -0
  281. package/dist/{pause.js → task.js} +5 -5
  282. package/dist/task.js.map +1 -0
  283. package/dist/three.d.ts +13 -24
  284. package/dist/three.js +26 -53
  285. package/dist/three.js.map +1 -1
  286. package/dist/tsl.d.ts +8 -12
  287. package/dist/tsl.js +11 -39
  288. package/dist/tsl.js.map +1 -1
  289. package/dist/typegpu.d.ts +37 -0
  290. package/dist/typegpu.js +37 -0
  291. package/dist/typegpu.js.map +1 -0
  292. package/dist/wind/bounds.js +2 -2
  293. package/dist/wind/bounds.js.map +1 -1
  294. package/dist/wind/hooks.d.ts +7 -4
  295. package/dist/wind/hooks.js +5 -2
  296. package/dist/wind/hooks.js.map +1 -1
  297. package/dist/wind/index.d.ts +2 -2
  298. package/dist/wind/index.js +15 -15
  299. package/dist/wind/index.js.map +1 -1
  300. package/dist/wind/sway.d.ts +2 -0
  301. package/dist/wind/sway.js +4 -1
  302. package/dist/wind/sway.js.map +1 -1
  303. package/package.json +18 -8
  304. package/skills/lod/SKILL.md +108 -31
  305. package/dist/bounds.js.map +0 -1
  306. package/dist/compile.d.ts +0 -4
  307. package/dist/compile.js +0 -100
  308. package/dist/compile.js.map +0 -1
  309. package/dist/deferred.d.ts +0 -12
  310. package/dist/deferred.js +0 -27
  311. package/dist/deferred.js.map +0 -1
  312. package/dist/fade.d.ts +0 -36
  313. package/dist/fade.js +0 -112
  314. package/dist/fade.js.map +0 -1
  315. package/dist/instanced/args.d.ts +0 -20
  316. package/dist/instanced/args.js +0 -77
  317. package/dist/instanced/args.js.map +0 -1
  318. package/dist/instanced/blocks.d.ts +0 -66
  319. package/dist/instanced/blocks.js +0 -294
  320. package/dist/instanced/blocks.js.map +0 -1
  321. package/dist/instanced/dirty.d.ts +0 -15
  322. package/dist/instanced/dirty.js +0 -96
  323. package/dist/instanced/dirty.js.map +0 -1
  324. package/dist/instanced/parts.d.ts +0 -14
  325. package/dist/instanced/parts.js +0 -79
  326. package/dist/instanced/parts.js.map +0 -1
  327. package/dist/instanced/select.d.ts +0 -92
  328. package/dist/instanced/select.js +0 -315
  329. package/dist/instanced/select.js.map +0 -1
  330. package/dist/instanced/store.d.ts +0 -31
  331. package/dist/instanced/store.js +0 -96
  332. package/dist/instanced/store.js.map +0 -1
  333. package/dist/levels.d.ts +0 -95
  334. package/dist/levels.js +0 -171
  335. package/dist/levels.js.map +0 -1
  336. package/dist/loader/bundle.d.ts +0 -25
  337. package/dist/loader/bundle.js +0 -241
  338. package/dist/loader/bundle.js.map +0 -1
  339. package/dist/loader/provenance.js.map +0 -1
  340. package/dist/loader.d.ts +0 -55
  341. package/dist/loader.js +0 -239
  342. package/dist/loader.js.map +0 -1
  343. package/dist/material.js.map +0 -1
  344. package/dist/mesh/codec.d.ts +0 -4
  345. package/dist/mesh/codec.js.map +0 -1
  346. package/dist/pause.d.ts +0 -6
  347. package/dist/pause.js.map +0 -1
  348. package/dist/queue.d.ts +0 -2
  349. package/dist/queue.js +0 -33
  350. package/dist/queue.js.map +0 -1
  351. package/dist/renderer.d.ts +0 -21
  352. package/dist/renderer.js +0 -83
  353. package/dist/renderer.js.map +0 -1
  354. package/dist/residency.d.ts +0 -44
  355. package/dist/residency.js +0 -205
  356. package/dist/residency.js.map +0 -1
  357. package/dist/simplify.js.map +0 -1
  358. package/dist/source/shading.js.map +0 -1
  359. package/dist/source/texels.js.map +0 -1
  360. package/dist/source/trace.js.map +0 -1
  361. package/dist/view.d.ts +0 -45
  362. package/dist/view.js +0 -131
  363. package/dist/view.js.map +0 -1
  364. /package/dist/{material.d.ts → levels/material.d.ts} +0 -0
@@ -0,0 +1,69 @@
1
+ import { type Camera, Color, type IndirectStorageBufferAttribute, Matrix4, StorageBufferAttribute, StorageInstancedBufferAttribute, type Node, type NodeBuilder, type Object3D } from "three/webgpu";
2
+ /**
3
+ * For one camera, the instances an InstancedLod's level meshes draw: per slot, the instance and its signed fade, and
4
+ * where the camera's indirect draws of them lie, `DRAW_BYTES` apart in the order of the InstancedLod's meshes.
5
+ */
6
+ export interface InstanceSlots {
7
+ /** the index of the instance each slot draws */
8
+ readonly indices: StorageBufferAttribute;
9
+ /** its signed fade */
10
+ readonly fades: StorageBufferAttribute;
11
+ /** Where the camera's indirect draws of the InstancedLod's meshes start (see rows.ts). */
12
+ readonly args: {
13
+ readonly offset: number;
14
+ readonly attribute: IndirectStorageBufferAttribute;
15
+ };
16
+ }
17
+ /** What an InstancedLod's level meshes draw their instances from: every pool index's matrix, and its colour (RGB and a pad). */
18
+ export interface DrawnInstances {
19
+ matrices: StorageInstancedBufferAttribute;
20
+ readonly colors: StorageInstancedBufferAttribute;
21
+ }
22
+ /** How a mesh of a level is drawn, which says where its fade and shadow size come from. */
23
+ export type FadeSource = {
24
+ kind: "object";
25
+ /** the signed fade */
26
+ fade: number;
27
+ /** the whole object's bounding diameter, world units */
28
+ diameter: number;
29
+ /** debug tint, white when off */
30
+ tint: Color;
31
+ } | {
32
+ kind: "instances";
33
+ /** per camera, the instance and signed fade of each slot; null for none (an ImpostorMesh of its own, drawing every instance) */
34
+ slots: ((camera: Camera) => InstanceSlots) | null;
35
+ /** one instance's bounding radius in its own space */
36
+ radius: number;
37
+ tint: Color;
38
+ /**
39
+ * For a plain mesh of an InstancedLod's level: the instances it draws, and `space`, where its geometry's space
40
+ * sits in the source's (InstancedLod draws template geometry moved into the instance's space). An ImpostorMesh
41
+ * carries its own instances.
42
+ */
43
+ level?: {
44
+ readonly instances: DrawnInstances;
45
+ readonly space: Matrix4;
46
+ };
47
+ };
48
+ /** Draw `mesh` as `source` says: its materials read it while it renders. */
49
+ export declare const setFadeSource: (mesh: Object3D, source: FadeSource) => void;
50
+ export declare const fadeSourceOf: (mesh: Object3D) => FadeSource | undefined;
51
+ /** This draw's debug tint (see `Lod.debug`). */
52
+ export declare const tint: import("three/webgpu").UniformNode<"color", Color>;
53
+ /** Interleaved gradient noise over the pixels of the target being drawn. */
54
+ export declare const dither: (pixel: Node<"vec2">) => Node<"float">;
55
+ /** Where `object`'s geometry space sits in its source's: moved for an InstancedLod's plain level mesh (see `FadeSource`). */
56
+ export declare const spaceOf: (object: Object3D | null) => Matrix4 | null;
57
+ /** This draw's instance matrix when its matrices live in storage, else null. */
58
+ export declare function instanceMatrixOf(object: Object3D): Node<"mat4"> | null;
59
+ /** The colour of a draw whose instances have none: given one from the start, a draw's shader stays the same once they do. */
60
+ export declare const white: StorageInstancedBufferAttribute;
61
+ export declare const instanceColor: import("three/webgpu").VaryingNode<"vec3">;
62
+ /** Apply the level's shared instance bindings before its own deformation, as Three does for InstancedMesh. */
63
+ export declare function placeInstances(builder: NodeBuilder): void;
64
+ /** This draw's signed fade. */
65
+ export declare const fade: import("three/src/nodes/TSL.js").FnNode<[], Node<"float">>;
66
+ /** Whether this pixel is this draw's, by its fade: false on the other level's pixels. */
67
+ export declare const keepsPixel: import("three/src/nodes/TSL.js").FnNode<[], Node<"bool">>;
68
+ /** `position` in a shadow map render, or nothing (a point) when the draw is too small to cast. */
69
+ export declare const castPosition: (position: Node<"vec3">) => Node<"vec3">;
@@ -0,0 +1,150 @@
1
+ import { Color, Matrix4, StorageBufferAttribute, StorageInstancedBufferAttribute, } from "three/webgpu";
2
+ import { Fn, NodeUpdateType, cameraProjectionMatrix, dot, float, fract, instanceIndex, modelWorldMatrix, normalLocal, positionLocal, transformNormal, varyingProperty, screenCoordinate, screenSize, select, storage, uniform, uniformGroup, varying, vec2, vec3, } from "three/tsl";
3
+ import { isImpostorMesh, isInstancedMesh, isStorageInstanced } from "../three.js";
4
+ import { column, isOrthographic, maxScale } from "../tsl.js";
5
+ /**
6
+ * Per level mesh, where its fade comes from: a side table, as three's Object3D has no typed place for a package's state
7
+ * (userData is the app's).
8
+ */
9
+ const sources = new WeakMap();
10
+ /** Draw `mesh` as `source` says: its materials read it while it renders. */
11
+ export const setFadeSource = (mesh, source) => void sources.set(mesh, source);
12
+ export const fadeSourceOf = (mesh) => sources.get(mesh);
13
+ const WHITE = new Color(1, 1, 1);
14
+ const of = (object) => (object ? sources.get(object) : undefined);
15
+ // Per-object values, shared by every material: each draw reads its own.
16
+ const objectFade = uniform(0).onObjectUpdate(({ object }) => {
17
+ const draw = of(object);
18
+ return draw?.kind === "object" ? draw.fade : 0;
19
+ });
20
+ // A mesh no level draws is never too small to cast.
21
+ const objectDiameter = uniform(0).onObjectUpdate(({ object }) => {
22
+ const draw = of(object);
23
+ return draw?.kind === "object" ? draw.diameter : 3.4e38;
24
+ });
25
+ const instanceRadius = uniform(0).onObjectUpdate(({ object }) => {
26
+ const draw = of(object);
27
+ return draw?.kind === "instances" ? draw.radius : 0;
28
+ });
29
+ /** This draw's debug tint (see `Lod.debug`). */
30
+ export const tint = uniform(new Color(1, 1, 1)).onObjectUpdate(({ object }) => of(object)?.tint ?? WHITE);
31
+ /** Interleaved gradient noise over the pixels of the target being drawn. */
32
+ export const dither = (pixel) => fract(float(52.9829189).mul(fract(dot(pixel, vec2(0.06711056, 0.00583715)))));
33
+ /** The level mesh `object` is, when it is an InstancedLod's plain one. */
34
+ function levelOf(object) {
35
+ const draw = of(object);
36
+ return draw?.kind === "instances" ? (draw.level ?? null) : null;
37
+ }
38
+ /** The instances where `object` reads its matrices and colours from storage: its own, or its InstancedLod's; else null. */
39
+ function instancesOf(object) {
40
+ if (isImpostorMesh(object))
41
+ return { matrices: object.instanceMatrix, colors: object.instanceColor };
42
+ const level = levelOf(object);
43
+ if (level)
44
+ return level.instances;
45
+ return isInstancedMesh(object) && isStorageInstanced(object.instanceMatrix) ? { matrices: object.instanceMatrix, colors: null } : null;
46
+ }
47
+ /** Where `object`'s geometry space sits in its source's: moved for an InstancedLod's plain level mesh (see `FadeSource`). */
48
+ export const spaceOf = (object) => levelOf(object)?.space ?? null;
49
+ // The draw buffers below are replaced per object, so they stay out of three's texture-keyed
50
+ // binding caches: each render object has its own bindings of this group, while its shader
51
+ // reads the shared nodes.
52
+ const instanceGroup = uniformGroup("lodInstances", 2, NodeUpdateType.OBJECT);
53
+ const identity = new StorageInstancedBufferAttribute(new Float32Array(new Matrix4().elements), 16);
54
+ const matrices = storage(identity, "mat4", 0)
55
+ .setName("lodInstanceMatrices")
56
+ .setGroup(instanceGroup)
57
+ .toReadOnly()
58
+ .onObjectUpdate(({ object }) => {
59
+ const instances = object && instancesOf(object);
60
+ if (!instances)
61
+ throw new Error("Lod: instance draw has no matrices");
62
+ return instances.matrices;
63
+ });
64
+ /** `object`'s slots as `camera` draws it, when it draws slots. */
65
+ function slotsOf(object, camera) {
66
+ const draw = of(object);
67
+ return draw?.kind === "instances" && draw.slots && camera ? draw.slots(camera) : null;
68
+ }
69
+ const zero = new StorageBufferAttribute(new Float32Array(1), 1);
70
+ const fades = storage(zero, "float", 0)
71
+ .setName("lodInstanceFades")
72
+ .setGroup(instanceGroup)
73
+ .toReadOnly()
74
+ .onObjectUpdate(({ object, camera }) => slotsOf(object, camera)?.fades ?? zero);
75
+ const none = new StorageBufferAttribute(new Uint32Array(1), 1);
76
+ const indices = storage(none, "uint", 0)
77
+ .setName("lodInstanceSlots")
78
+ .setGroup(instanceGroup)
79
+ .toReadOnly()
80
+ .onObjectUpdate(({ object, camera }) => slotsOf(object, camera)?.indices ?? none);
81
+ /** 1 when the draw's instances are slots the instance pass for each camera fills, else 0. */
82
+ const slotted = uniform(0, "uint").onObjectUpdate(({ object }) => {
83
+ const draw = of(object);
84
+ return Number(draw?.kind === "instances" && draw.slots !== null);
85
+ });
86
+ const instanceCaster = uniform(false).onObjectUpdate(({ object }) => of(object)?.kind === "instances");
87
+ /** The instance this draw's instance index stands for: the one in its slot, or itself. */
88
+ const instance = Fn(() => slotted.equal(1).select(indices.element(instanceIndex), instanceIndex));
89
+ /** This draw's instance matrix when its matrices live in storage, else null. */
90
+ export function instanceMatrixOf(object) {
91
+ return instancesOf(object) ? matrices.element(instance()) : null;
92
+ }
93
+ /** The colour of a draw whose instances have none: given one from the start, a draw's shader stays the same once they do. */
94
+ export const white = new StorageInstancedBufferAttribute(new Float32Array([1, 1, 1, 1]), 4);
95
+ const colors = storage(white, "vec4", 0)
96
+ .setName("lodInstanceColors")
97
+ .setGroup(instanceGroup)
98
+ .toReadOnly()
99
+ .onObjectUpdate(({ object }) => (object && instancesOf(object)?.colors) || white);
100
+ const colorIndex = uniform(0, "uint").onObjectUpdate(({ object }) => {
101
+ const colors = object && instancesOf(object)?.colors;
102
+ return Number(!!colors && colors !== white);
103
+ });
104
+ export const instanceColor = varying(colors.element(instance().mul(colorIndex)).xyz).setInterpolation("flat");
105
+ /** Apply the level's shared instance bindings before its own deformation, as Three does for InstancedMesh. */
106
+ export function placeInstances(builder) {
107
+ if (!levelOf(builder.object))
108
+ return;
109
+ const matrix = matrices.element(instance());
110
+ positionLocal.assign(matrix.mul(positionLocal).xyz);
111
+ if (builder.geometry.hasAttribute("normal"))
112
+ normalLocal.assign(transformNormal(normalLocal, matrix));
113
+ varyingProperty("vec3", "vInstanceColor").assign(instanceColor);
114
+ }
115
+ /** This draw's signed fade. */
116
+ export const fade = Fn((builder) => {
117
+ if (isImpostorMesh(builder.object))
118
+ return varying(fades.element(instanceIndex.mul(slotted)))
119
+ .setInterpolation("flat")
120
+ .add(objectFade);
121
+ const draw = sources.get(builder.object);
122
+ if (draw?.kind !== "instances" || !draw.slots)
123
+ return objectFade;
124
+ // Constant across the primitive: keep compute-written slots out of fragment bindings.
125
+ return varying(fades.element(instanceIndex)).setInterpolation("flat");
126
+ });
127
+ /** Whether this pixel is this draw's, by its fade: false on the other level's pixels. */
128
+ export const keepsPixel = Fn(() => {
129
+ const f = fade();
130
+ const d = dither(screenCoordinate.xy);
131
+ return select(f.greaterThanEqual(0), d.greaterThanEqual(f), d.lessThan(f.negate()));
132
+ });
133
+ /**
134
+ * Whether this draw is too small for the shadow map being drawn: narrower than a texel
135
+ * of an orthographic (directional light's) map, it would cover a texel centre only by
136
+ * chance, flickering as it or the map moves. Only valid in a shadow map render.
137
+ */
138
+ const tooSmallToCast = Fn((builder) => {
139
+ const object = builder.object;
140
+ const card = isImpostorMesh(object);
141
+ const instance = card || sources.get(object)?.kind === "instances" ? instanceMatrixOf(object) : null;
142
+ const instanced = instance ? maxScale(modelWorldMatrix.mul(instance)).mul(instanceRadius).mul(2) : objectDiameter;
143
+ const diameter = card ? select(instanceCaster, instanced, objectDiameter) : instanced;
144
+ // projection[1][1] is 2 × zoom / (top - bottom)
145
+ const texel = float(2).div(column(cameraProjectionMatrix, 1).y.mul(screenSize.y));
146
+ return isOrthographic(cameraProjectionMatrix).and(diameter.lessThan(texel));
147
+ });
148
+ /** `position` in a shadow map render, or nothing (a point) when the draw is too small to cast. */
149
+ export const castPosition = (position) => select(tooSmallToCast(), vec3(0), position);
150
+ //# sourceMappingURL=fade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fade.js","sourceRoot":"","sources":["../../src/levels/fade.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ import { Color, type Box3, type Object3D } from "three/webgpu";
2
+ import type { d } from "typegpu";
3
+ import { type DrawLevels } from "./draw.js";
4
+ import { LevelHeights } from "./load.js";
5
+ /**
6
+ * One level of a Lod or InstancedLod: an object given, or one `load` makes when a camera first needs it, which `box`
7
+ * bounds meanwhile. `lod.levels` holds the same shape, with `object` the Lod's own copy, once there is one. For an
8
+ * InstancedLod, `object` is the template its level meshes are made from, never in the scene.
9
+ *
10
+ * Objects you give or load are yours to dispose, as a three Mesh never disposes its geometry or material; a Lod frees
11
+ * only what it made of them. LodLoader's are freed when the last Lod holding them is disposed (see `hold`).
12
+ */
13
+ export interface LodLevel {
14
+ /** The level's object: yours to dispose. */
15
+ object?: Object3D;
16
+ /**
17
+ * Makes the level's object, yours to dispose. A load shared across several Lods runs once per Lod; memoize it to
18
+ * share one object.
19
+ */
20
+ load?: () => Promise<Object3D>;
21
+ /** A deferred level's bounds in the Lod's space; empty for a level that draws nothing. */
22
+ box?: Box3;
23
+ /**
24
+ * Largest on-screen height, in CSS pixels × Lod.quality, at which this level draws: Infinity for level 0, the finest;
25
+ * every later one at most (1 - Lod.fade) of its finer neighbour's, which leaves room for the fades. A deferred level
26
+ * needs one. A given level without one gets one measured from its surface deviation (see `simplify`, `bakeMesh`) or
27
+ * its impostor's texels, else half its finer neighbour's (512 for level 1), raised to leave room for the fades;
28
+ * `lod.levels` holds what it got.
29
+ */
30
+ maxPixels?: number;
31
+ /**
32
+ * Holds what the level's object comes from while a Lod draws it: every Lod made from the level, a copy or clone
33
+ * included, calls each distinct `hold` once as it is made, and the release it answers once it is disposed. LodLoader's
34
+ * levels free what they loaded when the last release is called, which spends them: a Lod made from them later throws.
35
+ * LodLoader's levels no Lod ever holds are never freed: they are yours until a Lod holds them.
36
+ */
37
+ hold?: () => () => void;
38
+ }
39
+ /** A level with its threshold, as `lod.levels` holds it. */
40
+ export type ThresholdedLevel = LodLevel & {
41
+ maxPixels: number;
42
+ };
43
+ /** Throws unless `levels` can be drawn: each given or deferred with a finite box, and thresholds as `LodLevel` says. */
44
+ export declare function checkLevels(levels: readonly ThresholdedLevel[], who: string): void;
45
+ /**
46
+ * `inputs` as `lod.levels` holds them: each object cloned, each threshold given or measured (see `LodLevel.maxPixels`)
47
+ * for a source `diameter` across. Throws unless they can be drawn.
48
+ */
49
+ export declare function levelsFrom(inputs: readonly LodLevel[], diameter: number, who: string): ThresholdedLevel[];
50
+ /** The bits of the levels that draw nothing: an empty object or box. */
51
+ export declare function emptyLevels(levels: readonly LodLevel[]): number;
52
+ /** Level `index`'s debug tint, or white. */
53
+ export declare const tintOf: (index: number, debug: boolean) => Color;
54
+ /** Surface deviation from the source, in the source's units. */
55
+ export declare const recordDeviation: (level: Object3D, deviation: number) => void;
56
+ export declare const deviationOf: (level: Object3D) => number | undefined;
57
+ /** What a level's default threshold is measured from: surface deviation, else impostor texels. */
58
+ interface Measured {
59
+ deviation?: number;
60
+ texels?: number;
61
+ }
62
+ export declare function measure(object: Object3D): Measured;
63
+ /** A level to find a threshold for: its own maxPixels, else what it measured. */
64
+ interface Measurable {
65
+ maxPixels?: number;
66
+ measured?: Measured;
67
+ }
68
+ /**
69
+ * Thresholds for `levels` of an object `diameter` across: each level's own maxPixels, else its measured surface
70
+ * deviation's or impostor texels' height, else half the previous one (512 for level 1), raised where needed to leave
71
+ * room for the fades. Throws if the result does not (see `checkLevels`).
72
+ */
73
+ export declare function resolveThresholds(levels: readonly Measurable[], diameter: number, who: string): number[];
74
+ /**
75
+ * A Lod's or InstancedLod's levels as levelsToDraw reads them (see `drawLevels`), checked and encoded again only when a
76
+ * threshold or the forced level has changed. What it returns is shared: read it, do not hold on to it.
77
+ */
78
+ export declare class EncodedLevels {
79
+ private readonly levels;
80
+ /** The bits of the levels that draw nothing. */
81
+ private readonly empty;
82
+ private readonly who;
83
+ private thresholds;
84
+ private forced;
85
+ /** For cameras that fade levels and for those that do not. */
86
+ private encoded;
87
+ constructor(levels: readonly ThresholdedLevel[],
88
+ /** The bits of the levels that draw nothing. */
89
+ empty: number, who: string);
90
+ /** The levels with `forced` the forced level, for a camera that `fades` levels or not. Throws unless they can be drawn. */
91
+ get(forced: number | null, fades: boolean): d.Infer<typeof DrawLevels>;
92
+ /**
93
+ * What `levels`, as `get` gave them, draw at each height with the levels of `loaded` loaded, all by default (see
94
+ * LevelHeights): worked out the first time it is asked, and anew with the levels.
95
+ */
96
+ heights(levels: d.Infer<typeof DrawLevels>, loaded?: number): LevelHeights;
97
+ private encode;
98
+ }
99
+ export {};
@@ -0,0 +1,155 @@
1
+ import { Color } from "three/webgpu";
2
+ import { at } from "../at.js";
3
+ import { levelBox } from "./bounds.js";
4
+ import { texelPixels } from "../impostor/impostor.js";
5
+ import { isImpostorMesh } from "../three.js";
6
+ import { FADE, MAX_LEVELS, drawLevels } from "./draw.js";
7
+ import { LevelHeights } from "./load.js";
8
+ /** Throws unless `levels` can be drawn: each given or deferred with a finite box, and thresholds as `LodLevel` says. */
9
+ export function checkLevels(levels, who) {
10
+ if (levels.length > MAX_LEVELS)
11
+ throw new Error(`${who}: ${levels.length} levels, but at most ${MAX_LEVELS}`);
12
+ levels.forEach(({ object, load, box }, i) => {
13
+ if (!object && !load)
14
+ throw new Error(`${who}: level ${i} has neither an object nor a load`);
15
+ if (!object && !box)
16
+ throw new Error(`${who}: deferred level ${i} needs a box`);
17
+ if (box && !box.isEmpty() && ![...box.min.toArray(), ...box.max.toArray()].every(Number.isFinite))
18
+ throw new Error(`${who}: level ${i}'s box must be finite`);
19
+ });
20
+ checkThresholds(levels.map(({ maxPixels }) => maxPixels), who);
21
+ }
22
+ /** Throws unless `thresholds` are maxPixels as `LodLevel` says. */
23
+ function checkThresholds(thresholds, who) {
24
+ thresholds.forEach((maxPixels, i) => {
25
+ if (i === 0 && maxPixels !== Infinity)
26
+ throw new Error(`${who}: level 0, the source, is used at any height: its maxPixels is Infinity, not ${maxPixels}`);
27
+ if (!(maxPixels > 0))
28
+ throw new Error(`${who}: maxPixels must be > 0, got ${maxPixels}`);
29
+ const finer = thresholds[i - 1];
30
+ if (finer !== undefined && maxPixels > finer * (1 - FADE))
31
+ throw new Error(`${who}: level ${i} has maxPixels ${maxPixels}, but at most ${finer * (1 - FADE)} (${1 - FADE} × level ${i - 1}'s ${finer}) leaves room for the fades`);
32
+ });
33
+ }
34
+ /**
35
+ * `inputs` as `lod.levels` holds them: each object cloned, each threshold given or measured (see `LodLevel.maxPixels`)
36
+ * for a source `diameter` across. Throws unless they can be drawn.
37
+ */
38
+ export function levelsFrom(inputs, diameter, who) {
39
+ const thresholds = resolveThresholds(inputs.map(({ object, maxPixels }) => ({ maxPixels, measured: object && maxPixels === undefined ? measure(object) : undefined })), diameter, who);
40
+ const levels = inputs.map((input, i) => ({ ...input, object: input.object?.clone(), maxPixels: at(thresholds, i) }));
41
+ checkLevels(levels, who);
42
+ return levels;
43
+ }
44
+ /** The bits of the levels that draw nothing: an empty object or box. */
45
+ export function emptyLevels(levels) {
46
+ return levels.reduce((bits, level, i) => (levelBox(level).isEmpty() ? bits | (1 << i) : bits), 0);
47
+ }
48
+ /** Debug tints by level index, see `Lod.debug`. */
49
+ const TINTS = [0xff6060, 0x60ff60, 0x6080ff, 0xffd040, 0xff60ff, 0x60ffff].map((hex) => new Color(hex));
50
+ const WHITE = new Color(1, 1, 1);
51
+ /** Level `index`'s debug tint, or white. */
52
+ export const tintOf = (index, debug) => (debug ? at(TINTS, index % TINTS.length) : WHITE);
53
+ /**
54
+ * Per simplified or baked object, its deviation: a side table, as three's objects have no typed place for it (userData
55
+ * is the app's).
56
+ */
57
+ const deviations = new WeakMap();
58
+ /** Surface deviation from the source, in the source's units. */
59
+ export const recordDeviation = (level, deviation) => void deviations.set(level, deviation);
60
+ export const deviationOf = (level) => deviations.get(level);
61
+ export function measure(object) {
62
+ return { deviation: deviationOf(object), texels: isImpostorMesh(object) ? texelPixels(object.impostor) : undefined };
63
+ }
64
+ /**
65
+ * Thresholds for `levels` of an object `diameter` across: each level's own maxPixels, else its measured surface
66
+ * deviation's or impostor texels' height, else half the previous one (512 for level 1), raised where needed to leave
67
+ * room for the fades. Throws if the result does not (see `checkLevels`).
68
+ */
69
+ export function resolveThresholds(levels, diameter, who) {
70
+ let finer = 1024;
71
+ const defaults = levels.map(({ maxPixels, measured }, index) => {
72
+ if (index === 0)
73
+ return Infinity;
74
+ const base = !measured
75
+ ? maxPixels
76
+ : measured.deviation !== undefined
77
+ ? diameter / Math.max(measured.deviation, diameter * 1e-4)
78
+ : (measured.texels ?? finer / 2);
79
+ if (base === undefined)
80
+ throw new Error(`${who}: deferred level ${index} needs maxPixels`);
81
+ finer = base;
82
+ return base;
83
+ });
84
+ const thresholds = levels.map(() => Infinity);
85
+ let next = 0;
86
+ for (let i = levels.length - 1; i > 0; i--) {
87
+ const value = levels[i]?.maxPixels ?? Math.max(at(defaults, i), 2 * next);
88
+ thresholds[i] = value;
89
+ next = value;
90
+ }
91
+ thresholds[0] = levels[0]?.maxPixels ?? Infinity;
92
+ checkThresholds(thresholds, who);
93
+ return thresholds;
94
+ }
95
+ /**
96
+ * A Lod's or InstancedLod's levels as levelsToDraw reads them (see `drawLevels`), checked and encoded again only when a
97
+ * threshold or the forced level has changed. What it returns is shared: read it, do not hold on to it.
98
+ */
99
+ export class EncodedLevels {
100
+ levels;
101
+ empty;
102
+ who;
103
+ thresholds = [];
104
+ forced = null;
105
+ /** For cameras that fade levels and for those that do not. */
106
+ encoded;
107
+ constructor(levels,
108
+ /** The bits of the levels that draw nothing. */
109
+ empty, who) {
110
+ this.levels = levels;
111
+ this.empty = empty;
112
+ this.who = who;
113
+ this.encoded = this.encode(null);
114
+ }
115
+ /** The levels with `forced` the forced level, for a camera that `fades` levels or not. Throws unless they can be drawn. */
116
+ get(forced, fades) {
117
+ let changed = forced !== this.forced;
118
+ for (let i = 0; i < this.levels.length && !changed; i++)
119
+ changed = this.levels[i]?.maxPixels !== this.thresholds[i];
120
+ if (changed)
121
+ this.encoded = this.encode(forced);
122
+ return (fades ? this.encoded.fading : this.encoded.still).levels;
123
+ }
124
+ /**
125
+ * What `levels`, as `get` gave them, draw at each height with the levels of `loaded` loaded, all by default (see
126
+ * LevelHeights): worked out the first time it is asked, and anew with the levels.
127
+ */
128
+ heights(levels, loaded = (1 << levels.count) - 1) {
129
+ const { fading, still } = this.encoded;
130
+ const encoding = levels === fading.levels ? fading : levels === still.levels ? still : null;
131
+ if (!encoding)
132
+ throw new Error(`${this.who}: heights of levels it did not encode, or no longer does`);
133
+ if (loaded === (1 << levels.count) - 1)
134
+ return (encoding.heights ??= new LevelHeights(levels));
135
+ const { loading } = encoding;
136
+ const found = loading.find((heights) => heights.loaded === loaded);
137
+ if (found)
138
+ return found;
139
+ const made = new LevelHeights(levels, loaded);
140
+ loading.unshift(made);
141
+ loading.length = Math.min(loading.length, 2);
142
+ return made;
143
+ }
144
+ encode(forced) {
145
+ const { levels, empty, who } = this;
146
+ checkLevels(levels, who);
147
+ if (forced !== null && !levels[forced])
148
+ throw new Error(`${who}: forceLevel ${forced} is not a level`);
149
+ this.thresholds = levels.map(({ maxPixels }) => maxPixels);
150
+ this.forced = forced;
151
+ const encoding = (fades) => ({ levels: drawLevels(levels, empty, forced, fades), heights: null, loading: [] });
152
+ return { fading: encoding(true), still: encoding(false) };
153
+ }
154
+ }
155
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/levels/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { type LoadingManager, type Object3D, type Renderer } from "three/webgpu";
2
+ /**
3
+ * A Lod's item on a LoadingManager, held while it loads: the manager hears of it in a microtask, once the render that
4
+ * changed it has returned, so what an app's callback does, such as throw or render, happens outside three's render.
5
+ */
6
+ export declare class LoadingItem {
7
+ private readonly lod;
8
+ /** The item's name: the kind of Lod and its uuid. */
9
+ private readonly name;
10
+ private readonly renderer;
11
+ /** The LoadingManager given; else the nearest Lod above's, else three's default (see `manager`). */
12
+ given: LoadingManager | undefined;
13
+ /** The LoadingManager the held item started on, which it ends on. */
14
+ private holding;
15
+ /** Whether the Lod was updated since the item's last look at its renderer, the renders then, and whether a look is due. */
16
+ private updated;
17
+ private renders;
18
+ private looking;
19
+ constructor(lod: Object3D,
20
+ /** The item's name: the kind of Lod and its uuid. */
21
+ name: string, renderer: Renderer);
22
+ /** Where the item goes. */
23
+ get manager(): LoadingManager;
24
+ /** A render updated the Lod: the next look at the renderer's renders does not end the item. */
25
+ touch(): void;
26
+ /** Hold the item if `held`, else end it; while it is held, look at the renderer's renders (see `look`). */
27
+ sync(held: boolean): void;
28
+ /** Report a failure on the LoadingManager the item is held on, and end the item. */
29
+ fail(): void;
30
+ private hold;
31
+ /**
32
+ * While the item is held, look a frame's time apart at the renderer's renders: a Lod its renderer rendered around for
33
+ * a frame without updating it (hidden, on a layer no camera tests, out of the scene) ends its item; its next update
34
+ * starts it again. Renders of other scenes in a separate task can end it early, and the next update reopens it; a
35
+ * renderer that only compiles holds a hidden Lod's item.
36
+ */
37
+ private look;
38
+ }
@@ -0,0 +1,97 @@
1
+ import { DefaultLoadingManager } from "three/webgpu";
2
+ import { hasLoadingManager } from "./renderer.js";
3
+ /** How long a held item waits between looks at its renderer's renders (see `look`): a frame's time. */
4
+ const LOOK_MS = 16;
5
+ /**
6
+ * A Lod's item on a LoadingManager, held while it loads: the manager hears of it in a microtask, once the render that
7
+ * changed it has returned, so what an app's callback does, such as throw or render, happens outside three's render.
8
+ */
9
+ export class LoadingItem {
10
+ lod;
11
+ name;
12
+ renderer;
13
+ /** The LoadingManager given; else the nearest Lod above's, else three's default (see `manager`). */
14
+ given;
15
+ /** The LoadingManager the held item started on, which it ends on. */
16
+ holding;
17
+ /** Whether the Lod was updated since the item's last look at its renderer, the renders then, and whether a look is due. */
18
+ updated = false;
19
+ renders = 0;
20
+ looking = false;
21
+ constructor(lod,
22
+ /** The item's name: the kind of Lod and its uuid. */
23
+ name, renderer) {
24
+ this.lod = lod;
25
+ this.name = name;
26
+ this.renderer = renderer;
27
+ }
28
+ /** Where the item goes. */
29
+ get manager() {
30
+ if (this.given)
31
+ return this.given;
32
+ for (let node = this.lod.parent; node; node = node.parent)
33
+ if (hasLoadingManager(node))
34
+ return node.manager;
35
+ return DefaultLoadingManager;
36
+ }
37
+ /** A render updated the Lod: the next look at the renderer's renders does not end the item. */
38
+ touch() {
39
+ this.updated = true;
40
+ }
41
+ /** Hold the item if `held`, else end it; while it is held, look at the renderer's renders (see `look`). */
42
+ sync(held) {
43
+ this.hold(held);
44
+ if (!this.holding || this.looking)
45
+ return;
46
+ // The first look only counts the renders: those still to come in this render are not without an update.
47
+ this.updated = true;
48
+ this.look();
49
+ }
50
+ /** Report a failure on the LoadingManager the item is held on, and end the item. */
51
+ fail() {
52
+ const manager = this.holding;
53
+ const { name } = this;
54
+ if (manager)
55
+ queueMicrotask(() => manager.itemError(name));
56
+ this.hold(false);
57
+ }
58
+ hold(held) {
59
+ if (held === (this.holding !== undefined))
60
+ return;
61
+ const { name } = this;
62
+ if (held) {
63
+ const manager = (this.holding = this.manager);
64
+ queueMicrotask(() => manager.itemStart(name));
65
+ return;
66
+ }
67
+ const manager = this.holding;
68
+ this.holding = undefined;
69
+ if (manager)
70
+ queueMicrotask(() => manager.itemEnd(name));
71
+ }
72
+ /**
73
+ * While the item is held, look a frame's time apart at the renderer's renders: a Lod its renderer rendered around for
74
+ * a frame without updating it (hidden, on a layer no camera tests, out of the scene) ends its item; its next update
75
+ * starts it again. Renders of other scenes in a separate task can end it early, and the next update reopens it; a
76
+ * renderer that only compiles holds a hidden Lod's item.
77
+ */
78
+ look() {
79
+ const { renderer } = this;
80
+ this.looking = true;
81
+ const timer = setTimeout(() => {
82
+ this.looking = false;
83
+ if (!this.holding)
84
+ return;
85
+ const renders = renderer.info.render.calls;
86
+ if (renders !== this.renders && !this.updated)
87
+ return this.hold(false);
88
+ this.renders = renders;
89
+ this.updated = false;
90
+ this.look();
91
+ }, LOOK_MS);
92
+ // A held item must not hold Node.js open.
93
+ if (typeof timer === "object" && timer !== null && "unref" in timer && typeof timer.unref === "function")
94
+ timer.unref();
95
+ }
96
+ }
97
+ //# sourceMappingURL=item.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"item.js","sourceRoot":"","sources":["../../src/levels/item.ts"],"names":[],"mappings":"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"}