babylon.quarks 0.25.0 → 0.26.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.
@@ -1121,6 +1121,18 @@ interface TrailSettings {
1121
1121
  * @type {boolean}
1122
1122
  */
1123
1123
  recordWorldSpace?: boolean;
1124
+ /**
1125
+ * Sweep the ribbon along this axis of the emitter instead of turning it to
1126
+ * face the camera: every sample records the axis as the emitter held it,
1127
+ * and the ribbon spans the particle's width along it, centred on the
1128
+ * particle. With the emitter on a blade, the axis along the blade and the
1129
+ * width the blade's length, the trail is the surface the blade swept, as a
1130
+ * weapon trail (Unreal's AnimTrail) is. The emitter's scale applies to the
1131
+ * width, and so does the axis's length: give a unit vector for the width
1132
+ * as set. Unset (the default): a camera-facing ribbon.
1133
+ * @type {Vector3}
1134
+ */
1135
+ sideAxis?: Vector3;
1124
1136
  }
1125
1137
  interface MeshSettings {
1126
1138
  /**
@@ -1760,6 +1772,12 @@ declare class TrailParticle implements Particle {
1760
1772
  headWidthScale: number;
1761
1773
  /** Ring buffer of recorded colors, 4 floats per sample. */
1762
1774
  historyColors: Float32Array;
1775
+ /**
1776
+ * Ring buffer of recorded side vectors, 3 floats per sample, in the space
1777
+ * the positions are recorded in. Empty unless the trail is swept along an
1778
+ * axis (`TrailSettings.sideAxis`); see {@link ensureSideHistory}.
1779
+ */
1780
+ historySides: Float32Array;
1763
1781
  /** Number of samples the ring buffers can hold. */
1764
1782
  historyCapacity: number;
1765
1783
  /** Slot the next sample is written to. */
@@ -1784,6 +1802,8 @@ declare class TrailParticle implements Particle {
1784
1802
  * @param {number} capacity - Number of samples to hold.
1785
1803
  */
1786
1804
  ensureHistoryCapacity(capacity: number): void;
1805
+ /** Allocates {@link historySides} for the current capacity, once a trail is swept. */
1806
+ ensureSideHistory(): void;
1787
1807
  /** Drops every recorded sample without releasing the buffers. */
1788
1808
  resetHistory(): void;
1789
1809
  /**
@@ -2149,6 +2169,13 @@ interface FrameOverLifeOptions {
2149
2169
  frameCount?: number;
2150
2170
  /** FPS mode: wrap back to the first frame of the segment (default) or hold its last. */
2151
2171
  loop?: boolean;
2172
+ /**
2173
+ * FPS mode: every `1 / fps` seconds show a random frame of the segment
2174
+ * instead of the next one, each particle its own sequence: the flicker of
2175
+ * lightning, sparks or a neon sign. Needs {@link frameCount}; `loop` does
2176
+ * not apply. Default false.
2177
+ */
2178
+ random?: boolean;
2152
2179
  /**
2153
2180
  * Per-particle frame offset, sampled once at birth: an `IntervalValue(0, n)`
2154
2181
  * starts each particle on a random frame (Unity's "Start Frame"). Default none.
@@ -2161,7 +2188,8 @@ interface FrameOverLifeOptions {
2161
2188
  * By default `frame` is sampled at the particle's life fraction. The
2162
2189
  * {@link FrameOverLifeOptions} add the rest of Unity's texture sheet
2163
2190
  * animation: playing at a fixed frame rate, several cycles per life, a frame
2164
- * segment that loops or holds, and a random start frame.
2191
+ * segment that loops or holds, a random start frame, and a random frame on
2192
+ * every tick.
2165
2193
  */
2166
2194
  declare class FrameOverLife implements Behavior {
2167
2195
  type: string;
@@ -2170,7 +2198,10 @@ declare class FrameOverLife implements Behavior {
2170
2198
  cycles: number;
2171
2199
  frameCount: number;
2172
2200
  loop: boolean;
2201
+ random: boolean;
2173
2202
  startFrame?: ValueGenerator;
2203
+ /** A per-particle sample that sets each particle's random sequence apart. */
2204
+ private readonly salt;
2174
2205
  constructor(frame: FunctionValueGenerator | ValueGenerator, options?: FrameOverLifeOptions);
2175
2206
  get frame(): FunctionValueGenerator | ValueGenerator;
2176
2207
  set frame(frame: FunctionValueGenerator | ValueGenerator);
@@ -2182,6 +2213,10 @@ declare class FrameOverLife implements Behavior {
2182
2213
  /** The tile for `particle` at `age` seconds, `t` being that age over its life. */
2183
2214
  frameAt(particle: Particle, age: number, t: number): number;
2184
2215
  private offset;
2216
+ /** The particle's salt; 0 for a particle born before this behaviour was added. */
2217
+ private saltOf;
2218
+ /** A stable pseudo-random number in [0, 1) for a tick of a particle's sequence. */
2219
+ private static hash;
2185
2220
  private static wrap;
2186
2221
  private sampleFrame;
2187
2222
  frameUpdate(delta: number): void;
@@ -3372,9 +3407,12 @@ interface MeshRim {
3372
3407
  strength: number;
3373
3408
  /**
3374
3409
  * `'add'` (default) adds the colour, for a glowing edge; `'mix'` blends the
3375
- * surface toward it, for an outline (a dark ink line with a dark colour).
3410
+ * surface toward it, for an outline (a dark ink line with a dark colour);
3411
+ * `'fade'` leaves the colour and fades the faces turned to the camera by
3412
+ * `strength` instead, alpha times `1 - strength * (1 - edge)`: a wall of
3413
+ * light that reads thick along its silhouette and thin across its face.
3376
3414
  */
3377
- mode: 'add' | 'mix';
3415
+ mode: 'add' | 'mix' | 'fade';
3378
3416
  }
3379
3417
  /**
3380
3418
  * A complete rim from a partial one, every field defaulted and kept in range,
@@ -3383,6 +3421,80 @@ interface MeshRim {
3383
3421
  declare function normalizeMeshRim(rim: Partial<MeshRim> | null | undefined): MeshRim | undefined;
3384
3422
  /** True when both describe the same rim (or both none). */
3385
3423
  declare function meshRimEqual(a: MeshRim | undefined, b: MeshRim | undefined): boolean;
3424
+ /**
3425
+ * Which texture coordinates a texture is sampled with, as Unity's UV channels
3426
+ * and Niagara's ribbon UV0 / UV1:
3427
+ *
3428
+ * - `0`: the particle's first UV, with the sprite sheet's cell applied: on a
3429
+ * sheet the current frame's cell, on a trail the cell's stretch along it, on
3430
+ * a mesh its first UV set. Read before the map's own layout and distortion,
3431
+ * so a texture on it does not move with them.
3432
+ * - `1`: the particle's own UV, never moved by the sheet. The whole quad on a
3433
+ * billboard, a stretched billboard or a beam (mirrored with the quad when it
3434
+ * flips); on a trail U along it the way the map's runs (from the tail, or
3435
+ * from the head with `uvFromHead`) and V across it; on a mesh its second UV
3436
+ * set (`instancingUVs2`), or its first when it has none.
3437
+ *
3438
+ * A mesh can then repeat its picture along UV0 while a mask on UV1 runs once
3439
+ * across its whole length, as a lightmap UV does in a game engine.
3440
+ */
3441
+ type UVChannel = 0 | 1;
3442
+ /**
3443
+ * How a texture is laid over the particle: its UV channel, then tiling and
3444
+ * offset as in Unity's material Tiling / Offset, then a scroll on the
3445
+ * renderer's clock as Unreal's Panner. Sampled at
3446
+ * `uv(channel) * tiling + offset + scroll * time`; the offset is used as
3447
+ * given, so a clamped texture can be moved off its edge, and only the
3448
+ * scroll's share is wrapped (over two repeats, so a mirrored texture stays
3449
+ * seamless). A texture that scrolls or tiles should repeat.
3450
+ */
3451
+ interface TextureUV {
3452
+ /** See {@link UVChannel}. Default 0. */
3453
+ channel: UVChannel;
3454
+ /** Repeats across the channel's 0…1, `[u, v]`. Default `[1, 1]`. */
3455
+ tiling: [number, number];
3456
+ /** Added after tiling, in texture UV units. Default `[0, 0]`. */
3457
+ offset: [number, number];
3458
+ /** UV units per second on the renderer's clock. Default `[0, 0]`. */
3459
+ scroll: [number, number];
3460
+ }
3461
+ /** A complete {@link TextureUV} from a partial one, with `defaults` under the fields left out. */
3462
+ declare function normalizeTextureUV(uv: Partial<TextureUV> | null | undefined, defaults?: Partial<TextureUV>): TextureUV;
3463
+ /** True when both lay a texture the same way. */
3464
+ declare function textureUVEqual(a: TextureUV, b: TextureUV): boolean;
3465
+ /** The fields of `uv` that differ from `defaults`, for JSON written only when set. */
3466
+ declare function textureUVToJSON(uv: TextureUV, defaults?: Partial<TextureUV>): Partial<TextureUV> | undefined;
3467
+ /**
3468
+ * Which value of the map's texel picks the colour along a gradient map's
3469
+ * ramp: one channel, so a texture can pack several masks (Unreal's and
3470
+ * Unity's channel-packed textures), or the Rec. 709 luminance of its colour.
3471
+ */
3472
+ type GradientMapChannel = 'r' | 'g' | 'b' | 'a' | 'luminance';
3473
+ /**
3474
+ * A gradient map (colour ramp): the map is recoloured by looking its
3475
+ * {@link channel} up along U of {@link ramp}. See
3476
+ * {@link VFXBatchSettings.gradientMap}.
3477
+ */
3478
+ interface ParticleGradientMap {
3479
+ /**
3480
+ * The ramp, read along U at mid V: low values on the left. Make it without
3481
+ * mipmaps and clamped. Required: without one there is no gradient map.
3482
+ */
3483
+ ramp: BaseTexture | null;
3484
+ /**
3485
+ * The texel value the ramp is looked up by. Default `'r'`. With `'a'` the
3486
+ * ramp's alpha becomes the texel's alpha, so a soft shape can glow at its
3487
+ * fringe and stay solid at its heart; with any other channel the ramp's
3488
+ * alpha multiplies the map's.
3489
+ */
3490
+ channel: GradientMapChannel;
3491
+ }
3492
+ /** The weights a texel is dotted with to look up the ramp, per {@link GradientMapChannel}. */
3493
+ declare const GRADIENT_MAP_WEIGHTS: Readonly<Record<GradientMapChannel, readonly [number, number, number, number]>>;
3494
+ /** A complete gradient map, or undefined when unset or without a ramp. */
3495
+ declare function normalizeGradientMap(gradientMap: Partial<ParticleGradientMap> | null | undefined): ParticleGradientMap | undefined;
3496
+ /** True when both recolour the same way (or both not at all). */
3497
+ declare function gradientMapEqual(a: ParticleGradientMap | undefined, b: ParticleGradientMap | undefined): boolean;
3386
3498
  /**
3387
3499
  * Alpha erosion: the particle's alpha decides how much of its shape is left
3388
3500
  * instead of how transparent it is, so `ColorOverLife` fading alpha out
@@ -3391,32 +3503,83 @@ declare function meshRimEqual(a: MeshRim | undefined, b: MeshRim | undefined): b
3391
3503
  */
3392
3504
  interface ParticleErosion {
3393
3505
  /**
3394
- * Mask whose red channel orders what goes first, sampled with the
3395
- * particle's UV (the quad, mesh or trail UV, unscrolled). Null: the map's
3396
- * own alpha, so a soft shape shrinks from its edges.
3506
+ * Mask whose red channel orders what goes first, laid by {@link maskUV}.
3507
+ * Null: the map's own alpha, so a soft shape shrinks from its edges.
3397
3508
  */
3398
3509
  mask: BaseTexture | null;
3510
+ /**
3511
+ * How the mask is laid over the particle, see {@link TextureUV}. On UV
3512
+ * channel 1 a gradient mask wipes a whole trail or mesh however its map
3513
+ * repeats. Default channel 0, untiled, still.
3514
+ */
3515
+ maskUV: TextureUV;
3399
3516
  /** Width of the soft transition at the cut, in mask units. Default 0.05. */
3400
3517
  softness: number;
3401
3518
  /** Width of the glowing band above the cut, in mask units; 0 (default) draws none. */
3402
3519
  edgeWidth: number;
3403
3520
  /** Colour added in the edge band, linear RGB, may exceed 1. Default `[1, 1, 1]`. */
3404
3521
  edgeColor: [number, number, number];
3405
- /** Mask UV scroll, UV units per second. Default `[0, 0]`. */
3406
- maskScroll: [number, number];
3407
3522
  }
3523
+ /** {@link ParticleErosion} as given: any field may be left out, the mask's layout too. */
3524
+ type ParticleErosionOptions = Partial<Omit<ParticleErosion, 'maskUV'>> & {
3525
+ maskUV?: Partial<TextureUV>;
3526
+ };
3408
3527
  /** A complete erosion from a partial one, every field defaulted, or undefined when `erosion` is unset. */
3409
- declare function normalizeErosion(erosion: Partial<ParticleErosion> | null | undefined): ParticleErosion | undefined;
3528
+ declare function normalizeErosion(erosion: ParticleErosionOptions | null | undefined): ParticleErosion | undefined;
3410
3529
  /** True when both describe the same erosion (or both none). */
3411
3530
  declare function erosionEqual(a: ParticleErosion | undefined, b: ParticleErosion | undefined): boolean;
3412
- /** A UV scroll speed, or undefined when unset or zero. */
3413
- declare function normalizeUVScroll(scroll: ArrayLike<number> | null | undefined): [number, number] | undefined;
3414
- /** True when both scroll the same way (or both not at all). */
3415
- declare function uvScrollEqual(a: [number, number] | undefined, b: [number, number] | undefined): boolean;
3531
+ /** The distortion noise's default layout: drifting up half a repeat a second. */
3532
+ declare const UV_DISTORTION_DEFAULT_UV: Partial<TextureUV>;
3533
+ /**
3534
+ * UV distortion: the map's UV pushed about by a noise texture, for heat
3535
+ * shimmer, licking flames and breathing auras. See
3536
+ * {@link VFXBatchSettings.uvDistortion}.
3537
+ */
3538
+ interface ParticleUVDistortion {
3539
+ /**
3540
+ * Noise whose red and green channels, around 0.5, push U and V. It should
3541
+ * wrap (repeat). Required: without one there is no distortion.
3542
+ */
3543
+ map: BaseTexture | null;
3544
+ /**
3545
+ * How the noise is laid over the particle, see {@link TextureUV}. Default
3546
+ * channel 0, untiled, scrolling `[0, 0.5]`.
3547
+ */
3548
+ mapUV: TextureUV;
3549
+ /** How far the map's UV is pushed at most, in UV units. Default 0.05. */
3550
+ strength: number;
3551
+ }
3552
+ /** {@link ParticleUVDistortion} as given: any field may be left out, the noise's layout too. */
3553
+ type ParticleUVDistortionOptions = Partial<Omit<ParticleUVDistortion, 'mapUV'>> & {
3554
+ mapUV?: Partial<TextureUV>;
3555
+ };
3556
+ /** A complete distortion from a partial one, or undefined when unset or without a map. */
3557
+ declare function normalizeUVDistortion(distortion: ParticleUVDistortionOptions | null | undefined): ParticleUVDistortion | undefined;
3558
+ /** True when both describe the same distortion (or both none). */
3559
+ declare function uvDistortionEqual(a: ParticleUVDistortion | undefined, b: ParticleUVDistortion | undefined): boolean;
3560
+ /**
3561
+ * The main map's layout, or undefined when it is the identity (channel 0,
3562
+ * untiled, unmoved, still), which costs nothing in the shader.
3563
+ */
3564
+ declare function normalizeMapUV(uv: Partial<TextureUV> | null | undefined): TextureUV | undefined;
3565
+ /** True when both lay the map the same way (or both as drawn). */
3566
+ declare function mapUVEqual(a: TextureUV | undefined, b: TextureUV | undefined): boolean;
3567
+ /**
3568
+ * True when a texture effect of `settings` samples UV channel 1, see
3569
+ * {@link UVChannel}: the map, the distortion noise or an erosion mask laid
3570
+ * on it.
3571
+ */
3572
+ declare function readsUV1(settings: {
3573
+ mapUV?: TextureUV;
3574
+ uvDistortion?: ParticleUVDistortion;
3575
+ erosion?: ParticleErosion;
3576
+ }): boolean;
3416
3577
  interface StoredBatchSettings {
3417
3578
  instancingGeometry: Float32Array;
3418
3579
  instancingIndices: Uint32Array | Uint16Array;
3419
3580
  instancingUVs?: Float32Array;
3581
+ /** The mesh's second UV set, see {@link UVChannel}. */
3582
+ instancingUVs2?: Float32Array;
3420
3583
  instancingNormals?: Float32Array;
3421
3584
  renderMode: RenderMode;
3422
3585
  renderOrder: number;
@@ -3453,10 +3616,12 @@ interface StoredBatchSettings {
3453
3616
  lighting?: MeshLighting;
3454
3617
  /** Mesh particle rim, see {@link VFXBatchSettings.rim}. */
3455
3618
  rim?: MeshRim;
3456
- /** Map UV scroll, see {@link VFXBatchSettings.uvScroll}. */
3457
- uvScroll?: [number, number];
3619
+ /** The main map's layout, see {@link VFXBatchSettings.mapUV}. */
3620
+ mapUV?: TextureUV;
3621
+ /** Map UV distortion, see {@link VFXBatchSettings.uvDistortion}. */
3622
+ uvDistortion?: ParticleUVDistortion;
3458
3623
  /** Colour ramp for the map, see {@link VFXBatchSettings.gradientMap}. */
3459
- gradientMap: BaseTexture | null;
3624
+ gradientMap?: ParticleGradientMap;
3460
3625
  /** Alpha erosion, see {@link VFXBatchSettings.erosion}. */
3461
3626
  erosion?: ParticleErosion;
3462
3627
  }
@@ -3501,6 +3666,8 @@ declare abstract class VFXBatch {
3501
3666
  * and erosion mask scrolling advance by.
3502
3667
  */
3503
3668
  time: number;
3669
+ /** True when a texture effect of this batch samples UV channel 1, see {@link UVChannel}. */
3670
+ protected usesUV1(): boolean;
3504
3671
  /** Defines of the texture effects (see `shaders/chunks/surface.ts`) this batch uses. */
3505
3672
  protected surfaceDefines(): string[];
3506
3673
  /** Adds the uniforms and samplers of the texture effects this batch uses. */
@@ -3529,6 +3696,8 @@ interface VFXBatchSettings {
3529
3696
  instancingGeometry: Float32Array;
3530
3697
  instancingIndices: Uint32Array | Uint16Array;
3531
3698
  instancingUVs?: Float32Array;
3699
+ /** The mesh's second UV set, see {@link UVChannel}. */
3700
+ instancingUVs2?: Float32Array;
3532
3701
  instancingNormals?: Float32Array;
3533
3702
  renderMode: RenderMode;
3534
3703
  renderOrder: number;
@@ -3604,20 +3773,12 @@ interface VFXBatchSettings {
3604
3773
  lighting?: MeshLighting;
3605
3774
  /** Rim (Fresnel) term on mesh particles; unset draws none. See {@link MeshRim}. */
3606
3775
  rim?: MeshRim;
3607
- /**
3608
- * Scrolls the map's UV by this many UV units per second, `[u, v]`, on the
3609
- * renderer's clock. The texture should wrap; scrolling one tile of a sheet
3610
- * runs into its neighbours. Unset or zero: no scroll. Systems that differ
3611
- * are batched apart.
3612
- */
3613
- uvScroll?: [number, number];
3614
- /**
3615
- * Colour ramp the map is recoloured through: the map's red channel picks
3616
- * a colour along U of this texture, and its alpha multiplies the map's. The
3617
- * particle colour still tints the result. Unset: none. Systems that differ
3618
- * are batched apart.
3619
- */
3620
- gradientMap?: BaseTexture | null;
3776
+ /** How the main map is laid over the particle, see {@link TextureUV}. Unset: as drawn. Systems that differ are batched apart. */
3777
+ mapUV?: TextureUV;
3778
+ /** Colour ramp the map is recoloured through, see {@link ParticleGradientMap}. Unset: none. Systems that differ are batched apart. */
3779
+ gradientMap?: ParticleGradientMap;
3780
+ /** Map UV distortion by a noise texture, see {@link ParticleUVDistortion}. Unset: none. Systems that differ are batched apart. */
3781
+ uvDistortion?: ParticleUVDistortion;
3621
3782
  /** Alpha erosion (dissolve / wipe), see {@link ParticleErosion}. Unset: none. Systems that differ are batched apart. */
3622
3783
  erosion?: ParticleErosion;
3623
3784
  }
@@ -3964,6 +4125,12 @@ interface ParticleSystemParameters {
3964
4125
  instancingGeometry?: Float32Array;
3965
4126
  instancingIndices?: Uint32Array | Uint16Array;
3966
4127
  instancingUVs?: Float32Array;
4128
+ /**
4129
+ * A second UV set for the mesh (glTF `TEXCOORD_1`, Unity's `uv2`), what
4130
+ * textures on UV channel 1 read on a mesh particle; see `UVChannel`.
4131
+ * Default none: channel 1 reads the first set.
4132
+ */
4133
+ instancingUVs2?: Float32Array;
3967
4134
  instancingNormals?: Float32Array;
3968
4135
  renderMode?: RenderMode;
3969
4136
  rendererEmitterSettings?: RendererEmitterSettings;
@@ -3993,12 +4160,14 @@ interface ParticleSystemParameters {
3993
4160
  lighting?: MeshLighting;
3994
4161
  /** Rim (Fresnel) term on mesh particles, see {@link ParticleSystem.rim}. Default none. */
3995
4162
  rim?: Partial<MeshRim>;
3996
- /** Map UV scroll in UV units per second, see {@link ParticleSystem.uvScroll}. Default none. */
3997
- uvScroll?: [number, number];
4163
+ /** The main map's layout, see {@link ParticleSystem.mapUV}. Default as drawn. */
4164
+ mapUV?: Partial<TextureUV>;
3998
4165
  /** Colour ramp for the map, see {@link ParticleSystem.gradientMap}. Default none. */
3999
- gradientMap?: BaseTexture | null;
4166
+ gradientMap?: Partial<ParticleGradientMap>;
4000
4167
  /** Alpha erosion, see {@link ParticleSystem.erosion}. Default none. */
4001
- erosion?: Partial<ParticleErosion>;
4168
+ erosion?: ParticleErosionOptions;
4169
+ /** Map UV distortion, see {@link ParticleSystem.uvDistortion}. Default none. */
4170
+ uvDistortion?: ParticleUVDistortionOptions;
4002
4171
  /** Multiplier on the time the system is advanced by, see {@link ParticleSystem.playbackSpeed}. Default 1. */
4003
4172
  playbackSpeed?: number;
4004
4173
  /** What the system does while off screen, see {@link CullingMode}. Default `'always'`. */
@@ -4264,22 +4433,28 @@ declare class ParticleSystem implements IParticleSystem {
4264
4433
  get rim(): MeshRim | undefined;
4265
4434
  set rim(rim: Partial<MeshRim> | undefined);
4266
4435
  /**
4267
- * Scrolls the map's UV by `[u, v]` UV units per second on the renderer's
4268
- * clock: flowing energy, lava, a smear running along a mesh. The texture
4269
- * should wrap. Undefined (the default) or zero does not scroll. Assign a
4270
- * new array to change it. Saved with the material in the effect JSON.
4271
- */
4272
- get uvScroll(): [number, number] | undefined;
4273
- set uvScroll(scroll: [number, number] | undefined);
4274
- /**
4275
- * Colour ramp the map is recoloured through (a gradient map): the map's
4276
- * red channel picks a colour along U of this texture, whose alpha
4277
- * multiplies the map's; the particle colour still tints the result. One
4278
- * greyscale texture then serves every palette. Null (the default): none.
4279
- * Saved with the material in the effect JSON.
4280
- */
4281
- get gradientMap(): BaseTexture | null;
4282
- set gradientMap(texture: BaseTexture | null);
4436
+ * How the main map is laid over the particle, see {@link TextureUV}: its
4437
+ * UV channel, tiling and offset (Unity's Tiling / Offset) and a scroll on
4438
+ * the renderer's clock (Unreal's Panner), for flowing energy, lava or a
4439
+ * smear running along a mesh. A scrolled or tiled map should repeat. On a
4440
+ * sprite sheet (UV channel 0) the layout applies to the sheet's UV, so a
4441
+ * scroll or tiling there runs into the neighbouring cells. Undefined (the
4442
+ * default), or the identity: the map as drawn. Fields left out take their
4443
+ * defaults; assign a new object to change it. Saved with the material in
4444
+ * the effect JSON.
4445
+ */
4446
+ get mapUV(): TextureUV | undefined;
4447
+ set mapUV(uv: Partial<TextureUV> | undefined);
4448
+ /**
4449
+ * Colour ramp the map is recoloured through (a gradient map), see
4450
+ * {@link ParticleGradientMap}: a channel of the map, or its luminance,
4451
+ * picks a colour along U of the ramp; the particle colour still tints the
4452
+ * result. One greyscale or channel-packed texture then serves every
4453
+ * palette. Undefined (the default), or without a ramp: none. Assign a new
4454
+ * object to change it. Saved with the material in the effect JSON.
4455
+ */
4456
+ get gradientMap(): ParticleGradientMap | undefined;
4457
+ set gradientMap(gradientMap: Partial<ParticleGradientMap> | undefined);
4283
4458
  /**
4284
4459
  * Alpha erosion, see {@link ParticleErosion}: the particle's alpha decides
4285
4460
  * how much of the shape is left rather than how transparent it is, so a
@@ -4290,7 +4465,16 @@ declare class ParticleSystem implements IParticleSystem {
4290
4465
  * Saved with the material in the effect JSON.
4291
4466
  */
4292
4467
  get erosion(): ParticleErosion | undefined;
4293
- set erosion(erosion: Partial<ParticleErosion> | undefined);
4468
+ set erosion(erosion: ParticleErosionOptions | undefined);
4469
+ /**
4470
+ * Map UV distortion, see {@link ParticleUVDistortion}: a scrolling noise
4471
+ * texture pushes the map's UV about, for heat shimmer and licking,
4472
+ * breathing shapes. Undefined (the default), or without a map: none.
4473
+ * Fields left out take their defaults; assign a new object to change it.
4474
+ * Saved with the material in the effect JSON.
4475
+ */
4476
+ get uvDistortion(): ParticleUVDistortion | undefined;
4477
+ set uvDistortion(distortion: ParticleUVDistortionOptions | undefined);
4294
4478
  /**
4295
4479
  * The emitter's world scale per axis, measured with {@link motionScale}
4296
4480
  * before every step; what `'hierarchy'` multiplies start speeds by. Taken
@@ -4311,7 +4495,19 @@ declare class ParticleSystem implements IParticleSystem {
4311
4495
  get softFarFade(): number;
4312
4496
  set softFarFade(v: number);
4313
4497
  get instancingGeometry(): Float32Array;
4498
+ /**
4499
+ * The mesh particles' positions. A new geometry with a different vertex
4500
+ * count drops UV sets and normals that no longer fit it: the first UV set
4501
+ * falls back to zeros, the second to none, the normals to +Z. Assign {@link instancingUVs} and
4502
+ * {@link instancingUVs2} after it.
4503
+ */
4314
4504
  set instancingGeometry(geometry: Float32Array);
4505
+ /** The mesh particles' first UV set, two values per vertex. */
4506
+ get instancingUVs(): Float32Array;
4507
+ set instancingUVs(uvs: Float32Array);
4508
+ /** The mesh particles' second UV set, read by textures on UV channel 1; see `UVChannel`. */
4509
+ get instancingUVs2(): Float32Array | undefined;
4510
+ set instancingUVs2(uvs: Float32Array | undefined);
4315
4511
  get blending(): number;
4316
4512
  set blending(blending: number);
4317
4513
  get renderMode(): RenderMode;
@@ -4479,6 +4675,18 @@ declare class ParticleSystem implements IParticleSystem {
4479
4675
  * in the effect JSON: it is where this instance is aimed at runtime.
4480
4676
  */
4481
4677
  beamEnd?: BeamEnd;
4678
+ /**
4679
+ * Multiplies every particle's colour, alpha included, as it is drawn:
4680
+ * a colour or a fade driven from code for this instance (Unity's custom
4681
+ * per-instance data, Unreal's user parameters). With {@link erosion},
4682
+ * alpha is the erosion level, so this wipes the shape in and out. The
4683
+ * particles' own colours are untouched, so clearing it restores them, and
4684
+ * systems with different tints still batch together. Under additive
4685
+ * (`ALPHA_ONEONE`) or premultiplied blending, which ignore alpha, fade
4686
+ * with the colour instead, or with erosion on. Unset (the default): none.
4687
+ * Not saved in the effect JSON; copied by {@link clone}.
4688
+ */
4689
+ tint?: Vector4;
4482
4690
  private readonly beamEndScratch;
4483
4691
  /** The world position of {@link beamEnd} into `out`; false when it is unset. */
4484
4692
  getBeamEnd(out: Vector3): boolean;
@@ -4577,6 +4785,7 @@ declare class ParticleSystem implements IParticleSystem {
4577
4785
  [uuid: string]: Behavior;
4578
4786
  }, scene?: Scene): ParticleSystem;
4579
4787
  private static nextSerializationId;
4788
+ /** Normals facing +Z, one array per geometry so systems sharing it still batch together. */
4580
4789
  private static createFallbackNormals;
4581
4790
  private toRendererSettingsJSON;
4582
4791
  private ensureGeometryMeta;
@@ -4890,6 +5099,13 @@ declare class SpriteBatch extends VFXBatch {
4890
5099
  private velocityVB?;
4891
5100
  constructor(settings: VFXBatchSettings, scene: Scene);
4892
5101
  setupBuffers(): void;
5102
+ /**
5103
+ * True when a mesh batch reads UV channel 1 and has a second UV set to
5104
+ * read it from, two values per vertex. A set of any other length is left
5105
+ * out with a warning, and channel 1 then reads the first set.
5106
+ */
5107
+ private warnedUV2;
5108
+ private meshUV2;
4893
5109
  /** Releases the instance vertex buffers so a resize does not leak GPU memory. */
4894
5110
  private disposeExpandableBuffers;
4895
5111
  private buildExpandableBuffers;
@@ -4956,6 +5172,8 @@ declare class SpriteBatch extends VFXBatch {
4956
5172
  private writeBeams;
4957
5173
  /** The quads that take a pivot and flip: every billboard kind, stretched included, but not meshes or beams. */
4958
5174
  private static takesPivotAndFlip;
5175
+ /** Multiplies `count` RGBA colours starting at `base` by a system's {@link ParticleSystem.tint}. */
5176
+ private static applyTint;
4959
5177
  /**
4960
5178
  * Negates the size of each flipped particle along the axes it flips on,
4961
5179
  * starting at `base` in `sizes`. The billboard shader scales the quad by
@@ -5025,6 +5243,8 @@ declare class TrailBatch extends VFXBatch {
5025
5243
  private previousBuffer;
5026
5244
  private nextBuffer;
5027
5245
  private uvBuffer;
5246
+ /** UV channel 1: along the trail and across it, without the sheet's cell; only when a texture reads it. */
5247
+ private uv1Buffer;
5028
5248
  private sideBuffer;
5029
5249
  private widthBuffer;
5030
5250
  private colorBuffer;
@@ -5053,6 +5273,12 @@ declare class TrailBatch extends VFXBatch {
5053
5273
  * frame costs a matrix compose per system; checking the transform cache
5054
5274
  * first makes a still emitter free.
5055
5275
  */
5276
+ /**
5277
+ * Writes a swept ribbon's vertex pair at `pi`: the sample at (x, y, z)
5278
+ * pushed `half` widths along its side (sx, sy, sz) one way for the first
5279
+ * vertex and the other way for the second.
5280
+ */
5281
+ private writeSweptPair;
5056
5282
  private static ensureWorldMatrix;
5057
5283
  update(): void;
5058
5284
  /**
@@ -5082,5 +5308,5 @@ declare class TrailBatch extends VFXBatch {
5082
5308
  dispose(): void;
5083
5309
  }
5084
5310
 
5085
- export { ApplyCollision, ApplyForce, ApplySequences, AxisAngleGenerator, BatchedParticleRenderer, BatchedRenderer, BehaviorFromJSON, BehaviorTypes, Bezier, BoxEmitFrom, BoxEmitter, ChangeEmitDirection, CircleEmitter, ColorBySpeed, ColorGeneratorFromJSON, ColorOverLife, ColorRange, ConeEmitter, ConstantColor, ConstantValue, DEG2RAD, DonutEmitter, EdgeEmitter, EffectPool, EmitSubParticleSystem, EmitterFromJSON, EmitterMode, EmitterShapes, Euler, EulerGenerator, ForceOverLife, FrameOverLife, GeneratorFromJSON, Gradient, GravityForce, GridEmitter, HemisphereEmitter, InheritVelocity, IntervalValue, LimitSpeedOverLife, MathUtils, Matrix3, Matrix4, MeshSurfaceEmitter, MeshSurfaceEmitterPlugin, NodeParticle, Noise, OrbitOverLife, ParticleEmitter, ParticleMeshPhysicsMaterial, ParticleMeshStandardMaterial, ParticleStore, ParticleSystem, PiecewiseBezier, PiecewiseFunction, Plugins, PointEmitter, QuarksLoader, QuarksPrefab, QuarksUtil, Quaternion, QuaternionView, RAD2DEG, RandomColor, RandomColorBetweenGradient, RandomQuatGenerator, RecordState, RectangleEmitter, RenderMode, Rotation3DOverLife, RotationBySpeed, RotationGeneratorFromJSON, RotationOverLife, SequencerFromJSON, ShapeTransform, SizeBySpeed, SizeOverLife, SpeedOverLife, SphereEmitter, SpriteBatch, SpriteParticle, SubEmitterInheritMask, SubParticleEmitMode, TextureSequencer, TrailBatch, TrailParticle, TurbulenceField, VFXBatch, ValueGeneratorFromJSON, Vector2, Vector3, Vector3Function, Vector3GeneratorFromJSON, Vector3View, Vector4, Vector4View, VelocityOverLife, WebGLCoordinateSystem, WebGPUCoordinateSystem, WidthOverLength, cacheEnvAtlas, ceilPowerOfTwo, clamp, createEnvAtlasFromFaceUrls, createSeededRandom, cubeFaceUrls, damp, defaultMeshLighting, degToRad, denormalize, ensureEnvAtlasFromCube, erosionEqual, euclideanModulo, floorPowerOfTwo, generateUUID, getCachedEnvAtlas, getPhysicsResolver, getRandomSource, getRegisteredShaderChunks, getShaderChunk, getValueFromEmitterMode, inverseLerp, isPowerOfTwo, lerp, loadPlugin, _default$7 as localParticlePhysicsVertShader, _default$6 as localParticleVertShader, mapLinear, meshRimEqual, normalize, normalizeErosion, normalizeMeshRim, normalizeUVScroll, _default$5 as particleFragShader, _default$4 as particlePhysicsFragShader, _default$3 as particleVertShader, pingpong, planBehaviorFusion, radToDeg, randFloat, randFloatSpread, randInt, random, registerShaderChunks, seededRandom, setPhysicsResolver, setQuaternionFromProperEuler, setRandomSource, smootherstep, smoothstep, _default$2 as stretchedBillboardVertShader, subEmitterInheritMask, _default$1 as trailFragShader, _default as trailVertShader, unloadPlugin, uvScrollEqual, withRandomSource };
5086
- export type { AdaptivePerformanceOptions, AdaptivePerformanceState, AnimationData, BabylonMetaData, BabylonParticleMaterialParameters, BeamEnd, Behavior, BehaviorPlugin, BillBoardSettings, BoxEmitterParameters, BurstParameters, BurstParametersJSON, CircleEmitterParameters, ColorGenerator, ConeEmitterParameters, Constructable, CullingMode, DonutEmitterParameters, EdgeEmitterParameters, EffectPoolOptions, EmissionState, EmitterShape, EmitterShapePlugin, EulerOrder, FieldType, FrameOverLifeOptions, FunctionColorGenerator, FunctionJSON, FunctionValueGenerator, FusedPass, FusionStep, GeneratorMemory, GridEmitterParameters, HemisphereEmitterParameters, IAnimationData, IEmitter, IParticle, IParticleSystem, IPrefab, InheritVelocityMode, JsonMetaData, MeshLighting, MeshLightingSettings, MeshRim, MeshSettings, ParameterPair, ParameterType, Particle, ParticleErosion, ParticleSystemEvent, ParticleSystemEventType, ParticleSystemJSONParameters, ParticleSystemParameters, Plugin, QuarksBatchLoadOptions, QuarksJSONLoadEntry, QuarksLoaderOptions, QuarksResourceKind, QuarksResourceResolver, QuarksTimelineClip, RandomSource, RectangleEmitterParameters, RendererEmitterSettings, Resource, RotationGenerator, ScalingMode, Sequencer, SerializationOptions, ShapeJSON, ShapeTransformJSON, SortMode, SphereEmitterParameters, StoredBatchSettings, StretchedBillBoardSettings, SubEmitterInheritance, TrailSettings, VFXBatchSettings, ValueGenerator, Vector3Generator, VelocityOverLifeSpace };
5311
+ export { ApplyCollision, ApplyForce, ApplySequences, AxisAngleGenerator, BatchedParticleRenderer, BatchedRenderer, BehaviorFromJSON, BehaviorTypes, Bezier, BoxEmitFrom, BoxEmitter, ChangeEmitDirection, CircleEmitter, ColorBySpeed, ColorGeneratorFromJSON, ColorOverLife, ColorRange, ConeEmitter, ConstantColor, ConstantValue, DEG2RAD, DonutEmitter, EdgeEmitter, EffectPool, EmitSubParticleSystem, EmitterFromJSON, EmitterMode, EmitterShapes, Euler, EulerGenerator, ForceOverLife, FrameOverLife, GRADIENT_MAP_WEIGHTS, GeneratorFromJSON, Gradient, GravityForce, GridEmitter, HemisphereEmitter, InheritVelocity, IntervalValue, LimitSpeedOverLife, MathUtils, Matrix3, Matrix4, MeshSurfaceEmitter, MeshSurfaceEmitterPlugin, NodeParticle, Noise, OrbitOverLife, ParticleEmitter, ParticleMeshPhysicsMaterial, ParticleMeshStandardMaterial, ParticleStore, ParticleSystem, PiecewiseBezier, PiecewiseFunction, Plugins, PointEmitter, QuarksLoader, QuarksPrefab, QuarksUtil, Quaternion, QuaternionView, RAD2DEG, RandomColor, RandomColorBetweenGradient, RandomQuatGenerator, RecordState, RectangleEmitter, RenderMode, Rotation3DOverLife, RotationBySpeed, RotationGeneratorFromJSON, RotationOverLife, SequencerFromJSON, ShapeTransform, SizeBySpeed, SizeOverLife, SpeedOverLife, SphereEmitter, SpriteBatch, SpriteParticle, SubEmitterInheritMask, SubParticleEmitMode, TextureSequencer, TrailBatch, TrailParticle, TurbulenceField, UV_DISTORTION_DEFAULT_UV, VFXBatch, ValueGeneratorFromJSON, Vector2, Vector3, Vector3Function, Vector3GeneratorFromJSON, Vector3View, Vector4, Vector4View, VelocityOverLife, WebGLCoordinateSystem, WebGPUCoordinateSystem, WidthOverLength, cacheEnvAtlas, ceilPowerOfTwo, clamp, createEnvAtlasFromFaceUrls, createSeededRandom, cubeFaceUrls, damp, defaultMeshLighting, degToRad, denormalize, ensureEnvAtlasFromCube, erosionEqual, euclideanModulo, floorPowerOfTwo, generateUUID, getCachedEnvAtlas, getPhysicsResolver, getRandomSource, getRegisteredShaderChunks, getShaderChunk, getValueFromEmitterMode, gradientMapEqual, inverseLerp, isPowerOfTwo, lerp, loadPlugin, _default$7 as localParticlePhysicsVertShader, _default$6 as localParticleVertShader, mapLinear, mapUVEqual, meshRimEqual, normalize, normalizeErosion, normalizeGradientMap, normalizeMapUV, normalizeMeshRim, normalizeTextureUV, normalizeUVDistortion, _default$5 as particleFragShader, _default$4 as particlePhysicsFragShader, _default$3 as particleVertShader, pingpong, planBehaviorFusion, radToDeg, randFloat, randFloatSpread, randInt, random, readsUV1, registerShaderChunks, seededRandom, setPhysicsResolver, setQuaternionFromProperEuler, setRandomSource, smootherstep, smoothstep, _default$2 as stretchedBillboardVertShader, subEmitterInheritMask, textureUVEqual, textureUVToJSON, _default$1 as trailFragShader, _default as trailVertShader, unloadPlugin, uvDistortionEqual, withRandomSource };
5312
+ export type { AdaptivePerformanceOptions, AdaptivePerformanceState, AnimationData, BabylonMetaData, BabylonParticleMaterialParameters, BeamEnd, Behavior, BehaviorPlugin, BillBoardSettings, BoxEmitterParameters, BurstParameters, BurstParametersJSON, CircleEmitterParameters, ColorGenerator, ConeEmitterParameters, Constructable, CullingMode, DonutEmitterParameters, EdgeEmitterParameters, EffectPoolOptions, EmissionState, EmitterShape, EmitterShapePlugin, EulerOrder, FieldType, FrameOverLifeOptions, FunctionColorGenerator, FunctionJSON, FunctionValueGenerator, FusedPass, FusionStep, GeneratorMemory, GradientMapChannel, GridEmitterParameters, HemisphereEmitterParameters, IAnimationData, IEmitter, IParticle, IParticleSystem, IPrefab, InheritVelocityMode, JsonMetaData, MeshLighting, MeshLightingSettings, MeshRim, MeshSettings, ParameterPair, ParameterType, Particle, ParticleErosion, ParticleErosionOptions, ParticleGradientMap, ParticleSystemEvent, ParticleSystemEventType, ParticleSystemJSONParameters, ParticleSystemParameters, ParticleUVDistortion, ParticleUVDistortionOptions, Plugin, QuarksBatchLoadOptions, QuarksJSONLoadEntry, QuarksLoaderOptions, QuarksResourceKind, QuarksResourceResolver, QuarksTimelineClip, RandomSource, RectangleEmitterParameters, RendererEmitterSettings, Resource, RotationGenerator, ScalingMode, Sequencer, SerializationOptions, ShapeJSON, ShapeTransformJSON, SortMode, SphereEmitterParameters, StoredBatchSettings, StretchedBillBoardSettings, SubEmitterInheritance, TextureUV, TrailSettings, UVChannel, VFXBatchSettings, ValueGenerator, Vector3Generator, VelocityOverLifeSpace };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "babylon.quarks",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "description": "A High-Performance Particle System for Babylon.js",
5
5
  "type": "module",
6
6
  "types": "./dist/types/index.d.ts",
@@ -12,15 +12,21 @@ import {TrailBatch} from './TrailBatch';
12
12
  import {
13
13
  defaultMeshLighting,
14
14
  erosionEqual,
15
+ gradientMapEqual,
16
+ mapUVEqual,
15
17
  MeshLighting,
16
18
  MeshLightingSettings,
17
19
  MeshRim,
18
20
  meshRimEqual,
19
21
  ParticleErosion,
22
+ ParticleGradientMap,
23
+ ParticleUVDistortion,
24
+ readsUV1,
20
25
  RenderMode,
21
26
  SortMode,
22
27
  StoredBatchSettings,
23
- uvScrollEqual,
28
+ TextureUV,
29
+ uvDistortionEqual,
24
30
  VFXBatch,
25
31
  } from './VFXBatch';
26
32
 
@@ -28,6 +34,8 @@ export interface VFXBatchSettings {
28
34
  instancingGeometry: Float32Array;
29
35
  instancingIndices: Uint32Array | Uint16Array;
30
36
  instancingUVs?: Float32Array;
37
+ /** The mesh's second UV set, see {@link UVChannel}. */
38
+ instancingUVs2?: Float32Array;
31
39
  instancingNormals?: Float32Array;
32
40
  renderMode: RenderMode;
33
41
  renderOrder: number;
@@ -103,20 +111,12 @@ export interface VFXBatchSettings {
103
111
  lighting?: MeshLighting;
104
112
  /** Rim (Fresnel) term on mesh particles; unset draws none. See {@link MeshRim}. */
105
113
  rim?: MeshRim;
106
- /**
107
- * Scrolls the map's UV by this many UV units per second, `[u, v]`, on the
108
- * renderer's clock. The texture should wrap; scrolling one tile of a sheet
109
- * runs into its neighbours. Unset or zero: no scroll. Systems that differ
110
- * are batched apart.
111
- */
112
- uvScroll?: [number, number];
113
- /**
114
- * Colour ramp the map is recoloured through: the map's red channel picks
115
- * a colour along U of this texture, and its alpha multiplies the map's. The
116
- * particle colour still tints the result. Unset: none. Systems that differ
117
- * are batched apart.
118
- */
119
- gradientMap?: BaseTexture | null;
114
+ /** How the main map is laid over the particle, see {@link TextureUV}. Unset: as drawn. Systems that differ are batched apart. */
115
+ mapUV?: TextureUV;
116
+ /** Colour ramp the map is recoloured through, see {@link ParticleGradientMap}. Unset: none. Systems that differ are batched apart. */
117
+ gradientMap?: ParticleGradientMap;
118
+ /** Map UV distortion by a noise texture, see {@link ParticleUVDistortion}. Unset: none. Systems that differ are batched apart. */
119
+ uvDistortion?: ParticleUVDistortion;
120
120
  /** Alpha erosion (dissolve / wipe), see {@link ParticleErosion}. Unset: none. Systems that differ are batched apart. */
121
121
  erosion?: ParticleErosion;
122
122
  }
@@ -323,6 +323,11 @@ export class BatchedRenderer extends TransformNode {
323
323
  a.uTileCount === b.uTileCount &&
324
324
  a.vTileCount === b.vTileCount &&
325
325
  a.instancingGeometry === b.instancingGeometry &&
326
+ // Trails draw their own strip and read none of the instanced geometry's UVs.
327
+ (a.renderMode === RenderMode.Trail || a.instancingUVs === b.instancingUVs) &&
328
+ // Normals, and the second UV set when read, only matter to meshes.
329
+ (a.renderMode !== RenderMode.Mesh || a.instancingNormals === b.instancingNormals) &&
330
+ (a.renderMode !== RenderMode.Mesh || !readsUV1(a) || a.instancingUVs2 === b.instancingUVs2) &&
326
331
  a.renderOrder === b.renderOrder &&
327
332
  a.layerMask === b.layerMask &&
328
333
  a.renderingGroupId === b.renderingGroupId &&
@@ -333,8 +338,9 @@ export class BatchedRenderer extends TransformNode {
333
338
  a.maxParticleSize === (b.maxParticleSize ?? Infinity) &&
334
339
  (a.lighting ?? 'fixed') === (b.lighting ?? 'fixed') &&
335
340
  meshRimEqual(a.rim, b.rim) &&
336
- uvScrollEqual(a.uvScroll, b.uvScroll) &&
337
- a.gradientMap === (b.gradientMap ?? null) &&
341
+ mapUVEqual(a.mapUV, b.mapUV) &&
342
+ uvDistortionEqual(a.uvDistortion, b.uvDistortion) &&
343
+ gradientMapEqual(a.gradientMap, b.gradientMap) &&
338
344
  erosionEqual(a.erosion, b.erosion)
339
345
  );
340
346
  }