@drawcall/lod 0.1.0 → 0.2.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 (147) hide show
  1. package/README.md +10 -69
  2. package/dist/at.d.ts +2 -0
  3. package/dist/at.js +8 -0
  4. package/dist/at.js.map +1 -0
  5. package/dist/baked/codec.d.ts +6 -3
  6. package/dist/baked/codec.js +22 -16
  7. package/dist/baked/codec.js.map +1 -1
  8. package/dist/baked/coverage.d.ts +3 -0
  9. package/dist/baked/coverage.js +45 -0
  10. package/dist/baked/coverage.js.map +1 -0
  11. package/dist/baked/index.d.ts +4 -0
  12. package/dist/baked/index.js +3 -35
  13. package/dist/baked/index.js.map +1 -1
  14. package/dist/baked/low.d.ts +2 -2
  15. package/dist/baked/low.js +4 -4
  16. package/dist/baked/low.js.map +1 -1
  17. package/dist/bounds.d.ts +12 -2
  18. package/dist/bounds.js +72 -10
  19. package/dist/bounds.js.map +1 -1
  20. package/dist/compile.d.ts +4 -0
  21. package/dist/compile.js +100 -0
  22. package/dist/compile.js.map +1 -0
  23. package/dist/deferred.d.ts +12 -0
  24. package/dist/deferred.js +27 -0
  25. package/dist/deferred.js.map +1 -0
  26. package/dist/dispose.d.ts +7 -3
  27. package/dist/dispose.js +33 -4
  28. package/dist/dispose.js.map +1 -1
  29. package/dist/fade.d.ts +5 -13
  30. package/dist/fade.js +62 -28
  31. package/dist/fade.js.map +1 -1
  32. package/dist/impostor/bake/index.d.ts +1 -0
  33. package/dist/impostor/bake/index.js +1 -0
  34. package/dist/impostor/bake/index.js.map +1 -1
  35. package/dist/impostor/bake/materials.js +11 -1
  36. package/dist/impostor/bake/materials.js.map +1 -1
  37. package/dist/impostor/codec.d.ts +2 -7
  38. package/dist/impostor/codec.js +16 -27
  39. package/dist/impostor/codec.js.map +1 -1
  40. package/dist/impostor/mesh/card.js +4 -1
  41. package/dist/impostor/mesh/card.js.map +1 -1
  42. package/dist/impostor/mesh/index.d.ts +6 -4
  43. package/dist/impostor/mesh/index.js +8 -10
  44. package/dist/impostor/mesh/index.js.map +1 -1
  45. package/dist/impostor/mesh/material.d.ts +7 -5
  46. package/dist/impostor/mesh/material.js +29 -26
  47. package/dist/impostor/mesh/material.js.map +1 -1
  48. package/dist/impostor/mesh/surface.d.ts +20 -16
  49. package/dist/impostor/mesh/surface.js +74 -55
  50. package/dist/impostor/mesh/surface.js.map +1 -1
  51. package/dist/impostor/octahedral.d.ts +1 -8
  52. package/dist/impostor/octahedral.js +3 -18
  53. package/dist/impostor/octahedral.js.map +1 -1
  54. package/dist/index.d.ts +7 -6
  55. package/dist/index.js +5 -4
  56. package/dist/index.js.map +1 -1
  57. package/dist/instanced/args.js +2 -2
  58. package/dist/instanced/args.js.map +1 -1
  59. package/dist/instanced/{bounds.d.ts → blocks.d.ts} +25 -9
  60. package/dist/instanced/{bounds.js → blocks.js} +76 -53
  61. package/dist/instanced/blocks.js.map +1 -0
  62. package/dist/instanced/dirty.d.ts +3 -0
  63. package/dist/instanced/dirty.js +40 -5
  64. package/dist/instanced/dirty.js.map +1 -1
  65. package/dist/instanced/index.d.ts +25 -51
  66. package/dist/instanced/index.js +189 -413
  67. package/dist/instanced/index.js.map +1 -1
  68. package/dist/instanced/meshes.d.ts +54 -13
  69. package/dist/instanced/meshes.js +178 -41
  70. package/dist/instanced/meshes.js.map +1 -1
  71. package/dist/instanced/parts.d.ts +14 -0
  72. package/dist/instanced/parts.js +79 -0
  73. package/dist/instanced/parts.js.map +1 -0
  74. package/dist/instanced/raycast.d.ts +13 -0
  75. package/dist/instanced/raycast.js +53 -0
  76. package/dist/instanced/raycast.js.map +1 -0
  77. package/dist/instanced/select.d.ts +17 -9
  78. package/dist/instanced/select.js +114 -63
  79. package/dist/instanced/select.js.map +1 -1
  80. package/dist/instanced/store.d.ts +31 -0
  81. package/dist/instanced/store.js +96 -0
  82. package/dist/instanced/store.js.map +1 -0
  83. package/dist/levels.d.ts +71 -48
  84. package/dist/levels.js +99 -74
  85. package/dist/levels.js.map +1 -1
  86. package/dist/loader/bundle.d.ts +25 -0
  87. package/dist/loader/bundle.js +241 -0
  88. package/dist/loader/bundle.js.map +1 -0
  89. package/dist/loader/cache.d.ts +15 -15
  90. package/dist/loader/cache.js +71 -33
  91. package/dist/loader/cache.js.map +1 -1
  92. package/dist/loader/provenance.d.ts +30 -0
  93. package/dist/loader/provenance.js +105 -0
  94. package/dist/loader/provenance.js.map +1 -0
  95. package/dist/loader/url.d.ts +13 -0
  96. package/dist/loader/url.js +31 -0
  97. package/dist/loader/url.js.map +1 -0
  98. package/dist/loader.d.ts +30 -74
  99. package/dist/loader.js +191 -186
  100. package/dist/loader.js.map +1 -1
  101. package/dist/lod.d.ts +20 -31
  102. package/dist/lod.js +105 -96
  103. package/dist/lod.js.map +1 -1
  104. package/dist/material.js +9 -4
  105. package/dist/material.js.map +1 -1
  106. package/dist/mesh/codec.d.ts +4 -0
  107. package/dist/mesh/codec.js +192 -0
  108. package/dist/mesh/codec.js.map +1 -0
  109. package/dist/queue.d.ts +2 -0
  110. package/dist/queue.js +33 -0
  111. package/dist/queue.js.map +1 -0
  112. package/dist/residency.d.ts +44 -0
  113. package/dist/residency.js +205 -0
  114. package/dist/residency.js.map +1 -0
  115. package/dist/simplify.js +5 -3
  116. package/dist/simplify.js.map +1 -1
  117. package/dist/source/{error.d.ts → deviation.d.ts} +3 -3
  118. package/dist/source/{error.js → deviation.js} +6 -6
  119. package/dist/source/deviation.js.map +1 -0
  120. package/dist/source/source.d.ts +1 -1
  121. package/dist/source/source.js +1 -1
  122. package/dist/three.d.ts +17 -5
  123. package/dist/three.js +24 -3
  124. package/dist/three.js.map +1 -1
  125. package/dist/tsl.d.ts +5 -5
  126. package/dist/tsl.js +12 -19
  127. package/dist/tsl.js.map +1 -1
  128. package/dist/view.d.ts +16 -1
  129. package/dist/view.js +57 -1
  130. package/dist/view.js.map +1 -1
  131. package/dist/wind/index.d.ts +2 -2
  132. package/dist/wind/index.js +31 -28
  133. package/dist/wind/index.js.map +1 -1
  134. package/dist/wind/sway.d.ts +2 -1
  135. package/package.json +9 -3
  136. package/skills/lod/SKILL.md +71 -109
  137. package/dist/impostor/cache.d.ts +0 -15
  138. package/dist/impostor/cache.js +0 -44
  139. package/dist/impostor/cache.js.map +0 -1
  140. package/dist/instanced/bounds.js.map +0 -1
  141. package/dist/lazy.d.ts +0 -64
  142. package/dist/lazy.js +0 -187
  143. package/dist/lazy.js.map +0 -1
  144. package/dist/loader/dispose.d.ts +0 -3
  145. package/dist/loader/dispose.js +0 -25
  146. package/dist/loader/dispose.js.map +0 -1
  147. package/dist/source/error.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawcall/lod",
3
- "version": "0.1.0",
3
+ "version": "0.2.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": [
@@ -29,17 +29,18 @@
29
29
  "LICENSE"
30
30
  ],
31
31
  "dependencies": {
32
- "@drawcall/glts": "^2.0.0",
33
32
  "fflate": "^0.8.2",
34
33
  "ktx-parse": "^2.0.0",
35
34
  "meshoptimizer": "^1.3.0",
36
35
  "three-mesh-bvh": "^0.9.15",
37
- "vitecache": "^0.1.2"
36
+ "vitecache": "^0.2.1"
38
37
  },
39
38
  "peerDependencies": {
39
+ "@drawcall/glts": "^4.0.0",
40
40
  "three": ">=0.185.0 <0.186.0"
41
41
  },
42
42
  "devDependencies": {
43
+ "@drawcall/glts": "^4.0.0",
43
44
  "@types/node": "^24.13.6",
44
45
  "@types/three": "^0.185.0",
45
46
  "@vitest/browser-playwright": "4.1.11",
@@ -63,6 +64,11 @@
63
64
  "publishConfig": {
64
65
  "access": "public"
65
66
  },
67
+ "peerDependenciesMeta": {
68
+ "@drawcall/glts": {
69
+ "optional": true
70
+ }
71
+ },
66
72
  "scripts": {
67
73
  "build": "rm -rf dist && tsc -p tsconfig.json",
68
74
  "typecheck": "tsc -p tsconfig.test.json",
@@ -1,137 +1,99 @@
1
1
  ---
2
2
  name: lod
3
- description: Use @drawcall/lod to give three.js objects levels of detail — load a model and get a simplified mesh, a baked low-poly mesh or an octahedral impostor that switch by on-screen size with a dithered fade, or switch your own levels — including crowds of instances, vegetation swaying in wind, buildings whose windows show the rooms behind them (interior mapping), shadows over large worlds, and preparing models that bake into good impostors. Use when a WebGPURenderer scene (`three/webgpu`) has many or large objects seen from far away; not for WebGLRenderer, skinned animation, or glass objects.
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 crowds, wind and interior mapping; not WebGLRenderer or skinned animation.
4
4
  ---
5
5
 
6
6
  # Level of detail with @drawcall/lod
7
7
 
8
- ## Which part to reach for
8
+ ## Start with the loader
9
9
 
10
- - **A model file → `LodLoader`.** It loads the model and builds its cheaper levels; impostors can be deferred until a view needs them. The result is a `Lod` you add to the scene. Three's renderer updates every `Lod` while it renders.
11
- - **Many copies of one object → `InstancedLod`** (`loadInstancesAsync`, or built from levels): every copy switches and fades on its own, with one draw per level and mesh.
12
- - **Levels you already have → `new Lod([source, ...levels])`**: any `Object3D` per level, another `Lod` included, detailed to cheap. Levels made by this package know how far off they are and pick their own switch size; hand-made ones need a `maxPixels`.
13
- - **Only ever far away, never switching → an `ImpostorMesh`** from `bakeImpostor`: one instanced draw for thousands of copies.
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 with per-instance matrices and colours.
14
11
 
15
- Which levels to build, by asset:
12
+ `loadAsync` resolves with the coarsest drawable level ready; finer levels load when the camera needs them. Include an impostor or baked mesh as the coarsest drawable when an overview should avoid constructing the source. A simplified coarsest 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.
16
13
 
17
- - **Foliage** — trees, bushes, grass, plants, anything of alpha-tested leaf cards → an impostor only (the loader's default). A simplified level in between tears the cards apart. A scan that models every leaf in many triangles is different: draw it from its own `simplify` copy (around a quarter of the triangles keeps the leaves' shape; far fewer smears them) and use that as the source.
18
- - **Hard-surface props** — rocks, vehicles, furniture → simplified, then impostor. Low-poly props need no levels: an impostor costs more than they do.
19
- - **Buildings** → baked (experimental), then impostor. The baked level is one low mesh carrying the source's colour, normals and roughness in its own textures, so window frames, gutters and doors survive as texture, onto a low shell you give it (see "Impostor-ready assets").
20
- - **Buildings you can see into** → the same, plus an `interior`: the rooms as a model of their own. Up close the real rooms show through the real glass; the baked level shows each room through its windows by interior mapping — a picture of the room that shifts with the view, at no geometry cost.
21
- - **Dense patches of plants** (a block of corn, a patch of grass) → the plants as an `InstancedLod` (source, impostor, then an empty level so far plants draw nothing), and one `bakeMesh` of a patch's plants onto a canopy as the far level of the patches (see "Impostor-ready assets").
14
+ Choose levels from the asset's silhouette, materials and expected viewing range. Alpha-tested leaf cards often work best as source → impostor; simplifying the cards can destroy their shape. Hard-surface props often suit source → simplified → impostor. Detailed structures can use source → baked shell → impostor, with interiors supplied separately for windows. Add an empty final level when the object should disappear at distance.
15
+
16
+ Register the source loaders on the loading manager before loading: a `GLTSLoader` for `.glts` URLs, and for `.glb` or `.gltf` models compressed with Draco or KTX2 a `GLTFLoader` configured with those decoders, since `LodLoader`'s fallback decodes meshopt only. 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.
17
+
18
+ This example creates a crowd from one procedural asset. `positions` contains placements in the crowd's space, and `scene` is the application's scene.
22
19
 
23
20
  ```ts
24
- import * as THREE from "three/webgpu";
25
- import { Lod, LodLoader } from "@drawcall/lod";
21
+ import { LoadingManager, Matrix4 } from "three/webgpu";
22
+ import { GLTSLoader } from "@drawcall/glts";
23
+ import { InstancedLod, LodLoader } from "@drawcall/lod";
26
24
 
27
- const manager = new THREE.LoadingManager();
28
- manager.addHandler(/\.glb$/i, new GLTFLoader(manager).setDRACOLoader(draco)); // LodLoader uses it
25
+ const manager = new LoadingManager();
26
+ manager.addHandler(/\.glts$/, new GLTSLoader(manager));
29
27
  const loader = new LodLoader(manager);
30
-
31
- const tree = await loader.loadAsync({ url: "/tree.glb", levels: [{ type: "impostor", layout: "hemi" }] });
32
- const shop = await loader.loadAsync({
33
- url: "/shop.glb",
28
+ const levels = await loader.loadAsync({
29
+ url: "/trees/oak.glts?seed=2",
34
30
  levels: [
35
- { type: "baked", low: "/shop-low.glb", interior: "/shop-rooms.glb" },
36
- { type: "impostor", layout: "hemi" },
31
+ { type: "impostor", layout: "hemi", maxPixels: 120, draw: { parallax: 2 } },
32
+ { type: "empty", maxPixels: 4 },
37
33
  ],
38
34
  });
39
- scene.add(tree, shop);
35
+ const trees = new InstancedLod(levels, positions.length);
40
36
 
41
- const forest = await loader.loadInstancesAsync("/tree.glb", spots.length);
42
- spots.forEach((spot, i) => forest.setMatrixAt(i, new THREE.Matrix4().setPosition(spot)));
43
- scene.add(forest);
44
-
45
- Lod.debug = true; // tint levels to see where each draws
37
+ const matrix = new Matrix4();
38
+ positions.forEach((position, index) => {
39
+ trees.setMatrixAt(index, matrix.makeTranslation(position));
40
+ });
41
+ scene.add(trees);
46
42
  ```
47
43
 
48
- ## How the parts combine
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. Keep all three in the same coordinate system.
45
+
46
+ ## Put each cache with its computation
47
+
48
+ Follow the [vitecache skill](https://github.com/drawcall-ai/vitecache/blob/main/packages/vitecache/skills/vitecache/SKILL.md) to configure the host. `LodLoader` writes a URL's derived levels to the cache directory when the app loads that URL with those levels under the Vite dev server with the vitecache plugin; `vite build` does not generate them, so load every deployed URL and level list during development and deploy the cache directory. A deployed miss builds the levels in the browser on every load without persisting them. When the app is deployed under a sub-path, pass that cache location to `LodLoader`. Deploy the original assets with the cache. Edits to the script, its helpers, packages and loaded files invalidate the derived levels; no dependency list is needed. A script that imports packages from the CDN at runtime, rather than from the app's installed or Vite-bundled packages, rebuilds its levels on every load, as does a source or a resource it loads from another origin, a same-origin URL without a project file such as a server route, or a package the app does not install.
49
+
50
+ 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](https://github.com/drawcall-ai/glts/blob/main/packages/glts/skills/glts/SKILL.md) describes; leave cheap generation uncached. Use the `encodeMesh` / `decodeMeshAsync` codec for asset-owned geometry caches. The GLTS build does not warm `LodLoader`'s derived levels.
51
+
52
+ ## Place, share and dispose levels
53
+
54
+ Load an asset once and build spatial crowds from its levels, each with its own instance count, placements and colours; clone a `Lod` for further independently placed copies. Reuse descriptors across owners; adjust each owner's resolved thresholds through its `levels` view. Clones and crowds share geometry, materials, textures and deferred loads. Dispose shared resources only after every copy has stopped drawing; disposal does not count references.
55
+
56
+ Use `onLevel` for application effects or shadow settings that apply when each level arrives. Keep source generation and its materials in the asset so that the same URL also loads correctly outside the LOD host.
57
+
58
+ Apply a shared `Wind` after assembling a LOD and before rendering; arriving levels inherit the effect. Apply it separately to nested LODs and independently managed batches.
49
59
 
50
- - **Vegetation in wind:** build the resting asset and its levels, then apply one `Wind` to the `Lod` or `InstancedLod`. Deferred impostors inherit that wind when they arrive. Update its time before rendering; share the same breeze across plants. Apply to individual plants or their instance batches, rather than a whole forest hierarchy. Broad sway moves the whole plant; it does not animate individual branches or leaves. Independent objects attached to a plant need to follow its motion too.
60
+ Seed the camera with `setViewportHeight` before preparing its first view, and refresh that height after resizing views whose levels may all be culled. Compile the initial scene with the actual camera and renderer before revealing it. Continue drawing while finer levels load so preparation can use the same rendering context.
51
61
 
52
- - **Switching is by on-screen height in CSS pixels:** a high-density screen picks the levels a standard one does and pays for its extra pixels in fill only. `Lod.quality` scales every measurement: below 1, cheaper levels take over sooner — the global performance knob (set it to the pixel ratio to switch by device pixels).
53
- - **Near a switch both levels draw** and split the pixels with a dither, so nothing pops. Elsewhere only one level is visible: hidden levels submit no draws or shadows, but their geometry and textures stay resident. Each level's switch size must stay far enough below the previous one's for one fade to end before the next begins; the `Lod` throws otherwise.
54
- - **Nested `Lod`s** switch their own levels; the parent hands over to and from them without the dither, and a hidden parent level hides everything inside.
55
- - **Clone instead of loading twice:** `clone()` shares geometry, textures and deferred atlas requests. A persistent cache avoids rebaking, but each separate load still reconstructs the model and its other levels. For hundreds of copies use `InstancedLod`, as a `Lod` per copy costs draws per copy.
56
- - **Split large crowds into regions:** use one `InstancedLod` per region so regions outside the view or a shadow map can skip their draws. Keep nearby instances together in the batch; one scattered world-sized crowd is hard to cull, while many tiny crowds spend the frame submitting draws. Cheap far cards can use larger batches than detailed source models; compare their draw overhead and culling cost separately. Check that your target devices offer the required WebGPU feature `indirect-first-instance`. Keep the batch's own transform uniformly scaled (instances may scale any way). Build its levels as templates without nested `Lod`s or InstancedMeshes; use `Lod` for hierarchies.
57
- - **Hierarchies on top** (a field whose plants exist only near the camera): level 0 may be an empty `Object3D`, and the `Lod` measures by the first level that draws. Draw the detail yourself where level 0 shows: `levelOf` on an `InstancedLod`, `visible` on a `Lod`'s level. `Lod.fade` is the share of a level's `maxPixels` its fade spans.
58
- - **Saving results:** persist impostors with `encodeImpostor` and baked meshes with `encodeBakedMesh`, before applying runtime material changes or adding them to a `Lod`. Decode cached results instead of repeating their bakes; the asynchronous impostor decoder avoids long synchronous JavaScript decompression where native streams are available. Simplified levels still need construction. An incompatible encoding change requires rebaking old files, and results need regeneration when their inputs or baking algorithm change.
59
- - **`dispose()` frees everything,** the source included. Clones share geometry and textures: dispose only once no clone draws any more.
62
+ ## Assemble levels you already have
60
63
 
61
- ## Cached and deferred impostors
64
+ Pass levels in finest-to-coarsest order. An empty object can be a deliberate culled level. A ladder needs measurable bounds; when all levels are deferred, it draws nothing until a level is ready.
62
65
 
63
- Use `LodLoader` with a GLTS asset to cache its impostors through vitecache. A whole authored GLTS asset is one cache unit: its source URL, observed dependency URLs and bake settings identify the result. Direct object input belongs inside an active GLTS execution; use the complete asset, and finish loading its resources before requesting levels. Outside GLTS, load a URL or compose `Lod`/`InstancedLod` from the building blocks. See the [GLTS skill](https://github.com/drawcall-ai/glts/blob/main/packages/glts/skills/glts/SKILL.md) for contextual loaders and sharing package instances.
66
+ Describe a deferred representation with a load function, bounds and a transition height. The function returns the object already placed in the owner'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.
64
67
 
65
- Enable vitecache in the host Vite app, and generate the public cache files before deployment. Follow the [vitecache skill](https://github.com/drawcall-ai/vitecache/blob/main/packages/vitecache/skills/vitecache/SKILL.md) for dependency declarations and deployment. Match the loader's cache location to the app's URL base; asset paths and cache paths are separate. GLTS tracks observed files, so declare additional generator packages or other inputs in the loader's cache dependencies. Procedural assets outside GLTS can combine `cachedImpostor` with explicit file and parameter dependencies; include every input that changes the asset, including helper code and textures. Do not reuse one dependency set for different asset variants.
68
+ Here, `loadDetailedMesh` loads the detailed object, `sourceBox` describes its bounds in the owner's space, and `coarseMesh` is already available.
66
69
 
67
70
  ```ts
68
- const trees = await loader.loadInstancesAsync(
69
- {
70
- url: "/assets/tree.glts",
71
- levels: [{ type: "impostor", layout: "hemi", lazy: true, maxPixels: 128 }],
72
- },
73
- spots.length,
74
- );
71
+ import { Lod } from "@drawcall/lod";
72
+
73
+ const object = new Lod([{ load: loadDetailedMesh, maxPixels: Infinity, box: sourceBox }, { object: coarseMesh }]);
74
+ scene.add(object);
75
75
  ```
76
76
 
77
- Use `LazyImpostor` when assembling levels yourself. Keep an eager source and a known switch height; while an atlas loads, a ready finer level stays visible. Keep the bake input alive and unchanged until loading finishes. If batching consumes or replaces its geometry, retain an authored snapshot for the deferred bake. Apply custom impostor material setup and refresh custom draw or shadow registries on `levelschange`, as well as at construction. Use `load()` to prefetch or explicitly retry; failures reject and automatic demand reports the error while retaining the finer fallback.
78
-
79
- Measure the first visible frame, a warm reload, and the first traversal separately. Cached atlas bytes avoid baking; deferred levels avoid reading and uploading unused atlases. They do not remove source loading, other derived-level construction, or first-use shader preparation. Check caches before constructing their expensive inputs, and persist baked meshes too when those dominate startup. Prefetch only the initial view if its fallback would be too expensive; include any custom instance-streaming updates before measuring demand.
80
-
81
- When preparing a view before its first render, seed its viewport with `setViewportHeight` before updating or prefetching LODs. This lets the first update exclude tiers that cannot draw; otherwise their shaders and textures can be prepared unnecessarily. Refresh the supplied height on resize, especially when every LOD is currently culled; normal draws continue measuring the viewport automatically.
82
-
83
- ## Impostor-ready assets
84
-
85
- - **Units and pivot:** Y up, metres, origin at the ground under the object, so instance matrices place it standing. Vary copies cheaply with per-instance colour (`setColorAt`): every variant model costs its own levels and bakes.
86
- - **Foliage leaves are alpha-tested** (glTF `MASK`, never `BLEND`), the alpha in the base colour texture, and the colour bled out into the transparent texels: black there darkens every mip, so the source darkens with distance and its bakes with it.
87
- - **Custom lighting is not baked.** Impostors and baked levels keep the surface (colour, normal, roughness) and light it as a standard material: lighting a source's node material changes on top, such as leaves glowing in back light, is lost, and such foliage reads darker once its impostor shows, worst against the light. Give each `ImpostorMesh`'s material (a `MeshStandardNodeMaterial`) the same change once the `Lod` or `InstancedLod` is built, for example as an `emissiveNode`.
88
- - **Jitter dense plantings** in position and rotation. Bakes and impostor views look along parallel rays: plants on a grid leave straight gaps there that no perspective view of the real plants shows.
89
- - **A building's low shell** is geometry only, generated from the same parameters as the building and in its space. Parts it leaves out (a chimney) show only as texture and lower the level's switch size. Close it where the source is closed (a floor for a floor); leave out faces nobody sees, which take texture space from those that are seen. Make glass see-through and the rooms their own model (see "Interiors").
90
- - **A canopy for a patch of plants** sits at the leaf tops, with side walls only on the outer edge of the whole field: inner walls show as a cliff where plants hand over. Rays that find no leaf at the top bake the leaves further down, so the canopy needs nothing under it. Whatever stands above the leaves (tassels, flowers) covers far more of a top-down bake than of any view across the field: bake the canopy from plants with fewer of them. Lay out the patch so rows run on across its borders, then copies tile without seams. Switch the plants on top per plant, by their own distance, not per patch: the hand-over then follows a smooth contour around the camera instead of patch edges.
91
-
92
- ## Performance
93
-
94
- - **Tune switch sizes on a standard screen.** They are in CSS pixels, so the choice holds on a high-density one; size anything of your own that reacts to on-screen size (how far plants exist, how many) in CSS pixels too, or a high-density screen multiplies it.
95
- - **When source geometry dominates,** lighten the source first, then let its impostor take over earlier — a larger `maxPixels` on the impostor level: lowering it keeps more copies at the source. Bake that impostor with the same `maxPixels`: above its default it shows its top mip magnified, which otherwise keeps the look of the source at the bake's size — foliage denser and darker than the leaves it replaces up close.
96
- - **Impostors cost fill.** Few triangles can still cover the screen many times: atlas sampling, lighting and overlapping cards can dominate even with parallax off. Compare dense individual plants with a patch's baked far level, not just triangle counts. Keep parallax for impostors seen large — without it they ghost (doubled trunks) — and turn it off only for impostors that only ever show small or densely packed, such as a field's plants.
97
- - **Count material groups as well as triangles.** Instancing combines copies of a model, but its separate materials still require separate draws in each pass. Merge compatible parts before creating LOD batches; packing textures alone does not combine draws. Preserve material and shadow behavior, and keep overlapping or thin parts separate if batching changes their appearance. For `bakeMesh`, bake from the authored materials before replacing them with GPU-only atlas materials.
98
- - **Keep the rendering conditions fixed when comparing performance:** viewport, pixel ratio, multisampling, shadows, wind and switch sizes. Disabling an effect can identify its cost, but is not an equivalent-looking optimization. Check moving transitions as well as stationary images; multisampling matters especially for thin twigs and grass.
99
- - **Judge changes by completed frame time.** Fewer draws, triangles or buffer bindings can still cost more if culling becomes coarser or preparation, vertex work or shading becomes heavier. Merged shadow casters can process parts that were previously skipped. Atlases can increase texture memory; preserve resolution and mip quality in the comparison. Measure CPU work and GPU completion separately; overlapping GPU pass durations do not add up to frame time. Recheck the original setup after each experiment to catch background-load drift. Compare images after the same movement history: streamed instance slots and cached shadows can differ even when the final camera pose is identical.
100
- - **Stream into existing batches:** reuse nearby regions' slots and change only the matrices or colours that actually changed. Rebuilding batches or rewriting the whole crowd during flight adds preparation and upload work even when few instances draw.
101
- - **Check the first flight as well as a warmed repeat.** Preparing the starting view does not prepare every later level and shadow variant. Measure first-use shader preparation and streaming separately from steady-state throughput. Any startup warmup needs its own loading-time and appearance checks, including simulation and streaming state, the first visible frame and later transitions. Free flight can still reveal new variants. Measure rendering separately from an overlay that counts every instance; count queries and temporary objects can cause periodic CPU and garbage-collection stalls.
102
-
103
- ## Shadows
104
-
105
- - **Levels are chosen from the viewing camera,** and every shadow map draws those same levels, including a finer fallback while an impostor loads. During a fade both levels cast, dithered as they draw, so the object casts one shadow.
106
- - **Casters narrower than a texel** of a directional light's shadow map draw nothing into it, so coarse cascades skip small casters by themselves.
107
- - **Shadow setups on the light or renderer reach every level**; impostors cast and receive at the surface they resolve. A per-material setup must run on the level meshes' materials after the `Lod` is built: the material you passed in is no longer drawn.
108
- - **Open models leak light** (eaves, window reveals, single walls): three casts with back faces only. Set `shadowSide = DoubleSide` on their materials, with about a texel of shadow `bias` against acne.
109
-
110
- ## Pitfalls
111
-
112
- - **Materials are replaced.** A `Lod` draws each mesh with a faded node-material copy of its material; the material you passed in is no longer drawn. Edit the material on the level's mesh after building. `ShaderMaterial`s are refused: write them as node materials.
113
- - **Authored levels are read once,** when the `Lod` is built: arbitrary meshes added or moved later are neither faded nor measured right. Build a new `Lod` instead. `LazyImpostor` is the supported way to defer an impostor level.
114
- - **Skinned meshes are refused,** and animation is ignored.
115
- - **Orthographic cameras** switch by on-screen size too, but swap levels at once.
116
- - **Several cameras:** each is measured at the viewport height it last drew the `Lod` at; a camera's first frame assumes a typical screen. An `InstancedLod` holds one selection at a time: a render nested in another (a reflection, a `CubeCamera`) that sees it replaces the selection the outer render draws, so keep it off the layers such cameras see. Renders one after the other are fine.
117
- - **Many `Lod`s appearing at once hitch** while three sets up each mesh's material; draw crowds with `InstancedLod`.
118
- - **Lines, points and sprites** in a level draw but do not fade. Raycasts hit the source only, whatever level shows.
119
- - **Canvas alpha:** impostor edges use alpha-to-coverage, which leaves fractional alpha in the frame, so the page shows through: create the renderer with `alpha: false`.
120
-
121
- - **Impostor layout `"hemi"`** covers views from the horizon up only: right for upright trees, rocks and buildings, wrong for anything seen from below.
122
- - **`.glts` URLs need a registered loader:** `manager.addHandler(/\.glts(?:[?#]|$)/i, new GLTSLoader(manager))`. Inside a `.glts` script, register the contextual `gltsLoader` on the contextual `loadingManager` instead. Share the host's package through GLTS when using `instanceof`; separately loaded package copies have different constructors.
123
- - **Baking a mesh is slow and CPU-bound** on the loading thread (it yields between chunks), and each baked level has its own textures in GPU memory. Bake once per model and clone; time and memory grow with `textureSize` squared, so small or only-far objects bake faster at a smaller one.
124
- - **Baked levels read textures on the CPU:** compressed textures (KTX2) fail the bake. Emissive, clearcoat and transmission are not baked; glass bakes opaque in its own colour unless it looks into an interior. Only alpha-tested surfaces cut holes.
125
- - **Specular level** (`ior`, `specularIntensity`, `specularColor`, glTF `KHR_materials_specular`) reaches an impostor only as one average for the whole object, so parts or maps that differ in it reflect alike; baked levels reflect like a plain dielectric, so a source with its specular turned down shows brighter at them.
126
- - **Clones of a built level** made by hand lose the measured error their switch size comes from; clone the whole `Lod` instead.
127
- - **Large worlds** (kilometres to millimetres) z-fight with the default depth buffer. Every level works with the renderer's `reversedDepthBuffer`.
128
-
129
- ## Interiors
130
-
131
- - **Rooms are their own model,** never part of the building's: only rooms given as the interior are left out of the baked exterior and shown through its windows. One baked level per model takes an interior.
132
- - **One direct child per room, filling its box:** walls, floor and ceiling on the box's faces, facing in. Rooms must not overlap; doorways between them, stairwells and several storeys are fine. A room's box should begin at the inside of the wall its windows are in; glass with no room just behind it stays plain glass.
133
- - **The glass must be see-through in the source:** transparent with opacity below 1, or transmissive. Dark but opaque glass gives no windows, and the bake fails when no glass looks into a room.
134
- - **Rooms are lit by the light reaching the window** — ambient, light probes and the environment, not the sun, which the walls would block — so they darken with the scene. For a dimmer room, darken its materials.
135
- - **Lamps glow through emissive (or unlit) materials.** Lights in an interior are refused: wherever the source draws they would be scene lights, recompiling every lit material at each switch.
136
- - **Furniture against a wall looks right;** things standing free in the room flatten onto the walls behind them.
137
- - **Calling `bakeMesh` yourself:** pass the interior and put it inside the source, so the source shows the real rooms; the bake leaves it out of the exterior either way.
77
+ A missing level uses the nearest ready finer representation, or the nearest coarser one if none is finer. Requests follow the visible view and begin ahead of the transition. Clones share loading work. Keep the resources used by a deferred load alive until it finishes.
78
+
79
+ For direct preparation and storage outside `LodLoader`, combine `simplify`, `bakeMesh`, or `bakeImpostor` with the corresponding codecs and drawing objects. Use `ImpostorMesh` directly when copies stay distant throughout their lifetime. For external detail systems, combine an empty near level with a coarse representation and use `levelOf` or level visibility to decide where to supply detail.
80
+
81
+ ## Prepare assets that survive transitions
82
+
83
+ Keep sources, simplified geometry, low shells and interiors in a consistent coordinate system. A ground-level pivot helps upright repeated assets. Use instance colour variation when it can replace separately baked variants.
84
+
85
+ Author foliage with alpha-tested cutouts and colour beyond the visible texture edges. Inspect the source at distance before baking: dark transparent texels can darken small mips and every derived representation. Match visual effects across representations so foliage does not change lighting at a transition.
86
+
87
+ Match a low shell to the source's occupied shape. Preserve important silhouette features and remove faces that will never be seen. Generate shell and source from the same parameters when possible. Keep rooms separate while authoring, with their boundaries just behind windows and furnishings near visible walls; include rooms in the detailed source when they should appear in the near view too.
88
+
89
+ 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.
90
+
91
+ ## Tune the complete scene
92
+
93
+ 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 handover, then inspect its coverage and colour from several angles.
94
+
95
+ Group nearby copies into spatial regions. Broad batches can lose useful culling, while tiny batches spend too much time submitting draws. Reuse instance slots and update changed matrices or colours instead of rebuilding whole crowds. Count material groups as well as triangles; an atlas alone does not combine draws. Each distinct material structure costs a pipeline compile on the first view, so variants should share material structure.
96
+
97
+ 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.
98
+
99
+ Compare cold startup, warm startup and first traversal under the same camera movement, viewport, shadows, wind and thresholds. Keep expensive diagnostic overlays outside measurements. A warm repeat does not reveal first-use work, and fewer draws can still lose to worse culling, shading or memory costs.
@@ -1,15 +0,0 @@
1
- import type { Object3D } from "three/webgpu";
2
- import { type CacheEntryOptions, type Dependencies } from "vitecache";
3
- import { type BakeImpostorOptions } from "./bake/index.js";
4
- import type { Impostor } from "./impostor.js";
5
- /** Cache location; browser basePath and Node root follow vitecache's conventions. */
6
- export type ImpostorCacheOptions = Pick<CacheEntryOptions, "basePath" | "root">;
7
- /**
8
- * Read or bake an impostor with vitecache. Declare every source input as a dependency;
9
- * bake options and the lod/three package versions are added automatically. Dependency
10
- * names beginning with `lod:` are reserved. URL dependencies need the vitecache Vite
11
- * plugin during development and build. Cache errors reject instead of hiding stale data.
12
- */
13
- export declare function cachedImpostor(source: Object3D, options: BakeImpostorOptions, dependencies: Dependencies, cacheOptions?: ImpostorCacheOptions): Promise<Impostor>;
14
- /** Shared persistence for the public bake and the loader's source-excluding bake. */
15
- export declare function cached(options: BakeImpostorOptions, dependencies: Dependencies, make: (options: BakeImpostorOptions) => Promise<Impostor>, cacheOptions?: ImpostorCacheOptions): Promise<Impostor>;
@@ -1,44 +0,0 @@
1
- import { CacheEntry } from "vitecache";
2
- import { bakeImpostor } from "./bake/index.js";
3
- import { decodeImpostorAsync, encodeImpostor } from "./codec.js";
4
- /**
5
- * Read or bake an impostor with vitecache. Declare every source input as a dependency;
6
- * bake options and the lod/three package versions are added automatically. Dependency
7
- * names beginning with `lod:` are reserved. URL dependencies need the vitecache Vite
8
- * plugin during development and build. Cache errors reject instead of hiding stale data.
9
- */
10
- export function cachedImpostor(source, options, dependencies, cacheOptions) {
11
- return cached(options, dependencies, (settings) => bakeImpostor(source, settings), cacheOptions);
12
- }
13
- /** Shared persistence for the public bake and the loader's source-excluding bake. */
14
- export async function cached(options, dependencies, make, cacheOptions) {
15
- const settings = { ...options };
16
- if (Object.keys(dependencies).some((name) => name.startsWith("lod:")))
17
- throw new Error("cachedImpostor: dependency names beginning with lod: are reserved");
18
- const entry = new CacheEntry({
19
- ...cacheOptions,
20
- version: "lod-impostor@1",
21
- dependencies: {
22
- ...dependencies,
23
- "lod:options": {
24
- value: {
25
- layout: settings.layout ?? null,
26
- frames: settings.frames ?? null,
27
- resolution: settings.resolution ?? null,
28
- maxPixels: settings.maxPixels ?? null,
29
- emissive: settings.emissive ?? null,
30
- supersample: settings.supersample ?? null,
31
- },
32
- },
33
- "lod:package": { package: "@drawcall/lod" },
34
- "lod:three": { package: "three" },
35
- },
36
- });
37
- const bytes = await entry.load();
38
- if (bytes !== undefined)
39
- return decodeImpostorAsync(bytes);
40
- const baked = await make(settings);
41
- await entry.save(encodeImpostor(baked));
42
- return baked;
43
- }
44
- //# sourceMappingURL=cache.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/impostor/cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAA6C,MAAM,WAAW,CAAC;AAClF,OAAO,EAAE,YAAY,EAA4B,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAMjE;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAgB,EAChB,OAA4B,EAC5B,YAA0B,EAC1B,YAAmC;IAEnC,OAAO,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,YAAY,CAAC,CAAC;AACnG,CAAC;AAED,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,OAA4B,EAC5B,YAA0B,EAC1B,IAAyD,EACzD,YAAmC;IAEnC,MAAM,QAAQ,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;IAChC,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;IAC5J,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC;QAC3B,GAAG,YAAY;QACf,OAAO,EAAE,gBAAgB;QACzB,YAAY,EAAE;YACZ,GAAG,YAAY;YACf,aAAa,EAAE;gBACb,KAAK,EAAE;oBACL,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,IAAI;oBAC/B,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,IAAI;oBAC/B,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,IAAI;oBACvC,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,IAAI;oBACrC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,IAAI,IAAI;oBACnC,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,IAAI;iBAC1C;aACF;YACD,aAAa,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE;YAC3C,WAAW,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE;SAClC;KACF,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;IACjC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"bounds.js","sourceRoot":"","sources":["../../src/instanced/bounds.ts"],"names":[],"mappings":"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"}
package/dist/lazy.d.ts DELETED
@@ -1,64 +0,0 @@
1
- import { Matrix4, Object3D, Sphere, type Camera, type Object3DEventMap } from "three/webgpu";
2
- import { type ImpostorMeshOptions } from "./impostor/mesh/index.js";
3
- import { type Impostor } from "./impostor/impostor.js";
4
- export interface LazyImpostorOptions {
5
- /** The switch height must be known before the atlas has loaded. */
6
- maxPixels: number;
7
- draw?: ImpostorMeshOptions;
8
- }
9
- export interface LazyImpostorEventMap extends Object3DEventMap {
10
- error: {
11
- error: unknown;
12
- };
13
- }
14
- export interface LevelsEventMap extends Object3DEventMap {
15
- levelschange: {};
16
- }
17
- interface Shared {
18
- factory: (() => Promise<Impostor>) | undefined;
19
- status: "idle" | "loading" | "ready" | "error";
20
- value: Impostor | undefined;
21
- error: unknown;
22
- promise: Promise<Impostor> | undefined;
23
- attempt: number;
24
- reported: number;
25
- users: Set<LazyImpostor>;
26
- }
27
- /**
28
- * An impostor level whose atlas is loaded only when a viewing camera may need it.
29
- * Put it after an eager source in Lod or InstancedLod. Until ready, the nearest
30
- * ready finer level draws instead. The factory can decode cached data or bake it;
31
- * it runs once across clones and concurrent requests. It does not upload textures.
32
- */
33
- export declare class LazyImpostor extends Object3D<LazyImpostorEventMap> {
34
- readonly isLazyImpostor = true;
35
- readonly options: LazyImpostorOptions;
36
- private readonly state;
37
- constructor(load: () => Promise<Impostor>, options: LazyImpostorOptions);
38
- get maxPixels(): number;
39
- get status(): Shared["status"] | "disposed";
40
- get error(): unknown;
41
- get impostor(): Impostor | undefined;
42
- /** Prefetch atlas data, or explicitly retry a failed request. Errors reject. */
43
- load(): Promise<Impostor>;
44
- copy(source: LazyImpostor): this;
45
- clone(): this;
46
- /** @internal LOD ownership; several crowds can share a template. */
47
- retain(): void;
48
- /** @internal Release a LOD's ownership of this template. */
49
- release(): void;
50
- /** @internal The card has been installed, not merely decoded. */
51
- get available(): boolean;
52
- /** @internal Install this descriptor's card before its LOD attaches draw hooks. */
53
- materialize(): void;
54
- /** @internal Demand starts one request, with one visible report on failure. */
55
- request(): void;
56
- /** Stops demand and releases this template's card. Pending work cannot install it. */
57
- dispose(): void;
58
- }
59
- export declare function available(object: Object3D): boolean;
60
- /** Each logical level's nearest available finer level; eager empty levels still cull. */
61
- export declare function fallbacks(objects: readonly Object3D[]): number[];
62
- /** Demand only from the viewing frustum; lazy shadow work uses the ready fallback. */
63
- export declare function inView(camera: Camera, root: Matrix4, sphere: Sphere): boolean;
64
- export {};