@woosh/meep-engine 3.14.3 → 3.14.4
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/package.json +1 -1
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +733 -726
- package/src/engine/network/NetworkSession.d.ts +24 -4
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +28 -4
- package/src/engine/network/orchestrator/NetworkPeer.d.ts +47 -6
- package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/NetworkPeer.js +184 -56
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +97 -11
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +304 -22
- package/src/engine/network/replication/Replicator.d.ts +14 -1
- package/src/engine/network/replication/Replicator.d.ts.map +1 -1
- package/src/engine/network/replication/Replicator.js +44 -3
- package/src/engine/network/sim/ActionLog.d.ts +21 -3
- package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
- package/src/engine/network/sim/ActionLog.js +24 -3
- package/src/engine/network/sim/SimAction.d.ts +15 -0
- package/src/engine/network/sim/SimAction.d.ts.map +1 -1
- package/src/engine/network/sim/SimAction.js +15 -0
- package/src/engine/network/sim/SimActionExecutor.d.ts +51 -1
- package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
- package/src/engine/network/sim/SimActionExecutor.js +73 -5
- package/src/engine/network/transport/Channel.d.ts +1 -1
- package/src/engine/network/transport/Channel.js +1 -1
- package/src/engine/simulation/Ticker.d.ts.map +1 -1
- package/src/engine/simulation/Ticker.js +4 -1
- package/src/engine/ui/GUIEngine.d.ts.map +1 -1
- package/src/engine/ui/GUIEngine.js +6 -0
- package/src/shade/playground/particle_system/README.md +98 -0
- package/src/shade/playground/particle_system/index.html +124 -0
- package/src/shade/playground/particle_system/main.d.ts +2 -0
- package/src/shade/playground/particle_system/main.d.ts.map +1 -0
- package/src/shade/playground/particle_system/main.js +180 -0
- package/src/shade/playground/particle_system/particle_scene.d.ts +52 -0
- package/src/shade/playground/particle_system/particle_scene.d.ts.map +1 -0
- package/src/shade/playground/particle_system/particle_scene.js +552 -0
- package/src/shade/playground/skinned_mesh_soup/README.md +122 -0
- package/src/shade/playground/skinned_mesh_soup/index.html +199 -0
- package/src/shade/playground/skinned_mesh_soup/main.d.ts +7 -0
- package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -0
- package/src/shade/playground/skinned_mesh_soup/main.js +564 -0
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts +23 -0
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts.map +1 -0
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.js +409 -0
- package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +1 -1
- package/src/shade/renderer/particles/cull/chunk_particle_cull.js +3 -1
- package/src/shade/renderer/particles/data/chunk_particle_emitter.js +1 -1
- package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts +1 -1
- package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts +89 -0
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -0
- package/src/shade/renderer/particles/isa/InstructionStream.js +162 -0
- package/src/shade/renderer/particles/isa/ParticleAssembler.d.ts +1 -48
- package/src/shade/renderer/particles/isa/ParticleAssembler.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/ParticleAssembler.js +25 -114
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.js +4 -2
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +4 -4
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +7 -5
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +3 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +3 -1
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +5 -2
- package/src/shade/renderer/particles/shaders/shader_particle_render.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_render.js +9 -2
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +3 -1
- package/src/shade/renderer/particles/prototypeParticleSystem.d.ts +0 -2
- package/src/shade/renderer/particles/prototypeParticleSystem.d.ts.map +0 -1
- package/src/shade/renderer/particles/prototypeParticleSystem.js +0 -448
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>meep — GPU particle system</title>
|
|
6
|
+
<style>
|
|
7
|
+
:root {
|
|
8
|
+
color-scheme: dark;
|
|
9
|
+
--bg: #05070a;
|
|
10
|
+
--panel: #1c1f25e0;
|
|
11
|
+
--line: #2b3038;
|
|
12
|
+
--text: #d6dae0;
|
|
13
|
+
--muted: #8b939f;
|
|
14
|
+
--fail: #ff6b6b;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
* { box-sizing: border-box; }
|
|
18
|
+
|
|
19
|
+
html, body { height: 100%; }
|
|
20
|
+
|
|
21
|
+
body {
|
|
22
|
+
margin: 0;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
background: var(--bg);
|
|
25
|
+
color: var(--text);
|
|
26
|
+
font: 14px/1.5 system-ui, -apple-system, Segoe UI, sans-serif;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#view {
|
|
30
|
+
display: block;
|
|
31
|
+
width: 100%;
|
|
32
|
+
height: 100%;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#hud {
|
|
36
|
+
position: fixed;
|
|
37
|
+
top: 12px;
|
|
38
|
+
left: 12px;
|
|
39
|
+
min-width: 210px;
|
|
40
|
+
padding: 10px 12px;
|
|
41
|
+
border: 1px solid var(--line);
|
|
42
|
+
border-radius: 8px;
|
|
43
|
+
background: var(--panel);
|
|
44
|
+
backdrop-filter: blur(6px);
|
|
45
|
+
font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
|
|
46
|
+
font-size: 12px;
|
|
47
|
+
pointer-events: none;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#hud h1 {
|
|
51
|
+
font: inherit;
|
|
52
|
+
font-weight: 600;
|
|
53
|
+
margin: 0 0 6px;
|
|
54
|
+
letter-spacing: 0.04em;
|
|
55
|
+
text-transform: uppercase;
|
|
56
|
+
color: var(--muted);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
#hud div { display: flex; gap: 10px; justify-content: space-between; }
|
|
60
|
+
#hud .key { color: var(--muted); }
|
|
61
|
+
|
|
62
|
+
#legend {
|
|
63
|
+
position: fixed;
|
|
64
|
+
bottom: 12px;
|
|
65
|
+
left: 12px;
|
|
66
|
+
max-width: 62ch;
|
|
67
|
+
padding: 10px 12px;
|
|
68
|
+
border: 1px solid var(--line);
|
|
69
|
+
border-radius: 8px;
|
|
70
|
+
background: var(--panel);
|
|
71
|
+
backdrop-filter: blur(6px);
|
|
72
|
+
font-size: 12.5px;
|
|
73
|
+
color: var(--muted);
|
|
74
|
+
pointer-events: none;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#legend b { color: var(--text); font-weight: 600; }
|
|
78
|
+
#legend p { margin: 0 0 4px; }
|
|
79
|
+
#legend p:last-child { margin-bottom: 0; }
|
|
80
|
+
|
|
81
|
+
#message {
|
|
82
|
+
position: fixed;
|
|
83
|
+
inset: 0;
|
|
84
|
+
display: none;
|
|
85
|
+
align-items: center;
|
|
86
|
+
justify-content: center;
|
|
87
|
+
padding: 32px;
|
|
88
|
+
text-align: center;
|
|
89
|
+
background: #05070ae6;
|
|
90
|
+
color: var(--fail);
|
|
91
|
+
font-size: 16px;
|
|
92
|
+
white-space: pre-wrap;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
#message:not(:empty) { display: flex; }
|
|
96
|
+
</style>
|
|
97
|
+
</head>
|
|
98
|
+
<body>
|
|
99
|
+
|
|
100
|
+
<canvas id="view"></canvas>
|
|
101
|
+
|
|
102
|
+
<div id="hud">
|
|
103
|
+
<h1>GPU particles</h1>
|
|
104
|
+
<div><span class="key">fps</span><span id="stat-fps">—</span></div>
|
|
105
|
+
<div><span class="key">alive</span><span id="stat-alive">—</span></div>
|
|
106
|
+
<div><span class="key">free</span><span id="stat-dead">—</span></div>
|
|
107
|
+
<div><span class="key">draw instances</span><span id="stat-draw">—</span></div>
|
|
108
|
+
<div><span class="key">sim workgroups</span><span id="stat-dispatch">—</span></div>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<div id="legend">
|
|
112
|
+
<p><b>Four emitters, one pool.</b> Additive fire at the pillar, an alpha soft-depth smoke column
|
|
113
|
+
above it, velocity-stretched sparks by the block, and a wide soft-depth dust drift.</p>
|
|
114
|
+
<p>Emit, simulate and the billboard draw are all GPU-sized — the simulate dispatch and the draw
|
|
115
|
+
read indirect args the build-indirect pass writes. The counters above are read back purely to
|
|
116
|
+
display; nothing on the CPU sizes a pass.</p>
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
<div id="message"></div>
|
|
120
|
+
|
|
121
|
+
<script type="module" src="./main.js"></script>
|
|
122
|
+
|
|
123
|
+
</body>
|
|
124
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/particle_system/main.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { ShadeGPUCommandContext } from "../../device/ShadeGPUCommandContext.js";
|
|
2
|
+
import {
|
|
3
|
+
device_supports_immediate_size,
|
|
4
|
+
immediate_data_supported,
|
|
5
|
+
} from "../../device/immediate_data_supported.js";
|
|
6
|
+
import { GraphicsContext } from "../../renderer/GraphicsContext.js";
|
|
7
|
+
import {
|
|
8
|
+
PARTICLE_IMMEDIATE_BYTES,
|
|
9
|
+
PARTICLE_STATS_BYTES,
|
|
10
|
+
create_particle_scene,
|
|
11
|
+
} from "./particle_scene.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The page for the GPU particle playground: acquire a device, build the scene
|
|
15
|
+
* ({@link ./particle_scene.js}, which is where the interesting part lives), and drive it from
|
|
16
|
+
* `requestAnimationFrame`.
|
|
17
|
+
*
|
|
18
|
+
* Serve the workspace with `npm run dev --workspace @woosh/meep-engine` and open
|
|
19
|
+
* `/src/shade/playground/particle_system/index.html`. See README.md for what to look at, and for
|
|
20
|
+
* the `?debug` query flag that swaps rAF for manual stepping.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** How often the counters are copied back for the overlay. Display only — nothing sizes a pass. */
|
|
24
|
+
const STATS_INTERVAL_FRAMES = 30;
|
|
25
|
+
|
|
26
|
+
/** Device pixels per CSS pixel, capped: 32k billboards at 3x cost more than they show. */
|
|
27
|
+
const MAX_PIXEL_RATIO = 2;
|
|
28
|
+
|
|
29
|
+
async function main() {
|
|
30
|
+
const canvas = document.getElementById("view");
|
|
31
|
+
|
|
32
|
+
if (navigator.gpu === undefined) {
|
|
33
|
+
return show_message("WebGPU is not available in this browser.");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const adapter = await navigator.gpu.requestAdapter();
|
|
37
|
+
|
|
38
|
+
if (adapter === null) {
|
|
39
|
+
return show_message("No WebGPU adapter — this browser exposes the API but has no usable GPU.");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const device = await adapter.requestDevice();
|
|
43
|
+
device.addEventListener?.("uncapturederror", (e) => console.error("WebGPU error:", e.error.message));
|
|
44
|
+
|
|
45
|
+
// Every compute pass here carries its per-dispatch state as immediate data, an optional
|
|
46
|
+
// capability. Refusing by name beats the pipeline-creation error a device without it raises,
|
|
47
|
+
// which names neither the shader nor the feature.
|
|
48
|
+
if (!immediate_data_supported() || !device_supports_immediate_size(device, PARTICLE_IMMEDIATE_BYTES)) {
|
|
49
|
+
return show_message(
|
|
50
|
+
"This browser's WebGPU offers no usable immediate data "
|
|
51
|
+
+ `(needs ${PARTICLE_IMMEDIATE_BYTES} bytes, offers ${device.limits.maxImmediateSize ?? 0}).\n`
|
|
52
|
+
+ "The particle emit / simulate / build-indirect passes all carry their per-dispatch\n"
|
|
53
|
+
+ "state that way, so none of them can be built here."
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const graphics = new GraphicsContext(device);
|
|
58
|
+
const context = canvas.getContext("webgpu");
|
|
59
|
+
const format = navigator.gpu.getPreferredCanvasFormat();
|
|
60
|
+
context.configure({ device, format, alphaMode: "opaque" });
|
|
61
|
+
|
|
62
|
+
const scene = create_particle_scene(graphics, { color_format: format });
|
|
63
|
+
|
|
64
|
+
// Manual frame stepping instead of rAF — opt in with ?debug. Useful for driving the loop a
|
|
65
|
+
// known number of frames in a headless / hidden tab, where rAF is suspended.
|
|
66
|
+
const debug = new URLSearchParams(location.search).has("debug");
|
|
67
|
+
|
|
68
|
+
const stats_buffer = device.createBuffer({
|
|
69
|
+
label: "particles/stats",
|
|
70
|
+
size: PARTICLE_STATS_BYTES,
|
|
71
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
|
|
72
|
+
});
|
|
73
|
+
let stats_pending = false;
|
|
74
|
+
|
|
75
|
+
let last = performance.now();
|
|
76
|
+
let frame_index = 0;
|
|
77
|
+
let fps = 0;
|
|
78
|
+
|
|
79
|
+
function frame(now) {
|
|
80
|
+
const dt = Math.min((now - last) / 1000, 0.05);
|
|
81
|
+
last = now;
|
|
82
|
+
// A rAF-driven loop steps by wall clock; ?debug steps by hand, where dt can be 0.
|
|
83
|
+
fps = dt > 0 ? fps * 0.9 + 0.1 / dt : fps;
|
|
84
|
+
|
|
85
|
+
// Back the canvas with device pixels, so a HiDPI display gets a sharp image rather than an
|
|
86
|
+
// upscaled CSS-pixel one.
|
|
87
|
+
const ratio = Math.min(window.devicePixelRatio || 1, MAX_PIXEL_RATIO);
|
|
88
|
+
const width = Math.max(1, Math.round(canvas.clientWidth * ratio));
|
|
89
|
+
const height = Math.max(1, Math.round(canvas.clientHeight * ratio));
|
|
90
|
+
|
|
91
|
+
if (canvas.width !== width || canvas.height !== height) {
|
|
92
|
+
canvas.width = width;
|
|
93
|
+
canvas.height = height;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const cmd = ShadeGPUCommandContext.create(graphics, "particles/frame");
|
|
97
|
+
|
|
98
|
+
scene.encode_frame(cmd, {
|
|
99
|
+
color_view: context.getCurrentTexture().createView(),
|
|
100
|
+
width,
|
|
101
|
+
height,
|
|
102
|
+
dt,
|
|
103
|
+
time: now / 1000,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const capture_stats = !stats_pending && frame_index % STATS_INTERVAL_FRAMES === 0;
|
|
107
|
+
if (capture_stats) {
|
|
108
|
+
scene.encode_stats_copy(cmd, stats_buffer);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
cmd.finish();
|
|
112
|
+
|
|
113
|
+
frame_index++;
|
|
114
|
+
|
|
115
|
+
if (capture_stats) {
|
|
116
|
+
stats_pending = true;
|
|
117
|
+
stats_buffer.mapAsync(GPUMapMode.READ).then(() => {
|
|
118
|
+
const bytes = stats_buffer.getMappedRange().slice(0);
|
|
119
|
+
stats_buffer.unmap();
|
|
120
|
+
stats_pending = false;
|
|
121
|
+
|
|
122
|
+
window.__stats = { frame: frame_index, fps, ...scene.read_stats(bytes) };
|
|
123
|
+
write_hud(window.__stats);
|
|
124
|
+
}).catch(() => {
|
|
125
|
+
stats_pending = false;
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (!debug) {
|
|
130
|
+
requestAnimationFrame(frame);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (debug) {
|
|
135
|
+
// Drive frames by hand when the tab is hidden (rAF suspended) — headless verification.
|
|
136
|
+
// Nothing is scheduled: a stray rAF frame interleaved with __step would make the count the
|
|
137
|
+
// caller asked for and the count that ran two different numbers.
|
|
138
|
+
window.__step = (n = 1) => {
|
|
139
|
+
for (let i = 0; i < n; i++) {
|
|
140
|
+
frame(performance.now());
|
|
141
|
+
}
|
|
142
|
+
return frame_index;
|
|
143
|
+
};
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
requestAnimationFrame(frame);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Push one stats snapshot into the overlay. Absent elements are simply skipped. */
|
|
151
|
+
function write_hud({ fps, alive, dead, dispatch, draw }) {
|
|
152
|
+
const put = (id, value) => {
|
|
153
|
+
const node = document.getElementById(id);
|
|
154
|
+
if (node !== null) {
|
|
155
|
+
node.textContent = value;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
put("stat-fps", fps.toFixed(0));
|
|
160
|
+
put("stat-alive", alive.toLocaleString());
|
|
161
|
+
put("stat-dead", dead.toLocaleString());
|
|
162
|
+
put("stat-draw", draw[1].toLocaleString());
|
|
163
|
+
put("stat-dispatch", dispatch[0].toLocaleString());
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function show_message(text) {
|
|
167
|
+
const existing = document.getElementById("message");
|
|
168
|
+
const node = existing ?? document.body.appendChild(document.createElement("div"));
|
|
169
|
+
|
|
170
|
+
if (existing === null) {
|
|
171
|
+
node.style.cssText = "position:fixed;inset:0;display:flex;align-items:center;justify-content:center;color:#fff;font-family:sans-serif;font-size:16px;white-space:pre-wrap;text-align:center";
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
node.textContent = text;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
main().catch((e) => {
|
|
178
|
+
console.error(e);
|
|
179
|
+
show_message("The particle playground failed to start — see the console.\n\n" + e.message);
|
|
180
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} ParticleSceneStats
|
|
3
|
+
* @property {number} alive particles alive at the end of the captured frame
|
|
4
|
+
* @property {number} dead free slots left in the pool
|
|
5
|
+
* @property {number} alive_in the snapshot next frame's simulate reads as its input length
|
|
6
|
+
* @property {number[]} dispatch simulate's indirect dispatch args, `[x, y, z]` workgroups
|
|
7
|
+
* @property {number[]} draw the billboard draw's indirect args, `[vertices, instances]`
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Build the scene against a live (or mock) device.
|
|
11
|
+
*
|
|
12
|
+
* @param {GraphicsContext} graphics
|
|
13
|
+
* @param {object} options
|
|
14
|
+
* @param {GPUTextureFormat} options.color_format format of the colour target frames are encoded into
|
|
15
|
+
* @param {number} [options.capacity] particle pool size
|
|
16
|
+
* @returns {object} the scene, see the returned object's own members
|
|
17
|
+
*/
|
|
18
|
+
export function create_particle_scene(graphics: GraphicsContext, { color_format, capacity }: {
|
|
19
|
+
color_format: GPUTextureFormat;
|
|
20
|
+
capacity?: number;
|
|
21
|
+
}): object;
|
|
22
|
+
/**
|
|
23
|
+
* The largest immediate block any of the three compute passes declares (emit's 20-byte settings
|
|
24
|
+
* struct). Immediate data is an optional WebGPU capability, so callers check for it up front rather
|
|
25
|
+
* than letting pipeline creation fail with an error that names neither pass nor feature.
|
|
26
|
+
*/
|
|
27
|
+
export const PARTICLE_IMMEDIATE_BYTES: 20;
|
|
28
|
+
/** Bytes of stats {@link ParticleScene#encode_stats_copy} writes: 8 counters, then both arg buffers. */
|
|
29
|
+
export const PARTICLE_STATS_BYTES: 64;
|
|
30
|
+
export type ParticleSceneStats = {
|
|
31
|
+
/**
|
|
32
|
+
* particles alive at the end of the captured frame
|
|
33
|
+
*/
|
|
34
|
+
alive: number;
|
|
35
|
+
/**
|
|
36
|
+
* free slots left in the pool
|
|
37
|
+
*/
|
|
38
|
+
dead: number;
|
|
39
|
+
/**
|
|
40
|
+
* the snapshot next frame's simulate reads as its input length
|
|
41
|
+
*/
|
|
42
|
+
alive_in: number;
|
|
43
|
+
/**
|
|
44
|
+
* simulate's indirect dispatch args, `[x, y, z]` workgroups
|
|
45
|
+
*/
|
|
46
|
+
dispatch: number[];
|
|
47
|
+
/**
|
|
48
|
+
* the billboard draw's indirect args, `[vertices, instances]`
|
|
49
|
+
*/
|
|
50
|
+
draw: number[];
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=particle_scene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"particle_scene.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/particle_system/particle_scene.js"],"names":[],"mappings":"AAwEA;;;;;;;GAOG;AAEH;;;;;;;;GAQG;AACH;IAJqC,YAAY;IACrB,QAAQ,GAAzB,MAAM;IACJ,MAAM,CA8OlB;AA3QD;;;;GAIG;AACH,0CAA2C;AAE3C,wGAAwG;AACxG,sCAAuC;;;;;WAOzB,MAAM;;;;UACN,MAAM;;;;cACN,MAAM;;;;cACN,MAAM,EAAE;;;;UACR,MAAM,EAAE"}
|