babylon.quarks 0.17.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 (72) hide show
  1. package/LICENSE +21 -0
  2. package/dist/babylon.quarks.cjs +2 -0
  3. package/dist/babylon.quarks.cjs.map +1 -0
  4. package/dist/babylon.quarks.esm.js +2 -0
  5. package/dist/babylon.quarks.esm.js.map +1 -0
  6. package/dist/types/BatchedParticleRenderer.d.ts +2 -0
  7. package/dist/types/BatchedRenderer.d.ts +40 -0
  8. package/dist/types/MeshSurfaceEmitter.d.ts +19 -0
  9. package/dist/types/ParticleEmitter.d.ts +16 -0
  10. package/dist/types/ParticleSystem.d.ts +226 -0
  11. package/dist/types/QuarksLoader.d.ts +28 -0
  12. package/dist/types/QuarksPrefab.d.ts +48 -0
  13. package/dist/types/QuarksUtil.d.ts +14 -0
  14. package/dist/types/SpriteBatch.d.ts +32 -0
  15. package/dist/types/TrailBatch.d.ts +27 -0
  16. package/dist/types/VFXBatch.d.ts +51 -0
  17. package/dist/types/index.d.ts +19 -0
  18. package/dist/types/materials/ParticleMaterials.d.ts +12 -0
  19. package/dist/types/materials/index.d.ts +1 -0
  20. package/dist/types/shaders/chunks/index.d.ts +1 -0
  21. package/dist/types/shaders/chunks/register-shader-chunks.d.ts +3 -0
  22. package/dist/types/shaders/chunks/soft_fragment.glsl.d.ts +2 -0
  23. package/dist/types/shaders/chunks/soft_pars_fragment.glsl.d.ts +2 -0
  24. package/dist/types/shaders/chunks/soft_pars_vertex.glsl.d.ts +2 -0
  25. package/dist/types/shaders/chunks/soft_vertex.glsl.d.ts +2 -0
  26. package/dist/types/shaders/chunks/tile_fragment.glsl.d.ts +2 -0
  27. package/dist/types/shaders/chunks/tile_pars_fragment.glsl.d.ts +2 -0
  28. package/dist/types/shaders/chunks/tile_pars_vertex.glsl.d.ts +2 -0
  29. package/dist/types/shaders/chunks/tile_vertex.glsl.d.ts +2 -0
  30. package/dist/types/shaders/index.d.ts +9 -0
  31. package/dist/types/shaders/local_particle_physics_vert.glsl.d.ts +2 -0
  32. package/dist/types/shaders/local_particle_vert.glsl.d.ts +2 -0
  33. package/dist/types/shaders/particle_frag.glsl.d.ts +2 -0
  34. package/dist/types/shaders/particle_physics_frag.glsl.d.ts +2 -0
  35. package/dist/types/shaders/particle_vert.glsl.d.ts +2 -0
  36. package/dist/types/shaders/stretched_bb_particle_vert.glsl.d.ts +2 -0
  37. package/dist/types/shaders/trail_frag.glsl.d.ts +2 -0
  38. package/dist/types/shaders/trail_vert.glsl.d.ts +2 -0
  39. package/package.json +58 -0
  40. package/src/BatchedParticleRenderer.ts +3 -0
  41. package/src/BatchedRenderer.ts +135 -0
  42. package/src/MeshSurfaceEmitter.ts +137 -0
  43. package/src/ParticleEmitter.ts +86 -0
  44. package/src/ParticleSystem.ts +1162 -0
  45. package/src/QuarksLoader.ts +503 -0
  46. package/src/QuarksPrefab.ts +307 -0
  47. package/src/QuarksUtil.ts +66 -0
  48. package/src/SpriteBatch.ts +391 -0
  49. package/src/TrailBatch.ts +345 -0
  50. package/src/VFXBatch.ts +102 -0
  51. package/src/index.ts +54 -0
  52. package/src/materials/ParticleMaterials.ts +23 -0
  53. package/src/materials/index.ts +1 -0
  54. package/src/shaders/chunks/index.ts +1 -0
  55. package/src/shaders/chunks/register-shader-chunks.ts +32 -0
  56. package/src/shaders/chunks/soft_fragment.glsl.ts +13 -0
  57. package/src/shaders/chunks/soft_pars_fragment.glsl.ts +20 -0
  58. package/src/shaders/chunks/soft_pars_vertex.glsl.ts +6 -0
  59. package/src/shaders/chunks/soft_vertex.glsl.ts +6 -0
  60. package/src/shaders/chunks/tile_fragment.glsl.ts +9 -0
  61. package/src/shaders/chunks/tile_pars_fragment.glsl.ts +9 -0
  62. package/src/shaders/chunks/tile_pars_vertex.glsl.ts +28 -0
  63. package/src/shaders/chunks/tile_vertex.glsl.ts +18 -0
  64. package/src/shaders/index.ts +9 -0
  65. package/src/shaders/local_particle_physics_vert.glsl.ts +66 -0
  66. package/src/shaders/local_particle_vert.glsl.ts +50 -0
  67. package/src/shaders/particle_frag.glsl.ts +61 -0
  68. package/src/shaders/particle_physics_frag.glsl.ts +67 -0
  69. package/src/shaders/particle_vert.glsl.ts +85 -0
  70. package/src/shaders/stretched_bb_particle_vert.glsl.ts +74 -0
  71. package/src/shaders/trail_frag.glsl.ts +21 -0
  72. package/src/shaders/trail_vert.glsl.ts +58 -0
@@ -0,0 +1,391 @@
1
+ import {Mesh} from '@babylonjs/core/Meshes/mesh';
2
+ import {VertexData} from '@babylonjs/core/Meshes/mesh.vertexData';
3
+ import {VertexBuffer} from '@babylonjs/core/Buffers/buffer';
4
+ import {Effect} from '@babylonjs/core/Materials/effect';
5
+ import {ShaderMaterial} from '@babylonjs/core/Materials/shaderMaterial';
6
+ import {Scene} from '@babylonjs/core/scene';
7
+ import {Constants} from '@babylonjs/core/Engines/constants';
8
+ import {Vector2 as BVector2, Vector3 as BVector3, Vector4 as BVector4} from '@babylonjs/core/Maths/math.vector';
9
+ import {
10
+ Vector3,
11
+ Vector4,
12
+ Quaternion,
13
+ Matrix3,
14
+ SpriteParticle,
15
+ StretchedBillBoardSettings,
16
+ } from 'quarks.core';
17
+ import {VFXBatch, RenderMode} from './VFXBatch';
18
+ import {VFXBatchSettings} from './BatchedRenderer';
19
+ import particle_vert from './shaders/particle_vert.glsl';
20
+ import particle_frag from './shaders/particle_frag.glsl';
21
+ import particle_physics_frag from './shaders/particle_physics_frag.glsl';
22
+ import stretched_bb_particle_vert from './shaders/stretched_bb_particle_vert.glsl';
23
+ import local_particle_physics_vert from './shaders/local_particle_physics_vert.glsl';
24
+
25
+ export class SpriteBatch extends VFXBatch {
26
+ private offsetBuffer!: Float32Array;
27
+ private rotationBuffer!: Float32Array;
28
+ private sizeBuffer!: Float32Array;
29
+ private colorBuffer!: Float32Array;
30
+ private uvTileBuffer!: Float32Array;
31
+ private velocityBuffer?: Float32Array;
32
+
33
+ private offsetVB!: VertexBuffer;
34
+ private rotationVB!: VertexBuffer;
35
+ private sizeVB!: VertexBuffer;
36
+ private colorVB!: VertexBuffer;
37
+ private uvTileVB!: VertexBuffer;
38
+ private velocityVB?: VertexBuffer;
39
+
40
+ constructor(settings: VFXBatchSettings, scene: Scene) {
41
+ super(settings, scene);
42
+ this.maxParticles = 1000;
43
+ this.setupBuffers();
44
+ this.rebuildMaterial();
45
+ }
46
+
47
+ setupBuffers(): void {
48
+ this.mesh.dispose();
49
+ this.mesh = new Mesh('spriteBatch', this.scene);
50
+ this.mesh.alwaysSelectAsActiveMesh = true;
51
+
52
+ const vertexData = new VertexData();
53
+ vertexData.positions = Array.from(this.settings.instancingGeometry);
54
+ vertexData.indices = Array.from(this.settings.instancingIndices);
55
+ if (this.settings.instancingUVs) {
56
+ vertexData.uvs = Array.from(this.settings.instancingUVs);
57
+ }
58
+ if (this.settings.instancingNormals) {
59
+ vertexData.normals = Array.from(this.settings.instancingNormals);
60
+ }
61
+ vertexData.applyToMesh(this.mesh, false);
62
+
63
+ this.buildExpandableBuffers();
64
+ }
65
+
66
+ private buildExpandableBuffers(): void {
67
+ const engine = this.scene.getEngine();
68
+
69
+ this.offsetBuffer = new Float32Array(this.maxParticles * 3);
70
+ this.offsetVB = new VertexBuffer(engine, this.offsetBuffer, 'offset', true, false, 3, true);
71
+ this.mesh.setVerticesBuffer(this.offsetVB);
72
+
73
+ this.colorBuffer = new Float32Array(this.maxParticles * 4);
74
+ this.colorVB = new VertexBuffer(engine, this.colorBuffer, 'color', true, false, 4, true);
75
+ this.mesh.setVerticesBuffer(this.colorVB);
76
+
77
+ this.sizeBuffer = new Float32Array(this.maxParticles * 3);
78
+ this.sizeVB = new VertexBuffer(engine, this.sizeBuffer, 'size', true, false, 3, true);
79
+ this.mesh.setVerticesBuffer(this.sizeVB);
80
+
81
+ this.uvTileBuffer = new Float32Array(this.maxParticles);
82
+ this.uvTileVB = new VertexBuffer(engine, this.uvTileBuffer, 'uvTile', true, false, 1, true);
83
+ this.mesh.setVerticesBuffer(this.uvTileVB);
84
+
85
+ if (this.settings.renderMode === RenderMode.Mesh) {
86
+ this.rotationBuffer = new Float32Array(this.maxParticles * 4);
87
+ this.rotationVB = new VertexBuffer(engine, this.rotationBuffer, 'rotation', true, false, 4, true);
88
+ } else {
89
+ this.rotationBuffer = new Float32Array(this.maxParticles);
90
+ this.rotationVB = new VertexBuffer(engine, this.rotationBuffer, 'rotation', true, false, 1, true);
91
+ }
92
+ this.mesh.setVerticesBuffer(this.rotationVB);
93
+
94
+ if (this.settings.renderMode === RenderMode.StretchedBillBoard) {
95
+ this.velocityBuffer = new Float32Array(this.maxParticles * 4);
96
+ this.velocityVB = new VertexBuffer(engine, this.velocityBuffer, 'velocity', true, false, 4, true);
97
+ this.mesh.setVerticesBuffer(this.velocityVB);
98
+ }
99
+
100
+ this.mesh.forcedInstanceCount = 0;
101
+ this.mesh.doNotSyncBoundingInfo = true;
102
+ }
103
+
104
+ expandBuffers(target: number): void {
105
+ while (target >= this.maxParticles) {
106
+ this.maxParticles *= 2;
107
+ }
108
+ this.setupBuffers();
109
+ this.rebuildMaterial();
110
+ }
111
+
112
+ rebuildMaterial(): void {
113
+ const shaderName = `quarksParticle_${this.settings.renderMode}_${Date.now()}`;
114
+ let vertexShader: string;
115
+ let fragmentShader: string;
116
+ const defines: string[] = [];
117
+
118
+ if (this.settings.renderMode === RenderMode.Mesh) {
119
+ vertexShader = local_particle_physics_vert;
120
+ fragmentShader = particle_physics_frag;
121
+ } else if (this.settings.renderMode === RenderMode.StretchedBillBoard) {
122
+ vertexShader = stretched_bb_particle_vert;
123
+ fragmentShader = particle_frag;
124
+ } else {
125
+ vertexShader = particle_vert;
126
+ fragmentShader = particle_frag;
127
+ }
128
+
129
+ if (this.settings.texture) {
130
+ defines.push('USE_MAP');
131
+ }
132
+ if (this.settings.uTileCount > 1 || this.settings.vTileCount > 1) {
133
+ defines.push('UV_TILE');
134
+ }
135
+ if (this.settings.blendTiles) {
136
+ defines.push('TILE_BLEND');
137
+ }
138
+ if (this.settings.softParticles) {
139
+ defines.push('SOFT_PARTICLES');
140
+ }
141
+ if (this.settings.materialAlphaTest > 0) {
142
+ defines.push('USE_ALPHATEST');
143
+ }
144
+ if (this.settings.renderMode === RenderMode.VerticalBillBoard) {
145
+ defines.push('VERTICAL');
146
+ }
147
+ if (this.settings.renderMode === RenderMode.HorizontalBillBoard) {
148
+ defines.push('HORIZONTAL');
149
+ }
150
+
151
+ Effect.ShadersStore[shaderName + 'VertexShader'] = vertexShader;
152
+ Effect.ShadersStore[shaderName + 'FragmentShader'] = fragmentShader;
153
+
154
+ const attributes = ['position', 'uv', 'offset', 'color', 'size', 'rotation', 'uvTile'];
155
+ if (this.settings.renderMode === RenderMode.Mesh) {
156
+ attributes.push('normal');
157
+ }
158
+ if (this.settings.renderMode === RenderMode.StretchedBillBoard) {
159
+ attributes.push('velocity');
160
+ }
161
+
162
+ const uniforms = ['world', 'view', 'projection', 'worldView', 'worldViewProjection'];
163
+ const samplers: string[] = [];
164
+
165
+ if (this.settings.uTileCount > 1 || this.settings.vTileCount > 1) {
166
+ uniforms.push('tileCountX');
167
+ uniforms.push('tileCountY');
168
+ }
169
+ if (this.settings.texture) {
170
+ samplers.push('map');
171
+ }
172
+ if (this.settings.renderMode === RenderMode.StretchedBillBoard) {
173
+ uniforms.push('speedFactor');
174
+ }
175
+ if (this.settings.softParticles) {
176
+ uniforms.push('softParams');
177
+ uniforms.push('projParams');
178
+ samplers.push('depthTexture');
179
+ }
180
+ if (this.settings.materialAlphaTest > 0) {
181
+ uniforms.push('alphaTest');
182
+ }
183
+ if (this.settings.renderMode === RenderMode.Mesh) {
184
+ uniforms.push('lightDirection');
185
+ uniforms.push('lightColor');
186
+ uniforms.push('ambientColor');
187
+ }
188
+
189
+ const mat = new ShaderMaterial(shaderName, this.scene,
190
+ {vertex: shaderName, fragment: shaderName},
191
+ {
192
+ attributes,
193
+ uniforms,
194
+ samplers,
195
+ defines,
196
+ needAlphaBlending: this.settings.materialTransparent,
197
+ }
198
+ );
199
+
200
+ if (this.settings.texture) {
201
+ mat.setTexture('map', this.settings.texture);
202
+ }
203
+ if (this.settings.uTileCount > 1 || this.settings.vTileCount > 1) {
204
+ mat.setFloat('tileCountX', this.settings.uTileCount);
205
+ mat.setFloat('tileCountY', this.settings.vTileCount);
206
+ }
207
+ if (this.settings.renderMode === RenderMode.StretchedBillBoard) {
208
+ mat.setFloat('speedFactor', this.settings.softNearFade > 0 ? this.settings.softNearFade : 1.0);
209
+ }
210
+ if (this.settings.softParticles) {
211
+ mat.setVector2('softParams', new BVector2(this.settings.softNearFade, 1.0 / Math.max(this.settings.softFarFade - this.settings.softNearFade, 0.0001)));
212
+ mat.onBindObservable.add(() => {
213
+ const camera = this.scene.activeCamera;
214
+ if (camera) {
215
+ mat.setVector4('projParams', new BVector4(camera.minZ, camera.maxZ, 0, 0));
216
+ }
217
+ });
218
+ }
219
+ if (this.settings.materialAlphaTest > 0) {
220
+ mat.setFloat('alphaTest', this.settings.materialAlphaTest);
221
+ }
222
+ if (this.settings.renderMode === RenderMode.Mesh) {
223
+ mat.setVector3('lightDirection', new BVector3(0.4, -1, 0.6));
224
+ mat.setVector3('lightColor', new BVector3(1, 1, 1));
225
+ mat.setVector3('ambientColor', new BVector3(0.35, 0.35, 0.35));
226
+ }
227
+
228
+ mat.backFaceCulling = false;
229
+
230
+ if (this.settings.materialTransparent) {
231
+ mat.alphaMode = this.settings.materialBlendMode;
232
+ } else {
233
+ mat.alphaMode = Constants.ALPHA_DISABLE;
234
+ }
235
+ mat.needDepthPrePass = this.settings.materialDepthWrite;
236
+ mat.forceDepthWrite = this.settings.materialDepthWrite;
237
+ mat.disableDepthWrite = !this.settings.materialDepthWrite;
238
+
239
+ this.mesh.material = mat;
240
+ }
241
+
242
+ private vector_ = new Vector3();
243
+ private vector2_ = new Vector3();
244
+ private vector3_ = new Vector3();
245
+ private quaternion_ = new Quaternion();
246
+ private quaternion2_ = new Quaternion();
247
+ private quaternion3_ = new Quaternion();
248
+ private rotationMat_ = new Matrix3();
249
+ private rotationMat2_ = new Matrix3();
250
+
251
+ update(): void {
252
+ let index = 0;
253
+ let particleCount = 0;
254
+
255
+ const visibleSystems = this.getVisibleSystems();
256
+ for (const system of visibleSystems) {
257
+ particleCount += system.particleNum;
258
+ }
259
+ if (particleCount > this.maxParticles) {
260
+ this.expandBuffers(particleCount);
261
+ }
262
+
263
+ for (const system of visibleSystems) {
264
+ const particles = system.particles;
265
+ const particleNum = system.particleNum;
266
+ const rotation = this.quaternion2_;
267
+ const translation = this.vector2_;
268
+ const scale = this.vector3_;
269
+ system.emitter.matrixWorld.decompose(translation, rotation, scale);
270
+ this.rotationMat_.setFromMatrix4(system.emitter.matrixWorld);
271
+
272
+ for (let j = 0; j < particleNum; j++, index++) {
273
+ const particle = particles[j] as SpriteParticle;
274
+
275
+ if (this.settings.renderMode === RenderMode.Mesh) {
276
+ let q: Quaternion;
277
+ if (system.worldSpace) {
278
+ q = particle.rotation as Quaternion;
279
+ } else {
280
+ let parentQ: Quaternion;
281
+ if (particle.parentMatrix) {
282
+ parentQ = this.quaternion3_.setFromRotationMatrix(particle.parentMatrix);
283
+ } else {
284
+ parentQ = rotation;
285
+ }
286
+ q = this.quaternion_;
287
+ q.copy(parentQ).multiply(particle.rotation as Quaternion);
288
+ }
289
+ const ri = index * 4;
290
+ this.rotationBuffer[ri] = q.x;
291
+ this.rotationBuffer[ri + 1] = q.y;
292
+ this.rotationBuffer[ri + 2] = q.z;
293
+ this.rotationBuffer[ri + 3] = q.w;
294
+ } else {
295
+ this.rotationBuffer[index] = particle.rotation as number;
296
+ }
297
+
298
+ let vec: Vector3;
299
+ if (system.worldSpace) {
300
+ vec = particle.position;
301
+ } else {
302
+ vec = this.vector_;
303
+ if (particle.parentMatrix) {
304
+ vec.copy(particle.position).applyMatrix4(particle.parentMatrix);
305
+ } else {
306
+ vec.copy(particle.position).applyMatrix4(system.emitter.matrixWorld);
307
+ }
308
+ }
309
+
310
+ const oi = index * 3;
311
+ this.offsetBuffer[oi] = vec.x;
312
+ this.offsetBuffer[oi + 1] = vec.y;
313
+ this.offsetBuffer[oi + 2] = vec.z;
314
+
315
+ const ci = index * 4;
316
+ this.colorBuffer[ci] = particle.color.x;
317
+ this.colorBuffer[ci + 1] = particle.color.y;
318
+ this.colorBuffer[ci + 2] = particle.color.z;
319
+ this.colorBuffer[ci + 3] = particle.color.w;
320
+
321
+ const si = index * 3;
322
+ if (system.worldSpace) {
323
+ this.sizeBuffer[si] = particle.size.x;
324
+ this.sizeBuffer[si + 1] = particle.size.y;
325
+ this.sizeBuffer[si + 2] = particle.size.z;
326
+ } else {
327
+ if (particle.parentMatrix) {
328
+ this.sizeBuffer[si] = particle.size.x;
329
+ this.sizeBuffer[si + 1] = particle.size.y;
330
+ this.sizeBuffer[si + 2] = particle.size.z;
331
+ } else {
332
+ this.sizeBuffer[si] = particle.size.x * Math.abs(scale.x);
333
+ this.sizeBuffer[si + 1] = particle.size.y * Math.abs(scale.y);
334
+ this.sizeBuffer[si + 2] = particle.size.z * Math.abs(scale.z);
335
+ }
336
+ }
337
+
338
+ this.uvTileBuffer[index] = particle.uvTile;
339
+
340
+ if (this.settings.renderMode === RenderMode.StretchedBillBoard && this.velocityBuffer) {
341
+ let speedFactor = (system.rendererEmitterSettings as StretchedBillBoardSettings).speedFactor;
342
+ if (speedFactor === 0) speedFactor = 0.001;
343
+ const lengthFactor = (system.rendererEmitterSettings as StretchedBillBoardSettings).lengthFactor;
344
+ let vel: Vector3;
345
+ if (system.worldSpace) {
346
+ vel = particle.velocity;
347
+ } else {
348
+ vel = this.vector_;
349
+ if (particle.parentMatrix) {
350
+ this.rotationMat2_.setFromMatrix4(particle.parentMatrix);
351
+ vel.copy(particle.velocity).applyMatrix3(this.rotationMat2_);
352
+ } else {
353
+ vel.copy(particle.velocity).applyMatrix3(this.rotationMat_);
354
+ }
355
+ }
356
+ const vi = index * 4;
357
+ this.velocityBuffer[vi] = vel.x * speedFactor;
358
+ this.velocityBuffer[vi + 1] = vel.y * speedFactor;
359
+ this.velocityBuffer[vi + 2] = vel.z * speedFactor;
360
+ this.velocityBuffer[vi + 3] = lengthFactor;
361
+ }
362
+ }
363
+ }
364
+
365
+ if (this.settings.renderMode === RenderMode.StretchedBillBoard && this.mesh.material instanceof ShaderMaterial && visibleSystems.length > 0) {
366
+ const speedFactor = (visibleSystems[0].rendererEmitterSettings as StretchedBillBoardSettings).speedFactor ?? 1.0;
367
+ this.mesh.material.setFloat('speedFactor', speedFactor === 0 ? 0.001 : speedFactor);
368
+ }
369
+
370
+ this.mesh.forcedInstanceCount = index;
371
+ this.mesh.setEnabled(index > 0);
372
+
373
+ if (index > 0) {
374
+ this.offsetVB.update(this.offsetBuffer);
375
+ this.sizeVB.update(this.sizeBuffer);
376
+ this.colorVB.update(this.colorBuffer);
377
+ this.uvTileVB.update(this.uvTileBuffer);
378
+ this.rotationVB.update(this.rotationBuffer);
379
+ if (this.settings.renderMode === RenderMode.StretchedBillBoard && this.velocityVB && this.velocityBuffer) {
380
+ this.velocityVB.update(this.velocityBuffer);
381
+ }
382
+ }
383
+ }
384
+
385
+ dispose(): void {
386
+ if (this.mesh.material) {
387
+ this.mesh.material.dispose();
388
+ }
389
+ super.dispose();
390
+ }
391
+ }