reze-engine 0.58.1 → 0.58.3
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/dist/effect-points.d.ts +30 -0
- package/dist/effect-points.d.ts.map +1 -0
- package/dist/effect-points.js +49 -0
- package/dist/engine.d.ts +25 -2
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +199 -35
- package/dist/graph/style-group.d.ts +7 -0
- package/dist/graph/style-group.d.ts.map +1 -1
- package/dist/light-grid.d.ts +25 -0
- package/dist/light-grid.d.ts.map +1 -0
- package/dist/light-grid.js +91 -0
- package/dist/model.d.ts +9 -0
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +6 -0
- package/dist/pmx-loader.d.ts.map +1 -1
- package/dist/pmx-loader.js +11 -6
- package/dist/shaders/cast-api.d.ts +1 -1
- package/dist/shaders/cast-layout.d.ts +5 -3
- package/dist/shaders/cast-layout.d.ts.map +1 -1
- package/dist/shaders/cast-layout.js +5 -3
- package/dist/shaders/directives.d.ts +3 -0
- package/dist/shaders/directives.d.ts.map +1 -1
- package/dist/shaders/directives.js +5 -0
- package/dist/shaders/lights.d.ts +14 -9
- package/dist/shaders/lights.d.ts.map +1 -1
- package/dist/shaders/lights.js +118 -65
- package/dist/shaders/passes/composite.d.ts +1 -1
- package/dist/shaders/passes/composite.d.ts.map +1 -1
- package/dist/shaders/passes/composite.js +2 -0
- package/dist/shaders/passes/grid.d.ts.map +1 -1
- package/dist/shaders/passes/grid.js +2 -0
- package/dist/shaders/passes/particles.d.ts +20 -1
- package/dist/shaders/passes/particles.d.ts.map +1 -1
- package/dist/shaders/passes/particles.js +36 -1
- package/dist/shaders/passes/trails.d.ts.map +1 -1
- package/dist/shaders/passes/trails.js +2 -1
- package/dist/shaders/points-api.d.ts +11 -0
- package/dist/shaders/points-api.d.ts.map +1 -0
- package/dist/shaders/points-api.js +58 -0
- package/package.json +1 -1
- package/src/effect-points.ts +67 -0
- package/src/engine.ts +215 -35
- package/src/graph/style-group.ts +12 -1
- package/src/light-grid.ts +139 -0
- package/src/model.ts +12 -0
- package/src/pmx-loader.ts +13 -6
- package/src/shaders/cast-layout.ts +5 -3
- package/src/shaders/directives.ts +8 -0
- package/src/shaders/lights.ts +118 -65
- package/src/shaders/passes/composite.ts +2 -0
- package/src/shaders/passes/grid.ts +2 -0
- package/src/shaders/passes/particles.ts +46 -2
- package/src/shaders/passes/trails.ts +2 -1
- package/src/shaders/points-api.ts +66 -0
|
@@ -11,6 +11,7 @@ import { clockApi, EFFECT_MATH_API, PARTICLE_STRUCT_WGSL, trailSlotsApi, viewpor
|
|
|
11
11
|
import { sceneIdFieldWgsl, sceneIdPadWgsl } from "./scene-contract"
|
|
12
12
|
import { idApi } from "../id-api"
|
|
13
13
|
import { sceneLightApi } from "../scene-light-api"
|
|
14
|
+
import { pointsApi } from "../points-api"
|
|
14
15
|
// GPU particles for user effects: a compute step and an instanced quad draw.
|
|
15
16
|
//
|
|
16
17
|
// Its own shader MODULE rather than more source spliced into composite.ts, for
|
|
@@ -100,6 +101,15 @@ type ParticleSource = {
|
|
|
100
101
|
* where every stacked fragment is otherwise shaded in full; the prepass is
|
|
101
102
|
* the shape of that rejection, done by hand and cheaply. */
|
|
102
103
|
cover: boolean
|
|
104
|
+
/** The effect defines `particleCount() -> u32`: how many of the pool are
|
|
105
|
+
* live this frame, as a function of its dials. The step is dispatched and
|
|
106
|
+
* the quads drawn for that many slots and no more, through indirect
|
|
107
|
+
* arguments a one-thread kernel writes first. A pool sized for its densest
|
|
108
|
+
* setting then costs its current setting: a lawn's spare 1.3M slots were
|
|
109
|
+
* read, written and issued as degenerate quads every frame, and that
|
|
110
|
+
* traffic alone was a third of the frame. The live slots are always the
|
|
111
|
+
* first N — an author whose live set is not a prefix has no use for this. */
|
|
112
|
+
live: boolean
|
|
103
113
|
/** The side of this effect's grid, or 0 when it declared none. Particles READ
|
|
104
114
|
* the grid; the kernel that steps it lives in the grid pass. A blade of grass
|
|
105
115
|
* bending where a foot pressed is the whole case: the bend has to persist and
|
|
@@ -109,6 +119,14 @@ type ParticleSource = {
|
|
|
109
119
|
|
|
110
120
|
/** Where the shading stage's five scene-light bindings start — see scene-light-api.ts. */
|
|
111
121
|
export const PARTICLE_LIGHT_BINDING = 10
|
|
122
|
+
/** The effect's named points (`#points`), in both stages — see points-api.ts. */
|
|
123
|
+
export const PARTICLE_POINTS_BINDING = 15
|
|
124
|
+
/** The indirect arguments a `particleCount` effect writes — compute stage only.
|
|
125
|
+
* Eight u32: the step's dispatch (groups, 1, 1, pad) then the quads' draw
|
|
126
|
+
* (6, count, 0, 0), so the draw reads at byte 16. */
|
|
127
|
+
export const PARTICLE_INDIRECT_BINDING = 16
|
|
128
|
+
export const PARTICLE_INDIRECT_BYTES = 32
|
|
129
|
+
export const PARTICLE_INDIRECT_DRAW_OFFSET = 16
|
|
112
130
|
|
|
113
131
|
/** Bytes per particle. Explicitly padded — see the struct below. */
|
|
114
132
|
export const PARTICLE_STRIDE = 48
|
|
@@ -168,13 +186,15 @@ fn rzCamPos() -> vec3f { return cam.camPos; }
|
|
|
168
186
|
`
|
|
169
187
|
|
|
170
188
|
/** Does the source define the particle contract? All three are required
|
|
171
|
-
* together; `cover` is optional and only means anything to a cutout
|
|
172
|
-
|
|
189
|
+
* together; `cover` is optional and only means anything to a cutout, and
|
|
190
|
+
* `count` is optional and bounds the frame's work — see particleCount. */
|
|
191
|
+
export function particleEntryPoints(wgsl: string): { init: boolean; step: boolean; shade: boolean; cover: boolean; count: boolean } {
|
|
173
192
|
return {
|
|
174
193
|
init: /\bfn\s+particleInit\s*\(/.test(wgsl),
|
|
175
194
|
step: /\bfn\s+particleStep\s*\(/.test(wgsl),
|
|
176
195
|
shade: /\bfn\s+particleShade\s*\(/.test(wgsl),
|
|
177
196
|
cover: /\bfn\s+particleCover\s*\(/.test(wgsl),
|
|
197
|
+
count: /\bfn\s+particleCount\s*\(/.test(wgsl),
|
|
178
198
|
}
|
|
179
199
|
}
|
|
180
200
|
|
|
@@ -212,8 +232,31 @@ ${src.paramsDecl}
|
|
|
212
232
|
// Stubbed: this module cannot read an attachment the scene pass writes — see
|
|
213
233
|
// id-api.ts. The author's whole file compiles here, so the names must exist.
|
|
214
234
|
idApi(false, 0, 0) + castDistanceStub() + sceneLightApi(false, 0, 0) +
|
|
235
|
+
// The named points, for real: particleInit is where a flame is put on a wick.
|
|
236
|
+
pointsApi(true, 0, PARTICLE_POINTS_BINDING) +
|
|
237
|
+
(src.live
|
|
238
|
+
? `@group(0) @binding(${PARTICLE_INDIRECT_BINDING}) var<storage, read_write> _rzIndirect: array<u32, 8>;\n`
|
|
239
|
+
: "") +
|
|
215
240
|
"\n// ── user effect ──\n" +
|
|
216
241
|
src.wgsl +
|
|
242
|
+
(src.live
|
|
243
|
+
? /* wgsl */ `
|
|
244
|
+
// The frame's live count, from the author's dials, into the arguments the
|
|
245
|
+
// step dispatch and both draws read. One thread; runs before the step.
|
|
246
|
+
@compute @workgroup_size(1)
|
|
247
|
+
fn rzCount() {
|
|
248
|
+
let n = min(particleCount(), pu.count);
|
|
249
|
+
_rzIndirect[0] = (n + 63u) / 64u;
|
|
250
|
+
_rzIndirect[1] = 1u;
|
|
251
|
+
_rzIndirect[2] = 1u;
|
|
252
|
+
_rzIndirect[3] = 0u;
|
|
253
|
+
_rzIndirect[4] = 6u;
|
|
254
|
+
_rzIndirect[5] = n;
|
|
255
|
+
_rzIndirect[6] = 0u;
|
|
256
|
+
_rzIndirect[7] = 0u;
|
|
257
|
+
}
|
|
258
|
+
`
|
|
259
|
+
: "") +
|
|
217
260
|
/* wgsl */ `
|
|
218
261
|
@compute @workgroup_size(64)
|
|
219
262
|
fn main(@builtin(global_invocation_id) gid: vec3u) {
|
|
@@ -289,6 +332,7 @@ ${src.paramsDecl}
|
|
|
289
332
|
// The sun's shadow and the world's ambient, for real: the shadow pass has
|
|
290
333
|
// run by the time this draws, inside the scene pass. See scene-light-api.ts.
|
|
291
334
|
sceneLightApi(true, 0, PARTICLE_LIGHT_BINDING) +
|
|
335
|
+
pointsApi(true, 0, PARTICLE_POINTS_BINDING) +
|
|
292
336
|
"\n// ── user effect ──\n" +
|
|
293
337
|
src.wgsl +
|
|
294
338
|
/* wgsl */ `
|
|
@@ -11,6 +11,7 @@ import { clockApi, EFFECT_MATH_API, PARTICLE_STRUCT_WGSL, trailSlotsApi, viewpor
|
|
|
11
11
|
import { sceneIdFieldWgsl, sceneIdPadWgsl } from "./scene-contract"
|
|
12
12
|
import { idApi } from "../id-api"
|
|
13
13
|
import { sceneLightApi } from "../scene-light-api"
|
|
14
|
+
import { pointsApi } from "../points-api"
|
|
14
15
|
// Ribbons along a bone's recorded path, drawn as geometry.
|
|
15
16
|
//
|
|
16
17
|
// This is the effect the whole geometry path was built for. As a fullscreen
|
|
@@ -302,7 +303,7 @@ fn rzTurnRadius(a: vec3f, b: vec3f, c: vec3f) -> f32 {
|
|
|
302
303
|
gridReadApi(0, 8, 9, src.gridSize) +
|
|
303
304
|
// Stubbed: this module cannot read an attachment the scene pass writes — see
|
|
304
305
|
// id-api.ts. The author's whole file compiles here, so the names must exist.
|
|
305
|
-
idApi(false, 0, 0) + castDistanceStub() + sceneLightApi(false, 0, 0) +
|
|
306
|
+
idApi(false, 0, 0) + castDistanceStub() + sceneLightApi(false, 0, 0) + pointsApi(false) +
|
|
306
307
|
"\n// ── user effect ──\n" +
|
|
307
308
|
src.wgsl +
|
|
308
309
|
/* wgsl */ `
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Named points on the models, for an effect that puts something at each one.
|
|
2
|
+
//
|
|
3
|
+
// #points flame
|
|
4
|
+
//
|
|
5
|
+
// gives the effect every bone whose name starts with `flame`, on every model in
|
|
6
|
+
// the scene — a stage, its parts, a prop, a character — as RzPoint: where the
|
|
7
|
+
// bone stands and where its tail points, in world space, this frame. A candle
|
|
8
|
+
// stage carries a bone per wick; a flame effect draws one flame on each, sized
|
|
9
|
+
// and stood up by the tail.
|
|
10
|
+
//
|
|
11
|
+
// BONES, because a bone is MMD's own word for a named point in a model. A stage
|
|
12
|
+
// that brings its candles as bones needs no side file, a hand-made stage can
|
|
13
|
+
// add them in any PMX editor, and a candle a character carries moves with the
|
|
14
|
+
// hand that holds it.
|
|
15
|
+
//
|
|
16
|
+
// Not the cast's anchors: those name up to sixteen bones on four characters,
|
|
17
|
+
// one bone per name. A stage is not a character, and fifty wicks share a
|
|
18
|
+
// prefix rather than each having a name worth declaring.
|
|
19
|
+
|
|
20
|
+
/** How many points one effect can read. A candlelit hall is fifty. */
|
|
21
|
+
export const MAX_EFFECT_POINTS = 256
|
|
22
|
+
|
|
23
|
+
/** Floats in a points buffer: a vec4 header (count), then two vec4s a point. */
|
|
24
|
+
export const POINTS_FLOATS = 4 + MAX_EFFECT_POINTS * 8
|
|
25
|
+
|
|
26
|
+
const STRUCT = /* wgsl */ `
|
|
27
|
+
/** One named point: where the bone stands, and where its tail points to. */
|
|
28
|
+
struct RzPoint {
|
|
29
|
+
pos: vec3f,
|
|
30
|
+
tip: vec3f,
|
|
31
|
+
}
|
|
32
|
+
`
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* rzPointCount / rzPoint. `bound` is false in every module that cannot read the
|
|
36
|
+
* buffer — the author's whole file is spliced into each module it has a mount
|
|
37
|
+
* in, so the names must resolve there too, and there they read as no points.
|
|
38
|
+
*/
|
|
39
|
+
export function pointsApi(bound: boolean, group = 0, binding = 0): string {
|
|
40
|
+
if (!bound) {
|
|
41
|
+
return (
|
|
42
|
+
STRUCT +
|
|
43
|
+
/* wgsl */ `
|
|
44
|
+
fn rzPointCount() -> u32 { return 0u; }
|
|
45
|
+
fn rzPoint(i: u32) -> RzPoint { var p: RzPoint; return p; }
|
|
46
|
+
`
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
return (
|
|
50
|
+
STRUCT +
|
|
51
|
+
/* wgsl */ `
|
|
52
|
+
@group(${group}) @binding(${binding}) var<storage, read> _rzPoints: array<vec4f>;
|
|
53
|
+
|
|
54
|
+
/** How many named points the scene has for this effect, this frame. */
|
|
55
|
+
fn rzPointCount() -> u32 { return min(u32(_rzPoints[0].x), ${MAX_EFFECT_POINTS}u); }
|
|
56
|
+
|
|
57
|
+
/** Point i, world space. */
|
|
58
|
+
fn rzPoint(i: u32) -> RzPoint {
|
|
59
|
+
var p: RzPoint;
|
|
60
|
+
p.pos = _rzPoints[1u + i * 2u].xyz;
|
|
61
|
+
p.tip = _rzPoints[2u + i * 2u].xyz;
|
|
62
|
+
return p;
|
|
63
|
+
}
|
|
64
|
+
`
|
|
65
|
+
)
|
|
66
|
+
}
|