babylon.quarks 0.26.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +769 -8
- package/README.md +10 -8
- package/dist/babylon.quarks.cjs +1 -1
- package/dist/babylon.quarks.cjs.map +1 -1
- package/dist/babylon.quarks.esm.js +1 -1
- package/dist/babylon.quarks.esm.js.map +1 -1
- package/dist/babylon.quarks.umd.min.js +1 -1
- package/dist/babylon.quarks.umd.min.js.map +1 -1
- package/dist/types/index.d.cts +6683 -0
- package/dist/types/index.d.ts +1959 -588
- package/package.json +12 -6
- package/src/BatchedRenderer.ts +204 -101
- package/src/EffectPool.ts +4 -1
- package/src/MeshSurfaceEmitter.ts +29 -4
- package/src/ParticleEmitter.ts +45 -15
- package/src/ParticleSystem.ts +909 -2061
- package/src/QuarksLoader.ts +421 -67
- package/src/QuarksPrefab.ts +91 -4
- package/src/QuarksSerializer.ts +484 -0
- package/src/QuarksUtil.ts +15 -0
- package/src/SpriteBatch.ts +106 -246
- package/src/TrailBatch.ts +533 -342
- package/src/VFXBatch.ts +236 -136
- package/src/batchKey.ts +237 -0
- package/src/effectResources.ts +79 -0
- package/src/envAtlas.ts +119 -17
- package/src/index.ts +32 -33
- package/src/nodeId.ts +13 -0
- package/src/shaderProgram.ts +325 -0
- package/src/shaderVariants.ts +225 -0
- package/src/shaders/chunks/fog.ts +4 -2
- package/src/shaders/chunks/sheet.ts +111 -0
- package/src/shaders/chunks/soft.ts +84 -0
- package/src/shaders/chunks/surface.ts +10 -0
- package/src/shaders/local_particle_physics_vert.glsl.ts +14 -28
- package/src/shaders/local_particle_physics_vert.wgsl.ts +16 -29
- package/src/shaders/particle_frag.glsl.ts +3 -22
- package/src/shaders/particle_frag.wgsl.ts +3 -23
- package/src/shaders/particle_physics_frag.glsl.ts +12 -25
- package/src/shaders/particle_physics_frag.wgsl.ts +12 -26
- package/src/shaders/particle_vert.glsl.ts +5 -27
- package/src/shaders/particle_vert.wgsl.ts +5 -26
- package/src/shaders/stretched_bb_particle_vert.glsl.ts +7 -33
- package/src/shaders/stretched_bb_particle_vert.wgsl.ts +7 -33
- package/src/shaders/trail_frag.glsl.ts +11 -1
- package/src/shaders/trail_frag.wgsl.ts +11 -0
- package/src/shaders/trail_vert.glsl.ts +45 -36
- package/src/shaders/trail_vert.wgsl.ts +46 -40
- package/src/softDepth.ts +136 -0
- package/src/system/BehaviorPlan.ts +85 -0
- package/src/system/BoundsTracker.ts +181 -0
- package/src/system/EmissionController.ts +360 -0
- package/src/system/EventDispatcher.ts +44 -0
- package/src/system/ParticleSpawner.ts +274 -0
- package/src/system/SimulationClock.ts +130 -0
- package/src/system/geometry.ts +111 -0
- package/src/system/integrate.ts +428 -0
- package/src/system/materialResolve.ts +116 -0
- package/src/system/normalize.ts +95 -0
- package/src/system/serialization.ts +401 -0
- package/src/system/settingsSchema.ts +317 -0
- package/src/system/types.ts +410 -0
- package/src/textureSource.ts +30 -0
- package/src/trailSettings.ts +51 -0
- package/src/BatchedParticleRenderer.ts +0 -3
- package/src/materials/ParticleMaterials.ts +0 -23
- package/src/materials/index.ts +0 -1
- package/src/shaders/chunks/index.ts +0 -1
- package/src/shaders/chunks/register-shader-chunks.ts +0 -32
- package/src/shaders/chunks/soft_fragment.glsl.ts +0 -13
- package/src/shaders/chunks/soft_pars_fragment.glsl.ts +0 -20
- package/src/shaders/chunks/soft_pars_vertex.glsl.ts +0 -6
- package/src/shaders/chunks/soft_vertex.glsl.ts +0 -6
- package/src/shaders/chunks/tile_fragment.glsl.ts +0 -9
- package/src/shaders/chunks/tile_pars_fragment.glsl.ts +0 -9
- package/src/shaders/chunks/tile_pars_vertex.glsl.ts +0 -28
- package/src/shaders/chunks/tile_vertex.glsl.ts +0 -18
- package/src/shaders/index.ts +0 -9
- package/src/shaders/local_particle_vert.glsl.ts +0 -50
package/src/VFXBatch.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {BoundingInfo} from '@babylonjs/core/Culling/boundingInfo';
|
|
2
|
-
import {Constants} from '@babylonjs/core/Engines/constants';
|
|
3
2
|
import {BaseTexture} from '@babylonjs/core/Materials/Textures/baseTexture';
|
|
3
|
+
import type {Effect} from '@babylonjs/core/Materials/effect';
|
|
4
4
|
import {ShaderMaterial} from '@babylonjs/core/Materials/shaderMaterial';
|
|
5
5
|
import {Color3} from '@babylonjs/core/Maths/math.color';
|
|
6
6
|
import {Vector2 as BVector2, Vector3 as BVector3, Vector4 as BVector4} from '@babylonjs/core/Maths/math.vector';
|
|
@@ -9,6 +9,8 @@ import {Scene} from '@babylonjs/core/scene';
|
|
|
9
9
|
import {IParticleSystem, Vector3} from 'quarks.core';
|
|
10
10
|
import {VFXBatchSettings} from './BatchedRenderer';
|
|
11
11
|
import type {ParticleSystem} from './ParticleSystem';
|
|
12
|
+
import {storedBatchSettings} from './batchKey';
|
|
13
|
+
import {DepthBinding, softDepthParams} from './softDepth';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* The order the particles of a batch are drawn in (Unity's Sort Mode). Alpha
|
|
@@ -23,12 +25,25 @@ import type {ParticleSystem} from './ParticleSystem';
|
|
|
23
25
|
*/
|
|
24
26
|
export type SortMode = 'none' | 'distance' | 'oldestInFront' | 'youngestInFront';
|
|
25
27
|
|
|
28
|
+
/** How a system draws its particles (Unity's Render Mode), see {@link ParticleSystem.renderMode}. */
|
|
26
29
|
export enum RenderMode {
|
|
30
|
+
/** A quad facing the camera (Unity's Billboard). The default. */
|
|
27
31
|
BillBoard = 0,
|
|
32
|
+
/**
|
|
33
|
+
* A quad facing the camera and stretched along the particle's velocity (Unity's Stretched
|
|
34
|
+
* Billboard), by `speedFactor` and `lengthFactor` in the system's `rendererEmitterSettings`.
|
|
35
|
+
*/
|
|
28
36
|
StretchedBillBoard = 1,
|
|
37
|
+
/** The system's mesh, one instance per particle (Unity's Mesh), see {@link ParticleSystem.instancingGeometry}. */
|
|
29
38
|
Mesh = 2,
|
|
39
|
+
/**
|
|
40
|
+
* A ribbon drawn through the particle's past positions (Unity's Trails module, Niagara's
|
|
41
|
+
* ribbon), facing the camera; its settings are `TrailSettings` in `rendererEmitterSettings`.
|
|
42
|
+
*/
|
|
30
43
|
Trail = 3,
|
|
44
|
+
/** A quad lying flat in the world's XZ plane, facing up (Unity's Horizontal Billboard). */
|
|
31
45
|
HorizontalBillBoard = 4,
|
|
46
|
+
/** A quad standing upright and turning only about the world's Y axis to face the camera (Unity's Vertical Billboard). */
|
|
32
47
|
VerticalBillBoard = 5,
|
|
33
48
|
/**
|
|
34
49
|
* A quad laid from each particle to the system's {@link ParticleSystem.beamEnd}
|
|
@@ -224,8 +239,9 @@ export type GradientMapChannel = 'r' | 'g' | 'b' | 'a' | 'luminance';
|
|
|
224
239
|
|
|
225
240
|
/**
|
|
226
241
|
* A gradient map (colour ramp): the map is recoloured by looking its
|
|
227
|
-
* {@link channel} up along U of {@link ramp}.
|
|
228
|
-
*
|
|
242
|
+
* {@link channel} up along U of {@link ramp}. Without a map the lookup reads
|
|
243
|
+
* white, so the ramp's right-hand end tints every particle, in every render
|
|
244
|
+
* mode alike. See {@link VFXBatchSettings.gradientMap}.
|
|
229
245
|
*/
|
|
230
246
|
export interface ParticleGradientMap {
|
|
231
247
|
/**
|
|
@@ -301,7 +317,13 @@ export interface ParticleErosion {
|
|
|
301
317
|
// Scrolling runs on the renderer's clock, not a system's playback speed.
|
|
302
318
|
|
|
303
319
|
/** {@link ParticleErosion} as given: any field may be left out, the mask's layout too. */
|
|
304
|
-
export type ParticleErosionOptions = Partial<Omit<ParticleErosion, 'maskUV'>> & {
|
|
320
|
+
export type ParticleErosionOptions = Partial<Omit<ParticleErosion, 'maskUV'>> & {
|
|
321
|
+
/** See {@link ParticleErosion.maskUV}; fields left out take their defaults. */
|
|
322
|
+
maskUV?: Partial<TextureUV>;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
/** The width of the soft band an erosion cut fades over when `softness` is left out, in mask units. */
|
|
326
|
+
export const EROSION_DEFAULT_SOFTNESS = 0.05;
|
|
305
327
|
|
|
306
328
|
/** A complete erosion from a partial one, every field defaulted, or undefined when `erosion` is unset. */
|
|
307
329
|
export function normalizeErosion(erosion: ParticleErosionOptions | null | undefined): ParticleErosion | undefined {
|
|
@@ -314,7 +336,7 @@ export function normalizeErosion(erosion: ParticleErosionOptions | null | undefi
|
|
|
314
336
|
return {
|
|
315
337
|
mask: erosion.mask ?? null,
|
|
316
338
|
maskUV: normalizeTextureUV(erosion.maskUV),
|
|
317
|
-
softness: Math.max(0.0001, num(erosion.softness,
|
|
339
|
+
softness: Math.max(0.0001, num(erosion.softness, EROSION_DEFAULT_SOFTNESS)),
|
|
318
340
|
edgeWidth: Math.max(0, num(erosion.edgeWidth, 0)),
|
|
319
341
|
edgeColor: [num(color[0], 1), num(color[1], 1), num(color[2], 1)],
|
|
320
342
|
};
|
|
@@ -363,7 +385,13 @@ export interface ParticleUVDistortion {
|
|
|
363
385
|
}
|
|
364
386
|
|
|
365
387
|
/** {@link ParticleUVDistortion} as given: any field may be left out, the noise's layout too. */
|
|
366
|
-
export type ParticleUVDistortionOptions = Partial<Omit<ParticleUVDistortion, 'mapUV'>> & {
|
|
388
|
+
export type ParticleUVDistortionOptions = Partial<Omit<ParticleUVDistortion, 'mapUV'>> & {
|
|
389
|
+
/** See {@link ParticleUVDistortion.mapUV}; fields left out take their defaults. */
|
|
390
|
+
mapUV?: Partial<TextureUV>;
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
/** How far a distortion pushes the map's UV at most when `strength` is left out, in UV units. */
|
|
394
|
+
export const UV_DISTORTION_DEFAULT_STRENGTH = 0.05;
|
|
367
395
|
|
|
368
396
|
/** A complete distortion from a partial one, or undefined when unset or without a map. */
|
|
369
397
|
export function normalizeUVDistortion(
|
|
@@ -376,7 +404,10 @@ export function normalizeUVDistortion(
|
|
|
376
404
|
return {
|
|
377
405
|
map: distortion.map,
|
|
378
406
|
mapUV: normalizeTextureUV(distortion.mapUV, UV_DISTORTION_DEFAULT_UV),
|
|
379
|
-
strength: Math.max(
|
|
407
|
+
strength: Math.max(
|
|
408
|
+
0,
|
|
409
|
+
typeof strength === 'number' && Number.isFinite(strength) ? strength : UV_DISTORTION_DEFAULT_STRENGTH
|
|
410
|
+
),
|
|
380
411
|
};
|
|
381
412
|
}
|
|
382
413
|
|
|
@@ -424,31 +455,58 @@ export function readsUV1(settings: {
|
|
|
424
455
|
);
|
|
425
456
|
}
|
|
426
457
|
|
|
458
|
+
/**
|
|
459
|
+
* A batch's copy of the {@link VFXBatchSettings} its systems share: every optional field
|
|
460
|
+
* defaulted, and every field the batch's render mode ignores at its default (an opaque batch's
|
|
461
|
+
* `materialBlendMode` reads `ALPHA_DISABLE`, a billboard batch's `rim` is unset). The renderer
|
|
462
|
+
* adds a system to the batch whose settings match its own.
|
|
463
|
+
*/
|
|
427
464
|
export interface StoredBatchSettings {
|
|
465
|
+
/** See {@link VFXBatchSettings.instancingGeometry}. */
|
|
428
466
|
instancingGeometry: Float32Array;
|
|
467
|
+
/** See {@link VFXBatchSettings.instancingIndices}. */
|
|
429
468
|
instancingIndices: Uint32Array | Uint16Array;
|
|
469
|
+
/** See {@link VFXBatchSettings.instancingUVs}. */
|
|
430
470
|
instancingUVs?: Float32Array;
|
|
431
471
|
/** The mesh's second UV set, see {@link UVChannel}. */
|
|
432
472
|
instancingUVs2?: Float32Array;
|
|
473
|
+
/** See {@link VFXBatchSettings.instancingNormals}. */
|
|
433
474
|
instancingNormals?: Float32Array;
|
|
475
|
+
/** See {@link VFXBatchSettings.renderMode}. */
|
|
434
476
|
renderMode: RenderMode;
|
|
477
|
+
/** See {@link VFXBatchSettings.renderOrder}. */
|
|
435
478
|
renderOrder: number;
|
|
479
|
+
/** See {@link VFXBatchSettings.uTileCount}. */
|
|
436
480
|
uTileCount: number;
|
|
481
|
+
/** See {@link VFXBatchSettings.vTileCount}. */
|
|
437
482
|
vTileCount: number;
|
|
483
|
+
/** See {@link VFXBatchSettings.blendTiles}. */
|
|
438
484
|
blendTiles: boolean;
|
|
485
|
+
/** See {@link VFXBatchSettings.softParticles}. */
|
|
439
486
|
softParticles: boolean;
|
|
487
|
+
/** See {@link VFXBatchSettings.softNearFade}. */
|
|
440
488
|
softNearFade: number;
|
|
489
|
+
/** See {@link VFXBatchSettings.softFarFade}. */
|
|
441
490
|
softFarFade: number;
|
|
491
|
+
/** See {@link VFXBatchSettings.materialBlendMode}. */
|
|
442
492
|
materialBlendMode: number;
|
|
493
|
+
/** See {@link VFXBatchSettings.materialTransparent}. */
|
|
443
494
|
materialTransparent: boolean;
|
|
495
|
+
/** See {@link VFXBatchSettings.materialDepthTest}. */
|
|
444
496
|
materialDepthTest: boolean;
|
|
497
|
+
/** See {@link VFXBatchSettings.materialDepthWrite}. */
|
|
445
498
|
materialDepthWrite: boolean;
|
|
499
|
+
/** See {@link VFXBatchSettings.materialAlphaTest}. */
|
|
446
500
|
materialAlphaTest: number;
|
|
447
|
-
texture
|
|
501
|
+
/** See {@link VFXBatchSettings.texture}. */
|
|
502
|
+
texture: BaseTexture | null;
|
|
503
|
+
/** See {@link VFXBatchSettings.reflectionTexture}. */
|
|
448
504
|
reflectionTexture: BaseTexture | null;
|
|
505
|
+
/** See {@link VFXBatchSettings.reflectionLevel}. */
|
|
449
506
|
reflectionLevel: number;
|
|
450
|
-
|
|
507
|
+
/** See {@link VFXBatchSettings.reflectionAtlas}. */
|
|
451
508
|
reflectionAtlas: BaseTexture | null;
|
|
509
|
+
/** See {@link VFXBatchSettings.layerMask}. */
|
|
452
510
|
layerMask: number;
|
|
453
511
|
/** Babylon rendering group the batch mesh draws in, see {@link VFXBatchSettings.renderingGroupId}. */
|
|
454
512
|
renderingGroupId: number;
|
|
@@ -476,56 +534,38 @@ export interface StoredBatchSettings {
|
|
|
476
534
|
erosion?: ParticleErosion;
|
|
477
535
|
}
|
|
478
536
|
|
|
537
|
+
/**
|
|
538
|
+
* One draw call of a {@link BatchedRenderer}: the systems that share a material, texture and
|
|
539
|
+
* geometry, drawn together from one instanced mesh. The renderer makes and frees batches as
|
|
540
|
+
* systems are added and their settings change; read them through `renderer.batches` to inspect
|
|
541
|
+
* what is drawn, not to change it.
|
|
542
|
+
*/
|
|
479
543
|
export abstract class VFXBatch {
|
|
544
|
+
/** The Babylon mesh the batch draws with. */
|
|
480
545
|
mesh: Mesh;
|
|
546
|
+
/** The systems drawn by this batch. */
|
|
481
547
|
systems: Set<IParticleSystem>;
|
|
548
|
+
/** The settings every system in the batch shares, with what the render mode ignores at its default. */
|
|
482
549
|
settings: StoredBatchSettings;
|
|
550
|
+
/** @internal */
|
|
483
551
|
protected maxParticles: number;
|
|
552
|
+
/** @internal */
|
|
484
553
|
protected scene: Scene;
|
|
554
|
+
/** @internal */
|
|
485
555
|
protected readonly visibleSystems: IParticleSystem[] = [];
|
|
556
|
+
/**
|
|
557
|
+
* The depth texture soft particles read, from {@link BatchedRenderer.setDepthTexture}.
|
|
558
|
+
* @internal
|
|
559
|
+
*/
|
|
560
|
+
protected depth: DepthBinding | null;
|
|
486
561
|
|
|
487
|
-
|
|
562
|
+
/** @internal */
|
|
563
|
+
protected constructor(settings: VFXBatchSettings, scene: Scene, depth: DepthBinding | null = null) {
|
|
488
564
|
this.scene = scene;
|
|
565
|
+
this.depth = depth;
|
|
489
566
|
this.maxParticles = 1000;
|
|
490
567
|
this.systems = new Set<IParticleSystem>();
|
|
491
|
-
this.settings =
|
|
492
|
-
instancingGeometry: settings.instancingGeometry,
|
|
493
|
-
instancingIndices: settings.instancingIndices,
|
|
494
|
-
instancingUVs: settings.instancingUVs,
|
|
495
|
-
instancingUVs2: settings.instancingUVs2,
|
|
496
|
-
instancingNormals: settings.instancingNormals,
|
|
497
|
-
renderMode: settings.renderMode,
|
|
498
|
-
renderOrder: settings.renderOrder,
|
|
499
|
-
uTileCount: settings.uTileCount,
|
|
500
|
-
vTileCount: settings.vTileCount,
|
|
501
|
-
blendTiles: settings.blendTiles,
|
|
502
|
-
softParticles: settings.softParticles,
|
|
503
|
-
softNearFade: settings.softNearFade,
|
|
504
|
-
softFarFade: settings.softFarFade,
|
|
505
|
-
materialBlendMode: settings.materialBlendMode,
|
|
506
|
-
materialTransparent: settings.materialTransparent,
|
|
507
|
-
materialDepthTest: settings.materialDepthTest,
|
|
508
|
-
materialDepthWrite: settings.materialDepthWrite,
|
|
509
|
-
materialAlphaTest: settings.materialAlphaTest,
|
|
510
|
-
texture: settings.texture,
|
|
511
|
-
reflectionTexture: settings.reflectionTexture ?? null,
|
|
512
|
-
reflectionLevel: settings.reflectionLevel ?? 1,
|
|
513
|
-
reflectionFaces: settings.reflectionFaces ?? null,
|
|
514
|
-
reflectionAtlas: settings.reflectionAtlas ?? null,
|
|
515
|
-
pivot: settings.pivot?.clone(),
|
|
516
|
-
sortMode: settings.sortMode ?? 'none',
|
|
517
|
-
minParticleSize: settings.minParticleSize ?? 0,
|
|
518
|
-
maxParticleSize: settings.maxParticleSize ?? Infinity,
|
|
519
|
-
layerMask: settings.layerMask,
|
|
520
|
-
renderingGroupId: settings.renderingGroupId ?? 0,
|
|
521
|
-
applyFog: settings.applyFog ?? true,
|
|
522
|
-
lighting: settings.lighting,
|
|
523
|
-
rim: normalizeMeshRim(settings.rim),
|
|
524
|
-
mapUV: normalizeMapUV(settings.mapUV),
|
|
525
|
-
uvDistortion: normalizeUVDistortion(settings.uvDistortion),
|
|
526
|
-
gradientMap: normalizeGradientMap(settings.gradientMap),
|
|
527
|
-
erosion: normalizeErosion(settings.erosion),
|
|
528
|
-
};
|
|
568
|
+
this.settings = storedBatchSettings(settings);
|
|
529
569
|
this.mesh = new Mesh('vfxBatch', scene);
|
|
530
570
|
this.configureMesh();
|
|
531
571
|
}
|
|
@@ -553,6 +593,12 @@ export abstract class VFXBatch {
|
|
|
553
593
|
mesh.alphaIndex = this.settings.renderOrder;
|
|
554
594
|
// The shaders fog themselves; Babylon's own fog pass does not apply to a ShaderMaterial.
|
|
555
595
|
mesh.applyFog = false;
|
|
596
|
+
// Its geometry is one quad or mesh at the origin, not the particles, so a pick or a
|
|
597
|
+
// collision against it would hit nothing that is drawn. The renderer rebuilds batches
|
|
598
|
+
// from its systems, so a scene serializer has nothing to write either.
|
|
599
|
+
mesh.isPickable = false;
|
|
600
|
+
mesh.checkCollisions = false;
|
|
601
|
+
mesh.doNotSerialize = true;
|
|
556
602
|
}
|
|
557
603
|
|
|
558
604
|
private readonly boundsMin_ = new Vector3();
|
|
@@ -615,23 +661,26 @@ export abstract class VFXBatch {
|
|
|
615
661
|
}
|
|
616
662
|
|
|
617
663
|
/**
|
|
618
|
-
*
|
|
619
|
-
*
|
|
620
|
-
*
|
|
664
|
+
* Writes a uniform that changes per bind, such as one read off the active camera, to the
|
|
665
|
+
* material for the next bind and to its bound effect for this one: ShaderMaterial uploads its
|
|
666
|
+
* stored values before the bind observers run, so a value written only to the material would
|
|
667
|
+
* reach the GPU one draw late, and with two cameras it would always be the other camera's.
|
|
621
668
|
*/
|
|
622
|
-
protected static
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
669
|
+
protected static writeBound(material: ShaderMaterial, write: (target: ShaderMaterial | Effect) => void): void {
|
|
670
|
+
write(material);
|
|
671
|
+
// An effect still compiling has no pipeline context to write to; it gets the stored value
|
|
672
|
+
// when it is first bound. A sub mesh's effect override is not reached here.
|
|
673
|
+
const effect = material.getEffect();
|
|
674
|
+
if (effect?.isReady()) {
|
|
675
|
+
write(effect);
|
|
627
676
|
}
|
|
628
|
-
const additive =
|
|
629
|
-
this.settings.materialTransparent &&
|
|
630
|
-
(this.settings.materialBlendMode === Constants.ALPHA_ADD ||
|
|
631
|
-
this.settings.materialBlendMode === Constants.ALPHA_ONEONE);
|
|
632
|
-
return additive ? ['FOG', 'FOG_ADDITIVE'] : ['FOG'];
|
|
633
677
|
}
|
|
634
678
|
|
|
679
|
+
/**
|
|
680
|
+
* The per-bind upload of the scene's current fog. Mode 0 (none) when the scene has fog
|
|
681
|
+
* disabled, so toggling fog at runtime needs no recompile.
|
|
682
|
+
* @internal
|
|
683
|
+
*/
|
|
635
684
|
protected bindFog(material: ShaderMaterial): void {
|
|
636
685
|
if (!this.settings.applyFog) {
|
|
637
686
|
return;
|
|
@@ -659,85 +708,19 @@ export abstract class VFXBatch {
|
|
|
659
708
|
return readsUV1(this.settings);
|
|
660
709
|
}
|
|
661
710
|
|
|
662
|
-
/** Defines of the texture effects (see `shaders/chunks/surface.ts`) this batch uses. */
|
|
663
|
-
protected surfaceDefines(): string[] {
|
|
664
|
-
const defines: string[] = [];
|
|
665
|
-
const {mapUV, uvDistortion, gradientMap, erosion} = this.settings;
|
|
666
|
-
if (this.usesUV1()) {
|
|
667
|
-
defines.push('UV1');
|
|
668
|
-
}
|
|
669
|
-
if (mapUV) {
|
|
670
|
-
defines.push('MAP_TRANSFORM');
|
|
671
|
-
if (mapUV.channel === 1) {
|
|
672
|
-
defines.push('MAP_UV1');
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
if (uvDistortion) {
|
|
676
|
-
defines.push('UV_DISTORTION');
|
|
677
|
-
if (uvDistortion.mapUV.channel === 1) {
|
|
678
|
-
defines.push('UV_DISTORTION_UV1');
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
if (gradientMap) {
|
|
682
|
-
defines.push('GRADIENT_MAP');
|
|
683
|
-
}
|
|
684
|
-
if (erosion) {
|
|
685
|
-
defines.push('EROSION');
|
|
686
|
-
if (erosion.mask) {
|
|
687
|
-
defines.push('EROSION_MASK');
|
|
688
|
-
if (erosion.maskUV.channel === 1) {
|
|
689
|
-
defines.push('EROSION_MASK_UV1');
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
return defines;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
/** Adds the uniforms and samplers of the texture effects this batch uses. */
|
|
697
|
-
protected surfaceUniforms(uniforms: string[], samplers: string[]): void {
|
|
698
|
-
const {mapUV, uvDistortion, gradientMap, erosion} = this.settings;
|
|
699
|
-
if (mapUV) {
|
|
700
|
-
uniforms.push('mapTransform');
|
|
701
|
-
}
|
|
702
|
-
if (uvDistortion) {
|
|
703
|
-
samplers.push('distortionMap');
|
|
704
|
-
uniforms.push('distortionTransform', 'distortionStrength');
|
|
705
|
-
}
|
|
706
|
-
if (gradientMap) {
|
|
707
|
-
samplers.push('gradientMap');
|
|
708
|
-
uniforms.push('gradientMapRange', 'gradientMapChannel');
|
|
709
|
-
}
|
|
710
|
-
if (erosion) {
|
|
711
|
-
uniforms.push('erosionParams', 'erosionEdgeColor');
|
|
712
|
-
if (erosion.mask) {
|
|
713
|
-
samplers.push('erosionMask');
|
|
714
|
-
uniforms.push('erosionMaskTransform');
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
|
|
719
711
|
/** Sets the texture effects' textures and constants, and advances their scrolling on every bind. */
|
|
720
712
|
protected bindSurface(material: ShaderMaterial): void {
|
|
721
713
|
const {mapUV, uvDistortion, gradientMap, erosion} = this.settings;
|
|
722
714
|
if (uvDistortion?.map) {
|
|
723
715
|
material.setTexture('distortionMap', uvDistortion.map);
|
|
724
|
-
material.setFloat('distortionStrength', uvDistortion.strength);
|
|
725
716
|
}
|
|
726
717
|
if (gradientMap?.ramp) {
|
|
727
718
|
material.setTexture('gradientMap', gradientMap.ramp);
|
|
728
|
-
const [r, g, b, a] = GRADIENT_MAP_WEIGHTS[gradientMap.channel];
|
|
729
|
-
material.setVector4('gradientMapChannel', new BVector4(r, g, b, a));
|
|
730
719
|
}
|
|
731
|
-
if (erosion) {
|
|
732
|
-
|
|
733
|
-
material.setTexture('erosionMask', erosion.mask);
|
|
734
|
-
}
|
|
735
|
-
material.setVector2('erosionParams', new BVector2(erosion.softness, erosion.edgeWidth));
|
|
736
|
-
material.setVector3(
|
|
737
|
-
'erosionEdgeColor',
|
|
738
|
-
new BVector3(erosion.edgeColor[0], erosion.edgeColor[1], erosion.edgeColor[2])
|
|
739
|
-
);
|
|
720
|
+
if (erosion?.mask) {
|
|
721
|
+
material.setTexture('erosionMask', erosion.mask);
|
|
740
722
|
}
|
|
723
|
+
this.writeSurfaceParams(material);
|
|
741
724
|
if (!mapUV && !uvDistortion && !erosion?.mask && !gradientMap) {
|
|
742
725
|
return;
|
|
743
726
|
}
|
|
@@ -760,9 +743,12 @@ export abstract class VFXBatch {
|
|
|
760
743
|
);
|
|
761
744
|
// Written to the material for the next bind and to the bound effect for
|
|
762
745
|
// this one: ShaderMaterial uploads its values before the bind observers run.
|
|
746
|
+
// The layouts are read off the settings on every bind, so a live change
|
|
747
|
+
// to a tiling or scroll reaches the next draw.
|
|
763
748
|
const write = () => {
|
|
764
749
|
const time = this.time;
|
|
765
750
|
const effect = material.getEffect();
|
|
751
|
+
const {mapUV, uvDistortion, gradientMap, erosion} = this.settings;
|
|
766
752
|
if (mapUV) {
|
|
767
753
|
transform(mapUV, time, mapTransform);
|
|
768
754
|
material.setVector4('mapTransform', mapTransform);
|
|
@@ -792,11 +778,56 @@ export abstract class VFXBatch {
|
|
|
792
778
|
material.onBindObservable.add(write);
|
|
793
779
|
}
|
|
794
780
|
|
|
795
|
-
|
|
781
|
+
/** Writes the texture effects' constants (the uniforms their live parameters set). */
|
|
782
|
+
private writeSurfaceParams(material: ShaderMaterial): void {
|
|
783
|
+
const {uvDistortion, gradientMap, erosion} = this.settings;
|
|
784
|
+
if (uvDistortion?.map) {
|
|
785
|
+
material.setFloat('distortionStrength', uvDistortion.strength);
|
|
786
|
+
}
|
|
787
|
+
if (gradientMap?.ramp) {
|
|
788
|
+
const [r, g, b, a] = GRADIENT_MAP_WEIGHTS[gradientMap.channel];
|
|
789
|
+
material.setVector4('gradientMapChannel', new BVector4(r, g, b, a));
|
|
790
|
+
}
|
|
791
|
+
if (erosion) {
|
|
792
|
+
material.setVector2('erosionParams', new BVector2(erosion.softness, erosion.edgeWidth));
|
|
793
|
+
material.setVector3(
|
|
794
|
+
'erosionEdgeColor',
|
|
795
|
+
new BVector3(erosion.edgeColor[0], erosion.edgeColor[1], erosion.edgeColor[2])
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
* Takes new live parameters (see {@link BatchedRenderer.updateSystem}): settings with the same
|
|
802
|
+
* shader key as the batch's, whose uniform values differ. They are copied into the batch's
|
|
803
|
+
* settings and written to its material, which is kept.
|
|
804
|
+
* @internal
|
|
805
|
+
*/
|
|
806
|
+
applyLiveSettings(settings: StoredBatchSettings): void {
|
|
807
|
+
Object.assign(this.settings, settings);
|
|
808
|
+
const material = this.mesh.material;
|
|
809
|
+
if (material instanceof ShaderMaterial) {
|
|
810
|
+
this.writeLiveUniforms(material);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Writes every uniform a live parameter sets, from the batch's settings. The base writes the
|
|
816
|
+
* ones every render mode has; a mode adds its own.
|
|
817
|
+
* @internal
|
|
818
|
+
*/
|
|
819
|
+
protected writeLiveUniforms(material: ShaderMaterial): void {
|
|
820
|
+
this.writeSoftParams(material);
|
|
821
|
+
this.writeSurfaceParams(material);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
/** @internal */
|
|
825
|
+
addSystem(system: IParticleSystem): void {
|
|
796
826
|
this.systems.add(system);
|
|
797
827
|
}
|
|
798
828
|
|
|
799
|
-
|
|
829
|
+
/** @internal */
|
|
830
|
+
removeSystem(system: IParticleSystem): void {
|
|
800
831
|
this.systems.delete(system);
|
|
801
832
|
}
|
|
802
833
|
|
|
@@ -819,21 +850,90 @@ export abstract class VFXBatch {
|
|
|
819
850
|
return visibleSystems;
|
|
820
851
|
}
|
|
821
852
|
|
|
822
|
-
|
|
853
|
+
/**
|
|
854
|
+
* Sets the depth texture soft particles read. Soft particles are compiled in only while there
|
|
855
|
+
* is one, as Unity turns them off for a camera without a depth texture, so attaching or
|
|
856
|
+
* removing it, or changing how it is packed, rebuilds a soft batch's material.
|
|
857
|
+
*
|
|
858
|
+
* @param depth - The binding, or a bare texture, read as `'linear'` and unpacked.
|
|
859
|
+
* @internal Use {@link BatchedRenderer.setDepthTexture}.
|
|
860
|
+
*/
|
|
861
|
+
applyDepthTexture(depth: DepthBinding | BaseTexture | null): void {
|
|
862
|
+
if (depth instanceof BaseTexture) {
|
|
863
|
+
depth = {texture: depth, encoding: 'linear', packed: false};
|
|
864
|
+
}
|
|
865
|
+
const previous = this.depth;
|
|
866
|
+
this.depth = depth;
|
|
867
|
+
if (!this.settings.softParticles) {
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
if (!previous !== !depth || previous?.packed !== depth?.packed) {
|
|
871
|
+
this.rebuildMaterial();
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
823
874
|
const material = this.mesh.material;
|
|
824
|
-
if (
|
|
825
|
-
material.setTexture('depthTexture',
|
|
875
|
+
if (depth && material instanceof ShaderMaterial) {
|
|
876
|
+
material.setTexture('depthTexture', depth.texture);
|
|
826
877
|
}
|
|
827
878
|
}
|
|
828
879
|
|
|
829
|
-
/**
|
|
880
|
+
/**
|
|
881
|
+
* Sets the soft-particle and alpha-test values on a material, and decodes the depth for the
|
|
882
|
+
* camera of each draw.
|
|
883
|
+
*/
|
|
884
|
+
protected bindSoft(material: ShaderMaterial): void {
|
|
885
|
+
this.writeSoftParams(material);
|
|
886
|
+
if (this.drawsSoft()) {
|
|
887
|
+
material.setTexture('depthTexture', this.depth!.texture);
|
|
888
|
+
// Reused across binds: this runs on every draw call.
|
|
889
|
+
const projParams = new BVector4(1, 0, 0, 1);
|
|
890
|
+
material.onBindObservable.add(() => {
|
|
891
|
+
const camera = this.scene.activeCamera;
|
|
892
|
+
if (camera && this.depth) {
|
|
893
|
+
softDepthParams(camera, this.depth.encoding, projParams);
|
|
894
|
+
VFXBatch.writeBound(material, (target) => target.setVector4('projParams', projParams));
|
|
895
|
+
}
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
/** Writes the soft-particle fade and the alpha cutoff, the live parameters every mode shares. */
|
|
901
|
+
private writeSoftParams(material: ShaderMaterial): void {
|
|
902
|
+
if (this.drawsSoft()) {
|
|
903
|
+
material.setVector2(
|
|
904
|
+
'softParams',
|
|
905
|
+
new BVector2(
|
|
906
|
+
this.settings.softNearFade,
|
|
907
|
+
1.0 / Math.max(this.settings.softFarFade - this.settings.softNearFade, 0.0001)
|
|
908
|
+
)
|
|
909
|
+
);
|
|
910
|
+
}
|
|
911
|
+
if (this.settings.materialAlphaTest > 0) {
|
|
912
|
+
material.setFloat('alphaTest', this.settings.materialAlphaTest);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/** True when this batch draws soft particles: they are on and a depth texture is attached. */
|
|
917
|
+
protected drawsSoft(): boolean {
|
|
918
|
+
return this.settings.softParticles && this.depth !== null;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
/**
|
|
922
|
+
* Sets the light `'fixed'` mesh particles are lit by. Batches that draw no meshes ignore it.
|
|
923
|
+
* @internal Use {@link BatchedRenderer.setMeshLighting}.
|
|
924
|
+
*/
|
|
830
925
|
applyMeshLighting(_lighting: MeshLightingSettings): void {}
|
|
831
926
|
|
|
927
|
+
/** @internal */
|
|
832
928
|
abstract setupBuffers(): void;
|
|
929
|
+
/** @internal */
|
|
833
930
|
abstract expandBuffers(target: number): void;
|
|
931
|
+
/** @internal */
|
|
834
932
|
abstract rebuildMaterial(): void;
|
|
933
|
+
/** @internal */
|
|
835
934
|
abstract update(): void;
|
|
836
935
|
|
|
936
|
+
/** @internal */
|
|
837
937
|
dispose(): void {
|
|
838
938
|
this.mesh.dispose();
|
|
839
939
|
}
|