@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.
- package/core/process/worker/WorkerBuilder.js +5 -1
- package/engine/Engine.d.ts +5 -1
- package/engine/Engine.js +35 -17
- package/engine/EngineHarness.js +9 -1
- package/engine/asset/loaders/image/codec/CodecWithFallback.js +1 -1
- package/engine/asset/loaders/image/png/PNGReader.js +19 -21
- package/engine/ecs/EntityManager.js +10 -0
- package/engine/graphics/ecs/camera/topdown/ComputeCameraFacingVector.js +21 -0
- package/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +10 -14
- package/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +4 -24
- package/engine/graphics/particles/particular/engine/ParticularEngine.js +1 -0
- package/engine/graphics/particles/particular/engine/emitter/PARTICLE_ATTRIBUTES.js +3 -0
- package/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +27 -15
- package/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +30 -10
- package/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +4 -6
- package/engine/graphics/particles/particular/engine/parameter/ParameterTrackSet.js +6 -3
- package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +271 -1
- package/engine/graphics/particles/particular/engine/renderers/billboard/prototypeBillboardRenderer.js +164 -0
- package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +10 -555
- package/engine/graphics/particles/particular/engine/simulator/AbstractSimulationStep.js +6 -0
- package/engine/graphics/particles/particular/engine/simulator/SimulationStepFixedPhysics.js +16 -1
- package/engine/graphics/particles/particular/engine/simulator/update_parameters.js +41 -0
- package/engine/graphics/render/buffer/FrameBufferManager.js +2 -0
- package/engine/graphics/render/visibility/IncrementalDeltaSet.js +5 -0
- package/engine/graphics/render/visibility/VisibilityComputer.js +6 -6
- package/engine/graphics/render/visibility/VisibilityFilter.js +10 -0
- 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
|
-
|
|
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 {
|
|
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
|
|
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)
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
|
@@ -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 (
|
|
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
|
|