@drawcall/lod 0.0.0-stage → 0.1.2

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 (178) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -2
  3. package/dist/baked/codec.d.ts +10 -0
  4. package/dist/baked/codec.js +291 -0
  5. package/dist/baked/codec.js.map +1 -0
  6. package/dist/baked/coverage.d.ts +3 -0
  7. package/dist/baked/coverage.js +45 -0
  8. package/dist/baked/coverage.js.map +1 -0
  9. package/dist/baked/index.d.ts +51 -0
  10. package/dist/baked/index.js +151 -0
  11. package/dist/baked/index.js.map +1 -0
  12. package/dist/baked/interior/faces.d.ts +26 -0
  13. package/dist/baked/interior/faces.js +105 -0
  14. package/dist/baked/interior/faces.js.map +1 -0
  15. package/dist/baked/interior/material.d.ts +31 -0
  16. package/dist/baked/interior/material.js +157 -0
  17. package/dist/baked/interior/material.js.map +1 -0
  18. package/dist/baked/interior/rooms.d.ts +22 -0
  19. package/dist/baked/interior/rooms.js +78 -0
  20. package/dist/baked/interior/rooms.js.map +1 -0
  21. package/dist/baked/low.d.ts +20 -0
  22. package/dist/baked/low.js +75 -0
  23. package/dist/baked/low.js.map +1 -0
  24. package/dist/baked/raster.d.ts +20 -0
  25. package/dist/baked/raster.js +71 -0
  26. package/dist/baked/raster.js.map +1 -0
  27. package/dist/baked/transfer.d.ts +36 -0
  28. package/dist/baked/transfer.js +243 -0
  29. package/dist/baked/transfer.js.map +1 -0
  30. package/dist/baked/unwrap.d.ts +9 -0
  31. package/dist/baked/unwrap.js +167 -0
  32. package/dist/baked/unwrap.js.map +1 -0
  33. package/dist/baked/xatlas.d.ts +2 -0
  34. package/dist/baked/xatlas.js +31 -0
  35. package/dist/baked/xatlas.js.map +1 -0
  36. package/dist/bounds.d.ts +33 -0
  37. package/dist/bounds.js +127 -0
  38. package/dist/bounds.js.map +1 -0
  39. package/dist/dispose.d.ts +5 -0
  40. package/dist/dispose.js +28 -0
  41. package/dist/dispose.js.map +1 -0
  42. package/dist/fade.d.ts +44 -0
  43. package/dist/fade.js +78 -0
  44. package/dist/fade.js.map +1 -0
  45. package/dist/impostor/bake/atlas.d.ts +51 -0
  46. package/dist/impostor/bake/atlas.js +190 -0
  47. package/dist/impostor/bake/atlas.js.map +1 -0
  48. package/dist/impostor/bake/index.d.ts +50 -0
  49. package/dist/impostor/bake/index.js +221 -0
  50. package/dist/impostor/bake/index.js.map +1 -0
  51. package/dist/impostor/bake/materials.d.ts +29 -0
  52. package/dist/impostor/bake/materials.js +156 -0
  53. package/dist/impostor/bake/materials.js.map +1 -0
  54. package/dist/impostor/bake/source.d.ts +3 -0
  55. package/dist/impostor/bake/source.js +23 -0
  56. package/dist/impostor/bake/source.js.map +1 -0
  57. package/dist/impostor/cache.d.ts +15 -0
  58. package/dist/impostor/cache.js +44 -0
  59. package/dist/impostor/cache.js.map +1 -0
  60. package/dist/impostor/codec.d.ts +14 -0
  61. package/dist/impostor/codec.js +137 -0
  62. package/dist/impostor/codec.js.map +1 -0
  63. package/dist/impostor/impostor.d.ts +67 -0
  64. package/dist/impostor/impostor.js +79 -0
  65. package/dist/impostor/impostor.js.map +1 -0
  66. package/dist/impostor/mesh/card.d.ts +38 -0
  67. package/dist/impostor/mesh/card.js +79 -0
  68. package/dist/impostor/mesh/card.js.map +1 -0
  69. package/dist/impostor/mesh/index.d.ts +66 -0
  70. package/dist/impostor/mesh/index.js +174 -0
  71. package/dist/impostor/mesh/index.js.map +1 -0
  72. package/dist/impostor/mesh/material.d.ts +63 -0
  73. package/dist/impostor/mesh/material.js +199 -0
  74. package/dist/impostor/mesh/material.js.map +1 -0
  75. package/dist/impostor/mesh/surface.d.ts +63 -0
  76. package/dist/impostor/mesh/surface.js +162 -0
  77. package/dist/impostor/mesh/surface.js.map +1 -0
  78. package/dist/impostor/mesh/textures.d.ts +4 -0
  79. package/dist/impostor/mesh/textures.js +37 -0
  80. package/dist/impostor/mesh/textures.js.map +1 -0
  81. package/dist/impostor/octahedral.d.ts +29 -0
  82. package/dist/impostor/octahedral.js +83 -0
  83. package/dist/impostor/octahedral.js.map +1 -0
  84. package/dist/index.d.ts +15 -0
  85. package/dist/index.js +16 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/instanced/args.d.ts +20 -0
  88. package/dist/instanced/args.js +77 -0
  89. package/dist/instanced/args.js.map +1 -0
  90. package/dist/instanced/bounds.d.ts +50 -0
  91. package/dist/instanced/bounds.js +271 -0
  92. package/dist/instanced/bounds.js.map +1 -0
  93. package/dist/instanced/dirty.d.ts +12 -0
  94. package/dist/instanced/dirty.js +61 -0
  95. package/dist/instanced/dirty.js.map +1 -0
  96. package/dist/instanced/index.d.ts +116 -0
  97. package/dist/instanced/index.js +573 -0
  98. package/dist/instanced/index.js.map +1 -0
  99. package/dist/instanced/meshes.d.ts +14 -0
  100. package/dist/instanced/meshes.js +54 -0
  101. package/dist/instanced/meshes.js.map +1 -0
  102. package/dist/instanced/select.d.ts +84 -0
  103. package/dist/instanced/select.js +264 -0
  104. package/dist/instanced/select.js.map +1 -0
  105. package/dist/lazy.d.ts +64 -0
  106. package/dist/lazy.js +187 -0
  107. package/dist/lazy.js.map +1 -0
  108. package/dist/levels.d.ts +72 -0
  109. package/dist/levels.js +146 -0
  110. package/dist/levels.js.map +1 -0
  111. package/dist/loader/cache.d.ts +15 -0
  112. package/dist/loader/cache.js +37 -0
  113. package/dist/loader/cache.js.map +1 -0
  114. package/dist/loader/dispose.d.ts +3 -0
  115. package/dist/loader/dispose.js +25 -0
  116. package/dist/loader/dispose.js.map +1 -0
  117. package/dist/loader.d.ts +99 -0
  118. package/dist/loader.js +234 -0
  119. package/dist/loader.js.map +1 -0
  120. package/dist/lod.d.ts +78 -0
  121. package/dist/lod.js +211 -0
  122. package/dist/lod.js.map +1 -0
  123. package/dist/material.d.ts +12 -0
  124. package/dist/material.js +52 -0
  125. package/dist/material.js.map +1 -0
  126. package/dist/pause.d.ts +6 -0
  127. package/dist/pause.js +20 -0
  128. package/dist/pause.js.map +1 -0
  129. package/dist/renderer.d.ts +21 -0
  130. package/dist/renderer.js +83 -0
  131. package/dist/renderer.js.map +1 -0
  132. package/dist/simplify.d.ts +24 -0
  133. package/dist/simplify.js +148 -0
  134. package/dist/simplify.js.map +1 -0
  135. package/dist/source/error.d.ts +14 -0
  136. package/dist/source/error.js +94 -0
  137. package/dist/source/error.js.map +1 -0
  138. package/dist/source/frame.d.ts +11 -0
  139. package/dist/source/frame.js +25 -0
  140. package/dist/source/frame.js.map +1 -0
  141. package/dist/source/shading.d.ts +96 -0
  142. package/dist/source/shading.js +224 -0
  143. package/dist/source/shading.js.map +1 -0
  144. package/dist/source/source.d.ts +23 -0
  145. package/dist/source/source.js +50 -0
  146. package/dist/source/source.js.map +1 -0
  147. package/dist/source/surface.d.ts +31 -0
  148. package/dist/source/surface.js +110 -0
  149. package/dist/source/surface.js.map +1 -0
  150. package/dist/source/texels.d.ts +45 -0
  151. package/dist/source/texels.js +191 -0
  152. package/dist/source/texels.js.map +1 -0
  153. package/dist/source/trace.d.ts +42 -0
  154. package/dist/source/trace.js +153 -0
  155. package/dist/source/trace.js.map +1 -0
  156. package/dist/three.d.ts +55 -0
  157. package/dist/three.js +103 -0
  158. package/dist/three.js.map +1 -0
  159. package/dist/tsl.d.ts +45 -0
  160. package/dist/tsl.js +99 -0
  161. package/dist/tsl.js.map +1 -0
  162. package/dist/view.d.ts +30 -0
  163. package/dist/view.js +75 -0
  164. package/dist/view.js.map +1 -0
  165. package/dist/wind/bounds.d.ts +3 -0
  166. package/dist/wind/bounds.js +47 -0
  167. package/dist/wind/bounds.js.map +1 -0
  168. package/dist/wind/hooks.d.ts +5 -0
  169. package/dist/wind/hooks.js +3 -0
  170. package/dist/wind/hooks.js.map +1 -0
  171. package/dist/wind/index.d.ts +57 -0
  172. package/dist/wind/index.js +196 -0
  173. package/dist/wind/index.js.map +1 -0
  174. package/dist/wind/sway.d.ts +29 -0
  175. package/dist/wind/sway.js +71 -0
  176. package/dist/wind/sway.js.map +1 -0
  177. package/package.json +69 -3
  178. package/skills/lod/SKILL.md +137 -0
@@ -0,0 +1,54 @@
1
+ import { BufferGeometry, Matrix4 } from "three/webgpu";
2
+ import { levelMaterial } from "../material.js";
3
+ // The meshes an InstancedLod draws its levels with, made from the levels' templates.
4
+ const IDENTITY = new Matrix4();
5
+ /** The index (or vertex) ranges `mesh` draws, clipped to its draw range; group order is preserved even for empty draws. */
6
+ export function ranges(mesh) {
7
+ const { geometry } = mesh;
8
+ const indexed = geometry.index !== null;
9
+ const total = geometry.index?.count ?? geometry.getAttribute("position").count;
10
+ const groups = Array.isArray(mesh.material) ? geometry.groups : [{ start: 0, count: total }];
11
+ return groups.map(({ start, count }) => {
12
+ const first = Math.min(total, Math.max(0, start, geometry.drawRange.start));
13
+ const end = Math.min(total, start + count, geometry.drawRange.start + geometry.drawRange.count);
14
+ return { count: Math.max(0, end - first), start: first, indexed };
15
+ });
16
+ }
17
+ /** The faded material of `mesh`'s material group `group`. */
18
+ export function groupMaterial(mesh, group) {
19
+ if (!Array.isArray(mesh.material))
20
+ return levelMaterial(mesh.material);
21
+ const index = mesh.geometry.groups[group]?.materialIndex ?? 0;
22
+ const material = mesh.material[index];
23
+ if (!material)
24
+ throw new Error(`InstancedLod: "${mesh.name}" has no material ${index}`);
25
+ return levelMaterial(material);
26
+ }
27
+ /** A geometry drawing `geometry`'s buffers from the indirect arguments at byte `offset`. */
28
+ export function indirect(geometry, selection, offset) {
29
+ const view = new BufferGeometry();
30
+ view.index = geometry.index;
31
+ for (const [name, attribute] of Object.entries(geometry.attributes))
32
+ view.setAttribute(name, attribute);
33
+ view.morphAttributes = geometry.morphAttributes;
34
+ view.boundingBox = geometry.boundingBox;
35
+ view.boundingSphere = geometry.boundingSphere;
36
+ view.setIndirect(selection.args, selection.argsOffset + offset);
37
+ return view;
38
+ }
39
+ /** Placed copies of geometries, shared by every InstancedLod drawing the same mesh the same way. */
40
+ const copies = new WeakMap();
41
+ /** `geometry` moved by `placement`: itself for the identity, else a copy made once. */
42
+ export function placed(geometry, placement) {
43
+ if (placement.equals(IDENTITY))
44
+ return geometry;
45
+ const known = copies.get(geometry) ?? [];
46
+ copies.set(geometry, known);
47
+ const hit = known.find((entry) => entry.placement.equals(placement));
48
+ if (hit)
49
+ return hit.geometry;
50
+ const copy = geometry.clone().applyMatrix4(placement);
51
+ known.push({ placement: placement.clone(), geometry: copy });
52
+ return copy;
53
+ }
54
+ //# sourceMappingURL=meshes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meshes.js","sourceRoot":"","sources":["../../src/instanced/meshes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import { type IndirectStorageBufferAttribute, StorageBufferAttribute, StorageInstancedBufferAttribute, Vector3, type ComputeNode, type Node, type Renderer, type Sphere } from "three/webgpu";
2
+ export { ARGS_BYTES } from "./args.js";
3
+ /** The slots every level draws from, `count` per level that draws, from its `first`. */
4
+ export interface Slots {
5
+ readonly matrices: StorageInstancedBufferAttribute;
6
+ readonly fades: StorageBufferAttribute;
7
+ /** RGB and a pad per slot, once the instances have colours */
8
+ colors: StorageInstancedBufferAttribute | null;
9
+ }
10
+ /** One indirect draw: a level's mesh, drawing `count` indices (or vertices) from `start`. */
11
+ export interface IndirectDraw {
12
+ level: number;
13
+ count: number;
14
+ start: number;
15
+ indexed: boolean;
16
+ }
17
+ export declare class Selection {
18
+ /** One instance's bounding sphere, in its own space. */
19
+ private readonly sphere;
20
+ private draws;
21
+ private fallback;
22
+ /** The instances' matrices, as `setMatrixAt` writes them. */
23
+ readonly matrices: StorageBufferAttribute;
24
+ /** The instances' colours (RGB, padded to four floats), once there are any. */
25
+ colors: StorageBufferAttribute | null;
26
+ readonly count: number;
27
+ readonly slots: Slots;
28
+ /** Per level, its first slot, or null for a level that draws nothing. */
29
+ readonly first: Array<number | null>;
30
+ /** Shared page containing this selection's draws, `ARGS_BYTES` apart. */
31
+ get args(): IndirectStorageBufferAttribute;
32
+ /** Byte offset of this selection's first draw in its page. */
33
+ get argsOffset(): number;
34
+ readonly eye: import("three/webgpu").UniformNode<"vec3", Vector3>;
35
+ /** Pixels per unit of subtense (perspective) or of size (orthographic), × Lod.quality. */
36
+ readonly scale: import("three/webgpu").UniformNode<"float", number>;
37
+ readonly ortho: import("three/webgpu").UniformNode<"uint", number>;
38
+ readonly fades: import("three/webgpu").UniformNode<"uint", number>;
39
+ /** The level every instance draws, or -1. */
40
+ readonly forced: import("three/webgpu").UniformNode<"int", number>;
41
+ /** Per level, its maxPixels (any finite stand-in for level 0's Infinity). */
42
+ readonly maxPixels: Array<{
43
+ value: number;
44
+ } & Node<"float">>;
45
+ private readonly counts;
46
+ private slice;
47
+ private readonly argsStart;
48
+ private kernels;
49
+ /**
50
+ * The renderers whose buffers hold the selection for the view and instances as they are
51
+ * (each renderer keeps its own copy of the buffers): see `aim` and `changed`.
52
+ */
53
+ private readonly current;
54
+ private revision;
55
+ private stable;
56
+ private readonly colorRenderers;
57
+ private rendererCount;
58
+ constructor(
59
+ /** 16 floats per instance */
60
+ matrices: Float32Array,
61
+ /** One instance's bounding sphere, in its own space. */
62
+ sphere: Sphere,
63
+ /** Per level, whether it draws anything. */
64
+ drawing: readonly boolean[], draws: readonly IndirectDraw[], fallback?: readonly number[]);
65
+ private allocate;
66
+ /** Lazy levels reserve slots up front, so installing draws keeps every shader binding valid. */
67
+ replace(draws: readonly IndirectDraw[], fallback: readonly number[]): void;
68
+ /** Select for this view next; the uniforms are set and compared here. */
69
+ aim(eye: Vector3, scale: number, ortho: boolean, fades: boolean, forced: number | null, levels: readonly {
70
+ maxPixels: number;
71
+ }[], stable?: object): void;
72
+ /** The instances changed since the last selection. */
73
+ changed(): void;
74
+ /** The passes `renderer` has to run for the selection to be current in its buffers, or none. */
75
+ take(renderer: Renderer): ComputeNode[];
76
+ /** Carry `colors` (4 floats per instance) with the instances from now on, into the slots. */
77
+ useColors(colors: Float32Array): void;
78
+ /** Frees its buffers and passes. */
79
+ dispose(): void;
80
+ private passes;
81
+ /** The pass that fills the slots. */
82
+ private selectPass;
83
+ private handOverPass;
84
+ }
@@ -0,0 +1,264 @@
1
+ import { StorageBufferAttribute, StorageInstancedBufferAttribute, Vector3, } from "three/webgpu";
2
+ import { Fn, If, Return, atomicAdd, atomicLoad, atomicStore, distance, float, instanceIndex, int, max, smoothstep, storage, uint, uniform, vec4, } from "three/tsl";
3
+ import { FADE } from "../levels.js";
4
+ import { maxScale } from "../tsl.js";
5
+ import { ARGS_BYTES, args } from "./args.js";
6
+ export { ARGS_BYTES } from "./args.js";
7
+ const CURRENT = [];
8
+ export class Selection {
9
+ sphere;
10
+ draws;
11
+ fallback;
12
+ /** The instances' matrices, as `setMatrixAt` writes them. */
13
+ matrices;
14
+ /** The instances' colours (RGB, padded to four floats), once there are any. */
15
+ colors = null;
16
+ count;
17
+ slots;
18
+ /** Per level, its first slot, or null for a level that draws nothing. */
19
+ first;
20
+ /** Shared page containing this selection's draws, `ARGS_BYTES` apart. */
21
+ get args() {
22
+ return this.slice.attribute;
23
+ }
24
+ /** Byte offset of this selection's first draw in its page. */
25
+ get argsOffset() {
26
+ return this.slice.offset;
27
+ }
28
+ // What the view sets before each selection (see InstancedLod.update).
29
+ eye = uniform(new Vector3());
30
+ /** Pixels per unit of subtense (perspective) or of size (orthographic), × Lod.quality. */
31
+ scale = uniform(0);
32
+ ortho = uniform(0, "uint");
33
+ fades = uniform(0, "uint");
34
+ /** The level every instance draws, or -1. */
35
+ forced = uniform(-1, "int");
36
+ /** Per level, its maxPixels (any finite stand-in for level 0's Infinity). */
37
+ maxPixels;
38
+ counts;
39
+ slice;
40
+ // Allocation location must not specialize the handover shader for every crowd.
41
+ argsStart = uniform(0, "uint");
42
+ kernels = null;
43
+ /**
44
+ * The renderers whose buffers hold the selection for the view and instances as they are
45
+ * (each renderer keeps its own copy of the buffers): see `aim` and `changed`.
46
+ */
47
+ current = new WeakMap();
48
+ revision = 0;
49
+ stable;
50
+ colorRenderers = new WeakSet();
51
+ rendererCount = 0;
52
+ constructor(
53
+ /** 16 floats per instance */
54
+ matrices,
55
+ /** One instance's bounding sphere, in its own space. */
56
+ sphere,
57
+ /** Per level, whether it draws anything. */
58
+ drawing, draws, fallback = drawing.map((_, i) => i)) {
59
+ this.sphere = sphere;
60
+ this.draws = draws;
61
+ this.fallback = fallback;
62
+ const count = matrices.length / 16;
63
+ this.count = count;
64
+ this.matrices = new StorageBufferAttribute(matrices, 16);
65
+ let next = 0;
66
+ this.first = drawing.map((draws) => (draws ? next++ * count : null));
67
+ const slots = Math.max(next * count, 1);
68
+ this.slots = { matrices: new StorageInstancedBufferAttribute(slots, 16), fades: new StorageBufferAttribute(slots, 1), colors: null };
69
+ this.maxPixels = drawing.map(() => uniform(0));
70
+ this.counts = new StorageBufferAttribute(new Uint32Array(drawing.length), 1);
71
+ this.slice = this.allocate(draws);
72
+ this.argsStart.value = this.argsOffset / 4;
73
+ }
74
+ allocate(draws) {
75
+ const values = new Uint32Array((draws.length * ARGS_BYTES) / 4);
76
+ draws.forEach((draw, k) => {
77
+ const at = (k * ARGS_BYTES) / 4;
78
+ const first = this.first[draw.level];
79
+ if (first === null || first === undefined)
80
+ throw new Error("InstancedLod: a draw of a level that draws nothing");
81
+ // indexed: count, instances, first index, base vertex, first instance;
82
+ // else: count, instances, first vertex, first instance.
83
+ values[at] = draw.count;
84
+ values[at + 2] = draw.start;
85
+ values[at + (draw.indexed ? 4 : 3)] = first;
86
+ });
87
+ return args.take(values);
88
+ }
89
+ /** Lazy levels reserve slots up front, so installing draws keeps every shader binding valid. */
90
+ replace(draws, fallback) {
91
+ const previous = this.slice;
92
+ this.slice = this.allocate(draws);
93
+ this.draws = draws;
94
+ this.fallback = fallback;
95
+ this.argsStart.value = this.argsOffset / 4;
96
+ previous.dispose();
97
+ for (const kernel of this.kernels ?? [])
98
+ kernel.dispose();
99
+ this.kernels = null;
100
+ this.changed();
101
+ }
102
+ /** Select for this view next; the uniforms are set and compared here. */
103
+ aim(eye, scale, ortho, fades, forced, levels, stable) {
104
+ const same = this.eye.value.equals(eye) &&
105
+ this.scale.value === scale &&
106
+ this.ortho.value === Number(ortho) &&
107
+ this.fades.value === Number(fades) &&
108
+ this.forced.value === (forced ?? -1) &&
109
+ levels.every((level, l) => this.maxPixels[l]?.value === Math.min(level.maxPixels, 3.4e38));
110
+ // The caller can prove that changed views still produce the same solid slots.
111
+ const reuse = stable !== undefined && stable === this.stable;
112
+ this.stable = stable;
113
+ if (same)
114
+ return;
115
+ if (!reuse)
116
+ this.revision++;
117
+ this.eye.value.copy(eye);
118
+ this.scale.value = scale;
119
+ this.ortho.value = Number(ortho);
120
+ this.fades.value = Number(fades);
121
+ this.forced.value = forced ?? -1;
122
+ // any finite stand-in for level 0's Infinity
123
+ levels.forEach((level, l) => {
124
+ const uniform = this.maxPixels[l];
125
+ if (uniform)
126
+ uniform.value = Math.min(level.maxPixels, 3.4e38);
127
+ });
128
+ }
129
+ /** The instances changed since the last selection. */
130
+ changed() {
131
+ this.revision++;
132
+ this.stable = undefined;
133
+ }
134
+ /** The passes `renderer` has to run for the selection to be current in its buffers, or none. */
135
+ take(renderer) {
136
+ if (this.current.get(renderer) === this.revision)
137
+ return CURRENT;
138
+ const first = !this.current.has(renderer);
139
+ if (first) {
140
+ this.rendererCount = Math.min(2, this.rendererCount + 1);
141
+ }
142
+ // Three clears updateRanges globally after one backend uploads them. A second,
143
+ // lagging renderer needs the whole current source, including earlier edits.
144
+ // Initial buffer creation also leaves ranges uncleared; start it with none.
145
+ if (first || this.rendererCount > 1) {
146
+ this.matrices.clearUpdateRanges();
147
+ }
148
+ if (this.colors && (!this.colorRenderers.has(renderer) || this.rendererCount > 1)) {
149
+ this.colorRenderers.add(renderer);
150
+ this.colors.clearUpdateRanges();
151
+ }
152
+ this.current.set(renderer, this.revision);
153
+ return this.passes();
154
+ }
155
+ /** Carry `colors` (4 floats per instance) with the instances from now on, into the slots. */
156
+ useColors(colors) {
157
+ if (this.colors)
158
+ return;
159
+ this.colors = new StorageBufferAttribute(colors, 4);
160
+ this.slots.colors = new StorageInstancedBufferAttribute(this.slots.matrices.count, 4);
161
+ for (const kernel of this.kernels ?? [])
162
+ kernel.dispose();
163
+ this.kernels = null;
164
+ this.changed();
165
+ }
166
+ /** Frees its buffers and passes. */
167
+ dispose() {
168
+ const { slots } = this;
169
+ for (const attribute of [this.matrices, this.colors, this.counts, slots.matrices, slots.fades, slots.colors])
170
+ attribute?.dispose();
171
+ for (const kernel of this.kernels ?? [])
172
+ kernel.dispose();
173
+ this.kernels = null;
174
+ this.slice.dispose();
175
+ }
176
+ passes() {
177
+ this.kernels ??= [this.selectPass(), this.handOverPass()];
178
+ return this.kernels;
179
+ }
180
+ /** The pass that fills the slots. */
181
+ selectPass() {
182
+ const { count, sphere, colors, slots } = this;
183
+ const matrices = storage(this.matrices, "mat4", count).setName("lodSourceMatrices");
184
+ const sources = colors ? storage(colors, "vec4", count).setName("lodSourceColors") : null;
185
+ const counts = storage(this.counts, "uint", this.first.length).setName("lodCounts").toAtomic();
186
+ const out = {
187
+ matrices: storage(slots.matrices, "mat4", slots.matrices.count).setName("lodSlotMatrices"),
188
+ fades: storage(slots.fades, "float", slots.fades.count).setName("lodSlotFades"),
189
+ colors: slots.colors && storage(slots.colors, "vec4", slots.colors.count).setName("lodSlotColors"),
190
+ };
191
+ return Fn(() => {
192
+ const m = matrices.element(instanceIndex).toVar();
193
+ const r = float(sphere.radius).mul(maxScale(m)).toVar();
194
+ If(r.equal(0), () => Return());
195
+ const centre = m.mul(vec4(sphere.center.x, sphere.center.y, sphere.center.z, 1)).xyz;
196
+ const size = r.mul(2).mul(this.scale);
197
+ const height = this.ortho
198
+ .equal(uint(1))
199
+ .select(size, size.div(max(distance(centre, this.eye), 1e-6)))
200
+ .toVar();
201
+ // The levels' maxPixels fall from level to level: the last one it fits is its level.
202
+ const chosen = int(0).toVar();
203
+ const top = float(0).toVar();
204
+ this.maxPixels.forEach((maxPixels, l) => {
205
+ if (l === 0)
206
+ return;
207
+ If(height.lessThanEqual(maxPixels), () => {
208
+ chosen.assign(l);
209
+ top.assign(maxPixels);
210
+ });
211
+ });
212
+ If(this.forced.greaterThanEqual(0), () => void chosen.assign(this.forced));
213
+ const t = float(0).toVar();
214
+ If(this.fades.equal(uint(1)).and(chosen.greaterThan(0)), () => void t.assign(smoothstep(top.mul(1 - FADE), top, height)));
215
+ const deferred = this.fallback.some((target, level) => target !== level);
216
+ const selected = deferred ? chosen.toVar() : chosen;
217
+ const finer = chosen.sub(1).toVar();
218
+ if (deferred) {
219
+ this.fallback.forEach((target, level) => {
220
+ If(chosen.equal(level), () => {
221
+ selected.assign(target);
222
+ finer.assign(this.fallback[level - 1] ?? target);
223
+ });
224
+ });
225
+ If(selected.equal(finer), () => void t.assign(0));
226
+ }
227
+ const emit = (level, first, fade) => {
228
+ const slot = atomicAdd(counts.element(level), uint(1)).add(first).toVar();
229
+ out.matrices.element(slot).assign(m);
230
+ out.fades.element(slot).assign(fade);
231
+ if (out.colors && sources)
232
+ out.colors.element(slot).assign(sources.element(instanceIndex));
233
+ };
234
+ this.first.forEach((first, level) => {
235
+ if (first === null)
236
+ return;
237
+ If(selected.equal(level), () => emit(level, first, t));
238
+ // The finer neighbour fading out with it.
239
+ If(finer.equal(level).and(t.greaterThan(0)), () => emit(level, first, t.negate()));
240
+ });
241
+ })().compute(count);
242
+ }
243
+ handOverPass() {
244
+ const counts = storage(this.counts, "uint", this.first.length).setName("lodCounts").toAtomic();
245
+ const args = storage(this.args, "uint", this.args.count).setName("lodDrawArgs");
246
+ return Fn(() => {
247
+ this.draws.forEach((draw, k) => {
248
+ const at = this.argsStart.add((k * ARGS_BYTES) / 4);
249
+ const first = this.first[draw.level];
250
+ if (first === null || first === undefined)
251
+ throw new Error("InstancedLod: a draw of a level that draws nothing");
252
+ // A new/reused slice may already have a GPU page. Initialize its fixed fields
253
+ // here too; uploading the CPU page would erase other crowds' live counts.
254
+ args.element(at).assign(uint(draw.count));
255
+ args.element(at.add(1)).assign(atomicLoad(counts.element(draw.level)));
256
+ args.element(at.add(2)).assign(uint(draw.start));
257
+ args.element(at.add(3)).assign(uint(draw.indexed ? 0 : first));
258
+ args.element(at.add(4)).assign(uint(draw.indexed ? first : 0));
259
+ });
260
+ this.first.forEach((_, l) => atomicStore(counts.element(l), uint(0)));
261
+ })().compute(1);
262
+ }
263
+ }
264
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/instanced/select.ts"],"names":[],"mappings":"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"}
package/dist/lazy.d.ts ADDED
@@ -0,0 +1,64 @@
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 {};