@woosh/meep-engine 2.27.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 (55) hide show
  1. package/core/geom/3d/plane_computeConvex3PlaneIntersection.js +17 -25
  2. package/core/geom/AABB2.d.ts +2 -0
  3. package/core/geom/GeometryMath.js +0 -127
  4. package/core/geom/random/randomPointInBox.js +12 -0
  5. package/core/geom/random/randomPointInCircle.js +18 -0
  6. package/core/geom/random/randomPointInPoint.js +8 -0
  7. package/core/geom/random/randomPointInSphere.js +31 -0
  8. package/core/geom/random/randomPointOnBox.js +33 -0
  9. package/core/geom/random/randomPointOnSphere.js +27 -0
  10. package/core/math/noise/sdnoise.js +24 -39
  11. package/core/process/worker/WorkerBuilder.js +5 -1
  12. package/editor/process/symbolic/makeParticleEmitterSymbolicDisplay.js +1 -1
  13. package/editor/view/ecs/components/particles/ParticleLayerController.js +2 -4
  14. package/engine/Engine.d.ts +5 -1
  15. package/engine/Engine.js +35 -17
  16. package/engine/EngineHarness.js +9 -1
  17. package/engine/animation/AnimationUtils.js +8 -0
  18. package/engine/asset/AssetManager.js +14 -3
  19. package/engine/asset/loaders/image/codec/CodecWithFallback.js +1 -1
  20. package/engine/asset/loaders/image/png/PNGReader.js +19 -21
  21. package/engine/ecs/EntityManager.js +10 -0
  22. package/engine/ecs/terrain/overlay/TerrainOverlay.js +8 -1
  23. package/engine/graphics/camera/makeOrbitalCameraController.js +2 -3
  24. package/engine/graphics/ecs/camera/topdown/ComputeCameraFacingVector.js +21 -0
  25. package/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts +2 -0
  26. package/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +26 -0
  27. package/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +4 -24
  28. package/engine/graphics/ecs/mesh/applyTransform.js +5 -7
  29. package/engine/graphics/particles/particular/engine/ParticularEngine.js +1 -0
  30. package/engine/graphics/particles/particular/engine/emitter/EmissionFromType.js +8 -0
  31. package/engine/graphics/particles/particular/engine/emitter/EmissionShapeType.js +9 -0
  32. package/engine/graphics/particles/particular/engine/emitter/PARTICLE_ATTRIBUTES.js +3 -0
  33. package/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +61 -36
  34. package/engine/graphics/particles/particular/engine/emitter/ParticleLayer.js +17 -20
  35. package/engine/graphics/particles/particular/engine/emitter/ParticleLayer.spec.js +3 -1
  36. package/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +30 -10
  37. package/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +4 -6
  38. package/engine/graphics/particles/particular/engine/parameter/ParameterTrackSet.js +6 -3
  39. package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +271 -1
  40. package/engine/graphics/particles/particular/engine/renderers/billboard/prototypeBillboardRenderer.js +164 -0
  41. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +10 -555
  42. package/engine/graphics/particles/particular/engine/simulator/AbstractSimulationStep.js +6 -0
  43. package/engine/graphics/particles/particular/engine/simulator/SimulationStepFixedPhysics.js +16 -1
  44. package/engine/graphics/particles/particular/engine/simulator/update_parameters.js +41 -0
  45. package/engine/graphics/render/buffer/FrameBufferManager.js +2 -0
  46. package/engine/graphics/render/visibility/IncrementalDeltaSet.js +5 -0
  47. package/engine/graphics/render/visibility/VisibilityComputer.js +6 -6
  48. package/engine/graphics/render/visibility/VisibilityFilter.js +10 -0
  49. package/engine/navigation/ecs/components/Path.d.ts +7 -0
  50. package/engine/navigation/ecs/components/Path.js +33 -49
  51. package/engine/navigation/ecs/path_following/PathFollower.d.ts +5 -15
  52. package/package.json +3 -3
  53. package/view/elements/progress/segmented/SegmentedResourceBarView.js +7 -0
  54. package/view/minimap/Minimap.js +1 -1
  55. package/view/util/DomSizeObserver.js +59 -10
@@ -74,8 +74,10 @@ export class ParticlePool {
74
74
  this.occupancy.set(index, true);
75
75
 
76
76
  //ensure attribute arrays are large enough
77
- if (this.capacity < index + 1) {
78
- this.growCapacity(index + 1);
77
+ const min_capacity = index + 1;
78
+
79
+ if (this.capacity < min_capacity) {
80
+ this.growCapacity(min_capacity);
79
81
  }
80
82
 
81
83
  return index;
@@ -86,7 +88,9 @@ export class ParticlePool {
86
88
  * @returns {boolean}
87
89
  */
88
90
  hasHoles() {
89
- return this.occupancy.nextClearBit(0) < this.occupancy.size();
91
+ const occupancy = this.occupancy;
92
+
93
+ return occupancy.nextClearBit(0) < occupancy.size();
90
94
  }
91
95
 
92
96
  /**
@@ -111,6 +115,8 @@ export class ParticlePool {
111
115
  holeIndex = occupancy.nextClearBit(0);
112
116
  lastIndex = occupancy.previousSetBit(occupancy.size());
113
117
 
118
+ const attributes = this.attributes;
119
+
114
120
  while (holeIndex < lastIndex) {
115
121
 
116
122
  //move occupancy flag from the last to the hole
@@ -119,7 +125,7 @@ export class ParticlePool {
119
125
 
120
126
  //move attribute values
121
127
  for (attributeIndex = 0; attributeIndex < numAttributes; attributeIndex++) {
122
- const attribute = this.attributes[attributeIndex];
128
+ const attribute = attributes[attributeIndex];
123
129
 
124
130
  const itemSize = attribute.itemSize;
125
131
 
@@ -127,13 +133,13 @@ export class ParticlePool {
127
133
  *
128
134
  * @type {Float32Array}
129
135
  */
130
- const oldArray = attribute.array;
136
+ const attribute_array = attribute.array;
131
137
 
132
138
  //do swaps in the old array
133
139
  const targetIndex = holeIndex * itemSize;
134
140
  const sourceIndex = lastIndex * itemSize;
135
141
 
136
- oldArray.copyWithin(targetIndex, sourceIndex, sourceIndex + itemSize);
142
+ attribute_array.copyWithin(targetIndex, sourceIndex, sourceIndex + itemSize);
137
143
  }
138
144
 
139
145
  //move hole and last cursors
@@ -269,7 +275,14 @@ export class ParticlePool {
269
275
  * @param {number} capacity
270
276
  */
271
277
  growCapacity(capacity) {
272
- const newCapacity = Math.floor(max3(capacity, this.capacity * this.growFactor, this.capacity + GROW_MIN_STEP));
278
+ const newCapacity = Math.floor(
279
+ max3(
280
+ capacity,
281
+ this.capacity * this.growFactor,
282
+ this.capacity + GROW_MIN_STEP
283
+ )
284
+ );
285
+
273
286
  this.setCapacity(newCapacity);
274
287
  }
275
288
 
@@ -278,8 +291,13 @@ export class ParticlePool {
278
291
  * @param {number} newCapacity
279
292
  */
280
293
  shrinkCapacity(newCapacity) {
281
- if (newCapacity < this.capacity * this.shrinkFactor && newCapacity < this.capacity - SHRINK_THRESHOLD) {
294
+ if (
295
+ newCapacity < this.capacity * this.shrinkFactor
296
+ && newCapacity < this.capacity - SHRINK_THRESHOLD
297
+ ) {
298
+
282
299
  this.setCapacity(newCapacity);
300
+
283
301
  }
284
302
  }
285
303
 
@@ -293,8 +311,10 @@ export class ParticlePool {
293
311
  return;
294
312
  }
295
313
 
296
- if (newCapacity < this.occupancy.size()) {
297
- throw new Error(`Can not set capacity (=${newCapacity}) below occupancy set size (=${this.occupancy.size()})`);
314
+ const occupancy_size = this.occupancy.size();
315
+
316
+ if (newCapacity < occupancy_size) {
317
+ throw new Error(`Can not set capacity (=${newCapacity}) below occupancy set size (=${occupancy_size})`);
298
318
  }
299
319
 
300
320
  this.capacity = newCapacity;
@@ -1,8 +1,5 @@
1
1
  import { inverseLerp } from "../../../../../../core/math/inverseLerp.js";
2
- import {
3
- computeHashFloatArray,
4
- computeHashIntegerArray
5
- } from "../../../../../../core/math/MathUtils.js";
2
+ import { computeHashFloatArray, computeHashIntegerArray } from "../../../../../../core/math/MathUtils.js";
6
3
  import { assert } from "../../../../../../core/assert.js";
7
4
  import { max2 } from "../../../../../../core/math/max2.js";
8
5
  import { min2 } from "../../../../../../core/math/min2.js";
@@ -123,11 +120,12 @@ export class ParameterLookupTable {
123
120
  /**
124
121
  *
125
122
  * @param {number} position
126
- * @param {number[]} result
123
+ * @param {number[]|Float32Array|Float64Array} result
127
124
  */
128
125
  sample(position, result) {
129
126
  assert.isNumber(position, 'position');
130
- assert.ok(position >= 0 && position <= 1, `position must be between 0 and 1, instead was ${position}`);
127
+ assert.greaterThanOrEqual(position, 0, 'position');
128
+ // assert.ok(position >= 0 && position <= 1, `position must be between 0 and 1, instead was ${position}`);
131
129
 
132
130
  const itemSize = this.itemSize;
133
131
  const data = this.data;
@@ -37,12 +37,15 @@ ParameterTrackSet.prototype.forEach = function (visitor) {
37
37
  */
38
38
  ParameterTrackSet.prototype.getTrackByName = function (name) {
39
39
  const tracks = this.tracks;
40
- const nTracks = tracks.length;
40
+
41
+ const tracks_array = tracks.asArray();
42
+
43
+ const nTracks = tracks_array.length;
41
44
 
42
45
  for (let i = 0; i < nTracks; i++) {
43
- const parameterTrack = tracks.get(i);
46
+ const parameterTrack = tracks_array[i];
44
47
 
45
- if(parameterTrack.name === name){
48
+ if (parameterTrack.name === name) {
46
49
  return parameterTrack;
47
50
  }
48
51
  }
@@ -1,3 +1,273 @@
1
- export class ParticleBillboardMaterial {
1
+ import { AddEquation, CustomBlending, Matrix4, OneFactor, OneMinusSrcAlphaFactor, ShaderMaterial } from "three";
2
+ import { Vector2 as ThreeVector2 } from "three/src/math/Vector2.js";
3
+ import { ParticleSpecification } from "../../../group/ParticleSpecification.js";
4
+ import { ParticleAttribute } from "../../../group/ParticleAttribute.js";
5
+ import { ParticleAttributeType, ParticleDataType } from "../../../group/ParticleGroup.js";
2
6
 
7
+ export const BILLBOARD_PARTICLE_SPECIFICATION = new ParticleSpecification();
8
+
9
+ BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('position', ParticleAttributeType.Vector3, ParticleDataType.Float32));
10
+ BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('atlasPatch', ParticleAttributeType.Vector4, ParticleDataType.Float32));
11
+ BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('size', ParticleAttributeType.Scalar, ParticleDataType.Float32));
12
+ BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('velocity', ParticleAttributeType.Vector3, ParticleDataType.Float32));
13
+ BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('rotation', ParticleAttributeType.Scalar, ParticleDataType.Float32));
14
+ BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('color', ParticleAttributeType.Vector4, ParticleDataType.Float32));
15
+ BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('blending', ParticleAttributeType.Scalar, ParticleDataType.Uint8));
16
+
17
+ export const BILLBOARD_PARTICLE_ATTRIBUTE_POSITION = 0;
18
+ export const BILLBOARD_PARTICLE_ATTRIBUTE_UV = 1;
19
+ export const BILLBOARD_PARTICLE_ATTRIBUTE_SIZE = 2;
20
+ export const BILLBOARD_PARTICLE_ATTRIBUTE_VELOCITY = 3;
21
+ export const BILLBOARD_PARTICLE_ATTRIBUTE_COLOR = 5;
22
+ export const BILLBOARD_PARTICLE_ATTRIBUTE_BLEND = 6;
23
+
24
+ const DEPTH_ERROR_MARGIN = 0.0001;
25
+
26
+ function make_vertex_shader() {
27
+ return `
28
+ uniform float cameraNear;
29
+ uniform float cameraFar;
30
+ uniform vec2 resolution;
31
+
32
+ attribute float size;
33
+ attribute vec4 color;
34
+ attribute vec4 atlasPatch;
35
+ attribute float rotation;
36
+ attribute vec3 velocity;
37
+ attribute float blending;
38
+
39
+ varying vec4 vPatch;
40
+ varying float vSize;
41
+ varying float vFadeDistance;
42
+ varying vec4 vColor;
43
+ varying vec2 vRotationMultiplier;
44
+ varying float vBlending;
45
+
46
+ void main() {
47
+
48
+ vColor = color;
49
+ vSize = size;
50
+ vPatch = atlasPatch;
51
+ vBlending = blending;
52
+
53
+ mat4 modelViewProjectionMatrix = projectionMatrix * modelViewMatrix;
54
+
55
+ vec4 position4 = vec4( position, 1.0 );
56
+
57
+ gl_Position = modelViewProjectionMatrix * position4;
58
+
59
+ float rotationGlobal = rotation;
60
+
61
+ //
62
+ #ifdef ALIGN_DIRECTION_ENABLED
63
+ if(velocity != vec3(0.0)){
64
+
65
+ vec4 vecNext = modelViewProjectionMatrix * (position4 + vec4(velocity,0.0) );
66
+
67
+ vec2 p_2 = gl_Position.xy / gl_Position.w;
68
+ vec2 vecNext_2 = vecNext.xy / vecNext.w;
69
+
70
+ vec2 direction = vecNext_2 - p_2;
71
+
72
+ float upAngle = atan(direction.y, direction.x) - 1.57079632679;
73
+
74
+ rotationGlobal = rotationGlobal + upAngle;
75
+
76
+ }
77
+ #endif
78
+ //
79
+
80
+ vRotationMultiplier = vec2( cos(rotationGlobal),sin(rotationGlobal) );
81
+
82
+ float radius = vSize/2.0;
83
+
84
+ #ifdef DEPTH_SOFT_ENABLED
85
+
86
+ vFadeDistance = 1.0 / radius;
87
+
88
+ #endif
89
+
90
+ gl_PointSize = resolution.y * projectionMatrix[1][1] * radius / gl_Position.w;
91
+ }`;
92
+ }
93
+
94
+ function make_fragment_shader() {
95
+ return `
96
+ uniform sampler2D tSpriteAtlas;
97
+ uniform sampler2D tDepth;
98
+ uniform float cameraNear;
99
+ uniform float cameraFar;
100
+ uniform mat4 modelViewMatrix;
101
+ uniform mat4 projectionMatrix;
102
+ uniform vec2 resolution;
103
+
104
+ varying float vFadeDistance;
105
+ varying vec4 vPatch;
106
+ varying float vSize;
107
+ varying vec4 vColor;
108
+ varying vec2 vRotationMultiplier;
109
+ varying float vBlending;
110
+
111
+ float depthToLinear( float z ) {
112
+ float f = cameraFar;
113
+ float n = cameraNear;
114
+
115
+ float d_n = 2.0*z - 1.0;
116
+
117
+ float fn = f*n;
118
+
119
+ float z_diff = f - n;
120
+
121
+ float denominator = (f + n - d_n * z_diff );
122
+
123
+ float z_view = (2.0*fn) / denominator;
124
+
125
+ return z_view-n;
126
+ }
127
+
128
+
129
+ float calculateFade(in float particleDepth, in float sceneDepth){
130
+ float zFade;
131
+
132
+ float linearParticleDepth = depthToLinear(particleDepth);
133
+
134
+ float linearSceneDepth = depthToLinear(sceneDepth);
135
+
136
+ float depthDelta = (linearSceneDepth - linearParticleDepth);
137
+
138
+ float inputDepth = depthDelta* vFadeDistance;
139
+
140
+ if(inputDepth <= 0.0){
141
+ return 0.0;
142
+ }
143
+
144
+ if(inputDepth >= 1.0){
145
+ return 1.0;
146
+ }
147
+
148
+ if(inputDepth <= 0.5){
149
+ zFade = 0.5 * pow( clamp(2.0*inputDepth, 0.0, 1.0), 2.0);
150
+ }else{
151
+ zFade = 1.0 - 0.5 * pow( clamp(2.0*(1.0 - inputDepth), 0.0, 1.0), 2.0);
152
+ }
153
+
154
+ return zFade;
155
+ }
156
+
157
+ void main() {
158
+ float fragmentDepth = gl_FragCoord.z;
159
+
160
+ vec2 pixelPosition = gl_FragCoord.xy / resolution;
161
+
162
+ float sceneDepth = texture2D( tDepth, pixelPosition ).x;
163
+
164
+ #ifdef DEPTH_READ_ENABLED
165
+
166
+ if(fragmentDepth + ${DEPTH_ERROR_MARGIN} > sceneDepth){
167
+ discard;
168
+ }
169
+
170
+ #endif
171
+
172
+ vec2 centeredUv = gl_PointCoord.xy - 0.5;
173
+
174
+ vec2 texelCoordinate = vec2( centeredUv.x* vRotationMultiplier.x - centeredUv.y* vRotationMultiplier.y, centeredUv.x * vRotationMultiplier.y + centeredUv.y * vRotationMultiplier.x) + 0.5;
175
+
176
+ texelCoordinate = clamp(texelCoordinate, vec2(0.0), vec2(1.0) );
177
+
178
+ vec2 uv = texelCoordinate*vPatch.zw + vPatch.xy;
179
+
180
+ vec4 spriteColor = texture2D( tSpriteAtlas, uv );
181
+
182
+ if(spriteColor.a == 0.0){
183
+ discard;
184
+ }
185
+
186
+ vec4 texel = spriteColor *vColor;
187
+
188
+ // premultiply alpha
189
+ texel.xyz *= texel.a;
190
+
191
+ if(vBlending > 0.1){
192
+ // additive blending
193
+ texel.a = 0.0;
194
+ }
195
+
196
+ #ifdef DEPTH_SOFT_ENABLED
197
+
198
+ float zFade = calculateFade(fragmentDepth, sceneDepth);
199
+ texel *= zFade;
200
+
201
+ #endif
202
+
203
+ gl_FragColor = texel;
204
+
205
+ }`;
206
+ }
207
+
208
+ /*
209
+ NOTES:
210
+ - To implement per-particle blend modes, we need to have access to what we're blending on to, that is - the color buffer
211
+ Having the color buffer - we can do just about any kind of a blend
212
+
213
+ - Support animation by adding animation sprite sheet to the main sprite atlas, record resolution of the sheet (in frames X,Y) and interpolate over tiles based on some parameter
214
+ */
215
+ export function make_particle_billboard_shader() {
216
+ const shader = new ShaderMaterial({
217
+ defines: {
218
+ DEPTH_READ_ENABLED: true,
219
+ DEPTH_SOFT_ENABLED: true,
220
+ ALIGN_DIRECTION_ENABLED: false,
221
+ },
222
+ uniforms: {
223
+ tSpriteAtlas: {
224
+ type: 't',
225
+ value: null
226
+ },
227
+ cameraNear: {
228
+ type: 'f',
229
+ value: 1,
230
+ },
231
+ cameraFar: {
232
+ type: 'f',
233
+ value: 1,
234
+ },
235
+ tDepth: {
236
+ type: 't',
237
+ value: null
238
+ },
239
+ tColor: {
240
+ type: 't',
241
+ value: null
242
+ },
243
+ modelViewMatrix: {
244
+ type: 'm4',
245
+ value: new Matrix4()
246
+ },
247
+ projectionMatrix: {
248
+ type: 'm4',
249
+ value: new Matrix4()
250
+ },
251
+ resolution: {
252
+ type: 'v2',
253
+ value: new ThreeVector2()
254
+ }
255
+ },
256
+ vertexShader: make_vertex_shader(),
257
+ fragmentShader: make_fragment_shader(),
258
+ blending: CustomBlending,
259
+ lights: false,
260
+ depthTest: true,
261
+ depthWrite: false,
262
+ transparent: true,
263
+ vertexColors: false,
264
+ glslVersion: 2
265
+ });
266
+
267
+ shader.blending = CustomBlending;
268
+ shader.blendEquation = AddEquation;
269
+ shader.blendSrc = OneFactor;
270
+ shader.blendDst = OneMinusSrcAlphaFactor;
271
+
272
+ return shader;
3
273
  }
@@ -0,0 +1,164 @@
1
+ import { EngineHarness } from "../../../../../../EngineHarness.js";
2
+ import { ParticlePool } from "../../emitter/ParticlePool.js";
3
+ import {
4
+ BILLBOARD_PARTICLE_ATTRIBUTE_BLEND,
5
+ BILLBOARD_PARTICLE_ATTRIBUTE_COLOR,
6
+ BILLBOARD_PARTICLE_ATTRIBUTE_POSITION,
7
+ BILLBOARD_PARTICLE_ATTRIBUTE_SIZE,
8
+ BILLBOARD_PARTICLE_ATTRIBUTE_UV,
9
+ BILLBOARD_PARTICLE_SPECIFICATION,
10
+ make_particle_billboard_shader
11
+ } from "./ParticleBillboardMaterial.js";
12
+ import { DataTexture, LinearFilter, LinearMipMapLinearFilter, Matrix4, Points } from "three";
13
+ import { StandardFrameBuffers } from "../../../../../GraphicsEngine.js";
14
+ import { ManagedAtlas } from "../../../../../texture/atlas/ManagedTextureAtlas.js";
15
+ import { writeSample2DDataToDataTexture } from "../../../../../texture/sampler/writeSampler2DDataToDataTexture.js";
16
+ import { ImageRGBADataLoader } from "../../../../../../asset/loaders/image/ImageRGBADataLoader.js";
17
+ import { EngineConfiguration } from "../../../../../../EngineConfiguration.js";
18
+ import { MeshSystem } from "../../../../../ecs/mesh/MeshSystem.js";
19
+ import EntityBuilder from "../../../../../../ecs/EntityBuilder.js";
20
+ import { Transform } from "../../../../../../ecs/transform/Transform.js";
21
+ import Mesh from "../../../../../ecs/mesh/Mesh.js";
22
+ import Vector3 from "../../../../../../../core/geom/Vector3.js";
23
+ import { RenderPassType } from "../../../../../render/RenderPassType.js";
24
+
25
+
26
+ const engineHarness = new EngineHarness();
27
+
28
+ async function init(engineHarness) {
29
+
30
+ const engine = await engineHarness.initialize();
31
+
32
+ const config = new EngineConfiguration();
33
+
34
+ config.addSystem(new MeshSystem(engine.graphics, engine.assetManager));
35
+ config.addLoader('image', new ImageRGBADataLoader());
36
+
37
+ await config.apply(engine);
38
+
39
+ main(engine);
40
+ }
41
+
42
+ /**
43
+ *
44
+ * @param {Engine} engine
45
+ * @returns {Promise<void>}
46
+ */
47
+ async function main(engine) {
48
+ const ecd = engine.entityManager.dataset;
49
+
50
+
51
+ const particle_pool = new ParticlePool(BILLBOARD_PARTICLE_SPECIFICATION);
52
+
53
+ const particle_a = particle_pool.create();
54
+
55
+ particle_pool.writeAttributeScalar(particle_a, BILLBOARD_PARTICLE_ATTRIBUTE_SIZE, 5);
56
+ particle_pool.writeAttributeVector3(particle_a, BILLBOARD_PARTICLE_ATTRIBUTE_POSITION, 5, 2, 5);
57
+ particle_pool.writeAttributeVector4(particle_a, BILLBOARD_PARTICLE_ATTRIBUTE_UV, 0, 0, 1, 1);
58
+ particle_pool.writeAttributeVector4(particle_a, BILLBOARD_PARTICLE_ATTRIBUTE_COLOR, 1, 1, 1, 1);
59
+ particle_pool.writeAttributeScalar(particle_a, BILLBOARD_PARTICLE_ATTRIBUTE_BLEND, 0);
60
+
61
+ const particle_b = particle_pool.create();
62
+
63
+ particle_pool.writeAttributeScalar(particle_b, BILLBOARD_PARTICLE_ATTRIBUTE_SIZE, 5);
64
+ particle_pool.writeAttributeVector3(particle_b, BILLBOARD_PARTICLE_ATTRIBUTE_POSITION, 10, 2, 5);
65
+ particle_pool.writeAttributeVector4(particle_b, BILLBOARD_PARTICLE_ATTRIBUTE_UV, 0, 0, 1, 1);
66
+ particle_pool.writeAttributeVector4(particle_b, BILLBOARD_PARTICLE_ATTRIBUTE_COLOR, 1, 1, 1, 1);
67
+ particle_pool.writeAttributeScalar(particle_b, BILLBOARD_PARTICLE_ATTRIBUTE_BLEND, 1);
68
+
69
+ const particle_c = particle_pool.create();
70
+
71
+ particle_pool.writeAttributeScalar(particle_c, BILLBOARD_PARTICLE_ATTRIBUTE_SIZE, 5);
72
+ particle_pool.writeAttributeVector3(particle_c, BILLBOARD_PARTICLE_ATTRIBUTE_POSITION, 10, 2, 10);
73
+ particle_pool.writeAttributeVector4(particle_c, BILLBOARD_PARTICLE_ATTRIBUTE_UV, 0, 0, 1, 1);
74
+ particle_pool.writeAttributeVector4(particle_c, BILLBOARD_PARTICLE_ATTRIBUTE_COLOR, 1, 1, 1, 1);
75
+ particle_pool.writeAttributeScalar(particle_c, BILLBOARD_PARTICLE_ATTRIBUTE_BLEND, 1);
76
+
77
+ const particle_d = particle_pool.create();
78
+
79
+ particle_pool.writeAttributeScalar(particle_d, BILLBOARD_PARTICLE_ATTRIBUTE_SIZE, 5);
80
+ particle_pool.writeAttributeVector3(particle_d, BILLBOARD_PARTICLE_ATTRIBUTE_POSITION, 5, 2, 10);
81
+ particle_pool.writeAttributeVector4(particle_d, BILLBOARD_PARTICLE_ATTRIBUTE_UV, 0, 0, 1, 1);
82
+ particle_pool.writeAttributeVector4(particle_d, BILLBOARD_PARTICLE_ATTRIBUTE_COLOR, 1, 1, 1, 1);
83
+ particle_pool.writeAttributeScalar(particle_d, BILLBOARD_PARTICLE_ATTRIBUTE_BLEND, 0);
84
+
85
+ particle_pool.compact();
86
+
87
+ const managedAtlas = new ManagedAtlas(engine.assetManager);
88
+ const sprite_atlas_texture = new DataTexture(new Uint8Array(4), 1, 1);
89
+ sprite_atlas_texture.generateMipmaps = true;
90
+ sprite_atlas_texture.minFilter = LinearMipMapLinearFilter;
91
+ sprite_atlas_texture.magFilter = LinearFilter;
92
+ sprite_atlas_texture.anisotropy = 0; // billboards don't need anisotropy
93
+
94
+
95
+ managedAtlas.acquire('data/textures/utility/uv_map_reference.jpg');
96
+ // managedAtlas.acquire('data/textures/particle/UETools/Star_41.png');
97
+
98
+ const shaderMaterial = make_particle_billboard_shader();
99
+
100
+ shaderMaterial.uniforms.tSpriteAtlas.value = sprite_atlas_texture;
101
+
102
+ managedAtlas.atlas.on.painted.add(() => {
103
+ writeSample2DDataToDataTexture(managedAtlas.atlas.sampler, sprite_atlas_texture);
104
+ });
105
+
106
+ const points = new Points(particle_pool.geometry.getValue(), shaderMaterial);
107
+ points.frustumCulled = false;
108
+
109
+ const layer = engine.graphics.layers.create('x');
110
+
111
+ layer.managed = true;
112
+ layer.visibleSet.initializeUpdate();
113
+ layer.visibleSet.push(points);
114
+ layer.visibleSet.finalizeUpdate();
115
+
116
+ layer.renderPass = RenderPassType.Transparent;
117
+
118
+ engine.graphics.on.visibilityConstructionStarted.add((renderer, camera, scene) => {
119
+ renderer.getSize(shaderMaterial.uniforms.resolution.value);
120
+
121
+ const projectionMatrix = camera.projectionMatrix;
122
+ const modelViewMatrix = (new Matrix4()).multiplyMatrices(camera.matrixWorldInverse, camera.matrixWorld);
123
+ const cameraNear = camera.near;
124
+ const cameraFar = camera.far;
125
+
126
+ const uniforms = shaderMaterial.uniforms;
127
+
128
+ uniforms.projectionMatrix.value = projectionMatrix;
129
+ uniforms.modelViewMatrix.value = modelViewMatrix;
130
+ uniforms.cameraNear.value = cameraNear;
131
+ uniforms.cameraFar.value = cameraFar;
132
+
133
+ const fb = engine.graphics.frameBuffers.getById(StandardFrameBuffers.ColorAndDepth);
134
+
135
+ uniforms.tDepth.value = fb.renderTarget.depthTexture;
136
+ uniforms.tColor.value = fb.renderTarget.texture;
137
+ });
138
+
139
+ EngineHarness.buildCamera({
140
+ engine,
141
+ target: new Vector3(5, 2, 5)
142
+ });
143
+
144
+ EngineHarness.buildOrbitalCameraController({
145
+ engine
146
+ });
147
+
148
+ EngineHarness.buildLights({
149
+ engine
150
+ });
151
+
152
+ EngineHarness.buildTerrain({
153
+ engine,
154
+ enableWater: false
155
+ });
156
+
157
+
158
+ new EntityBuilder()
159
+ .add(Mesh.fromJSON({ url: 'data/models/Jauntmessina/Red_Robot/gltf/Model.gltf' }))
160
+ .add(new Transform())
161
+ .build(ecd)
162
+ }
163
+
164
+ init(engineHarness);