babylon.quarks 0.20.0 → 0.23.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/CHANGELOG.md +105 -0
- package/README.md +2 -0
- package/dist/babylon.quarks.cjs +1 -1
- package/dist/babylon.quarks.cjs.map +1 -1
- package/dist/babylon.quarks.esm.js +1 -1
- package/dist/babylon.quarks.esm.js.map +1 -1
- package/dist/babylon.quarks.umd.min.js +1 -1
- package/dist/babylon.quarks.umd.min.js.map +1 -1
- package/dist/types/index.d.ts +523 -43
- package/package.json +1 -1
- package/src/BatchedRenderer.ts +59 -2
- package/src/ParticleSystem.ts +388 -59
- package/src/QuarksLoader.ts +381 -56
- package/src/SpriteBatch.ts +388 -111
- package/src/TrailBatch.ts +79 -63
- package/src/VFXBatch.ts +101 -0
- package/src/index.ts +9 -3
- package/src/shaders/particle_physics_frag.glsl.ts +26 -1
- package/src/shaders/particle_physics_frag.wgsl.ts +26 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,111 @@ All notable changes to the `babylon.quarks` package are documented here.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
5
5
|
and the project follows the `quarks.core` 0.x version line.
|
|
6
6
|
|
|
7
|
+
## [0.23.0] — 2026-10-18
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- CPU simulation and batch upload rewritten to work on the `ParticleStore` columns instead of
|
|
12
|
+
walking particle objects. Scalar attributes (`rotation`, `angularVelocity`, `uvTile`, `flip`,
|
|
13
|
+
`startSpeed`) and mesh quaternion rotations now live in store columns; the sprite batch copies
|
|
14
|
+
them as ranges and only visits particle objects for sub-emitted systems. Compiled behavior passes
|
|
15
|
+
(now built for single behaviors too) read and write the columns, interpolate sampled curves and
|
|
16
|
+
gradients inline and take per-particle random samples from a mirrored memory column, so a step
|
|
17
|
+
no longer touches the particle object for the built-in behaviors. Snapshots of size and colour
|
|
18
|
+
for the renderer are only kept when a behavior can change them, and the step's integration,
|
|
19
|
+
newborn fix-up and compaction run in one pass. Trail ribbons transform each recorded sample
|
|
20
|
+
once, upload indices straight to the GPU buffer (no per-frame sub mesh rebuild) and recompute
|
|
21
|
+
the emitter matrix only when its transform changed. `Noise` and `TurbulenceField` evaluate
|
|
22
|
+
constant generators once per frame and update through the columns. Measured on 50k particles:
|
|
23
|
+
billboards 2.1–2.9x faster per frame, trails 1.5x, noise/turbulence 1.2x.
|
|
24
|
+
- Assigning a `Quaternion` to a sprite particle's `rotation` or `angularVelocity` copies it into
|
|
25
|
+
the particle's store row; reading the property back returns a view of that row rather than the
|
|
26
|
+
assigned object. `RandomQuatGenerator` stores its sample as four numbers in the particle's
|
|
27
|
+
memory instead of a `Quaternion`. `TrailParticle.previous` (deprecated) is created on first use.
|
|
28
|
+
|
|
29
|
+
## [0.22.0] — 2026-10-17
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- Mesh particle lighting modes: `ParticleSystem.lighting` (constructor option `lighting`, saved
|
|
34
|
+
as `lighting` on the effect's `QuarksMaterial` and read back by `QuarksLoader`) is `'fixed'`
|
|
35
|
+
(default — exactly the light mesh particles had before), `'unlit'` (the lighting term is
|
|
36
|
+
compiled out with `MESH_UNLIT`: texture × particle colour, for emissive meshes) or `'scene'`
|
|
37
|
+
(the scene's first enabled `DirectionalLight` / `HemisphericLight`, re-read every frame:
|
|
38
|
+
direction, diffuse × intensity, `scene.ambientColor`, plus a hemispheric light's ground colour
|
|
39
|
+
in the ambient; falls back to the fixed light when the scene has neither). Systems with
|
|
40
|
+
different lighting are batched apart. The default is not written to JSON.
|
|
41
|
+
- `BatchedRenderer.setMeshLighting({direction, color, ambient})` (Babylon `Vector3` / `Color3`,
|
|
42
|
+
any subset) sets the `'fixed'` light for every mesh batch of the renderer, including later ones;
|
|
43
|
+
`getMeshLighting()` returns a copy, `defaultMeshLighting()` the built-in values
|
|
44
|
+
(`(0.4, -1, 0.6)`, white, `0.35` grey). Exposed in the editor's Renderer module as "Lighting".
|
|
45
|
+
- Mesh particle rim (Fresnel) term: `ParticleSystem.rim` (constructor option `rim`, saved as
|
|
46
|
+
`rim` on the effect's `QuarksMaterial`) — `{color: [r, g, b], power, strength, mode}` with
|
|
47
|
+
defaults `[1, 1, 1]`, `2`, `1`, `'add'`; any field may be left out. The edge term is
|
|
48
|
+
`pow(1 - |N·V|, power) * strength`; `'add'` adds `color` (glowing edge), `'mix'` blends toward it
|
|
49
|
+
(outline). Compiled in only when set (`MESH_RIM` / `MESH_RIM_MIX`), batched by value, written to
|
|
50
|
+
JSON only when set, and exposed in the editor's Renderer module. `normalizeMeshRim` /
|
|
51
|
+
`meshRimEqual` are exported.
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- **Behaviour change:** quarks.core `WidthOverLength` (Width over Trail) now reads its curve as a
|
|
56
|
+
multiplier on the width each trail sample was recorded with (the particle's `size.x` at that
|
|
57
|
+
moment), the way Unity's Width over Trail works, and gives the head sample the curve's value at
|
|
58
|
+
0, so a trail no longer flares out behind its head or steps at the tip. A new `absolute` flag
|
|
59
|
+
(`new WidthOverLength(curve, absolute = false)`, JSON field `absolute`) keeps the old reading —
|
|
60
|
+
the curve as the width in world units, the head at the particle's size. `toJSON` always writes
|
|
61
|
+
the flag; JSON without it (everything written by 0.21 and earlier, including the Unity
|
|
62
|
+
exporter's output) loads as `absolute: true`, so authored effects keep their look. Code that
|
|
63
|
+
builds `new WidthOverLength(curve)` gets the new multiplier behaviour: divide an absolute curve
|
|
64
|
+
by the start size, or pass `true`. `TrailParticle` gains `historyBaseSizes` (the unscaled
|
|
65
|
+
recorded widths) and `headWidthScale`.
|
|
66
|
+
|
|
67
|
+
### Fixed
|
|
68
|
+
|
|
69
|
+
- Burst `cycle` / `interval` are honoured: a burst fires `cycle` waves, `interval` seconds apart,
|
|
70
|
+
each rolling `probability` on its own. Repeats past the system's `duration` are dropped (a
|
|
71
|
+
looping system starts them over every loop), a `cycle` below 1 fires once, and a zero interval
|
|
72
|
+
fires every wave at once. Previously every burst fired a single wave.
|
|
73
|
+
- Emission over distance spreads the particles it owes along the path the emitter travelled
|
|
74
|
+
this step, each at its own metre mark (the spacing carries across steps), instead of spawning
|
|
75
|
+
all of them at the emitter's current position — a fast world-space emitter now leaves a
|
|
76
|
+
continuous trail rather than one clump per frame. Only the position is interpolated (rotation
|
|
77
|
+
and scale are the emitter's current ones) and the particles start at age 0. Local-space
|
|
78
|
+
systems, whose particles move with the emitter, are unchanged.
|
|
79
|
+
- A sub emitter whose target uuid is not in the effect no longer throws on every frame.
|
|
80
|
+
`QuarksLoader` unlinks it (`subParticleSystem = undefined`) with one `console.warn` naming the
|
|
81
|
+
emitter and the uuid — also when the uuid names a node that is not a particle emitter — and
|
|
82
|
+
quarks.core `EmitSubParticleSystem` skips any value that is not a resolved emitter. An
|
|
83
|
+
unresolved uuid string is written back unchanged by `toJSON`.
|
|
84
|
+
- quarks.core `RotationOverLife` turns mesh particles too: a quaternion rotation is turned about
|
|
85
|
+
the particle's local Z axis (the axis a number `startRotation` uses, and what Unity's Rotation
|
|
86
|
+
over Lifetime without separate axes does to meshes), in its own pass and in the fused pass, and
|
|
87
|
+
the step is kept for the renderer's in-between-step interpolation. It used to do nothing on
|
|
88
|
+
meshes, silently. `Rotation3DOverLife` remains the behavior for any other axis.
|
|
89
|
+
|
|
90
|
+
## [0.21.0] — 2026-10-16
|
|
91
|
+
|
|
92
|
+
### Added
|
|
93
|
+
|
|
94
|
+
- `QuarksResourceResolver` on `QuarksLoaderOptions` (`resolve` / `fetchJson`) so File pickers,
|
|
95
|
+
CDN layouts and virtual FS backends can resolve relative texture and geometry links without
|
|
96
|
+
calling `resolveExternalGeometries` by hand.
|
|
97
|
+
- `loadFromJSON(json, baseUrl?)` — same pipeline as `load(url)` when the effect document is
|
|
98
|
+
already in memory; `resolveResources` / static `resolveLinkedResources` for prepare-only.
|
|
99
|
+
- `loadAll(urls)` and `loadFromJSONAll(entries)` for battle / level preload: fetch effect docs
|
|
100
|
+
(optional `concurrency`), resolve every linked geometry/image across the pack so shared asset
|
|
101
|
+
urls hit a per-scene fetch cache once, then parse. `continueOnError` and `onProgress` (once per
|
|
102
|
+
settled effect) supported; without `continueOnError` the return type is `TransformNode[]`.
|
|
103
|
+
- `QuarksLoader.joinUrl` for portable baseUrl joining (data/blob/absolute urls left alone).
|
|
104
|
+
|
|
105
|
+
### Changed
|
|
106
|
+
|
|
107
|
+
- `load(url)` goes through `loadFromJSON` after fetching the effect JSON. Geometry JSON fetches
|
|
108
|
+
are deduped per scene; inlined array fields are copied so cached documents are not aliased
|
|
109
|
+
across effects. Prefer `load` / `loadFromJSON` / `resolveResources` over
|
|
110
|
+
`resolveExternalGeometries` (kept for compatibility).
|
|
111
|
+
|
|
7
112
|
## [0.20.0] — 2026-10-16
|
|
8
113
|
|
|
9
114
|
### Added
|
package/README.md
CHANGED
|
@@ -170,6 +170,8 @@ import {BatchedRenderer, QuarksLoader, QuarksUtil} from 'babylon.quarks';
|
|
|
170
170
|
const batchRenderer = new BatchedRenderer('particles', scene);
|
|
171
171
|
const loader = new QuarksLoader(scene);
|
|
172
172
|
const effect = await loader.load('effects/explosion.json');
|
|
173
|
+
// Or preload a battle pack — shared textures/geometries fetch once:
|
|
174
|
+
// const roots = await loader.loadAll(['fx/hit.json', 'fx/explosion.json'], { concurrency: 6 });
|
|
173
175
|
QuarksUtil.addToBatchRenderer(effect, batchRenderer);
|
|
174
176
|
QuarksUtil.play(effect);
|
|
175
177
|
```
|