@drawcall/lod 0.3.0 → 0.5.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 (204) hide show
  1. package/README.md +5 -8
  2. package/dist/bake.d.ts +16 -2
  3. package/dist/bake.js +92 -4
  4. package/dist/bake.js.map +1 -1
  5. package/dist/baked/index.d.ts +2 -2
  6. package/dist/baked/index.js +2 -2
  7. package/dist/baked/interior/faces.js +4 -2
  8. package/dist/baked/interior/faces.js.map +1 -1
  9. package/dist/baked/interior/material.js +1 -1
  10. package/dist/baked/interior/material.js.map +1 -1
  11. package/dist/baked/interior/rooms.d.ts +1 -1
  12. package/dist/baked/interior/rooms.js +1 -1
  13. package/dist/dispose.d.ts +3 -3
  14. package/dist/dispose.js +6 -6
  15. package/dist/dispose.js.map +1 -1
  16. package/dist/foliage.d.ts +32 -0
  17. package/dist/foliage.js +137 -0
  18. package/dist/foliage.js.map +1 -0
  19. package/dist/impostor/bake/index.d.ts +3 -3
  20. package/dist/impostor/bake/index.js +12 -3
  21. package/dist/impostor/bake/index.js.map +1 -1
  22. package/dist/impostor/bake/source.d.ts +2 -1
  23. package/dist/impostor/bake/source.js +2 -2
  24. package/dist/impostor/bake/source.js.map +1 -1
  25. package/dist/impostor/impostor.d.ts +1 -1
  26. package/dist/impostor/impostor.js +1 -1
  27. package/dist/impostor/ktx2/encode.js +5 -2
  28. package/dist/impostor/ktx2/encode.js.map +1 -1
  29. package/dist/impostor/ktx2/uastc.js +3 -2
  30. package/dist/impostor/ktx2/uastc.js.map +1 -1
  31. package/dist/impostor/ktx2/worker.js +0 -2
  32. package/dist/impostor/ktx2/worker.js.map +1 -1
  33. package/dist/impostor/mesh/card.d.ts +1 -1
  34. package/dist/impostor/mesh/index.d.ts +2 -2
  35. package/dist/impostor/mesh/index.js +3 -3
  36. package/dist/impostor/mesh/index.js.map +1 -1
  37. package/dist/index.d.ts +3 -6
  38. package/dist/index.js +3 -6
  39. package/dist/index.js.map +1 -1
  40. package/dist/instanced/camera.d.ts +13 -25
  41. package/dist/instanced/camera.js +17 -42
  42. package/dist/instanced/camera.js.map +1 -1
  43. package/dist/instanced/clusters.d.ts +68 -0
  44. package/dist/instanced/clusters.js +172 -0
  45. package/dist/instanced/clusters.js.map +1 -0
  46. package/dist/instanced/cull.d.ts +3 -3
  47. package/dist/instanced/cull.js +2 -2
  48. package/dist/instanced/cull.js.map +1 -1
  49. package/dist/instanced/instances.d.ts +39 -0
  50. package/dist/instanced/instances.js +104 -0
  51. package/dist/instanced/instances.js.map +1 -0
  52. package/dist/instanced/key.d.ts +1 -1
  53. package/dist/instanced/key.js +1 -1
  54. package/dist/instanced/key.js.map +1 -1
  55. package/dist/instanced/levels.d.ts +9 -9
  56. package/dist/instanced/levels.js +7 -6
  57. package/dist/instanced/levels.js.map +1 -1
  58. package/dist/instanced/lists.d.ts +29 -39
  59. package/dist/instanced/lists.js +45 -62
  60. package/dist/instanced/lists.js.map +1 -1
  61. package/dist/instanced/measure.d.ts +2 -2
  62. package/dist/instanced/measure.js +2 -2
  63. package/dist/instanced/meshes.d.ts +11 -9
  64. package/dist/instanced/meshes.js +26 -16
  65. package/dist/instanced/meshes.js.map +1 -1
  66. package/dist/instanced/mirror.d.ts +16 -12
  67. package/dist/instanced/mirror.js +51 -12
  68. package/dist/instanced/mirror.js.map +1 -1
  69. package/dist/instanced/raycast.d.ts +6 -9
  70. package/dist/instanced/raycast.js +15 -18
  71. package/dist/instanced/raycast.js.map +1 -1
  72. package/dist/instanced/rows.d.ts +22 -73
  73. package/dist/instanced/rows.js +24 -189
  74. package/dist/instanced/rows.js.map +1 -1
  75. package/dist/instanced/shape.d.ts +3 -1
  76. package/dist/instanced/shape.js +6 -3
  77. package/dist/instanced/shape.js.map +1 -1
  78. package/dist/instanced/sort.d.ts +36 -34
  79. package/dist/instanced/sort.js +168 -132
  80. package/dist/instanced/sort.js.map +1 -1
  81. package/dist/instanced/update.d.ts +17 -12
  82. package/dist/instanced/update.js +64 -85
  83. package/dist/instanced/update.js.map +1 -1
  84. package/dist/levels/compile/index.d.ts +4 -2
  85. package/dist/levels/compile/index.js +10 -2
  86. package/dist/levels/compile/index.js.map +1 -1
  87. package/dist/levels/compile/pipelines.d.ts +1 -1
  88. package/dist/levels/compile/pipelines.js +1 -6
  89. package/dist/levels/compile/pipelines.js.map +1 -1
  90. package/dist/levels/draw.d.ts +1 -1
  91. package/dist/levels/draw.js +3 -3
  92. package/dist/levels/fade.d.ts +13 -22
  93. package/dist/levels/fade.js +17 -38
  94. package/dist/levels/fade.js.map +1 -1
  95. package/dist/levels/index.d.ts +7 -7
  96. package/dist/levels/index.js +1 -1
  97. package/dist/levels/item.d.ts +10 -10
  98. package/dist/levels/item.js +15 -23
  99. package/dist/levels/item.js.map +1 -1
  100. package/dist/levels/load.d.ts +1 -1
  101. package/dist/levels/load.js +5 -3
  102. package/dist/levels/load.js.map +1 -1
  103. package/dist/levels/manager.d.ts +30 -31
  104. package/dist/levels/manager.js +75 -62
  105. package/dist/levels/manager.js.map +1 -1
  106. package/dist/levels/material.d.ts +2 -2
  107. package/dist/levels/material.js +2 -2
  108. package/dist/levels/renderer.d.ts +8 -5
  109. package/dist/levels/renderer.js +20 -4
  110. package/dist/levels/renderer.js.map +1 -1
  111. package/dist/levels/requests.d.ts +4 -1
  112. package/dist/levels/requests.js +3 -1
  113. package/dist/levels/requests.js.map +1 -1
  114. package/dist/loader/context.d.ts +9 -11
  115. package/dist/loader/context.js +12 -7
  116. package/dist/loader/context.js.map +1 -1
  117. package/dist/loader/entry.d.ts +4 -0
  118. package/dist/loader/entry.js +43 -0
  119. package/dist/loader/entry.js.map +1 -0
  120. package/dist/loader/index.d.ts +49 -35
  121. package/dist/loader/index.js +123 -135
  122. package/dist/loader/index.js.map +1 -1
  123. package/dist/loader/level.js +5 -5
  124. package/dist/loader/level.js.map +1 -1
  125. package/dist/loader/node.d.ts +26 -0
  126. package/dist/loader/node.js +199 -0
  127. package/dist/loader/node.js.map +1 -0
  128. package/dist/loader/request.d.ts +11 -44
  129. package/dist/loader/request.js +7 -47
  130. package/dist/loader/request.js.map +1 -1
  131. package/dist/loader/url.d.ts +10 -9
  132. package/dist/loader/url.js +21 -17
  133. package/dist/loader/url.js.map +1 -1
  134. package/dist/lod.d.ts +122 -62
  135. package/dist/lod.js +332 -187
  136. package/dist/lod.js.map +1 -1
  137. package/dist/meshopt.d.ts +1 -1
  138. package/dist/meshopt.js +3 -2
  139. package/dist/meshopt.js.map +1 -1
  140. package/dist/node-process.d.ts +5 -0
  141. package/dist/node-process.js +6 -0
  142. package/dist/node-process.js.map +1 -0
  143. package/dist/node.d.ts +2 -0
  144. package/dist/node.js +5 -0
  145. package/dist/node.js.map +1 -0
  146. package/dist/simplify/index.d.ts +2 -2
  147. package/dist/simplify/index.js +7 -7
  148. package/dist/simplify/index.js.map +1 -1
  149. package/dist/source/detail.d.ts +7 -2
  150. package/dist/source/detail.js +26 -22
  151. package/dist/source/detail.js.map +1 -1
  152. package/dist/source/sampler.js +5 -2
  153. package/dist/source/sampler.js.map +1 -1
  154. package/dist/three.d.ts +8 -7
  155. package/dist/three.js +5 -4
  156. package/dist/three.js.map +1 -1
  157. package/dist/wind/bounds.js +1 -1
  158. package/dist/wind/bounds.js.map +1 -1
  159. package/dist/wind/hooks.d.ts +1 -1
  160. package/dist/wind/hooks.js +1 -1
  161. package/dist/wind/index.d.ts +3 -3
  162. package/dist/wind/index.js +11 -9
  163. package/dist/wind/index.js.map +1 -1
  164. package/package.json +10 -6
  165. package/skills/lod/SKILL.md +65 -54
  166. package/dist/gpu.d.ts +0 -39
  167. package/dist/gpu.js +0 -41
  168. package/dist/gpu.js.map +0 -1
  169. package/dist/instanced/chunk.d.ts +0 -97
  170. package/dist/instanced/chunk.js +0 -156
  171. package/dist/instanced/chunk.js.map +0 -1
  172. package/dist/instanced/chunks.d.ts +0 -60
  173. package/dist/instanced/chunks.js +0 -208
  174. package/dist/instanced/chunks.js.map +0 -1
  175. package/dist/instanced/index.d.ts +0 -120
  176. package/dist/instanced/index.js +0 -290
  177. package/dist/instanced/index.js.map +0 -1
  178. package/dist/instanced/pages/buffers.d.ts +0 -37
  179. package/dist/instanced/pages/buffers.js +0 -15
  180. package/dist/instanced/pages/buffers.js.map +0 -1
  181. package/dist/instanced/pages/chunk.d.ts +0 -51
  182. package/dist/instanced/pages/chunk.js +0 -81
  183. package/dist/instanced/pages/chunk.js.map +0 -1
  184. package/dist/instanced/pages/index.d.ts +0 -74
  185. package/dist/instanced/pages/index.js +0 -269
  186. package/dist/instanced/pages/index.js.map +0 -1
  187. package/dist/instanced/pages/passes.d.ts +0 -21
  188. package/dist/instanced/pages/passes.js +0 -52
  189. package/dist/instanced/pages/passes.js.map +0 -1
  190. package/dist/instanced/pages/slots.d.ts +0 -11
  191. package/dist/instanced/pages/slots.js +0 -90
  192. package/dist/instanced/pages/slots.js.map +0 -1
  193. package/dist/instanced/pages/workgroup.d.ts +0 -14
  194. package/dist/instanced/pages/workgroup.js +0 -38
  195. package/dist/instanced/pages/workgroup.js.map +0 -1
  196. package/dist/levels/wait.d.ts +0 -27
  197. package/dist/levels/wait.js +0 -61
  198. package/dist/levels/wait.js.map +0 -1
  199. package/dist/loader/cache.d.ts +0 -12
  200. package/dist/loader/cache.js +0 -68
  201. package/dist/loader/cache.js.map +0 -1
  202. package/dist/loader/dependencies.d.ts +0 -32
  203. package/dist/loader/dependencies.js +0 -113
  204. package/dist/loader/dependencies.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * How a Lod or InstancedLod takes wind: it refuses it once it has rendered or prepares levels, whose shaders would then
2
+ * How a Lod takes wind: it refuses it once it has rendered or prepares levels, whose shaders would then
3
3
  * build in a frame; else it pads its setup-only culling and casters, while the levels it draws hold their rest bounds.
4
4
  */
5
5
  export const WIND = Symbol("wind");
@@ -15,7 +15,7 @@ export interface SwayOptions {
15
15
  }
16
16
  /**
17
17
  * A shared GPU breeze: an affine sway, fixed at the base and linear with height.
18
- * Bake/build levels first, apply once to the completed Lod, InstancedLod, mesh or
18
+ * Bake/build levels first, apply once to the completed Lod, mesh or
19
19
  * mesh group, then set time once before rendering each frame. All levels and shadow
20
20
  * passes share the motion. Simplified and baked meshes need no special preparation.
21
21
  *
@@ -28,7 +28,7 @@ export interface SwayOptions {
28
28
  * must stay fixed after applying; move/rotate/scale the root or its instances instead.
29
29
  * Nested LODs and nested instance batches must be applied individually; an
30
30
  * InstancedMesh sways only with its matrices in a storage buffer (an ImpostorMesh's are).
31
- * Lod, InstancedLod and ImpostorMesh clones retain the shared breeze. For ordinary
31
+ * Lod and ImpostorMesh clones retain the shared breeze. For ordinary
32
32
  * Mesh/Group clones, apply to each clone too: the material is shared but the sway is
33
33
  * the mesh's. Tangent-space normal maps are supported (tangents do not sway);
34
34
  * object-space normal maps are not.
@@ -47,7 +47,7 @@ export declare class Wind {
47
47
  set strength(value: number);
48
48
  get direction(): readonly [number, number];
49
49
  set direction([x, z]: readonly [number, number]);
50
- /** Attach once, after constructing all levels and before a Lod or InstancedLod first renders. Objects without this call draw with their original shaders. */
50
+ /** Attach once, after constructing all levels and before a Lod first renders. Objects without this call draw with their original shaders. */
51
51
  apply(root: Object3D, { amplitude, baseY, height }: SwayOptions): void;
52
52
  /** Attach meshes arriving with a deferred level; existing meshes retain their bounds. */
53
53
  private attach;
@@ -1,8 +1,9 @@
1
1
  import { Box3, Matrix4, ObjectSpaceNormalMap, Vector2 } from "three/webgpu";
2
2
  import { levelBox } from "../levels/bounds.js";
3
3
  import { boundingBox } from "../source/detail.js";
4
+ import { fadeSourceOf } from "../levels/fade.js";
4
5
  import { levelMaterial } from "../levels/material.js";
5
- import { isBatchedMesh, isImpostorMesh, isInstancedLod, isInstancedMesh, isLOD, isMesh, isSkinnedMesh, isStorageInstanced } from "../three.js";
6
+ import { isBatchedMesh, isImpostorMesh, isLod, isInstancedMesh, isLOD, isMesh, isSkinnedMesh, isStorageInstanced } from "../three.js";
6
7
  import { WIND } from "./hooks.js";
7
8
  import { windBounds } from "./bounds.js";
8
9
  import { setSway, swayMatrix, swaying } from "./sway.js";
@@ -14,7 +15,7 @@ const identity = new Matrix4();
14
15
  const impostorSway = swayMatrix();
15
16
  /**
16
17
  * A shared GPU breeze: an affine sway, fixed at the base and linear with height.
17
- * Bake/build levels first, apply once to the completed Lod, InstancedLod, mesh or
18
+ * Bake/build levels first, apply once to the completed Lod, mesh or
18
19
  * mesh group, then set time once before rendering each frame. All levels and shadow
19
20
  * passes share the motion. Simplified and baked meshes need no special preparation.
20
21
  *
@@ -27,7 +28,7 @@ const impostorSway = swayMatrix();
27
28
  * must stay fixed after applying; move/rotate/scale the root or its instances instead.
28
29
  * Nested LODs and nested instance batches must be applied individually; an
29
30
  * InstancedMesh sways only with its matrices in a storage buffer (an ImpostorMesh's are).
30
- * Lod, InstancedLod and ImpostorMesh clones retain the shared breeze. For ordinary
31
+ * Lod and ImpostorMesh clones retain the shared breeze. For ordinary
31
32
  * Mesh/Group clones, apply to each clone too: the material is shared but the sway is
32
33
  * the mesh's. Tangent-space normal maps are supported (tangents do not sway);
33
34
  * object-space normal maps are not.
@@ -75,7 +76,7 @@ export class Wind {
75
76
  throw new Error("Wind: direction must be nonzero");
76
77
  this.breeze.direction.set(x, z).normalize();
77
78
  }
78
- /** Attach once, after constructing all levels and before a Lod or InstancedLod first renders. Objects without this call draw with their original shaders. */
79
+ /** Attach once, after constructing all levels and before a Lod first renders. Objects without this call draw with their original shaders. */
79
80
  apply(root, { amplitude, baseY, height }) {
80
81
  if (bindings.has(root))
81
82
  throw new Error("Wind: already applied to this object");
@@ -88,7 +89,8 @@ export class Wind {
88
89
  added.traverse((node) => {
89
90
  if (node !== root && isLOD(node))
90
91
  throw new Error("Wind: apply to nested LODs individually");
91
- if (!isMesh(node))
92
+ // A Lod's meshes beside its level meshes draw nothing.
93
+ if (!isMesh(node) || (isLod(root) && !fadeSourceOf(node)))
92
94
  return;
93
95
  if (refreshing && swaying(node))
94
96
  return;
@@ -96,7 +98,7 @@ export class Wind {
96
98
  throw new Error("Wind: a mesh already belongs to a wind root");
97
99
  if (isSkinnedMesh(node) || isBatchedMesh(node))
98
100
  throw new Error("Wind: skinned and batched meshes are not supported");
99
- if (node !== root && !isInstancedLod(root) && (isInstancedMesh(node) || (isImpostorMesh(node) && node.count > 1)))
101
+ if (node !== root && !isLod(root) && (isInstancedMesh(node) || (isImpostorMesh(node) && node.count > 1)))
100
102
  throw new Error("Wind: apply to nested instance batches individually");
101
103
  if (isInstancedMesh(node) && !isStorageInstanced(node.instanceMatrix))
102
104
  throw new Error(`Wind: InstancedMesh "${node.name}" needs its instance matrices in a StorageInstancedBufferAttribute`);
@@ -116,9 +118,9 @@ export class Wind {
116
118
  invertible(root.matrixWorld);
117
119
  const inverse = root.matrixWorld.clone().invert();
118
120
  const placed = meshes.map((mesh) => {
119
- // InstancedLod has already placed ordinary geometry in instance space; its
121
+ // A Lod has already placed ordinary geometry in instance space; its
120
122
  // impostors carry placement separately. Avoid roundoff defeating the fast path.
121
- const placement = mesh === root || isInstancedLod(root) ? identity.clone() : inverse.clone().multiply(mesh.matrixWorld);
123
+ const placement = mesh === root || isLod(root) ? identity.clone() : inverse.clone().multiply(mesh.matrixWorld);
122
124
  invertible(placement);
123
125
  return { mesh, placement };
124
126
  });
@@ -136,7 +138,7 @@ export class Wind {
136
138
  if (isWindTarget(root) && !refreshing)
137
139
  root[WIND](padding, amplitude / size, base);
138
140
  for (const { mesh, placement } of placed) {
139
- if (!isInstancedLod(root))
141
+ if (!isLod(root))
140
142
  windBounds(mesh, placement, amplitude, base, size);
141
143
  setSway(mesh, { breeze: this.breeze, shape, placement, fromRoot: placement.clone().invert() });
142
144
  if (isImpostorMesh(mesh)) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/wind/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/wind/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawcall/lod",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "description": "Level of detail for three.js: octahedral impostors, simplified and baked meshes, with dithered switching by on-screen size. WebGPURenderer only.",
6
6
  "keywords": [
@@ -16,6 +16,7 @@
16
16
  "exports": {
17
17
  ".": {
18
18
  "types": "./dist/index.d.ts",
19
+ "node": "./dist/node.js",
19
20
  "default": "./dist/index.js"
20
21
  }
21
22
  },
@@ -29,20 +30,22 @@
29
30
  "LICENSE"
30
31
  ],
31
32
  "dependencies": {
33
+ "@drawcall/webgpu": "^0.2.1",
32
34
  "fflate": "^0.8.2",
35
+ "import-meta-resolve": "^4.2.0",
33
36
  "ktx-parse": "^2.0.0",
34
37
  "meshoptimizer": "^1.3.0",
35
- "three-mesh-bvh": "^0.9.15",
36
- "vitecache": "^0.2.1"
38
+ "three-mesh-bvh": "^0.9.15"
37
39
  },
38
40
  "peerDependencies": {
39
- "@drawcall/glts": "^4.1.0",
41
+ "@drawcall/glts": "^6.0.0",
40
42
  "three": ">=0.186.0",
41
- "typegpu": "^0.12.9"
43
+ "typegpu": "^0.12.9",
44
+ "vitecache": "^0.5.0"
42
45
  },
43
46
  "devDependencies": {
44
47
  "@babel/core": "^7.29.13",
45
- "@drawcall/glts": "^4.1.0",
48
+ "@drawcall/glts": "^6.0.0",
46
49
  "@drawcall/lod": "link:",
47
50
  "@typegpu/gl": "^0.12.9",
48
51
  "@typegpu/three": "^0.12.2",
@@ -57,6 +60,7 @@
57
60
  "typegpu": "0.12.9",
58
61
  "typescript": "^5.9.3",
59
62
  "unplugin-typegpu": "^0.12.8",
63
+ "vitecache": "^0.5.0",
60
64
  "vitest": "^4.0.17",
61
65
  "xatlas-wasm": "0.1.3"
62
66
  },
@@ -1,100 +1,109 @@
1
1
  ---
2
2
  name: lod
3
- description: Use @drawcall/lod for cached, progressively loaded levels of detail in three.js WebGPURenderer scenes. Covers model and procedural assets, mesh simplification, baked meshes, impostors, instanced copies, wind, interior mapping, asset preparation and capturing fully loaded frames; not WebGLRenderer or skinned animation.
3
+ description: Use @drawcall/lod for cached, progressively loaded levels of detail in three.js WebGPURenderer scenes. Covers model and procedural assets, LODs inside .glts assets, mesh simplification, baked meshes, impostors, instanced copies, wind, interior mapping, asset preparation and capturing fully loaded frames; not WebGLRenderer or skinned animation.
4
4
  ---
5
5
 
6
6
  # Level of detail with @drawcall/lod
7
7
 
8
8
  ## Start with the loader
9
9
 
10
- Give the host's `LodLoader` an asset URL and the representations to derive from it. Use `.glb` or `.gltf` for stored models and `.glts` for procedural assets. Put generation parameters in the asset URL's query: each distinct query is a distinct cache identity. Build a `Lod` from the returned levels for an independently placed object, or an `InstancedLod` for repeated objects, whose instances arrive and leave in chunks of matrices and colours, from the CPU or from a compute pass of yours.
10
+ Give a `CachedLodLoader` an asset URL and the representations to derive from it. Use `.glb` or `.gltf` for stored models and `.glts` for procedural assets. Put generation parameters in the asset URL's query: each distinct query is a distinct cache identity. Build a `Lod` from the returned levels. A `Lod` is driven like three's `InstancedMesh`: `new Lod(levels)` is one object at the Lod's own transform, and `new Lod(levels, count)` draws `count` copies placed by `instanceMatrix` and tinted by `instanceColor`.
11
11
 
12
- Make a `LodGpu` once the renderer is initialised and give it to every `Lod` and `InstancedLod` drawing with that renderer. Every InstancedLod of one LodGpu sorts for a camera in one compute call. A camera that draws only a few InstancedLods, such as a minimap's, can give those a LodGpu of their own, which bounds the per-camera list memory. `LodLoader` needs no renderer.
12
+ A `Lod` needs no renderer to be made, and neither does `CachedLodLoader`. It draws with the first `WebGPURenderer` that renders it, on WebGPU only: on the WebGL2 fallback it reports an error and draws nothing. Another renderer drawing it is its error, so a second renderer, such as a minimap's, needs Lods of its own.
13
13
 
14
- `loadAsync` resolves with the ladder before its levels load; each level loads when a camera first needs it. On a cold cache a derived level is built when it first loads, so a cold far camera builds only the coarse levels it needs. Give simplified and baked levels an explicit `maxPixels`: without one, a level is built with the ladder to measure its default. A simplified level also loads the source for its original materials; a source-only ladder loads its source eagerly. Prefer baked or impostor middle levels for an expensive `.glts`: a simplified level brings the script run forward to that viewing range.
14
+ `loadAsync` resolves with the ladder before its levels load; each level loads when a camera first needs it. A level the cache lacks is built when it first loads, so a far camera builds only the coarse levels it needs. Give simplified and baked levels an explicit `maxPixels`: without one, a level is built with the ladder to measure its default. A simplified level also loads the source for its original materials; a source-only ladder loads its source eagerly. Prefer baked or impostor middle levels for an expensive `.glts`: a simplified level brings the script run forward to that viewing range.
15
15
 
16
16
  Choose levels from the asset's silhouette, materials and expected viewing range. Alpha-tested leaf cards often work best as source → impostor; a simplified level has fewer of them, whole and enlarged to the same coverage, so at a low ratio its foliage reads coarser than the source up close. Hard-surface props often suit source → simplified → impostor. Detailed structures can use source → baked shell → impostor, with interiors supplied separately for windows. A very heavy source, such as a two-million-triangle scan, needs a simplified level between source and impostor, or every copy in mid range draws the full mesh. Add an empty final level when the object should disappear at distance.
17
17
 
18
- Register the source loaders on the loading manager before loading: a `GLTSLoader` for `.glts` URLs, and a `GLTFLoader` with the decoders for models compressed with Draco or KTX2. Follow the [GLTS skill](https://github.com/drawcall-ai/glts/blob/main/packages/glts/skills/glts/SKILL.md) for the Vite plugin, script authoring and resource lifetimes. The package carries its own workers and WebAssembly; it needs no Vite configuration beyond the vitecache plugin.
18
+ Register the source loaders on the page's loading manager before loading: a `GLTSLoader` for `.glts` URLs, and a `GLTFLoader` with the decoders for models compressed with Draco or KTX2. Follow the [GLTS skill](https://github.com/drawcall-ai/glts/blob/main/packages/glts/skills/glts/SKILL.md) for script authoring and resource lifetimes. The package carries its own workers and WebAssembly; it needs no Vite configuration beyond the vitecache plugin.
19
19
 
20
- This example draws many copies of one procedural asset. `positions` contains their placements in the InstancedLod's space, `renderer` is the application's WebGPURenderer and `scene` its scene.
20
+ This example draws many copies of one procedural asset. `positions` contains their placements in the Lod's space and `scene` is the application's scene.
21
21
 
22
22
  ```ts
23
- import { InstancedBufferAttribute, LoadingManager, Matrix4 } from "three/webgpu";
23
+ import { LoadingManager, Matrix4 } from "three/webgpu";
24
24
  import { GLTSLoader } from "@drawcall/glts";
25
- import { InstancedLod, LodGpu, LodLoader } from "@drawcall/lod";
26
-
27
- await renderer.init();
28
- const gpu = new LodGpu(renderer);
25
+ import { CachedLodLoader, Lod } from "@drawcall/lod";
29
26
 
30
27
  const manager = new LoadingManager();
31
28
  manager.addHandler(/\.glts$/, new GLTSLoader(manager));
32
- const loader = new LodLoader(manager);
33
- const levels = await loader.loadAsync({
29
+ const levels = await new CachedLodLoader(manager).loadAsync({
34
30
  url: "/trees/oak.glts?seed=2",
35
31
  levels: [
36
32
  { type: "impostor", layout: "hemi", maxPixels: 120, draw: { parallax: 2 } },
37
33
  { type: "empty", maxPixels: 4 },
38
34
  ],
39
35
  });
40
- const trees = new InstancedLod(levels, gpu);
36
+ const trees = new Lod(levels, positions.length);
41
37
 
42
38
  const matrix = new Matrix4();
43
- const matrices = new Float32Array(positions.flatMap((position) => matrix.makeTranslation(position).toArray()));
44
- trees.addChunk({ instanceMatrix: new InstancedBufferAttribute(matrices, 16) });
39
+ positions.forEach((position, i) => trees.setMatrixAt(i, matrix.makeTranslation(position)));
40
+ trees.instanceMatrix.needsUpdate = true;
45
41
  scene.add(trees);
46
42
  ```
47
43
 
48
44
  Supply authored low shells and baking interiors as asset URLs on a baked level; both resolve relative to the source asset as ordinary URLs, so a query-only value replaces the source's whole query. For a variant of the same script, repeat the source's generation parameters, for example the source URL plus `&part=low`. The source asset should be complete at full detail; a baking interior supplies room structure for the distant windows. Author all three in the same coordinate system.
49
45
 
50
- ## Put each cache with its computation
51
-
52
- Follow the [vitecache skill](https://github.com/drawcall-ai/vitecache/blob/main/packages/vitecache/skills/vitecache/SKILL.md) to configure the host. `LodLoader` writes each derived level to the cache directory when the app first loads that level under the Vite dev server with the vitecache plugin. A deployed miss builds the missing level in the browser each time it loads, without persisting it. When the app is deployed under a sub-path, pass that location as `new LodLoader(manager, { basePath })`.
46
+ ## Give a .glts asset its own levels
53
47
 
54
- To deploy every level prebuilt, load the ladders in a public `.glts` script, which `vite build` runs in Node as the [GLTS skill](https://github.com/drawcall-ai/glts/blob/main/packages/glts/skills/glts/SKILL.md#precomputing-into-the-build) describes. There `LodLoader` builds and saves every level of each ladder it loads, deferred ones included. Request the same URLs and levels as the app, from a helper beside the script that the app imports too; `onLevel` changes nothing cached, so the app adds its effects to the shared requests. Register the contextual `gltsLoader` for `.glts` sources, as the app registers its `GLTSLoader`, and add every level to `scene`: a level can hold a `.glts` source the script loaded, which GLTS requires beneath `scene`.
48
+ A `.glts` script can draw its asset at levels of detail, so that every glts host gets them without knowing of lod. Keep the detailed asset in a script of its own, here `./model.glts` beside the wrapping script; load its ladder with the wrapping script's `loadingManager`, which resolves URLs relative to the script, after giving that manager the script's `gltsLoader` for `.glts` sources. Add a `Lod` of it to the script's scene, tracked by the same manager, so that a host waiting on its loads, such as the glts CLI rendering the script, waits for the levels its cameras need:
55
49
 
56
50
  ```ts
57
- // public/precompute.glts
58
- import { gltsLoader, loadingManager, scene } from "@drawcall/glts";
59
- import { LodLoader } from "@drawcall/lod";
60
- import { ladders } from "./ladders.ts";
51
+ import { gltsLoader, loadingManager, onDispose, scene } from "@drawcall/glts";
52
+ import { CachedLodLoader, Lod } from "@drawcall/lod";
61
53
 
62
54
  loadingManager.addHandler(/\.glts$/i, gltsLoader);
63
- const loader = new LodLoader(loadingManager);
64
- for (const ladder of ladders) {
65
- for (const level of await loader.loadAsync(ladder)) scene.add(level.object ?? (await level.load()));
66
- }
55
+ const levels = await new CachedLodLoader(loadingManager).loadAsync({
56
+ url: "./model.glts",
57
+ levels: [
58
+ { type: "impostor", maxPixels: 120 },
59
+ { type: "empty", maxPixels: 4 },
60
+ ],
61
+ });
62
+ const lod = new Lod(levels, 1, { manager: loadingManager });
63
+ scene.add(lod);
64
+ onDispose(() => lod.dispose());
67
65
  ```
68
66
 
69
- Edits to the script, its helpers, packages and loaded files invalidate the derived levels; no dependency list is needed. A level rebuilds on every load when its source or anything the script loads cannot be tied to a project file: packages imported from a CDN at runtime or not installed by the app, resources from another origin, and same-origin URLs without a file, such as URLs a server answers dynamically. Precomputing such a level fails the build, so install every package the precomputed sources import.
67
+ A host that draws the asset many times calls `gltsLoader.loadInstancesAsync(url, count)`; glts hands that asset's `instanceMatrix`, `instanceColor`, `count`, `boundingBox` and `clusters` to the Lod, which then draws every copy.
68
+
69
+ ## Cache every level
70
70
 
71
- Cache expensive generation inside a `.glts` asset, such as geometry, rooms or generated texture data that would otherwise stall the first approach, as the GLTS skill describes; leave cheap generation uncached. Use the `encodeMeshAsync` / `decodeMeshAsync` codec for geometry an asset caches itself.
71
+ Follow the [vitecache skill](https://github.com/drawcall-ai/vitecache/blob/main/packages/vitecache/skills/vitecache/SKILL.md) to add its plugin and to write loads it finds: call `loadAsync` on `new CachedLodLoader(...)`, or on a variable initialized with one, with a literal request, one load per ladder the app uses. Constructor options, such as the loading manager and `onLevel`, change nothing stored. When the app is deployed under a sub-path, pass that location as `new CachedLodLoader(manager, { basePath })`.
72
+
73
+ The plugin repeats each load in Node, where the loader builds every level of the ladder and saves each with the public files its loads read and the versions of three and of the packages its `.glts` sources import; changing any of them rebuilds the levels, and pages read them. There, URLs such as `/trees/oak.glts` load from the app's `public` directory, `.glts` sources run with the packages the app installs, and bakes draw on a GPU through [@drawcall/webgpu](https://github.com/drawcall-ai/webgpu/blob/main/skills/webgpu/SKILL.md). Write asset URLs from the site root, and keep sources free of the DOM: they get WebGPU, `fetch` of the app's public files, image decoding and classic workers, but no `document` or 2D canvas. A load that fetches any other URL, or a source that imports a module from a CDN, fails the build, since no stored level could be checked against it.
74
+
75
+ A page that misses, for a load the plugin could not see, builds the level each time it loads, without saving it.
72
76
 
73
77
  ## Place, share and dispose levels
74
78
 
75
- Load an asset once and build an `InstancedLod` per spatial region from its levels, each with its own chunks of placements and colours; clone a `Lod` for further independently placed copies. Reuse the loaded levels across Lods; adjust each Lod's resolved thresholds through its `levels`. Clones and InstancedLods share geometry, materials, textures and deferred loads. Disposing a `Lod` or `InstancedLod` frees only what it made of its levels: objects you give or load are yours to dispose once every Lod drawing them is disposed, while `LodLoader` frees what it loaded when the last Lod holding its levels is disposed.
79
+ Load an asset once and build a `Lod` per spatial region from its levels, each with its own placements and colours; clone a `Lod` for a further copy with its own attributes. Reuse the loaded levels across Lods; adjust each Lod's resolved thresholds through its `levels`. Lods made from the same levels share geometry, materials, textures and deferred loads. Disposing a `Lod` frees only what it made of its levels: objects you give or load are yours to dispose once every Lod drawing them is disposed, while `CachedLodLoader` frees what it loaded, and the renderer it baked with, when the last Lod holding its levels is disposed.
76
80
 
77
- Use `onLevel` for application effects and shadow settings, `castShadow` and `shadowSide` included. Put source generation and its materials in the asset so that the same URL also loads correctly outside the LOD host.
81
+ Use the loader's `onLevel` option for application effects and shadow settings, `castShadow` and `shadowSide` included. Put source generation and its materials in the asset so that the same URL also loads correctly outside the LOD host.
78
82
 
79
83
  Levels draw with copies of the source's materials, made once through three's `clone`. A custom material class must carry its own state in `copy`, and changes meant to reach drawn levels belong in shared TSL uniforms rather than in properties set on the original afterwards.
80
84
 
81
- Apply a shared `Wind` after assembling a LOD and before its first render; arriving levels inherit the effect. A `Lod` or `InstancedLod` that has rendered refuses wind: its shaders would build in a frame. Apply it separately to nested LODs and independently managed batches.
85
+ Apply a shared `Wind` after assembling a LOD and before its first render; arriving levels inherit the effect. A `Lod` that has rendered refuses wind: its shaders would build in a frame.
82
86
 
83
87
  Levels are chosen by on-screen size in CSS pixels on the actual render target, so a lower renderer pixel ratio saves shading, not geometry. Compile the initial scene with the actual camera and renderer before revealing it. Render every frame while finer levels load: they upload and compile only inside renders.
84
88
 
85
- ## Add instances in chunks and thin them with distance
89
+ ## Place instances, and bound them
90
+
91
+ Edit instances as on an `InstancedMesh`: `setMatrixAt` and `setColorAt`, then set the attribute's `needsUpdate`; with `addUpdateRange`, only those ranges upload. Assigning a new `instanceMatrix` or `instanceColor` takes effect at the next render; `count` draws the first `count` instances. A matrix of scale 0 draws nothing, but prefer `count` and smaller Lods over parking many instances at scale 0.
92
+
93
+ Each camera loads the levels, and shows the level meshes, that the instances' bounds can need. Without `clusters`, the bounds are `boundingBox` if set, else what the CPU measures of the matrices; reaching from the camera to the horizon, they load every level. Give a Lod that spans a large area `clusters`: disjoint ranges of instances, each with a `boundingBox` in the Lod's space and, where known, `minScale` and `maxScale`. Each cluster is culled and chooses levels on its own, and only instances inside a cluster draw.
86
94
 
87
- A fixed set of copies is one chunk. For copies that exist only near the camera, such as plants on patches of ground, add a chunk when a patch comes into reach and remove it when the camera moves on; a few chunks a frame cost about what they hold. Prefer whole chunks over parking unused instances at scale 0. When a compute pass of your own writes the copies, give `addChunk` its storage attributes and the bounds the CPU cannot measure (see `InstancedLodChunkParameters`).
95
+ When a compute pass of yours writes the instances, assign a `StorageInstancedBufferAttribute` (`instancedArray(n, "mat4")`'s value) as `instanceMatrix`, and a four-float one as `instanceColor`. The Lod reads them in place every frame; no `needsUpdate` is needed. The CPU cannot read them, so set `boundingBox` or `clusters` yourself: without either, every level loads and the Lod warns once. When your pass also decides how many of a cluster's instances are live, from its start, set the cluster's `liveCount` to `{ attribute, index }`, the u32 your pass writes into a storage attribute, such as `instancedArray(n, "uint")`'s value, that all of the Lod's clusters share, so that only those are sorted and drawn. `count` remains the most the range holds. `computeBoundingBox`, `getLevelAt` and `raycast` work on CPU matrices only.
88
96
 
89
- Give an InstancedLod a `cullDistance` to thin it out towards a distance instead of cutting it off. `scaleSurvivors` enlarges the copies that remain so that small things like grass cover about as much; leave it off for objects whose size reads, such as trees. Thinning does not change which levels load: let the ladder's last drawn level end near `far`, or add an empty level there.
97
+ A Lod's `instanceMatrix` must fit one storage binding of the device: split large instance sets across Lods, or raise `maxStorageBufferBindingSize` in the renderer's `requiredLimits`.
90
98
 
91
- In this example `grass` is an InstancedLod, `camera` the camera it thins from, and `matrices` a patch's instance matrices, 16 floats each.
99
+ Give a Lod a `cullDistance` to thin it out towards a distance instead of cutting it off. `scaleSurvivors` enlarges the copies that remain so that small things like grass cover about as much; leave it off for objects whose size reads, such as trees. Thinning does not change which levels load: let the ladder's last drawn level end near `far`, or add an empty level there.
100
+
101
+ In this example `grass` is a Lod, `camera` the camera it thins from, and `matrices` and `bounds` a compute pass's instance matrices and the box they lie in.
92
102
 
93
103
  ```ts
94
104
  grass.cullDistance = { camera, near: 35, far: 60, scaleSurvivors: true };
95
- const chunk = grass.addChunk({ instanceMatrix: new InstancedBufferAttribute(matrices, 16) });
96
- // Later, when the patch leaves reach:
97
- grass.removeChunk(chunk);
105
+ grass.instanceMatrix = matrices;
106
+ grass.boundingBox = bounds;
98
107
  ```
99
108
 
100
109
  ## Assemble levels you already have
@@ -103,18 +112,18 @@ Pass levels in finest-to-coarsest order. An empty object can be a deliberate cul
103
112
 
104
113
  Describe a deferred representation with a load function, bounds and a transition height. The function returns the object already placed in the Lod's space; the bounds cover it in that same space, including its children. For a cached impostor, decode the atlas and return an `ImpostorMesh` with the intended draw settings.
105
114
 
106
- Here, `loadDetailedMesh` loads the detailed object, `sourceBox` describes its bounds in the Lod's space, `coarseMesh` is already available, and `gpu` is the renderer's LodGpu.
115
+ Here, `loadDetailedMesh` loads the detailed object, `sourceBox` describes its bounds in the Lod's space, and `coarseMesh` is already available.
107
116
 
108
117
  ```ts
109
118
  import { Lod } from "@drawcall/lod";
110
119
 
111
- const object = new Lod([{ load: loadDetailedMesh, maxPixels: Infinity, box: sourceBox }, { object: coarseMesh }], gpu);
120
+ const object = new Lod([{ load: loadDetailedMesh, maxPixels: Infinity, box: sourceBox }, { object: coarseMesh }]);
112
121
  scene.add(object);
113
122
  ```
114
123
 
115
- A level fades in over the coarser one drawn in its place once it arrives. A `Lod` loads the levels its on-screen height needs; an `InstancedLod` loads every level the heights of its chunks' instances can need for a camera, judged from each chunk's bounds, so give chunks tight bounds: a chunk reaching from the camera to the horizon loads every level. The resources a deferred load uses must stay alive until it finishes.
124
+ A level fades in over the coarser one drawn in its place once it arrives. A Lod loads every level its instances' bounds can need for a camera (see above). Levels are drawn as instanced meshes, so a level may not contain a three `LOD`, an `InstancedMesh` other than an `ImpostorMesh`, or lines, points and sprites. The resources a deferred load uses must stay alive until it finishes.
116
125
 
117
- For direct preparation and storage outside `LodLoader`, combine `simplify`, `bakeMesh`, or `bakeImpostor` with the corresponding codecs and drawing objects. Bakes that draw take a renderer made with `createBakeRenderer`, never the application's, whose canvas a bake would draw over. Use `ImpostorMesh` directly when copies stay distant throughout their lifetime. For external detail systems, combine an empty near level with a coarse representation and ask `lod.getLevel(camera)` or `chunk.getLevelAt(index, camera)` where to supply detail.
126
+ For direct preparation and storage outside `CachedLodLoader`, combine `simplify`, `bakeMesh`, or `bakeImpostor` with the corresponding codecs and drawing objects. Bakes that draw take a renderer made with `createBakeRenderer`, never the application's, whose canvas a bake would draw over. Use `ImpostorMesh` directly when copies stay distant throughout their lifetime. For external detail systems, combine an empty near level with a coarse representation and ask `lod.getLevelAt(index, camera)` where to supply detail.
118
127
 
119
128
  ## Prepare assets that survive transitions
120
129
 
@@ -122,28 +131,30 @@ Ship source models with deduplicated textures, sized to their on-screen use and
122
131
 
123
132
  Author sources, simplified geometry, low shells and interiors in one coordinate system. A ground-level pivot helps upright repeated assets.
124
133
 
125
- Author foliage with alpha-tested cut-outs and colour beyond the visible texture edges. The package supplies no foliage material: give cut-out source materials alpha to coverage and an alpha that holds coverage in smaller mips, for the camera and the shadow maps, or distant leaves thin out and vanish. Fill a cut-out's transparent texels with the mean colour of its opaque texels, as the last step, in a format that preserves colour under zero alpha: lossy webp discards it, PNG preserves it, and a KTX2 encoder needs checking. Mips average those texels in, so left dark they darken the distant source while an impostor, baked from full detail, holds its colour and turns brighter where the two switch. Dilating from the edges instead spreads their often dark fringe. Match visual effects across representations so foliage does not change lighting at a transition.
134
+ Author foliage with alpha-tested cut-outs and colour beyond the visible texture edges. Cut-out source materials need alpha to coverage and an alpha that holds coverage in smaller mips, for the camera and the shadow maps, or distant leaves thin out and vanish. Fill a cut-out's transparent texels with the mean colour of its opaque texels, as the last step, in a format that preserves colour under zero alpha: lossy webp discards it, PNG preserves it, and a KTX2 encoder needs checking. Mips average those texels in, so left dark they darken the distant source while an impostor, baked from full detail, holds its colour and turns brighter where the two switch. Dilating from the edges instead spreads their often dark fringe. Match visual effects across representations so foliage does not change lighting at a transition.
135
+
136
+ Use the package's foliage material for leaves, grass and other thin plant parts: it gives cut-outs that coverage and lets sunlight through to a leaf's shaded side, so back-lit plants glow instead of turning black. Convert a loaded plant model with `foliageModel`, or make a procedural asset's leaf material a `Foliage` with `foliage`. An impostor baked from either holds no light passing through its leaves: apply `foliageLevels` with the same translucency in the loader's `onLevel`, so that the impostor lights like its source at the switch.
126
137
 
127
138
  Custom shading on an impostor has little room: an impostor uses close to WebGPU's 16 varyings, so a colour node of your own may find none left; read per pixel what a mesh would carry. An impostor's `normalView` is one unit normal per texel, however many leaves that texel averages. For a lighting term of your own, read `cosine(impostor.material.spread, lightDirection)`, the mean of the clamped cosine over those leaves. Here `impostor` is the level's `ImpostorMesh` and `lightDirection` the view-space direction towards the light.
128
139
 
129
- Match a low shell to the source's occupied shape and fit it within the source's bounds: `LodLoader` rejects a level that reaches beyond them. Preserve important silhouette features and remove faces that will never be seen. Generate shell and source from the same parameters when possible. Author rooms separately, with their boundaries just behind windows and furnishings near visible walls; include rooms in the detailed source when they should appear up close too.
140
+ Match a low shell to the source's occupied shape and fit it within the source's bounds: `CachedLodLoader` rejects a level that reaches beyond them. Preserve important silhouette features and remove faces that will never be seen. Generate shell and source from the same parameters when possible. Author rooms separately, with their boundaries just behind windows and furnishings near visible walls; include rooms in the detailed source when they should appear up close too.
130
141
 
131
142
  For dense cover, combine near individuals with a baked distant patch. Jitter position and rotation to avoid aligned gaps, preserve continuity across tile borders, and use side walls only on exposed boundaries. An empty far level can stop drawing individuals once the patch carries their appearance.
132
143
 
133
144
  ## Wait for a complete frame before a screenshot
134
145
 
135
- Levels load as the camera comes to need them, so a frame drawn soon after loading can lack them. Give the Lods and InstancedLods a `manager` of their own, so that it tracks only them: each holds an item there while the levels its cameras need load, compile or fade in, and ends it once they are complete. Render the `Scene` that holds them each frame, since a Lod loads nothing before such a render.
146
+ Levels load as the camera comes to need them, so a frame drawn soon after loading can lack them. Give the Lods a `manager` of their own, so that it tracks only them: each holds an item there while the levels its cameras need load, compile or fade in, and ends it once they are complete. Render the `Scene` that holds them each frame, since a Lod loads nothing before such a render.
136
147
 
137
- To capture one frame, even with nothing cached, place the camera and render, then wait a frame; while the manager is loading, compile with `renderer.compileAsync(scene, camera)`, render again and wait a frame; capture after a quiet frame, one in which no item started or ended. After moving the camera, wait again. In this example `levels` and `treeLevels` are ladders from `LodLoader`, `gpu` the renderer's LodGpu, `instanceMatrix` an attribute of tree matrices, and `viewpoint` the camera position to capture.
148
+ To capture one frame, even with nothing cached, place the camera and render, then wait a frame; while the manager is loading, compile with `renderer.compileAsync(scene, camera)`, render again and wait a frame; capture after a quiet frame, one in which no item started or ended. After moving the camera, wait again. In this example `levels` and `treeLevels` are ladders from `CachedLodLoader`, `instanceMatrix` an attribute of tree matrices, and `viewpoint` the camera position to capture.
138
149
 
139
150
  ```ts
140
151
  import { LoadingManager } from "three/webgpu";
141
- import { InstancedLod, Lod } from "@drawcall/lod";
152
+ import { Lod } from "@drawcall/lod";
142
153
 
143
154
  const manager = new LoadingManager();
144
- const lod = new Lod(levels, gpu, { manager });
145
- const trees = new InstancedLod(treeLevels, gpu, { manager });
146
- trees.addChunk({ instanceMatrix });
155
+ const lod = new Lod(levels, 1, { manager });
156
+ const trees = new Lod(treeLevels, instanceMatrix.count, { manager });
157
+ trees.instanceMatrix = instanceMatrix;
147
158
  scene.add(lod, trees);
148
159
 
149
160
  camera.position.copy(viewpoint);
@@ -167,9 +178,9 @@ Loaded levels stay until their Lod is disposed, which nothing does for you: in a
167
178
 
168
179
  Tune transitions in the intended viewport with `Lod.debug`, then inspect motion through them. Use `Lod.quality` for a scene-wide adjustment and individual thresholds for particular assets. Give an impostor bake the intended screen size at its switch, then inspect its coverage and colour from several angles. Compare both sides of a switch under one camera, drawing each with the Lod's `forceLevel`, looking toward the sun as well as away: a mismatch can show in one light direction only.
169
180
 
170
- Group nearby copies into spatial regions. Broad batches can lose useful culling, while tiny batches spend too much time submitting draws. Add and remove chunks and move changed instances instead of rebuilding whole InstancedLods. Count material groups as well as triangles; an atlas alone does not combine draws. Each distinct material structure costs a pipeline compile on first use, so variants should share material structure.
181
+ Group nearby copies into spatial regions. Broad batches can lose useful culling, while tiny batches spend too much time submitting draws. Move changed instances, marking only their update ranges, instead of rebuilding whole Lods. Count material groups as well as triangles; an atlas alone does not combine draws. Each distinct material structure costs a pipeline compile on first use, so variants should share material structure.
171
182
 
172
- Avoid custom shadow nodes on lights that LOD objects should cast into. An `InstancedLod` draws for each camera, shadow maps' included, only the instances inside its frustum, at the level the map's texels resolve, so shadow casting costs about what the map can show. When it still dominates, turn `castShadow` off in `onLevel` on the levels that matter least to the shadow, such as small plants.
183
+ Avoid custom shadow nodes on lights that LOD objects should cast into. When shadow casting dominates, turn `castShadow` off in `onLevel` on the levels that matter least to the shadow, such as small plants.
173
184
 
174
185
  Judge impostors by covered screen area and overlap as well as triangle count. Compare individual cards with baked patches for dense cover, and inspect parallax and mip quality during transitions.
175
186
 
package/dist/gpu.d.ts DELETED
@@ -1,39 +0,0 @@
1
- import type { Renderer } from "three/webgpu";
2
- import { Compiler } from "./levels/compile/index.js";
3
- import { InstancePagePool } from "./instanced/pages/index.js";
4
- import { Sorter } from "./instanced/sort.js";
5
- /** How a LodGpu is sized. */
6
- export interface LodGpuOptions {
7
- /**
8
- * The most instances its InstancedLods hold at once, over all their chunks: 65536 by default. Its pool holds 64 bytes
9
- * of matrix and 16 of colour per instance room. Chunks that together outgrow it are reported (see
10
- * `InstancedLod.error`), naming it as the limit to raise. The lists each camera holds are
11
- * sized by every InstancedLod's own `maxInstanceCount` instead (see `InstancedLodOptions`).
12
- */
13
- maxInstanceCount?: number;
14
- /** The most chunks its InstancedLods hold at once: 256 by default. `addChunk` past it throws, naming it. */
15
- maxChunkCount?: number;
16
- }
17
- /**
18
- * What every Lod and InstancedLod drawing with one renderer shares, as PMREMGenerator is for environment maps: how
19
- * their levels compile, the page pool every InstancedLod's instances live in, and the passes that sort them for each
20
- * camera. Make it once the renderer is initialised (`await renderer.init()`), give it to each Lod and InstancedLod, and
21
- * dispose it once they are disposed.
22
- */
23
- export declare class LodGpu {
24
- readonly renderer: Renderer;
25
- /** The pool every InstancedLod's instances live in. */
26
- readonly pool: InstancePagePool;
27
- /** The rows, camera buffers and passes every InstancedLod sorts with. */
28
- readonly sorter: Sorter;
29
- /** How levels compile for the renderer. */
30
- readonly compiler: Compiler;
31
- constructor(renderer: Renderer, { maxInstanceCount, maxChunkCount }?: LodGpuOptions);
32
- /** Whether it was disposed: then no Lod or InstancedLod can be made with it, and its sort takes no camera. */
33
- get disposed(): boolean;
34
- /**
35
- * Release the pool and the sort's buffers and passes, once every Lod and InstancedLod made with it is disposed. The
36
- * renderer keeps the wrapper that shares pipelines among level meshes, which costs nothing once they are gone.
37
- */
38
- dispose(): void;
39
- }
package/dist/gpu.js DELETED
@@ -1,41 +0,0 @@
1
- import { Compiler } from "./levels/compile/index.js";
2
- import { InstancePagePool } from "./instanced/pages/index.js";
3
- import { Sorter } from "./instanced/sort.js";
4
- const DEFAULT_INSTANCES = 65536;
5
- const DEFAULT_CHUNKS = 256;
6
- /**
7
- * What every Lod and InstancedLod drawing with one renderer shares, as PMREMGenerator is for environment maps: how
8
- * their levels compile, the page pool every InstancedLod's instances live in, and the passes that sort them for each
9
- * camera. Make it once the renderer is initialised (`await renderer.init()`), give it to each Lod and InstancedLod, and
10
- * dispose it once they are disposed.
11
- */
12
- export class LodGpu {
13
- renderer;
14
- /** The pool every InstancedLod's instances live in. */
15
- pool;
16
- /** The rows, camera buffers and passes every InstancedLod sorts with. */
17
- sorter;
18
- /** How levels compile for the renderer. */
19
- compiler;
20
- constructor(renderer, { maxInstanceCount = DEFAULT_INSTANCES, maxChunkCount = DEFAULT_CHUNKS } = {}) {
21
- this.renderer = renderer;
22
- if (!renderer.initialized)
23
- throw new Error("LodGpu: initialise the renderer first (await renderer.init())");
24
- this.pool = new InstancePagePool(maxInstanceCount, maxChunkCount);
25
- this.sorter = new Sorter(renderer, this.pool);
26
- this.compiler = new Compiler(renderer);
27
- }
28
- /** Whether it was disposed: then no Lod or InstancedLod can be made with it, and its sort takes no camera. */
29
- get disposed() {
30
- return this.sorter.disposed;
31
- }
32
- /**
33
- * Release the pool and the sort's buffers and passes, once every Lod and InstancedLod made with it is disposed. The
34
- * renderer keeps the wrapper that shares pipelines among level meshes, which costs nothing once they are gone.
35
- */
36
- dispose() {
37
- this.sorter.dispose();
38
- this.pool.dispose();
39
- }
40
- }
41
- //# sourceMappingURL=gpu.js.map
package/dist/gpu.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"gpu.js","sourceRoot":"","sources":["../src/gpu.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAe7C,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAChC,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,OAAO,MAAM;IASN;IARX,uDAAuD;IAC9C,IAAI,CAAmB;IAChC,yEAAyE;IAChE,MAAM,CAAS;IACxB,2CAA2C;IAClC,QAAQ,CAAW;IAE5B,YACW,QAAkB,EAC3B,EAAE,gBAAgB,GAAG,iBAAiB,EAAE,aAAa,GAAG,cAAc,KAAoB,EAAE;QADnF,aAAQ,GAAR,QAAQ,CAAU;QAG3B,IAAI,CAAC,QAAQ,CAAC,WAAW;YAAE,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QAC5G,IAAI,CAAC,IAAI,GAAG,IAAI,gBAAgB,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;QAClE,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED,8GAA8G;IAC9G,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACH,OAAO;QACL,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC;CACF"}