@drawcall/lod 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/dist/bake.d.ts +22 -0
- package/dist/bake.js +88 -0
- package/dist/bake.js.map +1 -0
- package/dist/baked/codec.d.ts +3 -6
- package/dist/baked/codec.js +48 -154
- package/dist/baked/codec.js.map +1 -1
- package/dist/baked/coverage.d.ts +6 -3
- package/dist/baked/coverage.js +6 -3
- package/dist/baked/coverage.js.map +1 -1
- package/dist/baked/fields.d.ts +9 -0
- package/dist/baked/fields.js +22 -0
- package/dist/baked/fields.js.map +1 -0
- package/dist/baked/index.d.ts +12 -6
- package/dist/baked/index.js +22 -20
- package/dist/baked/index.js.map +1 -1
- package/dist/baked/interior/faces.d.ts +4 -3
- package/dist/baked/interior/faces.js +13 -10
- package/dist/baked/interior/faces.js.map +1 -1
- package/dist/baked/interior/material.d.ts +7 -10
- package/dist/baked/interior/material.js +29 -36
- package/dist/baked/interior/material.js.map +1 -1
- package/dist/baked/interior/rooms.js +1 -1
- package/dist/baked/interior/rooms.js.map +1 -1
- package/dist/baked/low.js +5 -4
- package/dist/baked/low.js.map +1 -1
- package/dist/baked/raster.js +6 -6
- package/dist/baked/raster.js.map +1 -1
- package/dist/baked/textures.d.ts +17 -0
- package/dist/baked/textures.js +95 -0
- package/dist/baked/textures.js.map +1 -0
- package/dist/baked/transfer.js +19 -18
- package/dist/baked/transfer.js.map +1 -1
- package/dist/baked/unwrap.js +4 -3
- package/dist/baked/unwrap.js.map +1 -1
- package/dist/baked/xatlas.js.map +1 -1
- package/dist/codec/container.d.ts +8 -0
- package/dist/codec/container.js +63 -0
- package/dist/codec/container.js.map +1 -0
- package/dist/codec/mesh.d.ts +8 -0
- package/dist/{mesh/codec.js → codec/mesh.js} +80 -52
- package/dist/codec/mesh.js.map +1 -0
- package/dist/dispose.d.ts +7 -4
- package/dist/dispose.js +20 -22
- package/dist/dispose.js.map +1 -1
- package/dist/gpu.d.ts +39 -0
- package/dist/gpu.js +41 -0
- package/dist/gpu.js.map +1 -0
- package/dist/impostor/bake/atlas.d.ts +4 -4
- package/dist/impostor/bake/atlas.js +12 -12
- package/dist/impostor/bake/atlas.js.map +1 -1
- package/dist/impostor/bake/fit.d.ts +8 -0
- package/dist/impostor/bake/fit.js +28 -0
- package/dist/impostor/bake/fit.js.map +1 -0
- package/dist/impostor/bake/index.d.ts +22 -14
- package/dist/impostor/bake/index.js +41 -134
- package/dist/impostor/bake/index.js.map +1 -1
- package/dist/impostor/bake/materials.d.ts +3 -3
- package/dist/impostor/bake/materials.js +51 -13
- package/dist/impostor/bake/materials.js.map +1 -1
- package/dist/impostor/bake/sheet.d.ts +8 -0
- package/dist/impostor/bake/sheet.js +90 -0
- package/dist/impostor/bake/sheet.js.map +1 -0
- package/dist/impostor/bake/source.d.ts +2 -2
- package/dist/impostor/bake/source.js +8 -19
- package/dist/impostor/bake/source.js.map +1 -1
- package/dist/impostor/codec.d.ts +4 -5
- package/dist/impostor/codec.js +36 -109
- package/dist/impostor/codec.js.map +1 -1
- package/dist/impostor/impostor.d.ts +31 -7
- package/dist/impostor/impostor.js +21 -6
- package/dist/impostor/impostor.js.map +1 -1
- package/dist/impostor/ktx2/encode.d.ts +26 -0
- package/dist/impostor/ktx2/encode.js +117 -0
- package/dist/impostor/ktx2/encode.js.map +1 -0
- package/dist/impostor/ktx2/transcode.d.ts +3 -0
- package/dist/impostor/ktx2/transcode.js +99 -0
- package/dist/impostor/ktx2/transcode.js.map +1 -0
- package/dist/impostor/ktx2/uastc.d.ts +7 -0
- package/dist/impostor/ktx2/uastc.js +64 -0
- package/dist/impostor/ktx2/uastc.js.map +1 -0
- package/dist/impostor/ktx2/wasm/encoder.d.ts +4 -0
- package/dist/impostor/ktx2/wasm/encoder.js +10 -0
- package/dist/impostor/ktx2/wasm/encoder.js.map +1 -0
- package/dist/impostor/ktx2/wasm/transcoder.d.ts +3 -0
- package/dist/impostor/ktx2/wasm/transcoder.js +9 -0
- package/dist/impostor/ktx2/wasm/transcoder.js.map +1 -0
- package/dist/impostor/ktx2/worker.d.ts +1 -0
- package/dist/impostor/ktx2/worker.js +12 -0
- package/dist/impostor/ktx2/worker.js.map +1 -0
- package/dist/impostor/mesh/card.d.ts +3 -3
- package/dist/impostor/mesh/card.js +7 -7
- package/dist/impostor/mesh/card.js.map +1 -1
- package/dist/impostor/mesh/index.d.ts +5 -4
- package/dist/impostor/mesh/index.js +8 -9
- package/dist/impostor/mesh/index.js.map +1 -1
- package/dist/impostor/mesh/material.d.ts +18 -9
- package/dist/impostor/mesh/material.js +40 -27
- package/dist/impostor/mesh/material.js.map +1 -1
- package/dist/impostor/mesh/surface.d.ts +1 -1
- package/dist/impostor/mesh/surface.js +13 -9
- package/dist/impostor/mesh/surface.js.map +1 -1
- package/dist/impostor/mesh/textures.d.ts +3 -3
- package/dist/impostor/mesh/textures.js +24 -34
- package/dist/impostor/mesh/textures.js.map +1 -1
- package/dist/index.d.ts +15 -10
- package/dist/index.js +13 -8
- package/dist/index.js.map +1 -1
- package/dist/instanced/camera.d.ts +46 -0
- package/dist/instanced/camera.js +70 -0
- package/dist/instanced/camera.js.map +1 -0
- package/dist/instanced/chunk.d.ts +97 -0
- package/dist/instanced/chunk.js +156 -0
- package/dist/instanced/chunk.js.map +1 -0
- package/dist/instanced/chunks.d.ts +60 -0
- package/dist/instanced/chunks.js +208 -0
- package/dist/instanced/chunks.js.map +1 -0
- package/dist/instanced/cull.d.ts +28 -0
- package/dist/instanced/cull.js +22 -0
- package/dist/instanced/cull.js.map +1 -0
- package/dist/instanced/index.d.ts +96 -66
- package/dist/instanced/index.js +229 -288
- package/dist/instanced/index.js.map +1 -1
- package/dist/instanced/key.d.ts +19 -0
- package/dist/instanced/key.js +45 -0
- package/dist/instanced/key.js.map +1 -0
- package/dist/instanced/levels.d.ts +60 -0
- package/dist/instanced/levels.js +130 -0
- package/dist/instanced/levels.js.map +1 -0
- package/dist/instanced/lists.d.ts +70 -0
- package/dist/instanced/lists.js +133 -0
- package/dist/instanced/lists.js.map +1 -0
- package/dist/instanced/measure.d.ts +28 -0
- package/dist/instanced/measure.js +203 -0
- package/dist/instanced/measure.js.map +1 -0
- package/dist/instanced/meshes.d.ts +42 -51
- package/dist/instanced/meshes.js +158 -180
- package/dist/instanced/meshes.js.map +1 -1
- package/dist/instanced/mirror.d.ts +20 -0
- package/dist/instanced/mirror.js +37 -0
- package/dist/instanced/mirror.js.map +1 -0
- package/dist/instanced/pages/buffers.d.ts +37 -0
- package/dist/instanced/pages/buffers.js +15 -0
- package/dist/instanced/pages/buffers.js.map +1 -0
- package/dist/instanced/pages/chunk.d.ts +51 -0
- package/dist/instanced/pages/chunk.js +81 -0
- package/dist/instanced/pages/chunk.js.map +1 -0
- package/dist/instanced/pages/index.d.ts +74 -0
- package/dist/instanced/pages/index.js +269 -0
- package/dist/instanced/pages/index.js.map +1 -0
- package/dist/instanced/pages/passes.d.ts +21 -0
- package/dist/instanced/pages/passes.js +52 -0
- package/dist/instanced/pages/passes.js.map +1 -0
- package/dist/instanced/pages/slots.d.ts +11 -0
- package/dist/instanced/pages/slots.js +90 -0
- package/dist/instanced/pages/slots.js.map +1 -0
- package/dist/instanced/pages/workgroup.d.ts +14 -0
- package/dist/instanced/pages/workgroup.js +38 -0
- package/dist/instanced/pages/workgroup.js.map +1 -0
- package/dist/instanced/raycast.d.ts +13 -11
- package/dist/instanced/raycast.js +33 -40
- package/dist/instanced/raycast.js.map +1 -1
- package/dist/instanced/rows.d.ts +108 -0
- package/dist/instanced/rows.js +209 -0
- package/dist/instanced/rows.js.map +1 -0
- package/dist/instanced/shape.d.ts +25 -0
- package/dist/instanced/shape.js +51 -0
- package/dist/instanced/shape.js.map +1 -0
- package/dist/instanced/sort.d.ts +63 -0
- package/dist/instanced/sort.js +162 -0
- package/dist/instanced/sort.js.map +1 -0
- package/dist/instanced/update.d.ts +30 -0
- package/dist/instanced/update.js +207 -0
- package/dist/instanced/update.js.map +1 -0
- package/dist/levels/bounds.d.ts +21 -0
- package/dist/levels/bounds.js +42 -0
- package/dist/levels/bounds.js.map +1 -0
- package/dist/levels/cameras.d.ts +48 -0
- package/dist/levels/cameras.js +122 -0
- package/dist/levels/cameras.js.map +1 -0
- package/dist/levels/compile/contexts.d.ts +30 -0
- package/dist/levels/compile/contexts.js +18 -0
- package/dist/levels/compile/contexts.js.map +1 -0
- package/dist/levels/compile/index.d.ts +39 -0
- package/dist/levels/compile/index.js +185 -0
- package/dist/levels/compile/index.js.map +1 -0
- package/dist/levels/compile/pipelines.d.ts +26 -0
- package/dist/levels/compile/pipelines.js +177 -0
- package/dist/levels/compile/pipelines.js.map +1 -0
- package/dist/levels/compiles.d.ts +29 -0
- package/dist/levels/compiles.js +50 -0
- package/dist/levels/compiles.js.map +1 -0
- package/dist/levels/draw.d.ts +102 -0
- package/dist/levels/draw.js +401 -0
- package/dist/levels/draw.js.map +1 -0
- package/dist/levels/fade.d.ts +69 -0
- package/dist/levels/fade.js +150 -0
- package/dist/levels/fade.js.map +1 -0
- package/dist/levels/index.d.ts +99 -0
- package/dist/levels/index.js +155 -0
- package/dist/levels/index.js.map +1 -0
- package/dist/levels/item.d.ts +38 -0
- package/dist/levels/item.js +97 -0
- package/dist/levels/item.js.map +1 -0
- package/dist/levels/load.d.ts +31 -0
- package/dist/levels/load.js +142 -0
- package/dist/levels/load.js.map +1 -0
- package/dist/levels/manager.d.ts +159 -0
- package/dist/levels/manager.js +339 -0
- package/dist/levels/manager.js.map +1 -0
- package/dist/{material.js → levels/material.js} +4 -3
- package/dist/levels/material.js.map +1 -0
- package/dist/levels/renderer.d.ts +29 -0
- package/dist/levels/renderer.js +41 -0
- package/dist/levels/renderer.js.map +1 -0
- package/dist/levels/requests.d.ts +49 -0
- package/dist/levels/requests.js +95 -0
- package/dist/levels/requests.js.map +1 -0
- package/dist/levels/screen.d.ts +14 -0
- package/dist/levels/screen.js +21 -0
- package/dist/levels/screen.js.map +1 -0
- package/dist/levels/wait.d.ts +27 -0
- package/dist/levels/wait.js +61 -0
- package/dist/levels/wait.js.map +1 -0
- package/dist/loader/build.d.ts +10 -0
- package/dist/loader/build.js +28 -0
- package/dist/loader/build.js.map +1 -0
- package/dist/loader/cache.d.ts +6 -9
- package/dist/loader/cache.js +17 -24
- package/dist/loader/cache.js.map +1 -1
- package/dist/loader/context.d.ts +46 -0
- package/dist/loader/context.js +91 -0
- package/dist/loader/context.js.map +1 -0
- package/dist/loader/{provenance.d.ts → dependencies.d.ts} +5 -3
- package/dist/loader/{provenance.js → dependencies.js} +12 -4
- package/dist/loader/dependencies.js.map +1 -0
- package/dist/loader/index.d.ts +62 -0
- package/dist/loader/index.js +284 -0
- package/dist/loader/index.js.map +1 -0
- package/dist/loader/level.d.ts +41 -0
- package/dist/loader/level.js +140 -0
- package/dist/loader/level.js.map +1 -0
- package/dist/loader/request.d.ts +87 -0
- package/dist/loader/request.js +59 -0
- package/dist/loader/request.js.map +1 -0
- package/dist/loader/url.d.ts +5 -2
- package/dist/loader/url.js +10 -6
- package/dist/loader/url.js.map +1 -1
- package/dist/lod.d.ts +81 -40
- package/dist/lod.js +196 -149
- package/dist/lod.js.map +1 -1
- package/dist/meshopt.d.ts +6 -0
- package/dist/meshopt.js +19 -0
- package/dist/meshopt.js.map +1 -0
- package/dist/simplify/cards.d.ts +14 -0
- package/dist/simplify/cards.js +128 -0
- package/dist/simplify/cards.js.map +1 -0
- package/dist/{simplify.d.ts → simplify/index.d.ts} +7 -4
- package/dist/{simplify.js → simplify/index.js} +41 -23
- package/dist/simplify/index.js.map +1 -0
- package/dist/{bounds.d.ts → source/detail.d.ts} +4 -23
- package/dist/{bounds.js → source/detail.js} +19 -51
- package/dist/source/detail.js.map +1 -0
- package/dist/source/deviation.js +6 -6
- package/dist/source/deviation.js.map +1 -1
- package/dist/source/{shading.d.ts → evaluator.d.ts} +10 -10
- package/dist/source/{shading.js → evaluator.js} +5 -5
- package/dist/source/evaluator.js.map +1 -0
- package/dist/source/{trace.d.ts → raycaster.d.ts} +6 -6
- package/dist/source/{trace.js → raycaster.js} +8 -8
- package/dist/source/raycaster.js.map +1 -0
- package/dist/source/{texels.d.ts → sampler.d.ts} +1 -1
- package/dist/source/{texels.js → sampler.js} +3 -3
- package/dist/source/sampler.js.map +1 -0
- package/dist/source/source.d.ts +1 -1
- package/dist/source/source.js +1 -1
- package/dist/source/source.js.map +1 -1
- package/dist/source/surface.js +1 -1
- package/dist/source/surface.js.map +1 -1
- package/dist/task.d.ts +6 -0
- package/dist/{pause.js → task.js} +5 -5
- package/dist/task.js.map +1 -0
- package/dist/three.d.ts +13 -24
- package/dist/three.js +26 -53
- package/dist/three.js.map +1 -1
- package/dist/tsl.d.ts +8 -12
- package/dist/tsl.js +11 -39
- package/dist/tsl.js.map +1 -1
- package/dist/typegpu.d.ts +37 -0
- package/dist/typegpu.js +37 -0
- package/dist/typegpu.js.map +1 -0
- package/dist/wind/bounds.js +2 -2
- package/dist/wind/bounds.js.map +1 -1
- package/dist/wind/hooks.d.ts +7 -4
- package/dist/wind/hooks.js +5 -2
- package/dist/wind/hooks.js.map +1 -1
- package/dist/wind/index.d.ts +2 -2
- package/dist/wind/index.js +15 -15
- package/dist/wind/index.js.map +1 -1
- package/dist/wind/sway.d.ts +2 -0
- package/dist/wind/sway.js +4 -1
- package/dist/wind/sway.js.map +1 -1
- package/package.json +18 -8
- package/skills/lod/SKILL.md +108 -31
- package/dist/bounds.js.map +0 -1
- package/dist/compile.d.ts +0 -4
- package/dist/compile.js +0 -100
- package/dist/compile.js.map +0 -1
- package/dist/deferred.d.ts +0 -12
- package/dist/deferred.js +0 -27
- package/dist/deferred.js.map +0 -1
- package/dist/fade.d.ts +0 -36
- package/dist/fade.js +0 -112
- package/dist/fade.js.map +0 -1
- package/dist/instanced/args.d.ts +0 -20
- package/dist/instanced/args.js +0 -77
- package/dist/instanced/args.js.map +0 -1
- package/dist/instanced/blocks.d.ts +0 -66
- package/dist/instanced/blocks.js +0 -294
- package/dist/instanced/blocks.js.map +0 -1
- package/dist/instanced/dirty.d.ts +0 -15
- package/dist/instanced/dirty.js +0 -96
- package/dist/instanced/dirty.js.map +0 -1
- package/dist/instanced/parts.d.ts +0 -14
- package/dist/instanced/parts.js +0 -79
- package/dist/instanced/parts.js.map +0 -1
- package/dist/instanced/select.d.ts +0 -92
- package/dist/instanced/select.js +0 -315
- package/dist/instanced/select.js.map +0 -1
- package/dist/instanced/store.d.ts +0 -31
- package/dist/instanced/store.js +0 -96
- package/dist/instanced/store.js.map +0 -1
- package/dist/levels.d.ts +0 -95
- package/dist/levels.js +0 -171
- package/dist/levels.js.map +0 -1
- package/dist/loader/bundle.d.ts +0 -25
- package/dist/loader/bundle.js +0 -241
- package/dist/loader/bundle.js.map +0 -1
- package/dist/loader/provenance.js.map +0 -1
- package/dist/loader.d.ts +0 -55
- package/dist/loader.js +0 -239
- package/dist/loader.js.map +0 -1
- package/dist/material.js.map +0 -1
- package/dist/mesh/codec.d.ts +0 -4
- package/dist/mesh/codec.js.map +0 -1
- package/dist/pause.d.ts +0 -6
- package/dist/pause.js.map +0 -1
- package/dist/queue.d.ts +0 -2
- package/dist/queue.js +0 -33
- package/dist/queue.js.map +0 -1
- package/dist/renderer.d.ts +0 -21
- package/dist/renderer.js +0 -83
- package/dist/renderer.js.map +0 -1
- package/dist/residency.d.ts +0 -44
- package/dist/residency.js +0 -205
- package/dist/residency.js.map +0 -1
- package/dist/simplify.js.map +0 -1
- package/dist/source/shading.js.map +0 -1
- package/dist/source/texels.js.map +0 -1
- package/dist/source/trace.js.map +0 -1
- package/dist/view.d.ts +0 -45
- package/dist/view.js +0 -131
- package/dist/view.js.map +0 -1
- /package/dist/{material.d.ts → levels/material.d.ts} +0 -0
package/dist/instanced/meshes.js
CHANGED
|
@@ -1,191 +1,169 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { drawOf, setDraw } from "../fade.js";
|
|
1
|
+
import { BufferGeometry, Matrix4, Mesh } from "three/webgpu";
|
|
2
|
+
import { setFadeSource } from "../levels/fade.js";
|
|
3
|
+
import { levelMaterial } from "../levels/material.js";
|
|
5
4
|
import { impostorInstances } from "../impostor/mesh/index.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
import { isImpostorMesh, isInstancedMesh, isLOD, isMesh, rejectSkinned } from "../three.js";
|
|
6
|
+
import { DRAW_BYTES } from "./rows.js";
|
|
7
|
+
// The meshes that draw an InstancedLod's level: one plain three Mesh per mesh and material group of its object, or an
|
|
8
|
+
// ImpostorMesh for an impostor, each drawing every instance in its level's list for a camera with one indirect draw.
|
|
9
|
+
const IDENTITY = new Matrix4();
|
|
10
|
+
/** `object`'s meshes and material groups, placed once in the instance's space, for level `level`. */
|
|
11
|
+
export function partsOf(object, level) {
|
|
12
|
+
rejectSkinned(object, "InstancedLod");
|
|
13
|
+
object.updateWorldMatrix(true, true);
|
|
14
|
+
const outside = object.parent ? object.parent.matrixWorld.clone().invert() : new Matrix4();
|
|
15
|
+
const found = [];
|
|
16
|
+
object.traverse((node) => {
|
|
17
|
+
if (isLOD(node))
|
|
18
|
+
throw new Error("InstancedLod: levels cannot contain a Lod or InstancedLod; nest them with Lod");
|
|
19
|
+
if (isInstancedMesh(node) && !isImpostorMesh(node))
|
|
20
|
+
throw new Error(`InstancedLod: levels cannot contain an InstancedMesh ("${node.name}")`);
|
|
21
|
+
if (!isMesh(node))
|
|
22
|
+
return;
|
|
23
|
+
const placement = outside.clone().multiply(node.matrixWorld);
|
|
24
|
+
ranges(node).forEach((range, group) => found.push({ template: node, placement, group, draw: { level, ...range } }));
|
|
25
|
+
});
|
|
26
|
+
return found;
|
|
27
|
+
}
|
|
28
|
+
/** The index (or vertex) ranges `mesh` draws, clipped to its draw range, in group order, empty draws included. */
|
|
29
|
+
function ranges(mesh) {
|
|
30
|
+
const { geometry } = mesh;
|
|
31
|
+
const indexed = geometry.index !== null;
|
|
32
|
+
const total = geometry.index?.count ?? geometry.getAttribute("position").count;
|
|
33
|
+
const groups = Array.isArray(mesh.material) ? geometry.groups : [{ start: 0, count: total }];
|
|
34
|
+
return groups.map(({ start, count }) => {
|
|
35
|
+
const first = Math.min(total, Math.max(0, start, geometry.drawRange.start));
|
|
36
|
+
const end = Math.min(total, start + count, geometry.drawRange.start + geometry.drawRange.count);
|
|
37
|
+
return { count: Math.max(0, end - first), start: first, indexed };
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/** The meshes drawing `parts`, tinted by `tint`. */
|
|
41
|
+
export function levelMeshes(parts, tint, inputs) {
|
|
42
|
+
let first = null;
|
|
43
|
+
const offset = (i) => (first === null ? null : (first + i) * DRAW_BYTES);
|
|
44
|
+
return {
|
|
45
|
+
meshes: parts.map((part, i) => levelMesh(part, () => offset(i), tint, inputs)),
|
|
46
|
+
draws: parts.map((part) => part.draw),
|
|
47
|
+
drawFrom: (start) => void (first = start),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Release `mesh`, which may never have been added. */
|
|
51
|
+
export function freeMesh(mesh) {
|
|
52
|
+
// ImpostorMesh.dispose also destroys its instance buffers, which are the InstancedLod's.
|
|
53
|
+
if (isImpostorMesh(mesh))
|
|
54
|
+
mesh.material.release();
|
|
55
|
+
mesh.geometry.dispose();
|
|
56
|
+
}
|
|
57
|
+
/** Point every mesh of `meshes` at `instances.matrices`, which changed: survivors scale, or no longer do. */
|
|
58
|
+
export function drawMatrices(meshes, instances) {
|
|
59
|
+
for (const mesh of meshes)
|
|
60
|
+
if (isImpostorMesh(mesh))
|
|
61
|
+
mesh.instanceMatrix = instances.matrices;
|
|
62
|
+
}
|
|
11
63
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* pass, a submit). Each renderer runs those its own buffers are not current with.
|
|
64
|
+
* Material group `group` of `template` drawn for every instance in level `level`'s list, from byte `offset()` of a
|
|
65
|
+
* camera's draws, once there is one.
|
|
15
66
|
*/
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
67
|
+
function levelMesh({ template, placement, group }, offset, tint, inputs) {
|
|
68
|
+
const { instances, bounds, box, slots, radius, drawFor } = inputs;
|
|
69
|
+
// An impostor card is placed in the shader; any other mesh draws its geometry moved into the instance's space, so
|
|
70
|
+
// the instance matrix is all it needs.
|
|
71
|
+
const mesh = isImpostorMesh(template) ? card(template, placement, inputs) : plain(template, placement, group, instances);
|
|
72
|
+
setFadeSource(mesh, {
|
|
73
|
+
kind: "instances",
|
|
74
|
+
slots,
|
|
75
|
+
radius,
|
|
76
|
+
tint,
|
|
77
|
+
level: isImpostorMesh(template) ? undefined : { instances, space: placement.clone().invert() },
|
|
78
|
+
});
|
|
79
|
+
mesh.name = template.name;
|
|
80
|
+
mesh.castShadow = template.castShadow;
|
|
81
|
+
mesh.receiveShadow = template.receiveShadow;
|
|
82
|
+
if (!isImpostorMesh(mesh))
|
|
83
|
+
mesh.geometry.boundingSphere = bounds;
|
|
84
|
+
mesh.geometry.boundingBox = box;
|
|
85
|
+
const previous = mesh.onBeforeRender;
|
|
86
|
+
// Each camera draws the instances in its own lists. A level compiling to join draws nothing yet: its pipelines do not
|
|
87
|
+
// depend on the indirect draw.
|
|
88
|
+
mesh.onBeforeRender = (renderer, scene, camera, geometry, material, drawn) => {
|
|
89
|
+
previous.call(mesh, renderer, scene, camera, geometry, material, drawn);
|
|
90
|
+
const start = offset();
|
|
91
|
+
if (start === null)
|
|
92
|
+
return;
|
|
93
|
+
const args = drawFor(renderer, camera);
|
|
94
|
+
mesh.geometry.setIndirect(args.attribute, args.offset + start);
|
|
95
|
+
};
|
|
96
|
+
return mesh;
|
|
32
97
|
}
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
constructor(selection, reaches, radius, owner) {
|
|
48
|
-
this.selection = selection;
|
|
49
|
-
this.reaches = reaches;
|
|
50
|
-
this.radius = radius;
|
|
51
|
-
this.owner = owner;
|
|
52
|
-
}
|
|
53
|
-
setRadius(radius) {
|
|
54
|
-
this.radius = radius;
|
|
55
|
-
for (const mesh of this.byLevel.flat()) {
|
|
56
|
-
const draw = drawOf(mesh);
|
|
57
|
-
if (draw?.kind === "instances")
|
|
58
|
-
draw.radius = radius;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
/** `level`'s `parts`, drawn from consecutive indirect arguments starting at byte `offset`. */
|
|
62
|
-
make(level, parts, offset) {
|
|
63
|
-
return parts.map((part, i) => this.mesh(level, part, offset + i * ARGS_BYTES));
|
|
64
|
-
}
|
|
65
|
-
/** Re-point every mesh at the indirect argument table, which moves as deferred levels append to it. */
|
|
66
|
-
relocate() {
|
|
67
|
-
const { args, argsOffset } = this.selection;
|
|
68
|
-
for (const [mesh, offset] of this.offsets)
|
|
69
|
-
mesh.geometry.setIndirect(args, argsOffset + offset);
|
|
70
|
-
}
|
|
71
|
-
/** Release `mesh`, which may never have been added. */
|
|
72
|
-
free(mesh) {
|
|
73
|
-
this.offsets.delete(mesh);
|
|
74
|
-
// ImpostorMesh.dispose also destroys instance buffers; the Selection owns ours.
|
|
75
|
-
if (isImpostorMesh(mesh))
|
|
76
|
-
mesh.material.release();
|
|
77
|
-
mesh.geometry.dispose();
|
|
78
|
-
}
|
|
79
|
-
/** Every level's meshes draw the instance colours the selection has begun to carry. */
|
|
80
|
-
recolor() {
|
|
81
|
-
for (const mesh of this.byLevel.flat()) {
|
|
82
|
-
mesh.instanceColor = this.selection.slots.colors;
|
|
83
|
-
// Instance colours change the shader.
|
|
84
|
-
if (!isImpostorMesh(mesh))
|
|
85
|
-
for (const material of [mesh.material].flat())
|
|
86
|
-
material.needsUpdate = true;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
/** Show only levels whose conservative bounds contain a possible selected instance; whether any may draw for `camera`. */
|
|
90
|
-
show(camera, matrixWorld) {
|
|
91
|
-
let shown = false;
|
|
92
|
-
for (let level = 0; level < this.byLevel.length; level++) {
|
|
93
|
-
const reach = at(this.reaches, level);
|
|
94
|
-
const visible = !reach.isEmpty();
|
|
95
|
-
const meshes = at(this.byLevel, level);
|
|
96
|
-
for (const mesh of meshes)
|
|
97
|
-
mesh.visible = visible;
|
|
98
|
-
shown ||= visible && meshes.length > 0 && inView(camera, matrixWorld, reach);
|
|
99
|
-
}
|
|
100
|
-
return shown;
|
|
101
|
-
}
|
|
102
|
-
/** Whether the selection runs before the next draw of any InstancedLod. */
|
|
103
|
-
schedule(selected) {
|
|
104
|
-
if (selected)
|
|
105
|
-
due.add(this.selection);
|
|
106
|
-
else
|
|
107
|
-
due.delete(this.selection);
|
|
108
|
-
}
|
|
109
|
-
dispose() {
|
|
110
|
-
// An ImpostorMesh frees its own material and geometry; the other meshes' faded
|
|
111
|
-
// materials go with the levels' originals.
|
|
112
|
-
for (const mesh of this.byLevel.flat()) {
|
|
113
|
-
mesh.removeFromParent();
|
|
114
|
-
this.free(mesh);
|
|
115
|
-
}
|
|
116
|
-
due.delete(this.selection);
|
|
117
|
-
this.byLevel.length = 0;
|
|
118
|
-
this.offsets.clear();
|
|
119
|
-
}
|
|
120
|
-
/** Material group `part.group` of `part.template` drawn for every instance in `level`'s slots. */
|
|
121
|
-
mesh(level, { template, placement, group }, offset) {
|
|
122
|
-
const { selection, owner } = this;
|
|
123
|
-
// An impostor card is placed in the shader; any other mesh draws its geometry moved
|
|
124
|
-
// into the instance's space, so the instance matrix is all it needs.
|
|
125
|
-
const mesh = isImpostorMesh(template)
|
|
126
|
-
? card(template, placement, selection)
|
|
127
|
-
: new Instances(placed(template.geometry, placement), groupMaterial(template, group), selection);
|
|
128
|
-
mesh.geometry = indirect(mesh.geometry, selection, offset);
|
|
129
|
-
this.offsets.set(mesh, offset);
|
|
130
|
-
setDraw(mesh, { kind: "instances", fades: selection.slots.fades, radius: this.radius, tint: level.tint });
|
|
131
|
-
if (!isImpostorMesh(template))
|
|
132
|
-
placeInterior(mesh, placement);
|
|
133
|
-
mesh.name = template.name;
|
|
134
|
-
mesh.castShadow = template.castShadow;
|
|
135
|
-
mesh.receiveShadow = template.receiveShadow;
|
|
136
|
-
mesh.boundingSphere = at(this.reaches, level.index);
|
|
137
|
-
watchViewport(mesh);
|
|
138
|
-
const previous = mesh.onBeforeRender;
|
|
139
|
-
// Selected once per view, before the first level mesh draws: in the view, or in a
|
|
140
|
-
// shadow pass that comes first. The GPU runs it before anything drawn after it.
|
|
141
|
-
mesh.onBeforeRender = (renderer, scene, camera, geometry, material, group) => {
|
|
142
|
-
if (!owner.live())
|
|
143
|
-
return;
|
|
144
|
-
previous.call(mesh, renderer, scene, camera, geometry, material, group);
|
|
145
|
-
const gpu = gpuRenderer(renderer);
|
|
146
|
-
// A caster outside the viewing frustum still needs its selection in a shadow draw.
|
|
147
|
-
due.add(selection);
|
|
148
|
-
// Each level's draws start at its slots (see select.ts).
|
|
149
|
-
if (!gpu.hasFeature("indirect-first-instance"))
|
|
150
|
-
throw new Error("InstancedLod: needs the GPU feature indirect-first-instance, which this device lacks");
|
|
151
|
-
passes.length = 0;
|
|
152
|
-
for (const each of due)
|
|
153
|
-
passes.push(...each.take(gpu));
|
|
154
|
-
due.clear();
|
|
155
|
-
if (passes.length > 0)
|
|
156
|
-
gpu.compute(passes);
|
|
157
|
-
};
|
|
158
|
-
const after = mesh.onAfterRender;
|
|
159
|
-
mesh.onAfterRender = (renderer, scene, camera, geometry, material, group) => {
|
|
160
|
-
after.call(mesh, renderer, scene, camera, geometry, material, group);
|
|
161
|
-
if (!inShadowPass(scene))
|
|
162
|
-
owner.drawn(camera, mesh);
|
|
163
|
-
};
|
|
164
|
-
return mesh;
|
|
165
|
-
}
|
|
98
|
+
/**
|
|
99
|
+
* A plain mesh drawing `template`'s geometry moved by `placement`, with a geometry of its own, which its draws point
|
|
100
|
+
* at their camera's indirect draws, over the moved one's buffers.
|
|
101
|
+
*/
|
|
102
|
+
function plain(template, placement, group, instances) {
|
|
103
|
+
const moved = placed(template.geometry, placement);
|
|
104
|
+
const geometry = new BufferGeometry();
|
|
105
|
+
geometry.index = moved.index;
|
|
106
|
+
for (const [name, attribute] of Object.entries(moved.attributes))
|
|
107
|
+
geometry.setAttribute(name, attribute);
|
|
108
|
+
geometry.morphAttributes = moved.morphAttributes;
|
|
109
|
+
// three's NodeMaterial multiplies a draw's colour by the varying vInstanceColor wherever its object has an
|
|
110
|
+
// instanceColor; placeInstances (see fade.ts) writes it.
|
|
111
|
+
return Object.assign(new Mesh(geometry, groupMaterial(template, group)), { instanceColor: instances.colors });
|
|
166
112
|
}
|
|
167
|
-
/** An impostor's cards for
|
|
168
|
-
function card(template, placement,
|
|
113
|
+
/** An impostor's cards for the instances in a level's list. */
|
|
114
|
+
function card(template, placement, { instances, bounds }) {
|
|
169
115
|
const mesh = impostorInstances(template, 0, placement);
|
|
170
|
-
// Indirect
|
|
171
|
-
// used by Three to specialize its shader for one object's storage bindings.
|
|
116
|
+
// Indirect draws give the count. Three otherwise keys a card's shader by its count, one per object.
|
|
172
117
|
mesh.count = 1;
|
|
173
|
-
mesh.instanceMatrix =
|
|
174
|
-
mesh.instanceColor =
|
|
118
|
+
mesh.instanceMatrix = instances.matrices;
|
|
119
|
+
mesh.instanceColor = instances.colors;
|
|
120
|
+
mesh.boundingSphere = bounds;
|
|
175
121
|
return mesh;
|
|
176
122
|
}
|
|
177
|
-
/**
|
|
178
|
-
function
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
123
|
+
/** The level material of `mesh`'s material group `group`. */
|
|
124
|
+
function groupMaterial(mesh, group) {
|
|
125
|
+
if (!Array.isArray(mesh.material))
|
|
126
|
+
return levelMaterial(mesh.material);
|
|
127
|
+
const index = mesh.geometry.groups[group]?.materialIndex ?? 0;
|
|
128
|
+
const material = mesh.material[index];
|
|
129
|
+
if (!material)
|
|
130
|
+
throw new Error(`InstancedLod: "${mesh.name}" has no material ${index}`);
|
|
131
|
+
return levelMaterial(material);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Placed copies of geometries, shared by every InstancedLod drawing the same mesh the same way: a side table, as three's
|
|
135
|
+
* BufferGeometry has no room for a package's state.
|
|
136
|
+
*/
|
|
137
|
+
const copies = new WeakMap();
|
|
138
|
+
/** `geometry` moved by `placement`: itself for the identity, else a copy made once. */
|
|
139
|
+
function placed(geometry, placement) {
|
|
140
|
+
if (placement.equals(IDENTITY))
|
|
141
|
+
return geometry;
|
|
142
|
+
const known = copies.get(geometry) ?? [];
|
|
143
|
+
copies.set(geometry, known);
|
|
144
|
+
const hit = known.find((entry) => entry.placement.equals(placement));
|
|
145
|
+
if (hit)
|
|
146
|
+
return hit.geometry;
|
|
147
|
+
const copy = geometry.clone();
|
|
148
|
+
const box = copy.boundingBox;
|
|
149
|
+
const sphere = copy.boundingSphere;
|
|
150
|
+
// applyMatrix4 otherwise recomputes both bounds by walking the transformed vertices.
|
|
151
|
+
copy.boundingBox = null;
|
|
152
|
+
copy.boundingSphere = null;
|
|
153
|
+
// Translations leave normals and tangents unchanged; scanning them stalls large source arrivals.
|
|
154
|
+
if (placement.clone().setPosition(0, 0, 0).equals(IDENTITY)) {
|
|
155
|
+
const position = copy.getAttribute("position");
|
|
156
|
+
if (position) {
|
|
157
|
+
position.applyMatrix4(placement);
|
|
158
|
+
position.needsUpdate = true;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else
|
|
162
|
+
copy.applyMatrix4(placement);
|
|
163
|
+
copy.boundingBox = box?.applyMatrix4(placement) ?? null;
|
|
164
|
+
copy.boundingSphere = sphere?.applyMatrix4(placement) ?? null;
|
|
165
|
+
geometry.addEventListener("dispose", () => copy.dispose());
|
|
166
|
+
known.push({ placement: placement.clone(), geometry: copy });
|
|
167
|
+
return copy;
|
|
190
168
|
}
|
|
191
169
|
//# sourceMappingURL=meshes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"meshes.js","sourceRoot":"","sources":["../../src/instanced/meshes.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"meshes.js","sourceRoot":"","sources":["../../src/instanced/meshes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { StorageBufferAttribute, type InstancedBufferAttribute } from "three/webgpu";
|
|
2
|
+
/**
|
|
3
|
+
* A storage attribute over a CPU chunk attribute's array, which the page pool reads it through, uploading what the app
|
|
4
|
+
* marks changed in it: binding the app's own attribute through storage() would flag it as a storage attribute, which
|
|
5
|
+
* three then pads (an RGB colour to four floats) and treats as one wherever else the app draws it.
|
|
6
|
+
*/
|
|
7
|
+
export declare class Mirror {
|
|
8
|
+
readonly source: InstancedBufferAttribute;
|
|
9
|
+
/** A matrix per item, or floats one by one, which three never pads. */
|
|
10
|
+
readonly attribute: StorageBufferAttribute;
|
|
11
|
+
/** The source's version it last took in. */
|
|
12
|
+
private version;
|
|
13
|
+
constructor(source: InstancedBufferAttribute);
|
|
14
|
+
/**
|
|
15
|
+
* Take in the source's edits, whose array it shares: upload the ranges the app marked changed (all of it without any),
|
|
16
|
+
* which three would upload and clear were it drawing the source itself. Whether the source changed.
|
|
17
|
+
*/
|
|
18
|
+
refresh(): boolean;
|
|
19
|
+
dispose(): void;
|
|
20
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { StorageBufferAttribute } from "three/webgpu";
|
|
2
|
+
/**
|
|
3
|
+
* A storage attribute over a CPU chunk attribute's array, which the page pool reads it through, uploading what the app
|
|
4
|
+
* marks changed in it: binding the app's own attribute through storage() would flag it as a storage attribute, which
|
|
5
|
+
* three then pads (an RGB colour to four floats) and treats as one wherever else the app draws it.
|
|
6
|
+
*/
|
|
7
|
+
export class Mirror {
|
|
8
|
+
source;
|
|
9
|
+
/** A matrix per item, or floats one by one, which three never pads. */
|
|
10
|
+
attribute;
|
|
11
|
+
/** The source's version it last took in. */
|
|
12
|
+
version;
|
|
13
|
+
constructor(source) {
|
|
14
|
+
this.source = source;
|
|
15
|
+
this.attribute = new StorageBufferAttribute(source.array, source.itemSize === 16 ? 16 : 1);
|
|
16
|
+
this.version = source.version;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Take in the source's edits, whose array it shares: upload the ranges the app marked changed (all of it without any),
|
|
20
|
+
* which three would upload and clear were it drawing the source itself. Whether the source changed.
|
|
21
|
+
*/
|
|
22
|
+
refresh() {
|
|
23
|
+
const { source, attribute } = this;
|
|
24
|
+
if (source.version === this.version)
|
|
25
|
+
return false;
|
|
26
|
+
this.version = source.version;
|
|
27
|
+
for (const { start, count } of source.updateRanges)
|
|
28
|
+
attribute.addUpdateRange(start, count);
|
|
29
|
+
source.clearUpdateRanges();
|
|
30
|
+
attribute.needsUpdate = true;
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
dispose() {
|
|
34
|
+
this.attribute.dispose();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=mirror.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mirror.js","sourceRoot":"","sources":["../../src/instanced/mirror.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAiC,MAAM,cAAc,CAAC;AAErF;;;;GAIG;AACH,MAAM,OAAO,MAAM;IAMI;IALrB,uEAAuE;IAC9D,SAAS,CAAyB;IAC3C,4CAA4C;IACpC,OAAO,CAAS;IAExB,YAAqB,MAAgC;QAAhC,WAAM,GAAN,MAAM,CAA0B;QACnD,IAAI,CAAC,SAAS,GAAG,IAAI,sBAAsB,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3F,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAChC,CAAC;IAED;;;OAGG;IACH,OAAO;QACL,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QACnC,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAClD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC9B,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC,YAAY;YAAE,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC3F,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC3B,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { StorageBufferAttribute, StorageInstancedBufferAttribute } from "three/webgpu";
|
|
2
|
+
/** Bits of an occupied page's entry that hold its page; those above hold its InstancedLod's row. */
|
|
3
|
+
export declare const PAGE_BITS = 16;
|
|
4
|
+
/** A page pool's sizes and buffers, which its passes read. */
|
|
5
|
+
export interface PoolBuffers {
|
|
6
|
+
readonly pages: number;
|
|
7
|
+
readonly slots: number;
|
|
8
|
+
/** The free page count, then the free page ids. */
|
|
9
|
+
readonly stack: StorageBufferAttribute;
|
|
10
|
+
/** Per window of a chunk's range, from its slot's first window (see `sources`): the page it holds. */
|
|
11
|
+
readonly table: StorageBufferAttribute;
|
|
12
|
+
/** Per window of a chunk's range: the window's instances, then where they start among the chunk's. */
|
|
13
|
+
readonly windows: StorageBufferAttribute;
|
|
14
|
+
/**
|
|
15
|
+
* Per slot, written by the CPU: its chunk's first window, its windows, its generation, and its InstancedLod's row
|
|
16
|
+
* plus one (0 while it holds no chunk).
|
|
17
|
+
*/
|
|
18
|
+
readonly sources: StorageBufferAttribute;
|
|
19
|
+
/**
|
|
20
|
+
* Per slot, written by the GPU, two vec4s: the generation it got to, its pages, its instances and the pages it needs;
|
|
21
|
+
* then the first window its pages are listed from.
|
|
22
|
+
*/
|
|
23
|
+
readonly states: StorageBufferAttribute;
|
|
24
|
+
/** How many pages chunks hold, then per page held its id and its InstancedLod's row (see `PAGE_BITS`). */
|
|
25
|
+
readonly occupied: StorageBufferAttribute;
|
|
26
|
+
/** Every pool index's instance matrix and colour (RGB and a pad), as the level meshes draw them. */
|
|
27
|
+
readonly matrices: StorageInstancedBufferAttribute;
|
|
28
|
+
readonly colors: StorageInstancedBufferAttribute;
|
|
29
|
+
}
|
|
30
|
+
/** `pool`'s buffers as one pass uses them: a node each, since a pass may not bind a buffer it writes twice. */
|
|
31
|
+
export declare function nodes(pool: PoolBuffers): {
|
|
32
|
+
stack: import("three/webgpu").StorageBufferNode<"uint">;
|
|
33
|
+
table: import("three/webgpu").StorageBufferNode<"uint">;
|
|
34
|
+
windows: import("three/webgpu").StorageBufferNode<"uint">;
|
|
35
|
+
sources: import("three/webgpu").StorageBufferNode<"uvec4">;
|
|
36
|
+
states: import("three/webgpu").StorageBufferNode<"uvec4">;
|
|
37
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { storage } from "three/tsl";
|
|
2
|
+
// The buffers of a page pool, which its passes read and write (see passes.ts).
|
|
3
|
+
/** Bits of an occupied page's entry that hold its page; those above hold its InstancedLod's row. */
|
|
4
|
+
export const PAGE_BITS = 16;
|
|
5
|
+
/** `pool`'s buffers as one pass uses them: a node each, since a pass may not bind a buffer it writes twice. */
|
|
6
|
+
export function nodes(pool) {
|
|
7
|
+
return {
|
|
8
|
+
stack: storage(pool.stack, "uint", 0).toAtomic(),
|
|
9
|
+
table: storage(pool.table, "uint", 0),
|
|
10
|
+
windows: storage(pool.windows, "uint", 0),
|
|
11
|
+
sources: storage(pool.sources, "uvec4", 0).toReadOnly(),
|
|
12
|
+
states: storage(pool.states, "uvec4", 0),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=buffers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffers.js","sourceRoot":"","sources":["../../../src/instanced/pages/buffers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,+EAA+E;AAE/E,oGAAoG;AACpG,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AA6B5B,+GAA+G;AAC/G,MAAM,UAAU,KAAK,CAAC,IAAiB;IACrC,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;QAChD,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACrC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACzC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE;QACvD,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;KACzC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type ComputeNode, type StorageBufferAttribute, type StorageInstancedBufferAttribute } from "three/webgpu";
|
|
2
|
+
import { type PoolBuffers } from "./buffers.js";
|
|
3
|
+
/**
|
|
4
|
+
* The attributes chunks are read from: matrices, colours or none (white) with the floats between instances' colours,
|
|
5
|
+
* and an instance count's buffer or none.
|
|
6
|
+
*/
|
|
7
|
+
export interface Attributes {
|
|
8
|
+
readonly matrices: Storage;
|
|
9
|
+
readonly colors: {
|
|
10
|
+
readonly attribute: Storage;
|
|
11
|
+
readonly stride: 3 | 4;
|
|
12
|
+
} | null;
|
|
13
|
+
readonly counts: Storage | null;
|
|
14
|
+
}
|
|
15
|
+
/** A storage attribute, of either kind. */
|
|
16
|
+
type Storage = StorageBufferAttribute | StorageInstancedBufferAttribute;
|
|
17
|
+
/** A chunk the count and write passes read: its slot, its first window, its range of its attributes, and where its instance count lies. */
|
|
18
|
+
export interface ChunkRange {
|
|
19
|
+
readonly slot: number;
|
|
20
|
+
readonly base: number;
|
|
21
|
+
readonly start: number;
|
|
22
|
+
readonly count: number;
|
|
23
|
+
readonly countIndex: number;
|
|
24
|
+
}
|
|
25
|
+
/** The chunk the count and write passes read next, set before each runs. */
|
|
26
|
+
export declare function chunkUniforms(): {
|
|
27
|
+
slot: import("three/webgpu").UniformNode<"uint", number>;
|
|
28
|
+
base: import("three/webgpu").UniformNode<"uint", number>;
|
|
29
|
+
start: import("three/webgpu").UniformNode<"uint", number>;
|
|
30
|
+
count: import("three/webgpu").UniformNode<"uint", number>;
|
|
31
|
+
countIndex: import("three/webgpu").UniformNode<"uint", number>;
|
|
32
|
+
};
|
|
33
|
+
export type ChunkUniforms = ReturnType<typeof chunkUniforms>;
|
|
34
|
+
/** Nodes reading a chunk's attributes, for their layout; pointed at each chunk's own before its passes run. */
|
|
35
|
+
export declare function chunkReads({ matrices, colors, counts }: Attributes): {
|
|
36
|
+
matrices: import("three/webgpu").StorageBufferNode<"mat4">;
|
|
37
|
+
colors: {
|
|
38
|
+
floats: import("three/webgpu").StorageBufferNode<"float">;
|
|
39
|
+
stride: 4 | 3;
|
|
40
|
+
} | null;
|
|
41
|
+
counts: import("three/webgpu").StorageBufferNode<"uint"> | null;
|
|
42
|
+
};
|
|
43
|
+
export type ChunkReads = ReturnType<typeof chunkReads>;
|
|
44
|
+
/** Counts each window's instances of `chunk`, read by `reads`: one workgroup per window. */
|
|
45
|
+
export declare function countPass(pool: PoolBuffers, chunk: ChunkUniforms, reads: ChunkReads): ComputeNode;
|
|
46
|
+
/**
|
|
47
|
+
* Writes each window's instances of `chunk`, read by `reads`, into its pages, in order, and clears the room past its
|
|
48
|
+
* last instance on its last page, which then draw nothing: one workgroup per window.
|
|
49
|
+
*/
|
|
50
|
+
export declare function writePass(pool: PoolBuffers, chunk: ChunkUniforms, reads: ChunkReads): ComputeNode;
|
|
51
|
+
export {};
|