@woosh/meep-engine 2.29.0 → 2.30.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 (27) hide show
  1. package/core/process/worker/WorkerBuilder.js +5 -1
  2. package/engine/Engine.d.ts +5 -1
  3. package/engine/Engine.js +35 -17
  4. package/engine/EngineHarness.js +9 -1
  5. package/engine/asset/loaders/image/codec/CodecWithFallback.js +1 -1
  6. package/engine/asset/loaders/image/png/PNGReader.js +19 -21
  7. package/engine/ecs/EntityManager.js +10 -0
  8. package/engine/graphics/ecs/camera/topdown/ComputeCameraFacingVector.js +21 -0
  9. package/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +10 -14
  10. package/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +4 -24
  11. package/engine/graphics/particles/particular/engine/ParticularEngine.js +1 -0
  12. package/engine/graphics/particles/particular/engine/emitter/PARTICLE_ATTRIBUTES.js +3 -0
  13. package/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +27 -15
  14. package/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +30 -10
  15. package/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +4 -6
  16. package/engine/graphics/particles/particular/engine/parameter/ParameterTrackSet.js +6 -3
  17. package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +271 -1
  18. package/engine/graphics/particles/particular/engine/renderers/billboard/prototypeBillboardRenderer.js +164 -0
  19. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +10 -555
  20. package/engine/graphics/particles/particular/engine/simulator/AbstractSimulationStep.js +6 -0
  21. package/engine/graphics/particles/particular/engine/simulator/SimulationStepFixedPhysics.js +16 -1
  22. package/engine/graphics/particles/particular/engine/simulator/update_parameters.js +41 -0
  23. package/engine/graphics/render/buffer/FrameBufferManager.js +2 -0
  24. package/engine/graphics/render/visibility/IncrementalDeltaSet.js +5 -0
  25. package/engine/graphics/render/visibility/VisibilityComputer.js +6 -6
  26. package/engine/graphics/render/visibility/VisibilityFilter.js +10 -0
  27. package/package.json +1 -1
@@ -1,175 +1,20 @@
1
1
  import { ManagedAtlas } from "../../../../texture/atlas/ManagedTextureAtlas.js";
2
- import { ParameterSheet } from "../parameter/ParameterSheet.js";
3
2
  import {
4
3
  ClampToEdgeWrapping,
5
4
  DataTexture,
6
5
  LinearFilter,
7
6
  LinearMipMapLinearFilter,
8
7
  Matrix4,
9
- NearestFilter,
10
8
  RGBAFormat,
11
- ShaderMaterial,
12
- UnsignedByteType,
13
- Vector2 as ThreeVector2
9
+ UnsignedByteType
14
10
  } from "three";
15
- import { SignalBinding } from "../../../../../../core/events/signal/SignalBinding.js";
16
11
  import Vector2 from "../../../../../../core/geom/Vector2.js";
17
- import Vector4 from "../../../../../../core/geom/Vector4.js";
18
- import { ParticleParameters } from "../emitter/ParticleParameters.js";
19
- import { capitalize } from "../../../../../../core/primitives/strings/StringUtils.js";
20
12
  import { HashMap } from "../../../../../../core/collection/HashMap.js";
21
- import { blendingType2three } from "../../../../texture/sampler/blendingType2Three.js";
22
13
  import { ParticleEmitterFlag } from "../emitter/ParticleEmitterFlag.js";
23
14
  import { writeSample2DDataToDataTexture } from "../../../../texture/sampler/writeSampler2DDataToDataTexture.js";
24
15
  import { TextureAtlasDebugger } from "../../../../texture/atlas/TextureAtlasDebugger.js";
25
16
  import { MaterialRecord } from "./MaterialRecord.js";
26
- import { AtlasLookupTexture } from "../../../../texture/atlas/AtlasLookupTexture.js";
27
-
28
- /**
29
- *
30
- * @param {number} itemCount
31
- * @return {string}
32
- */
33
- function itemCountToGLType(itemCount) {
34
- switch (itemCount) {
35
- case 1:
36
- return 'float';
37
- case 2:
38
- return 'vec2';
39
- case 3:
40
- return 'vec3';
41
- case 4:
42
- return 'vec4';
43
- default:
44
- throw new TypeError(`Unsupported itemCount '${itemCount}'`);
45
- }
46
- }
47
-
48
- /**
49
- *
50
- * @param {number} num
51
- * @returns {string}
52
- */
53
- function genFloat(num) {
54
- const str = num.toString();
55
- if (str.indexOf('.') === -1) {
56
- return str + '.0';
57
- } else {
58
- return str;
59
- }
60
- }
61
-
62
- function genParameterDecoderScalar() {
63
- return `float decodeParameterValueScalar(const in vec4 value, const in float offset, const in float rangeMultiplier){
64
- float unscaled = (value.x * 255.0 + value.y * 65280.0 + value.z * 16711680.0 + value.w * 4278190080.0);
65
- return unscaled * rangeMultiplier + offset;
66
- }`;
67
- }
68
-
69
- function genParameterDecoderVector2() {
70
- return `vec2 decodeParameterValueVector2(const in vec4 value, const in float offset, const in float rangeMultiplier){
71
- vec2 unscaled = vec2(value.x * 255.0 + value.y * 65280.0, value.z * 255.0 + value.w * 65280.0);
72
- return unscaled * rangeMultiplier + offset;
73
- }`;
74
- }
75
-
76
- function genParameterDecoderVector3() {
77
- return `vec3 decodeParameterValueVector3(const in vec4 value, const in float offset, const in float rangeMultiplier){
78
- vec3 unscaled = vec3(value.x * 255.0, value.y * 255.0, value.z * 255.0);
79
- return unscaled * rangeMultiplier + offset;
80
- }`;
81
- }
82
-
83
- function genParameterDecoderVector4() {
84
- return `vec4 decodeParameterValueVector4(const in vec4 value, const in float offset, const in float rangeMultiplier){
85
- vec4 unscaled = vec4(value.x * 255.0, value.y * 255.0, value.z * 255.0, value.w * 255.0);
86
- return unscaled * rangeMultiplier + offset;
87
- }`;
88
- }
89
-
90
- /**
91
- *
92
- * @param {ParticleParameter} parameter
93
- * @returns {string}
94
- */
95
- function computeDecoderFunctionName(parameter) {
96
- const itemSize = parameter.itemSize;
97
- if (itemSize === 1) {
98
- return 'decodeParameterValueScalar';
99
- } else if (itemSize === 2) {
100
- return 'decodeParameterValueVector2';
101
- } else if (itemSize === 3) {
102
- return 'genParameterDecoderVector3';
103
- } else if (itemSize === 4) {
104
- return 'decodeParameterValueVector4';
105
- } else {
106
- throw new Error(`Unsupported parameter itemSize(=${itemSize})`);
107
- }
108
- }
109
-
110
- /**
111
- *
112
- * @param {ParticleParameter} parameter
113
- * @returns {number}
114
- */
115
- function computeDecoderValueRangeMultiplier(parameter) {
116
- const valueRange = parameter.valueMax - parameter.valueMin;
117
-
118
- const itemSize = parameter.itemSize;
119
-
120
- let multiplier;
121
-
122
- if (itemSize === 1) {
123
- multiplier = 4294967295;
124
- } else if (itemSize === 2) {
125
- multiplier = 65535;
126
- } else if (itemSize === 3 || itemSize === 4) {
127
- multiplier = 255;
128
- } else {
129
- throw new Error(`Unsupported itemSize(=${itemSize})`);
130
- }
131
-
132
- return valueRange / multiplier;
133
- }
134
-
135
- /**
136
- *
137
- * @param {string} samplePosition
138
- * @param {string} uniformName
139
- * @returns {string}
140
- */
141
- function genParameterSampleTexel(samplePosition, uniformName) {
142
- const u = `${uniformName}.x + ${samplePosition} * ${uniformName}.z`;
143
- const v = `${uniformName}.y + layerPosition * ${uniformName}.w`;
144
-
145
- const textureCoordinates = `vec2( ${u}, ${v} )`;
146
-
147
- return `texture2D( tParameterSheet, ${textureCoordinates} )`;
148
- }
149
-
150
- /**
151
- *
152
- * @param {string|number} samplePosition
153
- * @param {ParticleParameter} parameter
154
- * @returns {string}
155
- */
156
- function genParameterSampleValue(samplePosition, parameter) {
157
- const uniformName = computeParameterUniformName(parameter);
158
-
159
- const decoderFunctionName = computeDecoderFunctionName(parameter);
160
-
161
- const v4Texel = genParameterSampleTexel(samplePosition, uniformName);
162
-
163
- const rangeMultiplier = computeDecoderValueRangeMultiplier(parameter);
164
-
165
- if (rangeMultiplier === 0) {
166
- const glType = itemCountToGLType(parameter.itemSize);
167
- //no range, don't need to read
168
- return `${glType}( ${genFloat(parameter.valueMin)} )`;
169
- }
170
-
171
- return `${decoderFunctionName}(${v4Texel}, ${genFloat(parameter.valueMin)}, ${genFloat(rangeMultiplier)})`;
172
- }
17
+ import { make_particle_billboard_shader } from "../renderers/billboard/ParticleBillboardMaterial.js";
173
18
 
174
19
  const EMITTER_MATERIAL_FLAGS = ParticleEmitterFlag.DepthSoftDisabled | ParticleEmitterFlag.DepthReadDisabled | ParticleEmitterFlag.AlignOnVelocity;
175
20
 
@@ -179,9 +24,8 @@ const EMITTER_MATERIAL_FLAGS = ParticleEmitterFlag.DepthSoftDisabled | ParticleE
179
24
  * @returns {number}
180
25
  */
181
26
  function computeEmitterMaterialHash(emitter) {
182
- const paramHash = emitter.parameters.hash();
183
27
 
184
- return paramHash ^ (emitter.flags & EMITTER_MATERIAL_FLAGS);
28
+ return (emitter.flags & EMITTER_MATERIAL_FLAGS);
185
29
  }
186
30
 
187
31
  /**
@@ -194,7 +38,7 @@ function computeEmitterMaterialEquality(a, b) {
194
38
  const aFlags = a.flags & EMITTER_MATERIAL_FLAGS;
195
39
  const bFlags = b.flags & EMITTER_MATERIAL_FLAGS;
196
40
 
197
- return (aFlags === bFlags) && a.parameters.equals(b.parameters);
41
+ return (aFlags === bFlags);
198
42
  }
199
43
 
200
44
 
@@ -260,12 +104,6 @@ export class ShaderManager {
260
104
  this.spriteAtlas = new ManagedAtlas(assetManager);
261
105
  this.spriteAtlas.autoUpdate = false;
262
106
 
263
- /**
264
- *
265
- * @type {ParameterSheet}
266
- */
267
- this.parameterSheet = new ParameterSheet();
268
-
269
107
  /**
270
108
  *
271
109
  * @type {DataTexture|null}
@@ -283,20 +121,6 @@ export class ShaderManager {
283
121
  */
284
122
  this.depthTexture = null;
285
123
 
286
- /**
287
- *
288
- * @type {DataTexture|null}
289
- */
290
- this.parameterTexture = buildDataTexture({
291
- generateMipmaps: false,
292
- magFilter: LinearFilter,
293
- minFilter: NearestFilter,
294
- anisotropy: 0
295
- });
296
-
297
- this.parameterLookup = new AtlasLookupTexture();
298
- this.parameterLookup.attach(this.parameterSheet.atlas);
299
-
300
124
  /**
301
125
  * material map is identified by parameter hash
302
126
  * @readonly
@@ -333,8 +157,6 @@ export class ShaderManager {
333
157
  //watch atlas updates
334
158
  this.spriteAtlas.atlas.on.painted.add(this.updateSpriteTexture, this);
335
159
 
336
- this.parameterSheet.atlas.on.painted.add(this.updateParameterTexture, this);
337
-
338
160
  // debugAtlas(this.parameterSheet.atlas, { scale: new Vector2(16, 16) });
339
161
  // debugAtlas(this.spriteAtlas.atlas, { scale: new Vector2(0.5, 0.5) });
340
162
  }
@@ -344,24 +166,8 @@ export class ShaderManager {
344
166
  */
345
167
  update() {
346
168
  this.spriteAtlas.atlas.update();
347
- this.parameterSheet.update();
348
169
  }
349
170
 
350
- /**
351
- * @private
352
- */
353
- updateParameterTexture() {
354
- const atlas = this.parameterSheet.atlas.sampler;
355
-
356
- const dataTexture = this.parameterTexture;
357
-
358
- writeSample2DDataToDataTexture(atlas, dataTexture);
359
-
360
- this.materialMap.forEach(function (entry) {
361
- const material = entry.material;
362
- material.uniforms.tParameterSheet.value = dataTexture;
363
- });
364
- }
365
171
 
366
172
  /**
367
173
  * @private
@@ -394,280 +200,19 @@ export class ShaderManager {
394
200
  * @param {ParticleEmitter} emitter
395
201
  */
396
202
  buildMaterial(emitter) {
397
- const parameters = emitter.parameters;
398
-
399
- const parameterArray = parameters.asArray();
400
-
401
- function vertexShader() {
402
- const paramScale = parameters.getParameterByName(ParticleParameters.Scale);
403
- const paramColor = parameters.getParameterByName(ParticleParameters.Color);
404
-
405
-
406
- const parameterUniforms = parameterArray.map(function (param) {
407
- return `uniform vec4 ${computeParameterUniformName(param)};`;
408
- }).join('\n');
409
-
410
- return `
411
- uniform float cameraNear;
412
- uniform float cameraFar;
413
- uniform vec2 resolution;
414
- uniform sampler2D tParameterSheet;
415
-
416
- ${parameterUniforms}
417
-
418
- attribute float size;
419
- attribute vec4 atlasPatch;
420
- attribute float age;
421
- attribute float deathAge;
422
- attribute float layerPosition;
423
- attribute float rotation;
424
- attribute vec3 velocity;
425
-
426
- varying vec4 vPatch;
427
-
428
- varying float vSize;
429
-
430
- varying float vFadeDistance;
431
-
432
- varying vec4 vColor;
433
-
434
- varying vec2 vRotationMultiplier;
435
-
436
- ${genParameterDecoderScalar()}
437
- ${genParameterDecoderVector4()}
438
-
439
- void main() {
440
- float relativeAge = clamp(age / deathAge, 0.0, 1.0);
441
-
442
- float paramScale = ${genParameterSampleValue('relativeAge', paramScale)};
443
- vColor = ${genParameterSampleValue('relativeAge', paramColor)};
444
-
445
-
446
- vSize = size * paramScale;
447
- vPatch = atlasPatch;
448
-
449
- mat4 modelViewProjectionMatrix = projectionMatrix * modelViewMatrix;
450
-
451
- vec4 position4 = vec4( position, 1.0 );
452
-
453
- gl_Position = modelViewProjectionMatrix * position4;
454
-
455
- float rotationGlobal = rotation;
456
-
457
- //
458
- #ifdef ALIGN_DIRECTION_ENABLED
459
- if(velocity != vec3(0.0)){
460
-
461
- vec4 vecNext = modelViewProjectionMatrix * (position4 + vec4(velocity,0.0) );
462
-
463
- vec2 p_2 = gl_Position.xy / gl_Position.w;
464
- vec2 vecNext_2 = vecNext.xy / vecNext.w;
465
-
466
- vec2 direction = vecNext_2 - p_2;
467
-
468
- float upAngle = atan(direction.y, direction.x) - 1.57079632679;
469
-
470
- rotationGlobal = rotationGlobal + upAngle;
471
-
472
- }
473
- #endif
474
- //
475
-
476
- vRotationMultiplier = vec2( cos(rotationGlobal),sin(rotationGlobal) );
477
-
478
- float radius = vSize/2.0;
479
-
480
- #ifdef DEPTH_SOFT_ENABLED
481
-
482
- vFadeDistance = 1.0 / radius;
483
-
484
- #endif
485
-
486
- gl_PointSize = resolution.y * projectionMatrix[1][1] * radius / gl_Position.w;
487
- }`;
488
- }
489
-
490
- const DEPTH_ERROR_MARGIN = 0.0001;
491
-
492
- /**
493
- * depthToLinear pulled from here: https://stackoverflow.com/questions/6652253/getting-the-true-z-value-from-the-depth-buffer
494
- * @returns {string}
495
- */
496
- function fragmentShader() {
497
- return `
498
- uniform sampler2D tSpriteAtlas;
499
- uniform sampler2D tDepth;
500
- uniform float cameraNear;
501
- uniform float cameraFar;
502
- uniform mat4 modelViewMatrix;
503
- uniform mat4 projectionMatrix;
504
- uniform vec2 resolution;
505
-
506
- varying float vFadeDistance;
507
- varying vec4 vPatch;
508
- varying float vSize;
509
- varying vec4 vColor;
510
- varying vec2 vRotationMultiplier;
511
-
512
- float depthToLinear( float z ) {
513
- float f = cameraFar;
514
- float n = cameraNear;
515
-
516
- float d_n = 2.0*z - 1.0;
517
-
518
- float fn = f*n;
519
-
520
- float z_diff = f - n;
521
-
522
- float denominator = (f + n - d_n * z_diff );
523
-
524
- float z_view = (2.0*fn) / denominator;
525
-
526
- return z_view-n;
527
- }
528
-
529
-
530
- float calculateFade(in float particleDepth, in float sceneDepth){
531
- float zFade;
532
-
533
- float linearParticleDepth = depthToLinear(particleDepth);
534
-
535
- float linearSceneDepth = depthToLinear(sceneDepth);
536
-
537
- float depthDelta = (linearSceneDepth - linearParticleDepth);
538
-
539
- float inputDepth = depthDelta* vFadeDistance;
540
-
541
- if(inputDepth <= 0.0){
542
- return 0.0;
543
- }
544
-
545
- if(inputDepth >= 1.0){
546
- return 1.0;
547
- }
548
-
549
- if(inputDepth <= 0.5){
550
- zFade = 0.5 * pow( clamp(2.0*inputDepth, 0.0, 1.0), 2.0);
551
- }else{
552
- zFade = 1.0 - 0.5 * pow( clamp(2.0*(1.0 - inputDepth), 0.0, 1.0), 2.0);
553
- }
554
-
555
- return zFade;
556
- }
557
-
558
- void main() {
559
- float fragmentDepth = gl_FragCoord.z;
560
-
561
- vec2 pixelPosition = gl_FragCoord.xy / resolution;
562
-
563
- float sceneDepth = texture2D( tDepth, pixelPosition ).x;
564
-
565
- #ifdef DEPTH_READ_ENABLED
566
-
567
- if(fragmentDepth + ${DEPTH_ERROR_MARGIN} > sceneDepth){
568
- discard;
569
- }
570
-
571
- #endif
572
-
573
- vec2 centeredUv = gl_PointCoord.xy - 0.5;
574
-
575
- vec2 texelCoordinate = vec2( centeredUv.x* vRotationMultiplier.x - centeredUv.y* vRotationMultiplier.y, centeredUv.x * vRotationMultiplier.y + centeredUv.y * vRotationMultiplier.x) + 0.5;
576
-
577
- texelCoordinate = clamp(texelCoordinate, vec2(0.0), vec2(1.0) );
578
-
579
- vec2 uv = texelCoordinate*vPatch.zw + vPatch.xy;
580
-
581
- vec4 spriteColor = texture2D( tSpriteAtlas, uv );
582
-
583
- if(spriteColor.a == 0.0){
584
- discard;
585
- }
586
-
587
- vec4 texel = spriteColor *vColor;
588
-
589
-
590
- #ifdef DEPTH_SOFT_ENABLED
591
-
592
- float zFade = calculateFade(fragmentDepth, sceneDepth);
593
-
594
- texel.a *= zFade;
595
-
596
- #endif
597
-
598
- gl_FragColor = texel;
599
-
600
- }`;
601
- }
602
-
603
- const uniforms = {
604
- tSpriteAtlas: {
605
- type: 't',
606
- value: this.spriteTexture
607
- },
608
- tParameterSheet: {
609
- type: 't',
610
- value: this.parameterTexture
611
- },
612
- cameraNear: {
613
- type: 'f',
614
- value: 1,
615
- },
616
- cameraFar: {
617
- type: 'f',
618
- value: 1,
619
- },
620
- tDepth: {
621
- type: 't',
622
- value: this.depthTexture
623
- },
624
- modelViewMatrix: {
625
- type: 'm4',
626
- value: new Matrix4()
627
- },
628
- projectionMatrix: {
629
- type: 'm4',
630
- value: new Matrix4()
631
- },
632
- resolution: {
633
- type: 'v2',
634
- value: new ThreeVector2(this.viewportSize.x, this.viewportSize.y)
635
- }
636
- };
637
-
638
- //add parameter uniforms
639
- parameterArray.forEach(function (param) {
640
- const uniformName = computeParameterUniformName(param);
641
- const vec4 = new Vector4();
642
- computeParameterSamplingRegion(param, vec4);
643
- uniforms[uniformName] = {
644
- type: 'v4',
645
- value: vec4
646
- };
647
- });
203
+ const shader = make_particle_billboard_shader();
648
204
 
649
- const blending = blendingType2three(emitter.blendingMode);
205
+ shader.uniforms.tSpriteAtlas.value = this.spriteTexture;
206
+ shader.uniforms.tDepth.value = this.depthTexture;
207
+ shader.uniforms.resolution.value.set(this.viewportSize.x, this.viewportSize.y)
650
208
 
651
- const defines = {
209
+ shader.defines = {
652
210
  DEPTH_READ_ENABLED: !emitter.getFlag(ParticleEmitterFlag.DepthReadDisabled),
653
211
  DEPTH_SOFT_ENABLED: !emitter.getFlag(ParticleEmitterFlag.DepthSoftDisabled),
654
212
  ALIGN_DIRECTION_ENABLED: emitter.getFlag(ParticleEmitterFlag.AlignOnVelocity)
655
213
  };
656
214
 
657
- const material = new ShaderMaterial({
658
- defines,
659
- uniforms,
660
- vertexShader: vertexShader(),
661
- fragmentShader: fragmentShader(),
662
- blending,
663
- lights: false,
664
- depthTest: true,
665
- depthWrite: false,
666
- transparent: true,
667
- vertexColors: false
668
- });
669
-
670
- return material;
215
+ return shader;
671
216
  }
672
217
 
673
218
  /**
@@ -861,64 +406,6 @@ export class ShaderManager {
861
406
  }
862
407
  }
863
408
 
864
- /**
865
- *
866
- * @param {ParticleParameter} parameter
867
- * @param {Vector4} result
868
- */
869
- function computeParameterSamplingRegion(parameter, result) {
870
- const patch = parameter.patch;
871
-
872
- if (patch === null) {
873
- result.set(0, 0, 0, 0);
874
- return;
875
- }
876
-
877
- const uv = patch.uv;
878
-
879
- const uHalfPixelOffset = (patch.uv.size.x) / (patch.size.x * 2);
880
-
881
- const u = uv.position.x + uHalfPixelOffset;
882
- const uRange = uv.size.x * ((patch.size.x - 1) / patch.size.x);
883
-
884
- const trackCount = parameter.getTrackCount();
885
-
886
- let vHalfTrackOffset;
887
-
888
-
889
- if (trackCount === 0) {
890
- //avoid division by zero
891
- vHalfTrackOffset = 0;
892
- } else {
893
- vHalfTrackOffset = patch.uv.size.y / (trackCount * 2);
894
- }
895
-
896
- const v = uv.position.y + vHalfTrackOffset;
897
-
898
- const patchHeight = patch.size.y;
899
-
900
- let vRange;
901
-
902
- if (patchHeight === 0) {
903
- //avoid division by zero
904
- vRange = 0;
905
- } else {
906
- vRange = uv.size.y * ((patchHeight - 1) / (patchHeight));
907
- }
908
-
909
- result.set(u, v, uRange, vRange);
910
- }
911
-
912
- /**
913
- *
914
- * @param {ParticleParameter} parameter
915
- * @returns {string}
916
- */
917
- function computeParameterUniformName(parameter) {
918
- return 'uPatch' + capitalize(parameter.name);
919
- }
920
-
921
-
922
409
  /**
923
410
  *
924
411
  * @param {ParticleEmitter} emitter
@@ -930,38 +417,6 @@ function createShaderEntry(emitter, shaderManager) {
930
417
  entry.count = 0;
931
418
  entry.parameters = emitter.parameters;
932
419
 
933
- const parameters = emitter.parameters.asArray();
934
-
935
- function updatePatches() {
936
- const material = entry.material;
937
-
938
- parameters.forEach(function (param) {
939
- const uniformName = computeParameterUniformName(param);
940
- const uniform = material.uniforms[uniformName];
941
-
942
- computeParameterSamplingRegion(param, uniform.value);
943
- });
944
- }
945
-
946
- //add parameters to parameter sheet
947
- const parameterCount = parameters.length;
948
-
949
- for (let i = 0; i < parameterCount; i++) {
950
- const particleParameter = parameters[i];
951
- shaderManager.parameterSheet.add(particleParameter);
952
-
953
- //watch for UV patch changes. These can occur when atlas is re-packed or re-sized
954
- const uv = particleParameter.patch.uv;
955
-
956
- const sbSize = new SignalBinding(uv.size.onChanged, updatePatches);
957
- const sbPosition = new SignalBinding(uv.position.onChanged, updatePatches);
958
-
959
- entry.signalBindings.push(
960
- sbSize,
961
- sbPosition
962
- );
963
- }
964
-
965
420
  const material = shaderManager.buildMaterial(emitter);
966
421
 
967
422
  entry.material = material;
@@ -13,6 +13,12 @@ export class AbstractSimulationStep {
13
13
  */
14
14
  this.particles = null;
15
15
 
16
+ /**
17
+ *
18
+ * @type {ParticleEmitter}
19
+ */
20
+ this.emitter = null;
21
+
16
22
  /**
17
23
  *
18
24
  * @type {Object[]}
@@ -8,6 +8,7 @@ import {
8
8
  PARTICLE_ATTRIBUTE_ROTATION_SPEED,
9
9
  PARTICLE_ATTRIBUTE_VELOCITY
10
10
  } from "../emitter/PARTICLE_ATTRIBUTES.js";
11
+ import { update_parameters } from "./update_parameters.js";
11
12
 
12
13
  const velocity = [];
13
14
  const position = [];
@@ -23,6 +24,14 @@ export class SimulationStepFixedPhysics extends AbstractSimulationStep {
23
24
 
24
25
  const layerMask = this.layer_mask;
25
26
 
27
+ const emitter = this.emitter;
28
+
29
+ /**
30
+ *
31
+ * @type {ParticleLayer[]}
32
+ */
33
+ const layers = emitter.layers.asArray();
34
+
26
35
  for (let i = 0; i < liveParticleCount; i++) {
27
36
 
28
37
  const layer_position = particles.readAttributeScalar(i, PARTICLE_ATTRIBUTE_LAYER_POSITION);
@@ -40,8 +49,10 @@ export class SimulationStepFixedPhysics extends AbstractSimulationStep {
40
49
 
41
50
  const newAge = age + timeDelta;
42
51
 
52
+ const normalized_age = newAge / deathAge;
53
+
43
54
  //retire dead particles
44
- if (newAge >= deathAge) {
55
+ if (normalized_age >= 1) {
45
56
  //add to trash
46
57
  particles.remove(i);
47
58
  //we're done with this particle
@@ -67,6 +78,10 @@ export class SimulationStepFixedPhysics extends AbstractSimulationStep {
67
78
  const p_z = position[2] + velocity[2] * timeDelta;
68
79
 
69
80
  particles.writeAttributeVector3(i, PARTICLE_ATTRIBUTE_POSITION, p_x, p_y, p_z);
81
+
82
+ const layer = layers[layer_index];
83
+
84
+ update_parameters(i, particles, layer, normalized_age);
70
85
  }
71
86
  }
72
87