babylon.quarks 0.28.0 → 0.29.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +160 -0
  2. package/dist/babylon.quarks.cjs +1 -1
  3. package/dist/babylon.quarks.cjs.map +1 -1
  4. package/dist/babylon.quarks.esm.js +1 -1
  5. package/dist/babylon.quarks.esm.js.map +1 -1
  6. package/dist/babylon.quarks.umd.min.js +1 -1
  7. package/dist/babylon.quarks.umd.min.js.map +1 -1
  8. package/dist/types/index.d.cts +602 -190
  9. package/dist/types/index.d.ts +602 -190
  10. package/package.json +1 -1
  11. package/src/BatchedRenderer.ts +13 -1
  12. package/src/EffectPool.ts +5 -4
  13. package/src/ParticleEmitter.ts +89 -24
  14. package/src/ParticleSystem.ts +213 -30
  15. package/src/QuarksLoader.ts +9 -0
  16. package/src/QuarksSerializer.ts +1 -1
  17. package/src/QuarksUtil.ts +24 -2
  18. package/src/SpriteBatch.ts +3 -0
  19. package/src/TrailBatch.ts +8 -1
  20. package/src/VFXBatch.ts +112 -0
  21. package/src/batchKey.ts +2 -0
  22. package/src/batchSettings.ts +2 -0
  23. package/src/index.ts +2 -0
  24. package/src/shaderProgram.ts +103 -0
  25. package/src/shaderVariants.ts +102 -5
  26. package/src/shaders/chunks/blend.ts +15 -7
  27. package/src/shaders/chunks/imageProcessing.ts +143 -0
  28. package/src/shaders/particle_frag.glsl.ts +2 -0
  29. package/src/shaders/particle_frag.wgsl.ts +2 -0
  30. package/src/shaders/particle_physics_frag.glsl.ts +2 -0
  31. package/src/shaders/particle_physics_frag.wgsl.ts +2 -0
  32. package/src/shaders/trail_frag.glsl.ts +2 -0
  33. package/src/shaders/trail_frag.wgsl.ts +2 -0
  34. package/src/system/EmissionController.ts +21 -16
  35. package/src/system/ParticleSpawner.ts +96 -19
  36. package/src/system/integrate.ts +61 -4
  37. package/src/system/normalize.ts +28 -1
  38. package/src/system/settingsSchema.ts +25 -7
  39. package/src/system/types.ts +83 -14
@@ -10,6 +10,7 @@ import { ShaderMaterial } from '@babylonjs/core/Materials/shaderMaterial.js';
10
10
  import { Mesh } from '@babylonjs/core/Meshes/mesh.js';
11
11
  import { Node } from '@babylonjs/core/node.js';
12
12
  import { Color3 } from '@babylonjs/core/Maths/math.color.js';
13
+ import { IImageProcessingConfigurationDefines } from '@babylonjs/core/Materials/imageProcessingConfiguration.defines.js';
13
14
 
14
15
  /**
15
16
  * A two-component vector (a three.js `Vector2` port), used for 2D quantities such as texture
@@ -1783,8 +1784,17 @@ interface PiecewiseBezierJSON {
1783
1784
  /** The curve's segments, each with the time it starts at. */
1784
1785
  functions: PiecewiseBezierSegmentJSON[];
1785
1786
  }
1787
+ /** A {@link RandomBetweenCurves}. */
1788
+ interface RandomBetweenCurvesJSON {
1789
+ /** The generator's type. */
1790
+ type: 'RandomBetweenCurves';
1791
+ /** One bound. */
1792
+ curve1: PiecewiseBezierJSON;
1793
+ /** The other bound. */
1794
+ curve2: PiecewiseBezierJSON;
1795
+ }
1786
1796
  /** The JSON of a value generator. */
1787
- type ValueGeneratorJSON = ConstantValueJSON | IntervalValueJSON | PiecewiseBezierJSON;
1797
+ type ValueGeneratorJSON = ConstantValueJSON | IntervalValueJSON | PiecewiseBezierJSON | RandomBetweenCurvesJSON;
1788
1798
  /** A {@link ConstantColor}. */
1789
1799
  interface ConstantColorJSON {
1790
1800
  /** The generator's type. */
@@ -1958,7 +1968,7 @@ type FunctionJSON = ValueGeneratorJSON | ColorGeneratorJSON | RotationGeneratorJ
1958
1968
  * - **Stateless / deterministic** (`ConstantValue`, `PiecewiseBezier`,
1959
1969
  * `Gradient`, `RandomColor`) — `startGen` is a no-op; `genValue` derives
1960
1970
  * output from inputs (`t`, params) alone.
1961
- * - **Sample-once stochastic** (`IntervalValue`, `ColorRange`,
1971
+ * - **Sample-once stochastic** (`IntervalValue`, `RandomBetweenCurves`, `ColorRange`,
1962
1972
  * `RandomColorBetweenGradient`, `RandomQuatGenerator`) — `startGen` pushes
1963
1973
  * one random sample into memory; `genValue` reads it. This is what keeps a
1964
1974
  * given particle's "random" startSize/color/rotation fixed for its life.
@@ -1973,6 +1983,8 @@ type FunctionJSON = ValueGeneratorJSON | ColorGeneratorJSON | RotationGeneratorJ
1973
1983
  * - `indexCount` lives on the generator (shared across particles), not on
1974
1984
  * memory. It is overwritten on every spawn; that is safe because each
1975
1985
  * `genValue` call during a spawn happens before the next spawn's `startGen`.
1986
+ * So a stochastic instance must not be shared between two settings or two
1987
+ * systems: give each its own, by `clone()`.
1976
1988
  * - The values stored in memory are not aliased — each particle's memory is
1977
1989
  * its own array, so two particles can hold different samples at the same
1978
1990
  * slot without interference.
@@ -2528,6 +2540,55 @@ declare class PiecewiseBezier extends PiecewiseFunction<Bezier> implements Funct
2528
2540
  startGen(memory: GeneratorMemory): void;
2529
2541
  }
2530
2542
 
2543
+ /**
2544
+ * A number over time between two curves, at a mix rolled once per particle and kept for its life
2545
+ * (Unity's Random Between Two Curves): each particle follows its own curve, the same fraction of the
2546
+ * way from {@link RandomBetweenCurves.curve1} to {@link RandomBetweenCurves.curve2} at every `t`.
2547
+ * Where it drives a start value, `t` is the system's cycle, as for any curve there.
2548
+ *
2549
+ * Where a system-level setting takes it (emission over time or distance, a burst's count, a shape's
2550
+ * speed, Noise's scroll speed), the mix is rolled once per play rather than at every emission step,
2551
+ * as a random range is there.
2552
+ *
2553
+ * Like every random generator, an instance holds the memory slot of its mix: give each setting its
2554
+ * own instance, and {@link RandomBetweenCurves.clone} one to reuse it.
2555
+ */
2556
+ declare class RandomBetweenCurves implements FunctionValueGenerator {
2557
+ curve1: PiecewiseBezier;
2558
+ curve2: PiecewiseBezier;
2559
+ /** Always `'function'`: the number depends on `t`. */
2560
+ readonly type: "function";
2561
+ /**
2562
+ * The slot of {@link GeneratorMemory} the mix lives in; -1 before the first roll.
2563
+ * @internal
2564
+ */
2565
+ indexCount: number;
2566
+ /**
2567
+ * @param curve1 - One bound (Unity's lower curve).
2568
+ * @param curve2 - The other bound (Unity's upper curve).
2569
+ */
2570
+ constructor(curve1: PiecewiseBezier, curve2: PiecewiseBezier);
2571
+ /** Rolls the particle's mix between the curves into a new slot of `memory`. */
2572
+ startGen(memory: GeneratorMemory): void;
2573
+ /** Has both curves sample their tables, as a single curve does; see {@link PiecewiseBezier.refreshTable}. */
2574
+ refreshTable(): void;
2575
+ /**
2576
+ * The particle's number at `t`; rolls its mix first if {@link RandomBetweenCurves.startGen}
2577
+ * never has. A particle that was not rolled for this instance (one alive when the setting was
2578
+ * replaced) takes the midway curve rather than a missing mix.
2579
+ */
2580
+ genValue(memory: GeneratorMemory, t?: number): number;
2581
+ /** The JSON form, `{type: 'RandomBetweenCurves', curve1, curve2}`. */
2582
+ toJSON(): RandomBetweenCurvesJSON;
2583
+ /**
2584
+ * Reads {@link RandomBetweenCurves.toJSON} output. A bound that is missing or not a curve warns
2585
+ * (throws when strict) and reads as a flat 0 curve, so one bad value does not cost the effect.
2586
+ */
2587
+ static fromJSON(json: RandomBetweenCurvesJSON): RandomBetweenCurves;
2588
+ /** A copy with copies of both curves. */
2589
+ clone(): RandomBetweenCurves;
2590
+ }
2591
+
2531
2592
  /**
2532
2593
  * A uniformly random rotation, rolled once per particle and kept for its life. Call
2533
2594
  * {@link RandomQuatGenerator.startGen} with each particle's memory when it spawns.
@@ -2976,7 +3037,10 @@ interface IEmitter {
2976
3037
  uuid: string;
2977
3038
  /** Whether the node, and so the system, is visible. */
2978
3039
  visible: boolean;
2979
- /** The node's world matrix. */
3040
+ /**
3041
+ * The matrix the system simulates and draws in: the node's world matrix, with the scale its
3042
+ * scaling mode applies on each axis (babylon.quarks' `ScalingMode`).
3043
+ */
2980
3044
  matrixWorld: Matrix4;
2981
3045
  }
2982
3046
  /**
@@ -3024,9 +3088,9 @@ interface IParticleSystem {
3024
3088
  */
3025
3089
  simulationStep?: number;
3026
3090
  /**
3027
- * What world-space forces and speed limits are multiplied by: the
3028
- * emitter's world scale when the system scales its motion with it (a
3029
- * world-space system in `'hierarchy'` scaling mode), 1 or undefined
3091
+ * What world-space forces and speed limits are multiplied by: the mean
3092
+ * scale of {@link IEmitter.matrixWorld}'s axes for a world-space system,
3093
+ * which carries what its scaling mode scales motion by; 1 or undefined
3030
3094
  * otherwise.
3031
3095
  * @type {number}
3032
3096
  */
@@ -3044,10 +3108,22 @@ interface IParticleSystem {
3044
3108
  */
3045
3109
  readonly isDisposed?: boolean;
3046
3110
  /**
3047
- * Whether the ParticleSystem should be automatically disposed when it finishes emitting particles.
3048
- * @type {string}
3111
+ * Whether the system is disposed once it has finished.
3112
+ * @deprecated Read {@link IParticleSystem.stopAction}: true is `'destroy'`.
3113
+ * @type {boolean}
3049
3114
  */
3050
3115
  autoDestroy: boolean;
3116
+ /**
3117
+ * What the system does once it has finished, as Unity's Stop Action: nothing (`'none'`),
3118
+ * disable its emitter (`'disable'`) or dispose itself (`'destroy'`). Undefined is `'none'`.
3119
+ */
3120
+ stopAction?: 'none' | 'disable' | 'destroy';
3121
+ /**
3122
+ * Whether particles outlive their lifetime: held or looped at the end of it until new ones
3123
+ * replace them, as with Unity's Ring Buffer Mode on a full system. A Death sub emitter does
3124
+ * not fire for them, since they do not die.
3125
+ */
3126
+ readonly ringBufferActive?: boolean;
3051
3127
  /**
3052
3128
  * Whether the system is in world space.
3053
3129
  * @type {boolean}
@@ -3097,8 +3173,11 @@ interface IParticleSystem {
3097
3173
  paused: boolean;
3098
3174
  /** True after `endEmit()` — emission window closed (non-looping duration elapsed). */
3099
3175
  readonly isEmitEnded: boolean;
3100
- /** Whether more particles can still spawn (bursts, rate, distance). */
3101
- hasPendingEmission(): boolean;
3176
+ /**
3177
+ * Whether more particles can still spawn (bursts, rate, distance): from the system's own
3178
+ * emission, or with `state` from one a sub emitter runs into it for a parent particle.
3179
+ */
3180
+ hasPendingEmission(state?: EmissionState): boolean;
3102
3181
  /** Non-looping system with no live particles and no pending emission. */
3103
3182
  isFinished(): boolean;
3104
3183
  /** Freezes the system where it is until {@link IParticleSystem.play}. */
@@ -3749,10 +3828,11 @@ interface Constructable<T> {
3749
3828
  /**
3750
3829
  * The kind of a field an editor shows for a shape or behavior: a number, an angle (`'radian'`), a
3751
3830
  * vector, a generator of some kind, a reference to a mesh or system, an enum (`'emitterMode'`,
3752
- * `'boxEmitFrom'`), a shape's local transform (`'shapeTransform'`), the properties a sub emitter
3753
- * inherits (`'subEmitterInherit'`, a list of `SubEmitterInheritance`), and so on.
3831
+ * `'boxEmitFrom'`, `'coneEmitFrom'`, `'gridSampling'`), a shape's local transform
3832
+ * (`'shapeTransform'`), the properties a sub emitter inherits (`'subEmitterInherit'`, a list of
3833
+ * `SubEmitterInheritance`), and so on.
3754
3834
  */
3755
- type FieldType = 'vec3' | 'value' | 'number' | 'range' | 'colorFunc' | 'valueFunc' | 'rotationFunc' | 'radian' | 'mesh' | 'particleSystem' | 'boolean' | 'string' | 'geometry' | 'emitterMode' | 'boxEmitFrom' | 'subEmitterInherit' | 'shapeTransform' | 'vec3Func';
3835
+ type FieldType = 'vec3' | 'value' | 'number' | 'range' | 'colorFunc' | 'valueFunc' | 'rotationFunc' | 'radian' | 'mesh' | 'particleSystem' | 'boolean' | 'string' | 'geometry' | 'emitterMode' | 'boxEmitFrom' | 'coneEmitFrom' | 'gridSampling' | 'subEmitterInherit' | 'shapeTransform' | 'vec3Func';
3756
3836
  /** A {@link FieldType}, or `'self'` for a field that refers to the system itself. */
3757
3837
  type ParameterType = FieldType | 'self';
3758
3838
  /**
@@ -3972,7 +4052,7 @@ declare class EmitterFrame {
3972
4052
  readonly position: Vector3;
3973
4053
  /** The emitter's world rotation. */
3974
4054
  readonly quaternion: Quaternion;
3975
- /** The emitter's world scale per axis. */
4055
+ /** The scale per axis of the emitter's `matrixWorld`, which its scaling mode sets. */
3976
4056
  readonly scale: Vector3;
3977
4057
  /** Inverse of {@link quaternion}. */
3978
4058
  readonly quaternionInverse: Quaternion;
@@ -3986,6 +4066,11 @@ declare class EmitterFrame {
3986
4066
  * true. A vector already in the simulation space is left as it is.
3987
4067
  */
3988
4068
  toSimulation(vector: Vector3, space: BehaviorSpace, worldSpace: boolean): Vector3;
4069
+ /**
4070
+ * The inverse of {@link toSimulation}: converts the direction `vector`, in the simulation
4071
+ * space, into `space`. A vector already in `space` is left as it is.
4072
+ */
4073
+ fromSimulation(vector: Vector3, space: BehaviorSpace, worldSpace: boolean): Vector3;
3989
4074
  /**
3990
4075
  * Converts the point `point`, authored in `space`, into the simulation
3991
4076
  * space, as {@link toSimulation} does for a direction but with the
@@ -4418,6 +4503,13 @@ declare class EmitSubParticleSystem implements Behavior {
4418
4503
  inherit?: SubEmitterInheritance[]);
4419
4504
  initialize(particle: Particle): void;
4420
4505
  update(particle: Particle, delta: number): void;
4506
+ /**
4507
+ * Whether emissions that parent particles started into the target are still running, so the
4508
+ * target has more particles to come. The parent is not finished while it has any.
4509
+ */
4510
+ hasPendingEmission(): boolean;
4511
+ /** The system this behavior emits into, when it is set, linked and not disposed. */
4512
+ get targetSystem(): IParticleSystem | undefined;
4421
4513
  /**
4422
4514
  * The system to emit into, or undefined when `subParticleSystem` does not
4423
4515
  * hold a resolved emitter — unset, or a uuid string a loader could not
@@ -4737,18 +4829,27 @@ declare class InheritVelocity implements Behavior {
4737
4829
 
4738
4830
  /** The JSON of a speed limit over life: a {@link LimitSpeedOverLife}. */
4739
4831
  interface LimitSpeedOverLifeJSON extends BehaviorJSON {
4740
- /** The limit. */
4741
- speed: ValueGeneratorJSON;
4832
+ /** The limit: one curve for the speed, or a `Vector3Function` for each axis. */
4833
+ speed: ValueGeneratorJSON | Vector3FunctionJSON;
4742
4834
  /** How much excess speed goes per step; 1 when absent. */
4743
4835
  dampen?: number;
4836
+ /** The space of per-axis limits; `'local'` when absent. Written only when not the default. */
4837
+ space?: BehaviorSpace;
4744
4838
  }
4745
4839
  /**
4746
4840
  * Limits the speed of particles over their life, like Unity's Limit Velocity over Lifetime: a
4747
4841
  * particle faster than `speed` loses part of the excess each step.
4842
+ *
4843
+ * With a {@link Vector3Function} as `speed` it is Unity's Separate Axes: each component of the
4844
+ * velocity, measured along the axes of {@link space}, is limited by its own curve and keeps its
4845
+ * sign. Applies in every render mode.
4748
4846
  */
4749
4847
  declare class LimitSpeedOverLife implements Behavior {
4750
- /** The speed limit over the particle's life. */
4751
- speed: FunctionValueGenerator;
4848
+ /**
4849
+ * The speed limit over the particle's life: one curve for the speed, or a
4850
+ * {@link Vector3Function} with a limit for each axis (Unity's Separate Axes).
4851
+ */
4852
+ speed: FunctionValueGenerator | ValueGenerator | Vector3Function;
4752
4853
  /**
4753
4854
  * How much of the excess speed goes, from 0 (none) to 1, clamped. At 60 steps a second each
4754
4855
  * step removes `dampen / 3` of it; other step lengths remove the share that compounds to the
@@ -4756,22 +4857,58 @@ declare class LimitSpeedOverLife implements Behavior {
4756
4857
  * limit is approached over a few steps rather than held exactly.
4757
4858
  */
4758
4859
  dampen: number;
4860
+ /**
4861
+ * The axes per-axis limits are measured along, as Unity's Space setting: the emitter's own
4862
+ * (`'local'`, the default), which turn and scale with it, or the world's. A single speed
4863
+ * limit has no axes and ignores it.
4864
+ */
4865
+ space: BehaviorSpace;
4759
4866
  type: string;
4760
4867
  /** Learned in {@link initialize}; its motion scale multiplies the limit of a world-space system. */
4761
4868
  ps?: IParticleSystem;
4869
+ /** The emitter's transform this frame, refreshed by {@link frameUpdate} for per-axis limits. */
4870
+ readonly _frame: EmitterFrame;
4871
+ /**
4872
+ * Scratch values.
4873
+ * @internal
4874
+ */
4875
+ _limit: Vector3;
4876
+ /** @internal */
4877
+ _velocity: Vector3;
4762
4878
  initialize(particle: Particle, particleSystem?: IParticleSystem): void;
4763
4879
  /** What the limit is multiplied by: the system's motion scale in world space, else 1. */
4764
4880
  motionScale(): number;
4765
4881
  constructor(
4766
- /** The speed limit over the particle's life. */
4767
- speed: FunctionValueGenerator,
4882
+ /**
4883
+ * The speed limit over the particle's life: one curve for the speed, or a
4884
+ * {@link Vector3Function} with a limit for each axis (Unity's Separate Axes).
4885
+ */
4886
+ speed: FunctionValueGenerator | ValueGenerator | Vector3Function,
4768
4887
  /**
4769
4888
  * How much of the excess speed goes, from 0 (none) to 1, clamped. At 60 steps a second each
4770
4889
  * step removes `dampen / 3` of it; other step lengths remove the share that compounds to the
4771
4890
  * same loss per second, so the result does not depend on the frame rate. Even at 1 the
4772
4891
  * limit is approached over a few steps rather than held exactly.
4773
4892
  */
4774
- dampen: number);
4893
+ dampen: number,
4894
+ /**
4895
+ * The axes per-axis limits are measured along, as Unity's Space setting: the emitter's own
4896
+ * (`'local'`, the default), which turn and scale with it, or the world's. A single speed
4897
+ * limit has no axes and ignores it.
4898
+ */
4899
+ space?: BehaviorSpace);
4900
+ /**
4901
+ * Whether the frame is read: per-axis limits authored in another space than the simulation's.
4902
+ * @internal
4903
+ */
4904
+ _convertsSpace(): boolean;
4905
+ /**
4906
+ * Limits each axis of `velocity` (in the simulation space) by the per-axis limits at `t`.
4907
+ * The excess is worked out in {@link space} and taken off in the simulation space, so an axis
4908
+ * the emitter's scale flattens keeps its velocity rather than losing it.
4909
+ * @internal
4910
+ */
4911
+ _limitAxes(particle: Particle, t: number, step: number, motionScale: number, convert: boolean): void;
4775
4912
  /** The share of the excess speed one step of `delta` seconds removes; see {@link dampen}. */
4776
4913
  dampenStep(delta: number): number;
4777
4914
  update(particle: Particle, delta: number): void;
@@ -4779,7 +4916,8 @@ declare class LimitSpeedOverLife implements Behavior {
4779
4916
  toJSON(): LimitSpeedOverLifeJSON;
4780
4917
  /**
4781
4918
  * Reads {@link LimitSpeedOverLife.toJSON} output; a field the JSON leaves out takes its
4782
- * default.
4919
+ * default, and a speed that is neither a number generator nor a `Vector3Function` warns and
4920
+ * reads as 0.
4783
4921
  */
4784
4922
  static fromJSON(json: LimitSpeedOverLifeJSON): Behavior;
4785
4923
  frameUpdate(delta: number): void;
@@ -5557,14 +5695,21 @@ interface ShapeJSON {
5557
5695
  height?: number;
5558
5696
  /** Depth of a box. */
5559
5697
  depth?: number;
5560
- /** Where a box emits from (its volume, shell or edges), a `BoxEmitFrom` value. */
5698
+ /**
5699
+ * Where a box emits from (its volume, shell or edges), a `BoxEmitFrom` value; where a cone
5700
+ * does (its base or volume), a `ConeEmitFrom` value.
5701
+ */
5561
5702
  emitFrom?: number;
5703
+ /** Height of the volume a cone emits from with `ConeEmitFrom.Volume`. */
5704
+ length?: number;
5562
5705
  /** Thickness of a box's shell along x, y and z. */
5563
5706
  boxThickness?: number[];
5564
5707
  /** Columns of a grid. */
5565
5708
  column?: number;
5566
5709
  /** Rows of a grid. */
5567
5710
  row?: number;
5711
+ /** How a grid picks its cells, a `GridSampling` value. */
5712
+ sampling?: number;
5568
5713
  /** Uuid of the mesh a mesh-surface shape emits from. */
5569
5714
  mesh?: string;
5570
5715
  /** The {@link EmitterMode} of the shape's arc. */
@@ -5796,6 +5941,15 @@ declare class CircleEmitter implements EmitterShape {
5796
5941
  clone(): EmitterShape;
5797
5942
  }
5798
5943
 
5944
+ /**
5945
+ * Which part of a cone particles start from (Unity's Cone Emit from).
5946
+ */
5947
+ declare enum ConeEmitFrom {
5948
+ /** The base disc, as Unity's Base. */
5949
+ Base = 0,
5950
+ /** Anywhere along the cone, from the base out to {@link ConeEmitter.length}, as Unity's Volume. */
5951
+ Volume = 1
5952
+ }
5799
5953
  /**
5800
5954
  * Interface representing the parameters for a cone emitter.
5801
5955
  */
@@ -5821,6 +5975,16 @@ interface ConeEmitterParameters {
5821
5975
  * Defaults to π/6.
5822
5976
  */
5823
5977
  angle?: number;
5978
+ /**
5979
+ * Which part of the cone particles start from; {@link ConeEmitFrom.Base}, the default, for the
5980
+ * base disc only.
5981
+ */
5982
+ emitFrom?: ConeEmitFrom;
5983
+ /**
5984
+ * Height of the cone along +z that {@link ConeEmitFrom.Volume} fills (Unity's Length); a
5985
+ * negative or non-finite value is read as 0. Defaults to 5, as in Unity. The base ignores it.
5986
+ */
5987
+ length?: number;
5824
5988
  /**
5825
5989
  * The mode of the emitter.
5826
5990
  * {@link EmitterMode}
@@ -5844,7 +6008,10 @@ interface ConeEmitterParameters {
5844
6008
  }
5845
6009
  /**
5846
6010
  * Emits from a disc in the xy plane into a cone along +z (Unity's Cone shape): a particle at the
5847
- * disc's rim heads out at the cone's angle, one at the centre straight along z.
6011
+ * disc's rim heads out at the cone's angle, one at the centre straight along z, and one between
6012
+ * them along the cone's side lines, tilted by atan(r · tan(angle)) at the fraction r of the radius.
6013
+ * With {@link ConeEmitFrom.Volume}, particles start anywhere on those lines up to
6014
+ * {@link ConeEmitter.length} along z.
5848
6015
  */
5849
6016
  declare class ConeEmitter implements EmitterShape {
5850
6017
  /** Always `'cone'`. */
@@ -5863,6 +6030,14 @@ declare class ConeEmitter implements EmitterShape {
5863
6030
  * π/2.
5864
6031
  */
5865
6032
  angle: number;
6033
+ /** Which part of the cone particles start from, see {@link ConeEmitFrom}. */
6034
+ emitFrom: ConeEmitFrom;
6035
+ /**
6036
+ * Height along +z of the volume {@link ConeEmitFrom.Volume} fills; read as 0 when negative or
6037
+ * not finite. Side lines steeper than 89° from the axis are followed as if at 89°, so a cone
6038
+ * opened to 90° fills out to about 57 times the length past the rim, not infinitely far.
6039
+ */
6040
+ length: number;
5866
6041
  /** How the start point moves along the arc, see {@link EmitterMode}. */
5867
6042
  mode: EmitterMode;
5868
6043
  /**
@@ -6103,6 +6278,20 @@ declare function EmitterFromJSON(json: ShapeJSON, meta: JsonMetaData): EmitterSh
6103
6278
  */
6104
6279
  declare function EmitterToJSON(shape: EmitterShape, meta?: JsonMetaData): ShapeJSON;
6105
6280
 
6281
+ /**
6282
+ * How a grid emitter picks the cell each particle starts in.
6283
+ */
6284
+ declare enum GridSampling {
6285
+ /** A random cell for every particle. */
6286
+ Random = 0,
6287
+ /**
6288
+ * The cells in turn, row by row from the one at -x, -y, starting over after the last, as
6289
+ * Niagara's Grid Location fills its cells by particle index: a burst of `row × column`
6290
+ * particles puts one in every cell. The turn carries on across bursts, loop cycles and prewarm;
6291
+ * only a restart (the shape's `reset()`) starts it over. Meant for grids of up to 2^53 cells.
6292
+ */
6293
+ Sequential = 1
6294
+ }
6106
6295
  /**
6107
6296
  * Interface representing the parameters for a grid emitter.
6108
6297
  */
@@ -6123,6 +6312,8 @@ interface GridEmitterParameters {
6123
6312
  * The number of rows in the grid.
6124
6313
  */
6125
6314
  row?: number;
6315
+ /** How each particle's cell is picked; {@link GridSampling.Random}, the default, at random. */
6316
+ sampling?: GridSampling;
6126
6317
  /**
6127
6318
  * Offset, rotation and scale of the shape within the particle system.
6128
6319
  * {@link ShapeTransform}
@@ -6130,8 +6321,9 @@ interface GridEmitterParameters {
6130
6321
  transform?: ShapeTransform;
6131
6322
  }
6132
6323
  /**
6133
- * Emits from the cells of a grid in the xy plane, centred on the origin and heading along +z: each particle starts at the centre of a random cell, so a 2 × 2 grid of
6134
- * width 2 emits from x = ±0.5.
6324
+ * Emits from the cells of a grid in the xy plane, centred on the origin and heading along +z: each
6325
+ * particle starts at the centre of a cell, picked at random or in turn (see {@link GridSampling}),
6326
+ * so a 2 × 2 grid of width 2 emits from x = ±0.5.
6135
6327
  */
6136
6328
  declare class GridEmitter implements EmitterShape {
6137
6329
  /** Always `'grid'`. */
@@ -6144,10 +6336,15 @@ declare class GridEmitter implements EmitterShape {
6144
6336
  column: number;
6145
6337
  /** Cells along y; read as a whole number of at least 1, and as 1 when not finite. */
6146
6338
  row: number;
6339
+ /** How each particle's cell is picked, see {@link GridSampling}. */
6340
+ sampling: GridSampling;
6147
6341
  transform?: ShapeTransform;
6342
+ /** The cell the next {@link GridSampling.Sequential} particle starts in. */
6343
+ private nextCell;
6148
6344
  constructor(parameters?: GridEmitterParameters);
6149
6345
  /**
6150
- * Starts `p` at the centre of a random cell of the grid, heading along +z at its start speed.
6346
+ * Starts `p` at the centre of a cell of the grid, picked by {@link GridEmitter.sampling},
6347
+ * heading along +z at its start speed.
6151
6348
  */
6152
6349
  initialize(p: Particle): void;
6153
6350
  /** The shape's JSON. */
@@ -6156,8 +6353,10 @@ declare class GridEmitter implements EmitterShape {
6156
6353
  static fromJSON(json: ShapeJSON): GridEmitter;
6157
6354
  /** A copy with the same settings. */
6158
6355
  clone(): EmitterShape;
6159
- /** Does nothing: the grid has no state. */
6356
+ /** Does nothing: the grid only moves on as it emits. */
6160
6357
  update(system: IParticleSystem, delta: number): void;
6358
+ /** Starts {@link GridSampling.Sequential} over at the first cell, so a restart replays the same cells. */
6359
+ reset(): void;
6161
6360
  }
6162
6361
 
6163
6362
  /**
@@ -6967,6 +7166,8 @@ interface StoredBatchSettings {
6967
7166
  renderingGroupId: number;
6968
7167
  /** Whether the scene's fog is applied, see {@link VFXBatchSettings.applyFog}. */
6969
7168
  applyFog: boolean;
7169
+ /** Whether the scene's image processing is applied, see {@link VFXBatchSettings.applyImageProcessing}. */
7170
+ applyImageProcessing: boolean;
6970
7171
  /** Billboard pivot in particle-size units, see {@link VFXBatchSettings.pivot}. */
6971
7172
  pivot?: Vector3;
6972
7173
  /** Draw order within the batch, see {@link SortMode}. */
@@ -6991,6 +7192,135 @@ interface StoredBatchSettings {
6991
7192
  erosion?: ParticleErosion;
6992
7193
  }
6993
7194
 
7195
+ /**
7196
+ * Picking the shader language a batch compiles in, and putting the source where
7197
+ * the engine will look for it.
7198
+ *
7199
+ * WebGPU speaks WGSL. Handing it GLSL is not an error — Babylon transpiles —
7200
+ * but the transpilers are two WASM modules it downloads from cdn.babylonjs.com
7201
+ * the first time a GLSL shader is compiled. That is a third-party request on
7202
+ * first draw, a hard failure under a Content-Security-Policy that does not list
7203
+ * the CDN or with no network at all, and a GLSL to SPIR-V to WGSL round trip
7204
+ * before the first particle appears. Shipping the WGSL means none of that
7205
+ * happens.
7206
+ *
7207
+ * The two languages live in separate stores keyed by the same name, so a scene
7208
+ * that somehow ran both would not collide.
7209
+ */
7210
+ interface ShaderSources {
7211
+ /** GLSL source, used on every WebGL engine. */
7212
+ glsl: string;
7213
+ /** WGSL source, used on WebGPU. */
7214
+ wgsl: string;
7215
+ }
7216
+
7217
+ /**
7218
+ * The part of a batch's settings that decides its shader: the render mode, which textures and
7219
+ * effects are compiled in, and the blend state the fog and the fade read. Everything else a
7220
+ * batch holds (geometry, draw order, the effects' parameters) is a buffer or a uniform value.
7221
+ */
7222
+ type ShaderSettings = Pick<StoredBatchSettings, 'renderMode' | 'texture' | 'reflectionAtlas' | 'uTileCount' | 'vTileCount' | 'blendTiles' | 'softParticles' | 'materialAlphaTest' | 'materialTransparent' | 'materialBlendMode' | 'applyFog' | 'applyImageProcessing' | 'pivot' | 'minParticleSize' | 'maxParticleSize' | 'lighting' | 'rim' | 'mapUV' | 'uvDistortion' | 'gradientMap' | 'erosion'>;
7223
+ /** What the material needs to know about the depth texture soft particles read. */
7224
+ interface ShaderDepth {
7225
+ /** Whether the depth is packed into four 8-bit channels, as a `DepthRenderer` of type `UNSIGNED_BYTE` writes it. */
7226
+ packed: boolean;
7227
+ }
7228
+ /**
7229
+ * What a batch knows at compile time that its settings do not say: whether the textures it
7230
+ * depends on are there to be sampled.
7231
+ */
7232
+ interface ShaderContext {
7233
+ /**
7234
+ * The depth texture soft particles read, when one is attached to the renderer. Soft particles
7235
+ * compile only with a depth texture.
7236
+ */
7237
+ depth: ShaderDepth | null;
7238
+ /** Whether the mesh batch's reflection atlas has finished loading; it is sampled only then. */
7239
+ envAtlasReady: boolean;
7240
+ /** Whether the mesh batch has a second UV set to read for {@link UVChannel} 1. */
7241
+ meshUV2: boolean;
7242
+ /**
7243
+ * The scene's image processing as `ImageProcessingConfiguration.prepareDefines` writes it;
7244
+ * null or left out for none. Compiled in only when the settings apply it, see
7245
+ * {@link ParticleSystem.applyImageProcessing}.
7246
+ */
7247
+ imageProcessing?: ShaderImageProcessing | null;
7248
+ }
7249
+ /**
7250
+ * The defines an `ImageProcessingConfiguration` prepares for a material
7251
+ * (`ImageProcessingConfigurationDefines`): which of its effects are on, and whether a post
7252
+ * process applies it instead.
7253
+ */
7254
+ type ShaderImageProcessing = Readonly<IImageProcessingConfigurationDefines>;
7255
+ /**
7256
+ * One compiled shader of the library: the sources in both languages and the defines, attributes,
7257
+ * uniforms and samplers the material is built with. Built by {@link shaderProgram} from a
7258
+ * batch's settings, so a batch and a shader validator describe the same material.
7259
+ */
7260
+ interface ShaderProgram {
7261
+ /** The name the sources are registered under in Babylon's shader store, one per render mode. */
7262
+ name: string;
7263
+ /** The vertex shader in both languages. */
7264
+ vertex: ShaderSources;
7265
+ /** The fragment shader in both languages. */
7266
+ fragment: ShaderSources;
7267
+ /** The preprocessor defines, without the `#define`. */
7268
+ defines: string[];
7269
+ /** The vertex attributes the material binds. */
7270
+ attributes: string[];
7271
+ /** The uniforms the material declares. */
7272
+ uniforms: string[];
7273
+ /** The texture samplers the material declares. */
7274
+ samplers: string[];
7275
+ }
7276
+ /**
7277
+ * How a particle's colour has to leave the fragment shader for its blend mode, so that its alpha
7278
+ * means coverage: alpha 0 leaves the frame as it was, alpha 1 draws the colour in full, and the
7279
+ * fades (soft particles, erosion, a rim fade, alpha over life) only lower alpha. Unity's particle
7280
+ * shaders do the same for their Alpha, Premultiply, Additive and Multiply modes. Alpha has no
7281
+ * such meaning for an opaque material, nor under `ALPHA_INTERPOLATE` (constant blend colour),
7282
+ * `ALPHA_REPLACE_COLOR` (replaces the frame) and `ALPHA_DUAL_SRC0_ADD_SRC1xDST` (reads a second
7283
+ * shader output the particle shaders do not write); these leave the colour as it is.
7284
+ *
7285
+ * - `'straight'`: the blend weighs the colour by its alpha itself (Babylon's `ALPHA_COMBINE`,
7286
+ * `ALPHA_ADD`, `ALPHA_LAYER_ACCUMULATE`, …) or does not blend; the colour leaves as it is.
7287
+ * - `'premultiply'`: the blend takes the colour at full weight, or the frame by one minus the
7288
+ * colour (`ALPHA_PREMULTIPLIED`, `ALPHA_ONEONE`, `ALPHA_SCREENMODE`, `ALPHA_SUBTRACT`,
7289
+ * `ALPHA_MAXIMIZED`, `ALPHA_MAX`, …), so the shader multiplies it by its alpha: black, which
7290
+ * these modes leave the frame alone with, at alpha 0. Textures stay straight alpha, as in
7291
+ * Unity's Premultiply mode. The fade is linear in alpha except under `ALPHA_MAXIMIZED`, whose
7292
+ * blend weighs the colour by alpha once more, and `ALPHA_MAX`.
7293
+ * - `'multiply'`: the blend multiplies the frame by the colour (`ALPHA_MULTIPLY`, `ALPHA_MIN`), so
7294
+ * the shader moves it toward white, which leaves the frame alone, as alpha falls. `ALPHA_MIN`
7295
+ * clamps a frame brighter than 1 (an HDR target) to 1 where a particle draws, even at alpha 0.
7296
+ */
7297
+ type BlendOutput = 'straight' | 'premultiply' | 'multiply';
7298
+ /**
7299
+ * What the scene's fog turns a particle's colour into with distance: the fog colour where the
7300
+ * particle covers the frame (`'color'`), black where it adds to it (`'black'`, or the fog would
7301
+ * add itself to the whole screen), white where it multiplies it (`'white'`). Unity fogs its
7302
+ * additive and multiply particles toward black and white for the same reason.
7303
+ */
7304
+ type FogTarget = 'color' | 'black' | 'white';
7305
+ /** The {@link BlendOutput} and {@link FogTarget} of a blend mode. */
7306
+ interface BlendCategory {
7307
+ /** How the colour leaves the shader. */
7308
+ output: BlendOutput;
7309
+ /** Where the fog takes the colour. */
7310
+ fogTarget: FogTarget;
7311
+ }
7312
+ /**
7313
+ * The {@link BlendCategory} of a material: an opaque one (`materialTransparent` false, or
7314
+ * `ALPHA_DISABLE`) is straight and fogs toward the fog colour; a transparent one by its Babylon
7315
+ * alpha mode. A mode this table does not know is straight and fogs toward the fog colour.
7316
+ */
7317
+ declare function blendCategory(settings: {
7318
+ materialTransparent: boolean;
7319
+ materialBlendMode: number;
7320
+ }): BlendCategory;
7321
+ /** The shader program a batch with `settings` compiles, given what it knows about its textures. */
7322
+ declare function shaderProgram(settings: ShaderSettings, context: ShaderContext): ShaderProgram;
7323
+
6994
7324
  /**
6995
7325
  * One draw call of a {@link BatchedRenderer}: the systems that share a material, texture and
6996
7326
  * geometry, drawn together from one instanced mesh. The renderer makes and frees batches as
@@ -7061,6 +7391,28 @@ declare abstract class VFXBatch {
7061
7391
  * @internal
7062
7392
  */
7063
7393
  protected bindFog(material: ShaderMaterial): void;
7394
+ /** The observer of the scene's image processing that rebuilds the material when its defines change. */
7395
+ private imageProcessingObserver;
7396
+ /**
7397
+ * The scene's image processing as the material compiles it, see {@link ShaderContext.imageProcessing}:
7398
+ * null when the batch does not apply it.
7399
+ * @internal
7400
+ */
7401
+ protected imageProcessing(): ShaderImageProcessing | null;
7402
+ /**
7403
+ * Binds the scene's image processing to a material compiled with `compiled`: its values on every
7404
+ * bind, unless a post process applies them, and the material's defines, uniforms and samplers
7405
+ * swapped in place whenever the configuration changes what it has to compile (tone mapping
7406
+ * switched on, a vignette, a colour grading texture, a post process taking over). The material
7407
+ * stays the same one: a configuration that flips back and forth within a frame, as a reflection
7408
+ * probe rendering in linear space does, only switches between the effects the engine has
7409
+ * cached for each set of defines. A colour grading texture is set on the material too, so
7410
+ * that the batch, like Babylon's own materials, is not drawn before it has loaded.
7411
+ * @internal
7412
+ */
7413
+ protected bindImageProcessing(material: ShaderMaterial, compiled: ShaderImageProcessing | null): void;
7414
+ /** Stops following the scene's image processing. @internal */
7415
+ protected releaseImageProcessing(): void;
7064
7416
  /**
7065
7417
  * Seconds of renderer time, set by the renderer before each fill; what UV
7066
7418
  * and erosion mask scrolling advance by.
@@ -7240,6 +7592,18 @@ interface VFXBatchSettings {
7240
7592
  * that differ are batched apart.
7241
7593
  */
7242
7594
  applyFog: boolean;
7595
+ /**
7596
+ * Whether the material applies the scene's image processing (`scene.imageProcessingConfiguration`:
7597
+ * exposure, contrast, tone mapping, vignette, colour curves, colour grading, dithering), as
7598
+ * Babylon's own `ParticleSystem` and its standard and PBR materials do; unset reads as true.
7599
+ * When the configuration is applied by a post process (a `DefaultRenderingPipeline` with image
7600
+ * processing on), the material leaves its colour in linear space for it, as those materials do.
7601
+ * Off, the material does neither: its colour is written as authored. That does not keep the
7602
+ * particles out of a post process, which processes the whole frame; particles that must reach
7603
+ * the screen untouched are drawn by a camera the pipeline is not attached to. Systems that
7604
+ * differ are batched apart. See {@link ParticleSystem.applyImageProcessing}.
7605
+ */
7606
+ applyImageProcessing?: boolean;
7243
7607
  /**
7244
7608
  * Offset of billboard quads from their particle, in particle-size units
7245
7609
  * (Unity's renderer Pivot). On billboards x/y move the quad in its own plane
@@ -7646,18 +8010,66 @@ interface BurstParameters {
7646
8010
  */
7647
8011
  type CullingMode = 'always' | 'pause' | 'pauseAndCatchUp';
7648
8012
  /**
7649
- * What the emitter's world scale does to a world-space system (Unity's
7650
- * Scaling Mode, as far as it differs here). A local-space system lives in its
7651
- * emitter's space, so its scale reaches everything either way.
8013
+ * What a system does once it has finished, its emission over and its last particle dead (Unity's
8014
+ * Stop Action):
8015
+ *
8016
+ * - `'none'` (the default): nothing; {@link ParticleSystem.restart} plays it again.
8017
+ * - `'disable'`: disables its emitter node (`setEnabled(false)`), and with it the nodes under it.
8018
+ * A disabled system is not advanced or drawn; enable the emitter again before playing it.
8019
+ * - `'destroy'`: disposes the system and its emitter, as `ParticleSystem.dispose()` does.
8020
+ *
8021
+ * Unity's Callback is the system's `finished` event, which fires whatever the stop action. The
8022
+ * action waits for the system's sub emitters, see {@link ParticleSystem.stopAction}. A disabled
8023
+ * emitter is state like any other: saved as not visible, and copied disabled by `clone`.
8024
+ */
8025
+ type StopAction = 'none' | 'disable' | 'destroy';
8026
+ /**
8027
+ * What a full system does with the particles it emits next (Unity's Ring Buffer Mode). It needs
8028
+ * {@link ParticleSystemParameters.maxParticles}; without a limit it is ignored.
7652
8029
  *
7653
- * - `'shape'` (default): the scale sizes the emission shape and the
7654
- * particles; speeds, forces and speed limits stay in world units, so a
7655
- * scaled-down effect moves as far as the full-size one.
7656
- * - `'hierarchy'`: the scale also multiplies start speeds (per axis),
7657
- * `ForceOverLife` and `LimitSpeedOverLife` (by the mean of the axes), so the
7658
- * whole effect, motion included, scales like a model would.
8030
+ * - `'disabled'` (the default): particles die at the end of their life, and a full system drops
8031
+ * what it would emit.
8032
+ * - `'pauseUntilReplaced'`: a particle at the end of its life stays where and as it is, frozen,
8033
+ * until a new particle replaces it, the oldest first. For footprints, decals and bullet holes.
8034
+ * - `'loopUntilReplaced'`: a particle at the end of its life goes back to an earlier point of it
8035
+ * and plays that part again, over and over, until a new particle replaces it; see
8036
+ * {@link ParticleSystem.ringBufferLoopRange}.
8037
+ *
8038
+ * Particles are never killed by age, so a system in either mode keeps its particles and does not
8039
+ * finish while it has any: a non-looping ring effect never fires `finished`, and an
8040
+ * `EffectPool` copy of it returns to the pool only when it is released. A replaced particle
8041
+ * does not fire `particleDied`, nor Death sub emitters, which never fire in either mode since
8042
+ * no particle dies. Lowering `maxParticles` drops the oldest particles over the new limit, also
8043
+ * without `particleDied`. Particles are replaced oldest first in the order they were emitted;
8044
+ * switching a mode on in a system whose particles have already died in a different order
8045
+ * replaces them in row order the first time round. `'oldestInFront'` and `'youngestInFront'`
8046
+ * sorting reads age, so a looping particle sorts by its age in the loop. Applies in every
8047
+ * render mode but Trail, whose particles always die at the end of their life.
8048
+ */
8049
+ type RingBufferMode = 'disabled' | 'pauseUntilReplaced' | 'loopUntilReplaced';
8050
+ /**
8051
+ * What the emitter's scale does to the system, as Unity's Scaling Mode, in world and local space
8052
+ * alike. The scale reaches the emission shape, the particles' size, their start speed and, in world
8053
+ * space, `ForceOverLife`, `ApplyForce` and `LimitSpeedOverLife` (by the mean of the axes), so a
8054
+ * scaled effect looks and moves like a scaled model, except where a mode leaves it out:
8055
+ *
8056
+ * - `'local'` (default, as in Unity): only the emitter's own `scaling`; its parents' scale is left
8057
+ * out, so an effect keeps its size under a scaled character or prop.
8058
+ * - `'hierarchy'`: the emitter's whole world scale, its parents' included.
8059
+ * - `'shape'`: the world scale sizes the emission shape alone; the particles keep their size and
8060
+ * speed, so a bigger emitter spreads the same particles over a larger area.
8061
+ *
8062
+ * Under every mode the emitter's position, rotation and any mirroring come from the whole
8063
+ * hierarchy; only the length of each axis changes. A sub emission starts in its parent particle's
8064
+ * frame and takes its size and speed from that, not from the sub emitter's scale; `'shape'` still
8065
+ * scales its shape by the sub emitter's world scale. With a non-uniform scale `'shape'` stretches
8066
+ * where particles start, not the directions the shape sends them.
8067
+ *
8068
+ * Known differences from Unity: a world force (`ForceOverLife`, `ApplyForce`, and so the gravity
8069
+ * the Unity exporter writes) is scaled with the motion in `'local'` and `'hierarchy'`, where
8070
+ * Unity's gravity is not.
7659
8071
  */
7660
- type ScalingMode = 'shape' | 'hierarchy';
8072
+ type ScalingMode = 'local' | 'hierarchy' | 'shape';
7661
8073
  /**
7662
8074
  * Where a {@link RenderMode.Beam} system's quads end: a point in world space,
7663
8075
  * or anything with a world position, such as a Babylon `TransformNode`, read
@@ -7686,7 +8098,12 @@ type BeamEnd = {
7686
8098
  * default named on it, the same default `fromJSON` gives a file that leaves it out.
7687
8099
  */
7688
8100
  interface ParticleSystemParameters {
7689
- /** See {@link ParticleSystem.autoDestroy}. Default false. */
8101
+ /** What the system does once it has finished, see {@link StopAction}. Default `'none'`. */
8102
+ stopAction?: StopAction;
8103
+ /**
8104
+ * `true` is `stopAction: 'destroy'`; read only when `stopAction` is left out.
8105
+ * @deprecated Use `stopAction: 'destroy'`.
8106
+ */
7690
8107
  autoDestroy?: boolean;
7691
8108
  /** See {@link ParticleSystem.looping}. Default true. */
7692
8109
  looping?: boolean;
@@ -7718,6 +8135,10 @@ interface ParticleSystemParameters {
7718
8135
  emissionBursts?: Array<BurstParameters>;
7719
8136
  /** Most particles alive at once; emission past it is dropped. Leave unset for no limit. */
7720
8137
  maxParticles?: number;
8138
+ /** What a full system does with new particles, see {@link RingBufferMode}. Default `'disabled'`. */
8139
+ ringBufferMode?: RingBufferMode;
8140
+ /** See {@link ParticleSystem.ringBufferLoopRange}. Default the whole life, (0, 1). */
8141
+ ringBufferLoopRange?: Vector2;
7721
8142
  /** See {@link ParticleSystem.onlyUsedByOther}. Default false. */
7722
8143
  onlyUsedByOther?: boolean;
7723
8144
  /** See {@link ParticleSystem.behaviors}. Default none. */
@@ -7804,7 +8225,7 @@ interface ParticleSystemParameters {
7804
8225
  playbackSpeed?: number;
7805
8226
  /** What the system does while off screen, see {@link CullingMode}. Default `'always'`. */
7806
8227
  cullingMode?: CullingMode;
7807
- /** What the emitter's scale does to a world-space system, see {@link ScalingMode}. Default `'shape'`. */
8228
+ /** What the emitter's scale does to the system, see {@link ScalingMode}. Default `'local'`. */
7808
8229
  scalingMode?: ScalingMode;
7809
8230
  /** Seed for this system's own random generator, see {@link ParticleSystem.seed}. Default none. */
7810
8231
  seed?: number;
@@ -7822,6 +8243,8 @@ interface ParticleSystemParameters {
7822
8243
  renderingGroupId?: number;
7823
8244
  /** Whether the scene's fog applies, see {@link ParticleSystem.applyFog}. Default true. */
7824
8245
  applyFog?: boolean;
8246
+ /** Whether the scene's image processing applies, see {@link ParticleSystem.applyImageProcessing}. Default true. */
8247
+ applyImageProcessing?: boolean;
7825
8248
  /** Scene the emitter node is created in. Default Babylon's last created scene. */
7826
8249
  scene?: Scene;
7827
8250
  }
@@ -7853,7 +8276,9 @@ interface BurstParametersJSON {
7853
8276
  interface ParticleSystemJSONParameters {
7854
8277
  /** The quarks.core version line the system was written with. */
7855
8278
  version: string;
7856
- /** See {@link ParticleSystem.autoDestroy}. */
8279
+ /** Written only when not `'none'`. */
8280
+ stopAction?: StopAction;
8281
+ /** Read from older files: `true` is `stopAction: 'destroy'`. No longer written. */
7857
8282
  autoDestroy?: boolean;
7858
8283
  /** See {@link ParticleSystem.looping}. */
7859
8284
  looping?: boolean;
@@ -7885,6 +8310,10 @@ interface ParticleSystemJSONParameters {
7885
8310
  emissionBursts?: Array<BurstParametersJSON>;
7886
8311
  /** See {@link ParticleSystem.maxParticles}. */
7887
8312
  maxParticles?: number;
8313
+ /** Written only when not `'disabled'`. */
8314
+ ringBufferMode?: RingBufferMode;
8315
+ /** `[start, end]`; written only when not `[0, 1]`. */
8316
+ ringBufferLoopRange?: [number, number];
7888
8317
  /** See {@link ParticleSystem.onlyUsedByOther}. */
7889
8318
  onlyUsedByOther?: boolean;
7890
8319
  /**
@@ -7902,11 +8331,13 @@ interface ParticleSystemJSONParameters {
7902
8331
  renderingGroupId?: number;
7903
8332
  /** Written only when false. */
7904
8333
  applyFog?: boolean;
8334
+ /** Written only when false. */
8335
+ applyImageProcessing?: boolean;
7905
8336
  /** Written only when not 1. */
7906
8337
  playbackSpeed?: number;
7907
8338
  /** Written only when not `'always'`. */
7908
8339
  cullingMode?: CullingMode;
7909
- /** Written only when not `'shape'`. */
8340
+ /** Written only when not `'local'`. */
7910
8341
  scalingMode?: ScalingMode;
7911
8342
  /** Written only when set. */
7912
8343
  seed?: number;
@@ -8033,12 +8464,27 @@ declare class ParticleEmitter extends TransformNode {
8033
8464
  system: IParticleSystem;
8034
8465
  private _matrixWorld;
8035
8466
  private _matrixWorldFlag;
8036
- /**
8037
- * The node's world matrix in quarks.core form. Mirrored from Babylon's
8038
- * matrix only when that matrix actually changed (tracked by its
8039
- * `updateFlag`), so repeated reads inside a frame are free.
8467
+ private _matrixWorldMode;
8468
+ private readonly _shapeScale;
8469
+ /**
8470
+ * The matrix the system simulates and draws in, in quarks.core form: the node's world matrix,
8471
+ * with the length of each axis set by the system's {@link ScalingMode}. `'hierarchy'` keeps the
8472
+ * whole world scale; `'local'` sets each axis to the node's own `scaling` (times
8473
+ * `scalingDeterminant`), leaving the parents' scale out; `'shape'` sets each to 1, and
8474
+ * {@link shapeScale} applies the world scale to the emission shape alone. Only the axes'
8475
+ * lengths change, so position, rotation and any mirroring from the hierarchy are kept. An axis
8476
+ * that a parent scales to 0 has no direction left: it is rebuilt square to the other two. A
8477
+ * node whose system has no scaling mode reads as `'hierarchy'`. Recomputed only when Babylon's
8478
+ * matrix changed (tracked by its `updateFlag`) or the mode did, so repeated reads inside a frame
8479
+ * are free.
8040
8480
  */
8041
8481
  get matrixWorld(): Matrix4;
8482
+ /**
8483
+ * What the system's emission shape is scaled by before {@link matrixWorld} places it: the
8484
+ * node's world scale in `'shape'` mode, which leaves the particles and their motion unscaled,
8485
+ * and 1 otherwise. Read it after `matrixWorld`, which refreshes it.
8486
+ */
8487
+ get shapeScale(): Vector3;
8042
8488
  /** Whether the node and its parents are enabled; setting it is `setEnabled`. */
8043
8489
  get visible(): boolean;
8044
8490
  set visible(value: boolean);
@@ -8048,7 +8494,7 @@ declare class ParticleEmitter extends TransformNode {
8048
8494
  /**
8049
8495
  * Disposes the node and the particle system it carries, so `root.dispose()` on an effect tree
8050
8496
  * also removes its systems from their renderer. Safe to call more than once. When a system
8051
- * disposes its own emitter (`ParticleSystem.dispose()`, `autoDestroy`), the systems of child
8497
+ * disposes its own emitter (`ParticleSystem.dispose()`, a `destroy` stop action), the systems of child
8052
8498
  * emitters keep playing until they finish or are disposed themselves.
8053
8499
  */
8054
8500
  dispose(doNotRecurse?: boolean, disposeMaterialAndTextures?: boolean): void;
@@ -8076,8 +8522,31 @@ declare class ParticleEmitter extends TransformNode {
8076
8522
  * start values and emission, and the particle's age over its life inside behaviors.
8077
8523
  */
8078
8524
  declare class ParticleSystem implements IParticleSystem {
8079
- /** Dispose the system, its emitter and its batch slot when it finishes. Default false. */
8080
- autoDestroy: boolean;
8525
+ /**
8526
+ * What the system does once it has finished (Unity's Stop Action): nothing, disable its
8527
+ * emitter, or dispose it; see {@link StopAction}. `'none'` by default.
8528
+ *
8529
+ * As in Unity, the action waits for the system's sub emitters: it runs once the system has
8530
+ * finished and none of the systems it emits into, nor theirs, has a particle left (see
8531
+ * {@link isAlive}), so disabling or disposing a parent does not cut its sub emitters'
8532
+ * particles short. A sub emitter target ({@link onlyUsedByOther}) takes no stop action of its
8533
+ * own: it is empty between its parent's bursts, and its parent decides when the effect is done.
8534
+ */
8535
+ stopAction: StopAction;
8536
+ /**
8537
+ * Skips the {@link stopAction} while true, so a tool can play an effect over and over (an
8538
+ * editor's preview, a gallery, a pool of reused copies) and still save the stop action it
8539
+ * was authored with, as Unity applies stop actions only in Play mode. The `finished` event
8540
+ * fires either way. False by default; never saved, cloned or loaded.
8541
+ */
8542
+ ignoreStopAction: boolean;
8543
+ /**
8544
+ * Whether the system disposes itself when it finishes: `stopAction === 'destroy'`. Setting it
8545
+ * true sets that stop action, and false turns a `'destroy'` one into `'none'`.
8546
+ * @deprecated Use {@link stopAction}.
8547
+ */
8548
+ get autoDestroy(): boolean;
8549
+ set autoDestroy(value: boolean);
8081
8550
  /**
8082
8551
  * Start a looping system as if it had already run one full cycle (Unity's Prewarm), so a fire
8083
8552
  * or a mist is full from its first frame. Default false.
@@ -8144,9 +8613,24 @@ declare class ParticleSystem implements IParticleSystem {
8144
8613
  /**
8145
8614
  * Most particles alive at once (Unity's Max Particles); emission past it is dropped. Undefined
8146
8615
  * means no limit, as does a negative or NaN count given to the constructor; a fraction is
8147
- * rounded down.
8616
+ * rounded down. With a {@link ringBufferMode}, new particles replace the oldest instead.
8148
8617
  */
8149
8618
  maxParticles?: number;
8619
+ /**
8620
+ * What a full system does with new particles (Unity's Ring Buffer Mode): drop them, or
8621
+ * replace the oldest, which wait frozen or looping until then; see {@link RingBufferMode}.
8622
+ * `'disabled'` by default. Takes effect only with {@link maxParticles}.
8623
+ */
8624
+ ringBufferMode: RingBufferMode;
8625
+ /**
8626
+ * The part of its life a particle plays again in `'loopUntilReplaced'` (Unity's Loop Range):
8627
+ * at the end of its life it goes back to `x` and plays to `y`, as fractions of its life, 0 to
8628
+ * 1. (0, 1), the default, replays its whole life. Both ends are read clamped into 0..1 and in
8629
+ * order, however the vector was set. A range of no length, such as (0.5, 0.5), holds the
8630
+ * particle still at that point of its life; behaviors that act by age stop with it, those
8631
+ * that act per second (rotation speed, forces) still run.
8632
+ */
8633
+ ringBufferLoopRange: Vector2;
8150
8634
  /**
8151
8635
  * The system emits nothing of its own and only spawns what an `EmitSubParticleSystem` on
8152
8636
  * another system sends it (a Unity sub emitter). Default false.
@@ -8225,8 +8709,11 @@ declare class ParticleSystem implements IParticleSystem {
8225
8709
  get time(): number;
8226
8710
  /** Whether {@link endEmit} ran, or a non-looping system reached the end of its duration. */
8227
8711
  get isEmitEnded(): boolean;
8228
- /** Whether continuous or queued emission can still spawn particles before the system is done. */
8229
- hasPendingEmission(): boolean;
8712
+ /**
8713
+ * Whether continuous or queued emission can still spawn particles before the system is done:
8714
+ * its own, or with `state` one a sub emitter runs into this system for a parent particle.
8715
+ */
8716
+ hasPendingEmission(state?: EmissionState): boolean;
8230
8717
  /**
8231
8718
  * No particles left and nothing left to emit: a non-looping system that
8232
8719
  * ran its course, or a looping one whose emission was ended with
@@ -8385,15 +8872,7 @@ declare class ParticleSystem implements IParticleSystem {
8385
8872
  */
8386
8873
  get uvDistortion(): ParticleUVDistortion | undefined;
8387
8874
  set uvDistortion(distortion: ParticleUVDistortionOptions | undefined);
8388
- /**
8389
- * The emitter's world scale per axis, measured with {@link motionScale}
8390
- * before every step; what `'hierarchy'` multiplies start speeds by. Taken
8391
- * from the system's own emitter rather than the emission matrix, whose
8392
- * columns carry a parent particle's velocity for a sub emitter.
8393
- * @internal
8394
- */
8395
- readonly hierarchyScale: Vector3;
8396
- /** The mean world scale of the emitter for a world-space `'hierarchy'` system, else 1. */
8875
+ /** The mean scale of the emitter's matrix for a world-space system, else 1. */
8397
8876
  private measureMotionScale;
8398
8877
  /**
8399
8878
  * Distance in world units in front of the scene at which a soft particle is fully faded out,
@@ -8508,6 +8987,27 @@ declare class ParticleSystem implements IParticleSystem {
8508
8987
  */
8509
8988
  get applyFog(): boolean;
8510
8989
  set applyFog(apply: boolean);
8990
+ /**
8991
+ * Whether the particles' material applies the scene's image processing (exposure, contrast,
8992
+ * tone mapping, vignette, colour curves, colour grading, dithering of
8993
+ * `scene.imageProcessingConfiguration`), as Babylon's own particle systems and materials do;
8994
+ * true by default. A scene whose configuration does nothing leaves the colour as it is, and
8995
+ * one applied by a post process gets the colour in linear space. Particles that multiply the
8996
+ * frame (`ALPHA_MULTIPLY`) are a factor rather than light and are not tone mapped.
8997
+ *
8998
+ * As in Babylon, the processing runs on each particle before it is blended: tone mapping
8999
+ * clamps an HDR colour to the displayable range, and an additive particle picks up what the
9000
+ * configuration does to black (a contrast below 1, colour curves or an
9001
+ * opaque vignette lift it). The configuration is the scene's;
9002
+ * there is no per-system one.
9003
+ *
9004
+ * Switched off, the material writes its colour as authored, and leaves it in gamma space under
9005
+ * a post process, which still processes the frame the particles are in. To keep particles out
9006
+ * of a post process, draw them with a camera the pipeline is not attached to. Saved in the
9007
+ * effect JSON only when switched off.
9008
+ */
9009
+ get applyImageProcessing(): boolean;
9010
+ set applyImageProcessing(apply: boolean);
8511
9011
  /**
8512
9012
  * Multiplier on the time this system is advanced by (Unity's Simulation
8513
9013
  * Speed): 2 runs the effect twice as fast, 0 freezes it without pausing the
@@ -8541,12 +9041,13 @@ declare class ParticleSystem implements IParticleSystem {
8541
9041
  private emissionMultiplierValue;
8542
9042
  /** What this system does while off screen, see {@link CullingMode}. `'always'` by default. */
8543
9043
  cullingMode: CullingMode;
8544
- /** What the emitter's world scale does to a world-space system, see {@link ScalingMode}. `'shape'` by default. */
9044
+ /** What the emitter's scale does to the system, see {@link ScalingMode}. `'local'` by default. */
8545
9045
  scalingMode: ScalingMode;
8546
9046
  /**
8547
- * What world-space forces and speed limits are multiplied by this step:
8548
- * the mean of the emitter's world scale axes in `'hierarchy'` mode, 1
8549
- * otherwise. Updated before every simulation step.
9047
+ * What world-space forces and speed limits are multiplied by this step: the mean of the axes
9048
+ * of the scale the {@link scalingMode} applies (the emitter's own in `'local'`, its world scale
9049
+ * in `'hierarchy'`, 1 in `'shape'`) in a world-space system, 1 in a local-space one, whose
9050
+ * emitter matrix scales them already. Updated before every simulation step.
8550
9051
  */
8551
9052
  motionScale: number;
8552
9053
  /**
@@ -8652,7 +9153,7 @@ declare class ParticleSystem implements IParticleSystem {
8652
9153
  /**
8653
9154
  * Stops emission and lets the particles alive die out (Unity's `Stop` with
8654
9155
  * `StopEmitting`). The system fires `emitEnd`, then `finished` when the last particle has
8655
- * died, and is disposed then if {@link autoDestroy} is set. {@link restart} starts it again.
9156
+ * died, and then does what its {@link stopAction} says. {@link restart} starts it again.
8656
9157
  */
8657
9158
  endEmit(): void;
8658
9159
  /** Whether {@link dispose} has run. A disposed system emits nothing and cannot be restarted. */
@@ -8767,13 +9268,35 @@ declare class ParticleSystem implements IParticleSystem {
8767
9268
  */
8768
9269
  private simulateStep;
8769
9270
  private stepOnce;
9271
+ /** Whether a sub emitter of this system still has an emission running into its target. */
9272
+ private hasPendingSubEmission;
9273
+ /**
9274
+ * Whether the system still has particles or emission to come (Unity's `IsAlive`): not
9275
+ * {@link isFinished}, or, with `withSubEmitters` (the default), any system it emits into
9276
+ * through an `EmitSubParticleSystem`, and theirs, still has particles.
9277
+ */
9278
+ isAlive(withSubEmitters?: boolean): boolean;
9279
+ /** Whether a system this one emits into has particles, or one of theirs; `seen` stops a cycle. */
9280
+ private subEmittersAlive;
9281
+ /**
9282
+ * Whether particles outlive their lifetime, held or looped until replaced: a {@link ringBufferMode}
9283
+ * on a system with {@link maxParticles}, outside the Trail render mode.
9284
+ */
9285
+ get ringBufferActive(): boolean;
8770
9286
  /** Re-points every particle at the store, for {@link snapshotPreviousState}. */
8771
9287
  private readonly rebindParticles;
8772
9288
  /** The one `particleDied` event, filled in for each death so a death allocates nothing. */
8773
9289
  private readonly particleDiedEvent;
8774
9290
  /** Fires `particleDied` for a particle the step retired. */
8775
9291
  private readonly fireParticleDied;
9292
+ /** The ring buffer step for {@link integrateSprites}, or undefined when particles die by age. */
9293
+ private ringBufferStep;
9294
+ private readonly ringStep;
9295
+ /** Set on each finish until the {@link stopAction} has run, which waits for the sub emitters. */
9296
+ private stopActionPending;
8776
9297
  private notifyFinished;
9298
+ /** Runs a pending {@link stopAction} once no system this one emits into has particles left. */
9299
+ private applyStopAction;
8777
9300
  /**
8778
9301
  * Spawns what this step's emission calls for. Called by the simulation step, and by
8779
9302
  * `EmitSubParticleSystem` on a sub emitter target with the parent particle's state and matrix.
@@ -9036,7 +9559,7 @@ declare class QuarksPrefab extends TransformNode implements IPrefab {
9036
9559
  * reads every earlier version, and files written before the field existed, and warns about a
9037
9560
  * file from a newer version.
9038
9561
  */
9039
- declare const QUARKS_FORMAT_VERSION = 1;
9562
+ declare const QUARKS_FORMAT_VERSION = 2;
9040
9563
  /** An image a texture reads: a url, a root-relative path, or a `data:` URI. */
9041
9564
  interface QuarksImageJSON {
9042
9565
  /** Unique within the file; other entries refer to it by this. */
@@ -9451,7 +9974,8 @@ interface EffectPlacement {
9451
9974
  * it; a copy whose every system has finished goes back to the pool by itself,
9452
9975
  * so a one-shot effect needs nothing more. A looping effect is ended with
9453
9976
  * {@link stop}, which lets its particles die out before the copy returns, or
9454
- * dropped at once with {@link release}.
9977
+ * dropped at once with {@link release}. A ring buffer effect (`ringBufferMode`)
9978
+ * never finishes, since its particles never die: release it.
9455
9979
  *
9456
9980
  * Idle copies are parked disabled, which costs the renderer nothing, and keep
9457
9981
  * their place in its batches, so acquiring one allocates nothing.
@@ -9907,7 +10431,12 @@ declare class QuarksUtil {
9907
10431
  static pause(root: Node): void;
9908
10432
  /** Restarts every system under `root` from the beginning, see {@link ParticleSystem.restart}. */
9909
10433
  static restart(root: Node): void;
9910
- /** Sets {@link ParticleSystem.autoDestroy} on every system under `root`. */
10434
+ /** Sets {@link ParticleSystem.stopAction} on every system under `root`. */
10435
+ static setStopAction(root: Node, stopAction: StopAction): void;
10436
+ /**
10437
+ * Sets {@link ParticleSystem.autoDestroy} on every system under `root`.
10438
+ * @deprecated Use {@link QuarksUtil.setStopAction} with `'destroy'`.
10439
+ */
9911
10440
  static setAutoDestroy(root: Node, autoDestroy: boolean): void;
9912
10441
  /** Ends emission on every system under `root` and lets the particles die out, see {@link ParticleSystem.endEmit}. */
9913
10442
  static endEmit(root: Node): void;
@@ -9951,123 +10480,6 @@ declare class QuarksUtil {
9951
10480
  private static traverseNode;
9952
10481
  }
9953
10482
 
9954
- /**
9955
- * Picking the shader language a batch compiles in, and putting the source where
9956
- * the engine will look for it.
9957
- *
9958
- * WebGPU speaks WGSL. Handing it GLSL is not an error — Babylon transpiles —
9959
- * but the transpilers are two WASM modules it downloads from cdn.babylonjs.com
9960
- * the first time a GLSL shader is compiled. That is a third-party request on
9961
- * first draw, a hard failure under a Content-Security-Policy that does not list
9962
- * the CDN or with no network at all, and a GLSL to SPIR-V to WGSL round trip
9963
- * before the first particle appears. Shipping the WGSL means none of that
9964
- * happens.
9965
- *
9966
- * The two languages live in separate stores keyed by the same name, so a scene
9967
- * that somehow ran both would not collide.
9968
- */
9969
- interface ShaderSources {
9970
- /** GLSL source, used on every WebGL engine. */
9971
- glsl: string;
9972
- /** WGSL source, used on WebGPU. */
9973
- wgsl: string;
9974
- }
9975
-
9976
- /**
9977
- * The part of a batch's settings that decides its shader: the render mode, which textures and
9978
- * effects are compiled in, and the blend state the fog and the fade read. Everything else a
9979
- * batch holds (geometry, draw order, the effects' parameters) is a buffer or a uniform value.
9980
- */
9981
- type ShaderSettings = Pick<StoredBatchSettings, 'renderMode' | 'texture' | 'reflectionAtlas' | 'uTileCount' | 'vTileCount' | 'blendTiles' | 'softParticles' | 'materialAlphaTest' | 'materialTransparent' | 'materialBlendMode' | 'applyFog' | 'pivot' | 'minParticleSize' | 'maxParticleSize' | 'lighting' | 'rim' | 'mapUV' | 'uvDistortion' | 'gradientMap' | 'erosion'>;
9982
- /** What the material needs to know about the depth texture soft particles read. */
9983
- interface ShaderDepth {
9984
- /** Whether the depth is packed into four 8-bit channels, as a `DepthRenderer` of type `UNSIGNED_BYTE` writes it. */
9985
- packed: boolean;
9986
- }
9987
- /**
9988
- * What a batch knows at compile time that its settings do not say: whether the textures it
9989
- * depends on are there to be sampled.
9990
- */
9991
- interface ShaderContext {
9992
- /**
9993
- * The depth texture soft particles read, when one is attached to the renderer. Soft particles
9994
- * compile only with a depth texture.
9995
- */
9996
- depth: ShaderDepth | null;
9997
- /** Whether the mesh batch's reflection atlas has finished loading; it is sampled only then. */
9998
- envAtlasReady: boolean;
9999
- /** Whether the mesh batch has a second UV set to read for {@link UVChannel} 1. */
10000
- meshUV2: boolean;
10001
- }
10002
- /**
10003
- * One compiled shader of the library: the sources in both languages and the defines, attributes,
10004
- * uniforms and samplers the material is built with. Built by {@link shaderProgram} from a
10005
- * batch's settings, so a batch and a shader validator describe the same material.
10006
- */
10007
- interface ShaderProgram {
10008
- /** The name the sources are registered under in Babylon's shader store, one per render mode. */
10009
- name: string;
10010
- /** The vertex shader in both languages. */
10011
- vertex: ShaderSources;
10012
- /** The fragment shader in both languages. */
10013
- fragment: ShaderSources;
10014
- /** The preprocessor defines, without the `#define`. */
10015
- defines: string[];
10016
- /** The vertex attributes the material binds. */
10017
- attributes: string[];
10018
- /** The uniforms the material declares. */
10019
- uniforms: string[];
10020
- /** The texture samplers the material declares. */
10021
- samplers: string[];
10022
- }
10023
- /**
10024
- * How a particle's colour has to leave the fragment shader for its blend mode, so that its alpha
10025
- * means coverage: alpha 0 leaves the frame as it was, alpha 1 draws the colour in full, and the
10026
- * fades (soft particles, erosion, a rim fade, alpha over life) only lower alpha. Unity's particle
10027
- * shaders do the same for their Alpha, Premultiply, Additive and Multiply modes. Alpha has no
10028
- * such meaning for an opaque material, nor under `ALPHA_INTERPOLATE` (constant blend colour),
10029
- * `ALPHA_REPLACE_COLOR` (replaces the frame) and `ALPHA_DUAL_SRC0_ADD_SRC1xDST` (reads a second
10030
- * shader output the particle shaders do not write); these leave the colour as it is.
10031
- *
10032
- * - `'straight'`: the blend weighs the colour by its alpha itself (Babylon's `ALPHA_COMBINE`,
10033
- * `ALPHA_ADD`, `ALPHA_LAYER_ACCUMULATE`, …) or does not blend; the colour leaves as it is.
10034
- * - `'premultiply'`: the blend takes the colour at full weight, or the frame by one minus the
10035
- * colour (`ALPHA_PREMULTIPLIED`, `ALPHA_ONEONE`, `ALPHA_SCREENMODE`, `ALPHA_SUBTRACT`,
10036
- * `ALPHA_MAXIMIZED`, `ALPHA_MAX`, …), so the shader multiplies it by its alpha: black, which
10037
- * these modes leave the frame alone with, at alpha 0. Textures stay straight alpha, as in
10038
- * Unity's Premultiply mode. The fade is linear in alpha except under `ALPHA_MAXIMIZED`, whose
10039
- * blend weighs the colour by alpha once more, and `ALPHA_MAX`.
10040
- * - `'multiply'`: the blend multiplies the frame by the colour (`ALPHA_MULTIPLY`, `ALPHA_MIN`), so
10041
- * the shader moves it toward white, which leaves the frame alone, as alpha falls. `ALPHA_MIN`
10042
- * clamps a frame brighter than 1 (an HDR target) to 1 where a particle draws, even at alpha 0.
10043
- */
10044
- type BlendOutput = 'straight' | 'premultiply' | 'multiply';
10045
- /**
10046
- * What the scene's fog turns a particle's colour into with distance: the fog colour where the
10047
- * particle covers the frame (`'color'`), black where it adds to it (`'black'`, or the fog would
10048
- * add itself to the whole screen), white where it multiplies it (`'white'`). Unity fogs its
10049
- * additive and multiply particles toward black and white for the same reason.
10050
- */
10051
- type FogTarget = 'color' | 'black' | 'white';
10052
- /** The {@link BlendOutput} and {@link FogTarget} of a blend mode. */
10053
- interface BlendCategory {
10054
- /** How the colour leaves the shader. */
10055
- output: BlendOutput;
10056
- /** Where the fog takes the colour. */
10057
- fogTarget: FogTarget;
10058
- }
10059
- /**
10060
- * The {@link BlendCategory} of a material: an opaque one (`materialTransparent` false, or
10061
- * `ALPHA_DISABLE`) is straight and fogs toward the fog colour; a transparent one by its Babylon
10062
- * alpha mode. A mode this table does not know is straight and fogs toward the fog colour.
10063
- */
10064
- declare function blendCategory(settings: {
10065
- materialTransparent: boolean;
10066
- materialBlendMode: number;
10067
- }): BlendCategory;
10068
- /** The shader program a batch with `settings` compiles, given what it knows about its textures. */
10069
- declare function shaderProgram(settings: ShaderSettings, context: ShaderContext): ShaderProgram;
10070
-
10071
10483
  /**
10072
10484
  * One shader the library can compile: a {@link ShaderProgram} with the settings that produce it,
10073
10485
  * named for the renderer's benefit. See {@link shaderVariants}.
@@ -10081,8 +10493,8 @@ interface ShaderVariant {
10081
10493
  /**
10082
10494
  * Every shader program the library can compile, one per distinct set of defines: every render
10083
10495
  * mode with every combination of sheet, map, soft particles, alpha test and fog, every blend
10084
- * resolve with and without fog and soft particles, and the texture effects alone and together on
10085
- * each shader family. What a shader validator compiles, and what
10496
+ * resolve with and without fog and soft particles, the texture effects alone and together on
10497
+ * each shader family, and the scene's image processing on every render mode. What a shader validator compiles, and what
10086
10498
  * an application can warm the shader cache with before its first frame (Unity's
10087
10499
  * ShaderVariantCollection). Built by {@link shaderProgram}, so a variant here is a material a
10088
10500
  * batch would build.
@@ -10104,5 +10516,5 @@ declare function shaderVariants(): ShaderVariant[];
10104
10516
  */
10105
10517
  declare function textureSourceUrl(texture: Texture): string | undefined;
10106
10518
 
10107
- export { ApplyCollision, ApplyForce, ApplySequences, AxisAngleGenerator, BatchedRenderer, BehaviorFromJSON, BehaviorToJSON, BehaviorTypes, Bezier, BoxEmitFrom, BoxEmitter, ChangeEmitDirection, CircleEmitter, ColorBySpeed, ColorGeneratorFromJSON, ColorOverLife, ColorRange, ConeEmitter, ConstantColor, ConstantValue, ContinuousLinearFunction, DEG2RAD, DonutEmitter, EROSION_DEFAULT_SOFTNESS, EdgeEmitter, EffectPool, EmitSubParticleSystem, EmitterFrame, EmitterFromJSON, EmitterMode, EmitterShapes, EmitterToJSON, Euler, EulerGenerator, ForceOverLife, FrameOverLife, GRADIENT_MAP_WEIGHTS, GeneratorFromJSON, Gradient, GravityForce, GridEmitter, HemisphereEmitter, InheritVelocity, IntervalValue, LimitSpeedOverLife, MAX_TRAIL_TESSELLATION, MathUtils, Matrix3, Matrix4, MeshSurfaceEmitter, MeshSurfaceEmitterPlugin, NodeParticle, Noise, OrbitOverLife, ParticleEmitter, ParticleStore, ParticleSystem, PiecewiseBezier, PiecewiseFunction, Plugins, PointEmitter, QUARKS_FORMAT_VERSION, QuarksFormatError, QuarksLoader, QuarksPrefab, QuarksUtil, Quaternion, QuaternionView, RAD2DEG, RandomColor, RandomColorBetweenGradient, RandomQuatGenerator, RecordState, RectangleEmitter, RenderMode, Rotation3DOverLife, RotationBySpeed, RotationGeneratorFromJSON, RotationOverLife, SequencerFromJSON, ShapeTransform, SizeBySpeed, SizeOverLife, SpeedOverLife, SphereEmitter, SpriteParticle, SubEmitterInheritMask, SubParticleEmitMode, TextureSequencer, TrailParticle, TurbulenceField, UV_DISTORTION_DEFAULT_STRENGTH, UV_DISTORTION_DEFAULT_UV, VFXBatch, ValueGeneratorFromJSON, Vector2, Vector3, Vector3Function, Vector3GeneratorFromJSON, Vector3View, Vector4, Vector4View, VelocityOverLife, WebGLCoordinateSystem, WebGPUCoordinateSystem, WidthOverLength, blendCategory, cacheEnvAtlas, ceilPowerOfTwo, clamp, createEnvAtlasFromFaceUrls, createSeededRandom, cubeFaceUrls, currentFormatPath, damp, decodeSoftDepth, defaultMeshLighting, degToRad, denormalize, disposeEnvAtlas, ensureEnvAtlasFromCube, erosionEqual, euclideanModulo, floorPowerOfTwo, generateUUID, getCachedEnvAtlas, getPhysicsResolver, getRandomSource, getValueFromEmitterMode, gradientMapEqual, inverseLerp, isPowerOfTwo, lerp, loadPlugin, mapLinear, mapUVEqual, meshRimEqual, normalize, normalizeErosion, normalizeGradientMap, normalizeMapUV, normalizeMeshRim, normalizeTextureUV, normalizeUVDistortion, pingpong, planBehaviorFusion, quarksNodeId, radToDeg, randFloat, randFloatSpread, randInt, random, readBehaviorSpace, readFormat, readFormatPart, readsUV1, seededRandom, serializeEffect, setPhysicsResolver, setQuaternionFromProperEuler, setRandomSource, shaderProgram, shaderVariants, smootherstep, smoothstep, softDepthParams, speedFraction, subEmitterInheritMask, textureSourceUrl, textureUVEqual, textureUVToJSON, trailCurveTension, trailLifetime, trailMinVertexDistance, trailTessellation, trailTextureMode, trailTextureScale, unloadPlugin, uvDistortionEqual, warnFormat, withRandomSource };
10108
- export type { AdaptivePerformanceOptions, AdaptivePerformanceState, AnimationData, AnimationJSON, ApplyCollisionJSON, ApplyForceJSON, ApplySequencesJSON, AxisAngleJSON, BabylonMetaData, BeamEnd, Behavior, BehaviorJSON, BehaviorPlugin, BehaviorSpace, BezierJSON, BezierSplit, BillBoardSettings, BlendCategory, BlendOutput, BoxEmitterParameters, BufferAttributeJSON, BufferGeometryAttributesJSON, BufferGeometryDataJSON, BufferGeometryJSON, BufferIndexJSON, BurstParameters, BurstParametersJSON, ChangeEmitDirectionJSON, CircleEmitterParameters, ColorBySpeedJSON, ColorGenerator, ColorGeneratorJSON, ColorJSON, ColorOverLifeJSON, ColorRangeJSON, ConeEmitterParameters, ConstantColorJSON, ConstantValueJSON, Constructable, ContinuousLinearFunctionJSON, ContinuousLinearKeyJSON, ContinuousLinearSubType, ContinuousLinearSubTypeOf, ContinuousLinearValueJSON, CullingMode, DepthTextureOptions, DonutEmitterParameters, EdgeEmitterParameters, EffectDocumentJSON, EffectGeometryJSON, EffectImageJSON, EffectPlacement, EffectPoolOptions, EmissionState, EmitSubParticleSystemJSON, EmitterShape, EmitterShapePlugin, ErosionJSON, EulerJSON, EulerOrder, FieldType, FogTarget, ForceOverLifeJSON, FormatReadOptions, FrameOverLifeJSON, FrameOverLifeOptions, FunctionColorGenerator, FunctionJSON, FunctionValueGenerator, FusedPass, FusionStep, GeneratorMemory, GeometryArrays, GeometryEntry, GradientJSON, GradientMapChannel, GradientMapJSON, GradientRangeJSON, GravityForceJSON, GridEmitterParameters, HemisphereEmitterParameters, IAnimationData, IEmitter, IParticle, IParticleSystem, IPrefab, InheritVelocityJSON, InheritVelocityMode, InterleavedBufferJSON, IntervalValueJSON, JsonMetaData, LimitSpeedOverLifeJSON, MaterialTextureRef, MeshLighting, MeshLightingSettings, MeshRim, MeshSettings, NoiseJSON, ObjectValueType, OrbitOverLifeJSON, ParameterPair, ParameterType, Particle, ParticleEmitterJSON, ParticleErosion, ParticleErosionOptions, ParticleGradientMap, ParticleMaterialSource, ParticleSystemEvent, ParticleSystemEventType, ParticleSystemJSONParameters, ParticleSystemParameters, ParticleUVDistortion, ParticleUVDistortionOptions, PhysicsResolver, PiecewiseBezierJSON, PiecewiseBezierSegmentJSON, PlaneGeometryJSON, Plugin, QuarksBatchLoadOptions, QuarksEffectJSON, QuarksGeometryEntryJSON, QuarksGeometryJSON, QuarksImageJSON, QuarksJSONLoadEntry, QuarksLoadOptions, QuarksLoaderOptions, QuarksMaterialJSON, QuarksNodeJSON, QuarksPrefabJSON, QuarksResolveOptions, QuarksResourceKind, QuarksResourceResolver, QuarksTextureJSON, QuarksTimelineClip, RGBJSON, RandomColorBetweenGradientJSON, RandomColorJSON, RandomQuatJSON, RandomSource, RectangleEmitterParameters, RenderFace, RendererEmitterSettings, RendererEmitterSettingsJSON, Resource, Rotation3DOverLifeJSON, RotationBySpeedJSON, RotationGenerator, RotationGeneratorJSON, RotationOverLifeJSON, ScalingMode, SequenceJSON, Sequencer, SequencerJSON, SerializationOptions, SerializeEffectOptions, ShaderContext, ShaderDepth, ShaderProgram, ShaderSettings, ShaderSources, ShaderVariant, ShapeJSON, ShapeTransformJSON, SizeBySpeedJSON, SizeOverLifeJSON, SoftDepthEncoding, SortMode, SpeedOverLifeJSON, SphereEmitterParameters, SphereGeometryJSON, StoredBatchSettings, StretchedBillBoardSettings, SubEmitterInheritance, TextureSequencerJSON, TextureUV, TrailOptions, TrailSettings, TrailSettingsJSON, TrailTextureMode, TurbulenceFieldJSON, UVChannel, UVDistortionJSON, VFXBatchSettings, ValueGenerator, ValueGeneratorJSON, Vector2JSON, Vector3ArrayJSON, Vector3FunctionJSON, Vector3Generator, Vector3GeneratorJSON, Vector3JSON, Vector4JSON, VelocityOverLifeJSON, VelocityOverLifeSpace, WidthOverLengthJSON };
10519
+ export { ApplyCollision, ApplyForce, ApplySequences, AxisAngleGenerator, BatchedRenderer, BehaviorFromJSON, BehaviorToJSON, BehaviorTypes, Bezier, BoxEmitFrom, BoxEmitter, ChangeEmitDirection, CircleEmitter, ColorBySpeed, ColorGeneratorFromJSON, ColorOverLife, ColorRange, ConeEmitFrom, ConeEmitter, ConstantColor, ConstantValue, ContinuousLinearFunction, DEG2RAD, DonutEmitter, EROSION_DEFAULT_SOFTNESS, EdgeEmitter, EffectPool, EmitSubParticleSystem, EmitterFrame, EmitterFromJSON, EmitterMode, EmitterShapes, EmitterToJSON, Euler, EulerGenerator, ForceOverLife, FrameOverLife, GRADIENT_MAP_WEIGHTS, GeneratorFromJSON, Gradient, GravityForce, GridEmitter, GridSampling, HemisphereEmitter, InheritVelocity, IntervalValue, LimitSpeedOverLife, MAX_TRAIL_TESSELLATION, MathUtils, Matrix3, Matrix4, MeshSurfaceEmitter, MeshSurfaceEmitterPlugin, NodeParticle, Noise, OrbitOverLife, ParticleEmitter, ParticleStore, ParticleSystem, PiecewiseBezier, PiecewiseFunction, Plugins, PointEmitter, QUARKS_FORMAT_VERSION, QuarksFormatError, QuarksLoader, QuarksPrefab, QuarksUtil, Quaternion, QuaternionView, RAD2DEG, RandomBetweenCurves, RandomColor, RandomColorBetweenGradient, RandomQuatGenerator, RecordState, RectangleEmitter, RenderMode, Rotation3DOverLife, RotationBySpeed, RotationGeneratorFromJSON, RotationOverLife, SequencerFromJSON, ShapeTransform, SizeBySpeed, SizeOverLife, SpeedOverLife, SphereEmitter, SpriteParticle, SubEmitterInheritMask, SubParticleEmitMode, TextureSequencer, TrailParticle, TurbulenceField, UV_DISTORTION_DEFAULT_STRENGTH, UV_DISTORTION_DEFAULT_UV, VFXBatch, ValueGeneratorFromJSON, Vector2, Vector3, Vector3Function, Vector3GeneratorFromJSON, Vector3View, Vector4, Vector4View, VelocityOverLife, WebGLCoordinateSystem, WebGPUCoordinateSystem, WidthOverLength, blendCategory, cacheEnvAtlas, ceilPowerOfTwo, clamp, createEnvAtlasFromFaceUrls, createSeededRandom, cubeFaceUrls, currentFormatPath, damp, decodeSoftDepth, defaultMeshLighting, degToRad, denormalize, disposeEnvAtlas, ensureEnvAtlasFromCube, erosionEqual, euclideanModulo, floorPowerOfTwo, generateUUID, getCachedEnvAtlas, getPhysicsResolver, getRandomSource, getValueFromEmitterMode, gradientMapEqual, inverseLerp, isPowerOfTwo, lerp, loadPlugin, mapLinear, mapUVEqual, meshRimEqual, normalize, normalizeErosion, normalizeGradientMap, normalizeMapUV, normalizeMeshRim, normalizeTextureUV, normalizeUVDistortion, pingpong, planBehaviorFusion, quarksNodeId, radToDeg, randFloat, randFloatSpread, randInt, random, readBehaviorSpace, readFormat, readFormatPart, readsUV1, seededRandom, serializeEffect, setPhysicsResolver, setQuaternionFromProperEuler, setRandomSource, shaderProgram, shaderVariants, smootherstep, smoothstep, softDepthParams, speedFraction, subEmitterInheritMask, textureSourceUrl, textureUVEqual, textureUVToJSON, trailCurveTension, trailLifetime, trailMinVertexDistance, trailTessellation, trailTextureMode, trailTextureScale, unloadPlugin, uvDistortionEqual, warnFormat, withRandomSource };
10520
+ export type { AdaptivePerformanceOptions, AdaptivePerformanceState, AnimationData, AnimationJSON, ApplyCollisionJSON, ApplyForceJSON, ApplySequencesJSON, AxisAngleJSON, BabylonMetaData, BeamEnd, Behavior, BehaviorJSON, BehaviorPlugin, BehaviorSpace, BezierJSON, BezierSplit, BillBoardSettings, BlendCategory, BlendOutput, BoxEmitterParameters, BufferAttributeJSON, BufferGeometryAttributesJSON, BufferGeometryDataJSON, BufferGeometryJSON, BufferIndexJSON, BurstParameters, BurstParametersJSON, ChangeEmitDirectionJSON, CircleEmitterParameters, ColorBySpeedJSON, ColorGenerator, ColorGeneratorJSON, ColorJSON, ColorOverLifeJSON, ColorRangeJSON, ConeEmitterParameters, ConstantColorJSON, ConstantValueJSON, Constructable, ContinuousLinearFunctionJSON, ContinuousLinearKeyJSON, ContinuousLinearSubType, ContinuousLinearSubTypeOf, ContinuousLinearValueJSON, CullingMode, DepthTextureOptions, DonutEmitterParameters, EdgeEmitterParameters, EffectDocumentJSON, EffectGeometryJSON, EffectImageJSON, EffectPlacement, EffectPoolOptions, EmissionState, EmitSubParticleSystemJSON, EmitterShape, EmitterShapePlugin, ErosionJSON, EulerJSON, EulerOrder, FieldType, FogTarget, ForceOverLifeJSON, FormatReadOptions, FrameOverLifeJSON, FrameOverLifeOptions, FunctionColorGenerator, FunctionJSON, FunctionValueGenerator, FusedPass, FusionStep, GeneratorMemory, GeometryArrays, GeometryEntry, GradientJSON, GradientMapChannel, GradientMapJSON, GradientRangeJSON, GravityForceJSON, GridEmitterParameters, HemisphereEmitterParameters, IAnimationData, IEmitter, IParticle, IParticleSystem, IPrefab, InheritVelocityJSON, InheritVelocityMode, InterleavedBufferJSON, IntervalValueJSON, JsonMetaData, LimitSpeedOverLifeJSON, MaterialTextureRef, MeshLighting, MeshLightingSettings, MeshRim, MeshSettings, NoiseJSON, ObjectValueType, OrbitOverLifeJSON, ParameterPair, ParameterType, Particle, ParticleEmitterJSON, ParticleErosion, ParticleErosionOptions, ParticleGradientMap, ParticleMaterialSource, ParticleSystemEvent, ParticleSystemEventType, ParticleSystemJSONParameters, ParticleSystemParameters, ParticleUVDistortion, ParticleUVDistortionOptions, PhysicsResolver, PiecewiseBezierJSON, PiecewiseBezierSegmentJSON, PlaneGeometryJSON, Plugin, QuarksBatchLoadOptions, QuarksEffectJSON, QuarksGeometryEntryJSON, QuarksGeometryJSON, QuarksImageJSON, QuarksJSONLoadEntry, QuarksLoadOptions, QuarksLoaderOptions, QuarksMaterialJSON, QuarksNodeJSON, QuarksPrefabJSON, QuarksResolveOptions, QuarksResourceKind, QuarksResourceResolver, QuarksTextureJSON, QuarksTimelineClip, RGBJSON, RandomBetweenCurvesJSON, RandomColorBetweenGradientJSON, RandomColorJSON, RandomQuatJSON, RandomSource, RectangleEmitterParameters, RenderFace, RendererEmitterSettings, RendererEmitterSettingsJSON, Resource, RingBufferMode, Rotation3DOverLifeJSON, RotationBySpeedJSON, RotationGenerator, RotationGeneratorJSON, RotationOverLifeJSON, ScalingMode, SequenceJSON, Sequencer, SequencerJSON, SerializationOptions, SerializeEffectOptions, ShaderContext, ShaderDepth, ShaderProgram, ShaderSettings, ShaderSources, ShaderVariant, ShapeJSON, ShapeTransformJSON, SizeBySpeedJSON, SizeOverLifeJSON, SoftDepthEncoding, SortMode, SpeedOverLifeJSON, SphereEmitterParameters, SphereGeometryJSON, StopAction, StoredBatchSettings, StretchedBillBoardSettings, SubEmitterInheritance, TextureSequencerJSON, TextureUV, TrailOptions, TrailSettings, TrailSettingsJSON, TrailTextureMode, TurbulenceFieldJSON, UVChannel, UVDistortionJSON, VFXBatchSettings, ValueGenerator, ValueGeneratorJSON, Vector2JSON, Vector3ArrayJSON, Vector3FunctionJSON, Vector3Generator, Vector3GeneratorJSON, Vector3JSON, Vector4JSON, VelocityOverLifeJSON, VelocityOverLifeSpace, WidthOverLengthJSON };