babylon.quarks 0.26.0 → 0.28.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 (83) hide show
  1. package/CHANGELOG.md +1194 -8
  2. package/README.md +13 -9
  3. package/dist/babylon.quarks.cjs +1 -1
  4. package/dist/babylon.quarks.cjs.map +1 -1
  5. package/dist/babylon.quarks.esm.js +1 -1
  6. package/dist/babylon.quarks.esm.js.map +1 -1
  7. package/dist/babylon.quarks.umd.min.js +1 -1
  8. package/dist/babylon.quarks.umd.min.js.map +1 -1
  9. package/dist/types/index.d.cts +10108 -0
  10. package/dist/types/index.d.ts +5794 -998
  11. package/package.json +18 -7
  12. package/src/BatchedRenderer.ts +274 -156
  13. package/src/EffectPool.ts +94 -12
  14. package/src/MeshSurfaceEmitter.ts +50 -14
  15. package/src/ParticleEmitter.ts +75 -17
  16. package/src/ParticleSystem.ts +981 -2066
  17. package/src/QuarksLoader.ts +666 -194
  18. package/src/QuarksPrefab.ts +367 -73
  19. package/src/QuarksSerializer.ts +512 -0
  20. package/src/QuarksUtil.ts +77 -7
  21. package/src/SpriteBatch.ts +127 -252
  22. package/src/TrailBatch.ts +545 -348
  23. package/src/VFXBatch.ts +238 -596
  24. package/src/batchKey.ts +239 -0
  25. package/src/batchSettings.ts +546 -0
  26. package/src/effectDocumentJSON.ts +261 -0
  27. package/src/effectResources.ts +76 -0
  28. package/src/envAtlas.ts +126 -18
  29. package/src/geometryUtil.ts +1 -1
  30. package/src/index.ts +69 -35
  31. package/src/nodeId.ts +36 -0
  32. package/src/shaderProgram.ts +419 -0
  33. package/src/shaderVariants.ts +245 -0
  34. package/src/shaders/chunks/blend.ts +31 -0
  35. package/src/shaders/chunks/fog.ts +12 -5
  36. package/src/shaders/chunks/sheet.ts +111 -0
  37. package/src/shaders/chunks/soft.ts +85 -0
  38. package/src/shaders/chunks/surface.ts +12 -2
  39. package/src/shaders/local_particle_physics_vert.glsl.ts +14 -28
  40. package/src/shaders/local_particle_physics_vert.wgsl.ts +16 -29
  41. package/src/shaders/particle_frag.glsl.ts +5 -22
  42. package/src/shaders/particle_frag.wgsl.ts +5 -23
  43. package/src/shaders/particle_physics_frag.glsl.ts +16 -26
  44. package/src/shaders/particle_physics_frag.wgsl.ts +14 -26
  45. package/src/shaders/particle_vert.glsl.ts +5 -27
  46. package/src/shaders/particle_vert.wgsl.ts +5 -26
  47. package/src/shaders/stretched_bb_particle_vert.glsl.ts +7 -33
  48. package/src/shaders/stretched_bb_particle_vert.wgsl.ts +7 -33
  49. package/src/shaders/trail_frag.glsl.ts +13 -0
  50. package/src/shaders/trail_frag.wgsl.ts +13 -0
  51. package/src/shaders/trail_vert.glsl.ts +45 -36
  52. package/src/shaders/trail_vert.wgsl.ts +46 -40
  53. package/src/softDepth.ts +136 -0
  54. package/src/system/BehaviorPlan.ts +85 -0
  55. package/src/system/BoundsTracker.ts +181 -0
  56. package/src/system/EmissionController.ts +358 -0
  57. package/src/system/EventDispatcher.ts +60 -0
  58. package/src/system/ParticleSpawner.ts +274 -0
  59. package/src/system/SimulationClock.ts +130 -0
  60. package/src/system/geometry.ts +104 -0
  61. package/src/system/integrate.ts +428 -0
  62. package/src/system/materialResolve.ts +165 -0
  63. package/src/system/normalize.ts +100 -0
  64. package/src/system/serialization.ts +422 -0
  65. package/src/system/settingsSchema.ts +339 -0
  66. package/src/system/types.ts +449 -0
  67. package/src/textureSource.ts +30 -0
  68. package/src/trailSettings.ts +54 -0
  69. package/src/BatchedParticleRenderer.ts +0 -3
  70. package/src/materials/ParticleMaterials.ts +0 -23
  71. package/src/materials/index.ts +0 -1
  72. package/src/shaders/chunks/index.ts +0 -1
  73. package/src/shaders/chunks/register-shader-chunks.ts +0 -32
  74. package/src/shaders/chunks/soft_fragment.glsl.ts +0 -13
  75. package/src/shaders/chunks/soft_pars_fragment.glsl.ts +0 -20
  76. package/src/shaders/chunks/soft_pars_vertex.glsl.ts +0 -6
  77. package/src/shaders/chunks/soft_vertex.glsl.ts +0 -6
  78. package/src/shaders/chunks/tile_fragment.glsl.ts +0 -9
  79. package/src/shaders/chunks/tile_pars_fragment.glsl.ts +0 -9
  80. package/src/shaders/chunks/tile_pars_vertex.glsl.ts +0 -28
  81. package/src/shaders/chunks/tile_vertex.glsl.ts +0 -18
  82. package/src/shaders/index.ts +0 -9
  83. package/src/shaders/local_particle_vert.glsl.ts +0 -50
@@ -1,4 +1,5 @@
1
1
  import {fogVertexDeclarationWGSL, fogVertexWGSL} from './chunks/fog';
2
+ import {sheetVertexDeclarationWGSL, sheetVertexWGSL} from './chunks/sheet';
2
3
 
3
4
  export default /* wgsl */ `
4
5
  attribute position: vec3f;
@@ -13,11 +14,7 @@ attribute uvTile: f32;
13
14
  uniform world: mat4x4f;
14
15
  uniform view: mat4x4f;
15
16
  uniform projection: mat4x4f;
16
-
17
- #ifdef UV_TILE
18
- uniform tileCountX: f32;
19
- uniform tileCountY: f32;
20
- #endif
17
+ ${sheetVertexDeclarationWGSL}
21
18
 
22
19
  varying vUV: vec2f;
23
20
  varying vColor: vec4f;
@@ -32,11 +29,6 @@ varying vUV1: vec2f;
32
29
  varying vNormal: vec3f;
33
30
  varying vWorldPos: vec3f;
34
31
 
35
- #ifdef TILE_BLEND
36
- varying vUV2: vec2f;
37
- varying vTileBlend: f32;
38
- #endif
39
-
40
32
  #ifdef SOFT_PARTICLES
41
33
  varying projPosition: vec4f;
42
34
  varying linearDepth: f32;
@@ -52,9 +44,18 @@ fn applyQuaternion(v: vec3f, q: vec4f) -> vec3f {
52
44
  ${fogVertexDeclarationWGSL}
53
45
  @vertex
54
46
  fn main(input: VertexInputs) -> FragmentInputs {
55
- let scaledPosition = vertexInputs.position * vertexInputs.size;
47
+ let size = vertexInputs.size;
48
+ let scaledPosition = vertexInputs.position * size;
56
49
  let rotatedPosition = applyQuaternion(scaledPosition, vertexInputs.rotation);
57
- let rotatedNormal = normalize(applyQuaternion(vertexInputs.normal, vertexInputs.rotation));
50
+ // A normal scales by the inverse of the size, so a stretched mesh keeps its normals
51
+ // perpendicular; a flat size counts as a sliver rather than dividing by zero.
52
+ let safeSize = vec3f(
53
+ select(1e-6, size.x, abs(size.x) > 1e-6),
54
+ select(1e-6, size.y, abs(size.y) > 1e-6),
55
+ select(1e-6, size.z, abs(size.z) > 1e-6));
56
+ // A mirrored size (an odd number of negative components) turns the winding inside out, so the
57
+ // normal is turned with it and the fragment's front-face test agrees with the geometry.
58
+ let rotatedNormal = normalize(applyQuaternion(vertexInputs.normal / safeSize, vertexInputs.rotation)) * sign(safeSize.x * safeSize.y * safeSize.z);
58
59
  let localPos = rotatedPosition + vertexInputs.offset;
59
60
 
60
61
  let worldPos = uniforms.world * vec4f(localPos, 1.0);
@@ -68,25 +69,11 @@ ${fogVertexWGSL('viewPos.xyz')}
68
69
 
69
70
  #ifdef SOFT_PARTICLES
70
71
  vertexOutputs.projPosition = clipPosition;
71
- vertexOutputs.linearDepth = -viewPos.z;
72
+ // View depth is +z ahead of a left-handed camera and -z ahead of a right-handed one.
73
+ vertexOutputs.linearDepth = abs(viewPos.z);
72
74
  #endif
73
75
 
74
- #ifdef UV_TILE
75
- let tc = vec2f(uniforms.tileCountX, uniforms.tileCountY);
76
- let baseTile = floor(vertexInputs.uvTile);
77
- let tileU = (baseTile % tc.x) / tc.x;
78
- let tileV = 1.0 - floor(baseTile / tc.x) / tc.y - 1.0 / tc.y;
79
- vertexOutputs.vUV = vertexInputs.uv / tc + vec2f(tileU, tileV);
80
- #ifdef TILE_BLEND
81
- let nextTile = ceil(vertexInputs.uvTile);
82
- let nextU = (nextTile % tc.x) / tc.x;
83
- let nextV = 1.0 - floor(nextTile / tc.x) / tc.y - 1.0 / tc.y;
84
- vertexOutputs.vUV2 = vertexInputs.uv / tc + vec2f(nextU, nextV);
85
- vertexOutputs.vTileBlend = fract(vertexInputs.uvTile);
86
- #endif
87
- #else
88
- vertexOutputs.vUV = vertexInputs.uv;
89
- #endif
76
+ ${sheetVertexWGSL('vertexInputs.uv')}
90
77
 
91
78
  #ifdef UV1
92
79
  #ifdef MESH_UV2
@@ -1,4 +1,6 @@
1
+ import {blendFragmentGLSL} from './chunks/blend';
1
2
  import {fogFragmentDeclarationGLSL, fogFragmentGLSL} from './chunks/fog';
3
+ import {softFragmentDeclarationGLSL, softFragmentGLSL} from './chunks/soft';
2
4
  import {surfaceColorGLSL, surfaceFragmentDeclarationGLSL} from './chunks/surface';
3
5
 
4
6
  export default /* glsl */ `
@@ -17,26 +19,16 @@ varying float vTileBlend;
17
19
  uniform sampler2D map;
18
20
  #endif
19
21
 
20
- #ifdef SOFT_PARTICLES
21
- uniform sampler2D depthTexture;
22
- uniform vec2 softParams;
23
- uniform vec4 projParams;
24
- varying vec4 projPosition;
25
- varying float linearDepth;
26
- #endif
27
22
 
28
23
  #ifdef USE_ALPHATEST
29
24
  uniform float alphaTest;
30
25
  #endif
31
26
 
32
27
  ${fogFragmentDeclarationGLSL}
28
+ ${softFragmentDeclarationGLSL}
33
29
  ${surfaceFragmentDeclarationGLSL}
34
30
  void main() {
35
31
  ${surfaceColorGLSL(true)}
36
- #ifdef USE_COLOR_AS_ALPHA
37
- baseColor.a *= (baseColor.r + baseColor.g + baseColor.b) / 3.0;
38
- #endif
39
-
40
32
  #ifdef USE_ALPHATEST
41
33
  if (baseColor.a < alphaTest) discard;
42
34
  #else
@@ -44,17 +36,8 @@ ${surfaceColorGLSL(true)}
44
36
  #endif
45
37
 
46
38
  ${fogFragmentGLSL('baseColor.rgb')}
39
+ ${softFragmentGLSL('baseColor')}
40
+ ${blendFragmentGLSL('baseColor')}
47
41
  gl_FragColor = baseColor;
48
-
49
- #ifdef SOFT_PARTICLES
50
- vec2 p2 = projPosition.xy / projPosition.w;
51
- p2 = 0.5 * p2 + 0.5;
52
- float readDepth = texture2D(depthTexture, p2.xy).r;
53
- float zNear = projParams.x;
54
- float zFar = projParams.y;
55
- float viewDepth = (zFar * zNear) / (zFar - readDepth * (zFar - zNear));
56
- float fade = clamp(softParams.y * ((viewDepth - softParams.x) - linearDepth), 0.0, 1.0);
57
- gl_FragColor *= fade;
58
- #endif
59
42
  }
60
43
  `;
@@ -1,4 +1,6 @@
1
+ import {blendFragmentWGSL} from './chunks/blend';
1
2
  import {fogFragmentDeclarationWGSL, fogFragmentWGSL} from './chunks/fog';
3
+ import {softFragmentDeclarationWGSL, softFragmentWGSL} from './chunks/soft';
2
4
  import {surfaceColorWGSL, surfaceFragmentDeclarationWGSL} from './chunks/surface';
3
5
 
4
6
  export default /* wgsl */ `
@@ -18,46 +20,26 @@ var mapSampler: sampler;
18
20
  var map: texture_2d<f32>;
19
21
  #endif
20
22
 
21
- #ifdef SOFT_PARTICLES
22
- var depthTextureSampler: sampler;
23
- var depthTexture: texture_2d<f32>;
24
- uniform softParams: vec2f;
25
- uniform projParams: vec4f;
26
- varying projPosition: vec4f;
27
- varying linearDepth: f32;
28
- #endif
29
23
 
30
24
  #ifdef USE_ALPHATEST
31
25
  uniform alphaTest: f32;
32
26
  #endif
33
27
 
34
28
  ${fogFragmentDeclarationWGSL}
29
+ ${softFragmentDeclarationWGSL}
35
30
  ${surfaceFragmentDeclarationWGSL}
36
31
  @fragment
37
32
  fn main(input: FragmentInputs) -> FragmentOutputs {
38
33
  ${surfaceColorWGSL(true)}
39
- #ifdef USE_COLOR_AS_ALPHA
40
- baseColor.a *= (baseColor.r + baseColor.g + baseColor.b) / 3.0;
41
- #endif
42
-
43
34
  #ifdef USE_ALPHATEST
44
35
  if (baseColor.a < uniforms.alphaTest) { discard; }
45
36
  #else
46
37
  if (baseColor.a < 0.01) { discard; }
47
38
  #endif
48
39
 
49
- #ifdef SOFT_PARTICLES
50
- var p2 = fragmentInputs.projPosition.xy / fragmentInputs.projPosition.w;
51
- p2 = 0.5 * p2 + 0.5;
52
- let readDepth = textureSample(depthTexture, depthTextureSampler, p2).r;
53
- let zNear = uniforms.projParams.x;
54
- let zFar = uniforms.projParams.y;
55
- let viewDepth = (zFar * zNear) / (zFar - readDepth * (zFar - zNear));
56
- let fade = clamp(uniforms.softParams.y * ((viewDepth - uniforms.softParams.x) - fragmentInputs.linearDepth), 0.0, 1.0);
57
- baseColor *= fade;
58
- #endif
59
-
60
40
  ${fogFragmentWGSL('baseColor')}
41
+ ${softFragmentWGSL('baseColor')}
42
+ ${blendFragmentWGSL('baseColor')}
61
43
  fragmentOutputs.color = baseColor;
62
44
  }
63
45
  `;
@@ -1,4 +1,6 @@
1
+ import {blendFragmentGLSL} from './chunks/blend';
1
2
  import {fogFragmentDeclarationGLSL, fogFragmentGLSL} from './chunks/fog';
3
+ import {softFragmentDeclarationGLSL, softFragmentGLSL} from './chunks/soft';
2
4
  import {surfaceColorGLSL, surfaceFragmentDeclarationGLSL} from './chunks/surface';
3
5
 
4
6
  export default /* glsl */ `
@@ -79,29 +81,18 @@ vec3 sampleEnvAtlas(vec3 r) {
79
81
  }
80
82
  #endif
81
83
 
82
- #ifdef SOFT_PARTICLES
83
- uniform sampler2D depthTexture;
84
- uniform vec2 softParams;
85
- uniform vec4 projParams;
86
- varying vec4 projPosition;
87
- varying float linearDepth;
88
- #endif
89
84
 
90
85
  #ifdef USE_ALPHATEST
91
86
  uniform float alphaTest;
92
87
  #endif
93
88
 
94
89
  ${fogFragmentDeclarationGLSL}
90
+ ${softFragmentDeclarationGLSL}
95
91
  ${surfaceFragmentDeclarationGLSL}
96
92
  void main() {
97
93
  ${surfaceColorGLSL(true)}
98
- #ifdef USE_ALPHATEST
99
- if (baseColor.a < alphaTest) discard;
100
- #else
101
- if (baseColor.a < 0.01) discard;
102
- #endif
103
-
104
- vec3 N = normalize(vNormal);
94
+ // A back face lights, reflects and rims as the face the camera sees.
95
+ vec3 N = normalize(vNormal) * (gl_FrontFacing ? 1.0 : -1.0);
105
96
  #ifdef MESH_UNLIT
106
97
  vec3 color = baseColor.rgb;
107
98
  #else
@@ -132,18 +123,17 @@ ${surfaceColorGLSL(true)}
132
123
  #endif
133
124
  #endif
134
125
 
135
- ${fogFragmentGLSL('color')}
136
- gl_FragColor = vec4(color, baseColor.a);
137
-
138
- #ifdef SOFT_PARTICLES
139
- vec2 p2 = projPosition.xy / projPosition.w;
140
- p2 = 0.5 * p2 + 0.5;
141
- float readDepth = texture2D(depthTexture, p2.xy).r;
142
- float zNear = projParams.x;
143
- float zFar = projParams.y;
144
- float viewDepth = (zFar * zNear) / (zFar - readDepth * (zFar - zNear));
145
- float fade = clamp(softParams.y * ((viewDepth - softParams.x) - linearDepth), 0.0, 1.0);
146
- gl_FragColor *= fade;
126
+ // After the rim, so a fade that empties a face can discard it.
127
+ #ifdef USE_ALPHATEST
128
+ if (baseColor.a < alphaTest) discard;
129
+ #else
130
+ if (baseColor.a < 0.01) discard;
147
131
  #endif
132
+
133
+ ${fogFragmentGLSL('color')}
134
+ vec4 finalColor = vec4(color, baseColor.a);
135
+ ${softFragmentGLSL('finalColor')}
136
+ ${blendFragmentGLSL('finalColor')}
137
+ gl_FragColor = finalColor;
148
138
  }
149
139
  `;
@@ -1,4 +1,6 @@
1
+ import {blendFragmentWGSL} from './chunks/blend';
1
2
  import {fogFragmentDeclarationWGSL, fogFragmentWGSL} from './chunks/fog';
3
+ import {softFragmentDeclarationWGSL, softFragmentWGSL} from './chunks/soft';
2
4
  import {surfaceColorWGSL, surfaceFragmentDeclarationWGSL} from './chunks/surface';
3
5
 
4
6
  export default /* wgsl */ `
@@ -78,31 +80,19 @@ fn sampleEnvAtlas(r: vec3f) -> vec3f {
78
80
  }
79
81
  #endif
80
82
 
81
- #ifdef SOFT_PARTICLES
82
- var depthTextureSampler: sampler;
83
- var depthTexture: texture_2d<f32>;
84
- uniform softParams: vec2f;
85
- uniform projParams: vec4f;
86
- varying projPosition: vec4f;
87
- varying linearDepth: f32;
88
- #endif
89
83
 
90
84
  #ifdef USE_ALPHATEST
91
85
  uniform alphaTest: f32;
92
86
  #endif
93
87
 
94
88
  ${fogFragmentDeclarationWGSL}
89
+ ${softFragmentDeclarationWGSL}
95
90
  ${surfaceFragmentDeclarationWGSL}
96
91
  @fragment
97
92
  fn main(input: FragmentInputs) -> FragmentOutputs {
98
93
  ${surfaceColorWGSL(true)}
99
- #ifdef USE_ALPHATEST
100
- if (baseColor.a < uniforms.alphaTest) { discard; }
101
- #else
102
- if (baseColor.a < 0.01) { discard; }
103
- #endif
104
-
105
- let N = normalize(fragmentInputs.vNormal);
94
+ // A back face lights, reflects and rims as the face the camera sees.
95
+ let N = normalize(fragmentInputs.vNormal) * select(-1.0, 1.0, fragmentInputs.frontFacing);
106
96
  #ifdef MESH_UNLIT
107
97
  var color = baseColor.rgb;
108
98
  #else
@@ -133,20 +123,18 @@ ${surfaceColorWGSL(true)}
133
123
  #endif
134
124
  #endif
135
125
 
136
- var finalColor = vec4f(color, baseColor.a);
137
-
138
- #ifdef SOFT_PARTICLES
139
- var p2 = fragmentInputs.projPosition.xy / fragmentInputs.projPosition.w;
140
- p2 = 0.5 * p2 + 0.5;
141
- let readDepth = textureSample(depthTexture, depthTextureSampler, p2).r;
142
- let zNear = uniforms.projParams.x;
143
- let zFar = uniforms.projParams.y;
144
- let viewDepth = (zFar * zNear) / (zFar - readDepth * (zFar - zNear));
145
- let fade = clamp(uniforms.softParams.y * ((viewDepth - uniforms.softParams.x) - fragmentInputs.linearDepth), 0.0, 1.0);
146
- finalColor *= fade;
126
+ // After the rim, so a fade that empties a face can discard it.
127
+ #ifdef USE_ALPHATEST
128
+ if (baseColor.a < uniforms.alphaTest) { discard; }
129
+ #else
130
+ if (baseColor.a < 0.01) { discard; }
147
131
  #endif
148
132
 
133
+ var finalColor = vec4f(color, baseColor.a);
134
+
149
135
  ${fogFragmentWGSL('finalColor')}
136
+ ${softFragmentWGSL('finalColor')}
137
+ ${blendFragmentWGSL('finalColor')}
150
138
  fragmentOutputs.color = finalColor;
151
139
  }
152
140
  `;
@@ -1,4 +1,5 @@
1
1
  import {fogVertexDeclarationGLSL, fogVertexGLSL} from './chunks/fog';
2
+ import {sheetVertexDeclarationGLSL, sheetVertexGLSL} from './chunks/sheet';
2
3
 
3
4
  export default /* glsl */ `
4
5
  // Per-vertex attributes
@@ -16,12 +17,7 @@ attribute float uvTile;
16
17
  uniform mat4 world;
17
18
  uniform mat4 view;
18
19
  uniform mat4 projection;
19
- uniform mat4 worldViewProjection;
20
-
21
- #ifdef UV_TILE
22
- uniform float tileCountX;
23
- uniform float tileCountY;
24
- #endif
20
+ ${sheetVertexDeclarationGLSL}
25
21
 
26
22
  #ifdef PIVOT
27
23
  // Quad offset in particle-size units: xy in the quad's plane, z toward the camera.
@@ -35,10 +31,6 @@ varying vec4 vColor;
35
31
  // The particle's own UV, never moved by the sheet (UV channel 1).
36
32
  varying vec2 vUV1;
37
33
  #endif
38
- #ifdef TILE_BLEND
39
- varying vec2 vUV2;
40
- varying float vTileBlend;
41
- #endif
42
34
  #ifdef SOFT_PARTICLES
43
35
  varying vec4 projPosition;
44
36
  varying float linearDepth;
@@ -103,25 +95,11 @@ void main() {
103
95
  ${fogVertexGLSL('mvPosition.xyz')}
104
96
  #ifdef SOFT_PARTICLES
105
97
  projPosition = gl_Position;
106
- linearDepth = -mvPosition.z;
98
+ // View depth is +z ahead of a left-handed camera and -z ahead of a right-handed one.
99
+ linearDepth = abs(mvPosition.z);
107
100
  #endif
108
101
 
109
- #ifdef UV_TILE
110
- vec2 tc = vec2(tileCountX, tileCountY);
111
- float baseTile = floor(uvTile);
112
- float tileU = mod(baseTile, tc.x) / tc.x;
113
- float tileV = 1.0 - floor(baseTile / tc.x) / tc.y - 1.0 / tc.y;
114
- vUV = uv / tc + vec2(tileU, tileV);
115
- #ifdef TILE_BLEND
116
- float nextTile = ceil(uvTile);
117
- float nextU = mod(nextTile, tc.x) / tc.x;
118
- float nextV = 1.0 - floor(nextTile / tc.x) / tc.y - 1.0 / tc.y;
119
- vUV2 = uv / tc + vec2(nextU, nextV);
120
- vTileBlend = fract(uvTile);
121
- #endif
122
- #else
123
- vUV = uv;
124
- #endif
102
+ ${sheetVertexGLSL('uv')}
125
103
 
126
104
  #ifdef UV1
127
105
  vUV1 = uv;
@@ -1,4 +1,5 @@
1
1
  import {fogVertexDeclarationWGSL, fogVertexWGSL} from './chunks/fog';
2
+ import {sheetVertexDeclarationWGSL, sheetVertexWGSL} from './chunks/sheet';
2
3
 
3
4
  export default /* wgsl */ `
4
5
  // Per-vertex attributes
@@ -16,11 +17,7 @@ attribute uvTile: f32;
16
17
  uniform world: mat4x4f;
17
18
  uniform view: mat4x4f;
18
19
  uniform projection: mat4x4f;
19
-
20
- #ifdef UV_TILE
21
- uniform tileCountX: f32;
22
- uniform tileCountY: f32;
23
- #endif
20
+ ${sheetVertexDeclarationWGSL}
24
21
 
25
22
  #ifdef PIVOT
26
23
  // Quad offset in particle-size units: xy in the quad's plane, z toward the camera.
@@ -34,10 +31,6 @@ varying vColor: vec4f;
34
31
  // The particle's own UV, never moved by the sheet (UV channel 1).
35
32
  varying vUV1: vec2f;
36
33
  #endif
37
- #ifdef TILE_BLEND
38
- varying vUV2: vec2f;
39
- varying vTileBlend: f32;
40
- #endif
41
34
  #ifdef SOFT_PARTICLES
42
35
  varying projPosition: vec4f;
43
36
  varying linearDepth: f32;
@@ -105,25 +98,11 @@ fn main(input: VertexInputs) -> FragmentInputs {
105
98
  ${fogVertexWGSL('mvPosition.xyz')}
106
99
  #ifdef SOFT_PARTICLES
107
100
  vertexOutputs.projPosition = clipPosition;
108
- vertexOutputs.linearDepth = -mvPosition.z;
101
+ // View depth is +z ahead of a left-handed camera and -z ahead of a right-handed one.
102
+ vertexOutputs.linearDepth = abs(mvPosition.z);
109
103
  #endif
110
104
 
111
- #ifdef UV_TILE
112
- let tc = vec2f(uniforms.tileCountX, uniforms.tileCountY);
113
- let baseTile = floor(vertexInputs.uvTile);
114
- let tileU = (baseTile % tc.x) / tc.x;
115
- let tileV = 1.0 - floor(baseTile / tc.x) / tc.y - 1.0 / tc.y;
116
- vertexOutputs.vUV = vertexInputs.uv / tc + vec2f(tileU, tileV);
117
- #ifdef TILE_BLEND
118
- let nextTile = ceil(vertexInputs.uvTile);
119
- let nextU = (nextTile % tc.x) / tc.x;
120
- let nextV = 1.0 - floor(nextTile / tc.x) / tc.y - 1.0 / tc.y;
121
- vertexOutputs.vUV2 = vertexInputs.uv / tc + vec2f(nextU, nextV);
122
- vertexOutputs.vTileBlend = fract(vertexInputs.uvTile);
123
- #endif
124
- #else
125
- vertexOutputs.vUV = vertexInputs.uv;
126
- #endif
105
+ ${sheetVertexWGSL('vertexInputs.uv')}
127
106
 
128
107
  #ifdef UV1
129
108
  vertexOutputs.vUV1 = vertexInputs.uv;
@@ -1,4 +1,5 @@
1
1
  import {fogVertexDeclarationGLSL, fogVertexGLSL} from './chunks/fog';
2
+ import {sheetVertexDeclarationGLSL, sheetVertexGLSL} from './chunks/sheet';
2
3
 
3
4
  export default /* glsl */ `
4
5
  // Per-vertex attributes
@@ -17,12 +18,7 @@ attribute vec4 velocity;
17
18
  uniform mat4 world;
18
19
  uniform mat4 view;
19
20
  uniform mat4 projection;
20
- uniform float speedFactor;
21
-
22
- #ifdef UV_TILE
23
- uniform float tileCountX;
24
- uniform float tileCountY;
25
- #endif
21
+ ${sheetVertexDeclarationGLSL}
26
22
 
27
23
  #ifdef PIVOT
28
24
  // Streak offset in particle-size units: x from head to tail, y across.
@@ -36,10 +32,6 @@ varying vec4 vColor;
36
32
  // The particle's own UV, never moved by the sheet (UV channel 1).
37
33
  varying vec2 vUV1;
38
34
  #endif
39
- #ifdef TILE_BLEND
40
- varying vec2 vUV2;
41
- varying float vTileBlend;
42
- #endif
43
35
  #ifdef SOFT_PARTICLES
44
36
  varying vec4 projPosition;
45
37
  varying float linearDepth;
@@ -61,15 +53,11 @@ void main() {
61
53
  float vlength = length(viewVelocity);
62
54
  // Stretch direction is the velocity direction; only a genuinely motionless particle has none.
63
55
  // Deriving it via normalize keeps the stretch aligned even when the speed contribution is ~0
64
- // (e.g. speedFactor 0), instead of collapsing the whole burst onto a fixed screen axis.
56
+ // (e.g. a speed factor of 0), instead of collapsing the whole burst onto a fixed screen axis.
65
57
  vec3 vdir = vlength > 0.000001 ? viewVelocity / vlength : vec3(0.0, 0.0, 1.0);
66
- #ifdef BEAM
67
- // Seen straight along its length a beam has no side to face; any will do.
58
+ // Seen straight along its length a streak has no side to face; any will do.
68
59
  vec3 sideRaw = cross(mvPosition.xyz, vdir);
69
60
  vec3 side = dot(sideRaw, sideRaw) > 1e-12 ? normalize(sideRaw) : vec3(1.0, 0.0, 0.0);
70
- #else
71
- vec3 side = normalize(cross(mvPosition.xyz, vdir));
72
- #endif
73
61
  #ifdef SIZE_LIMITS
74
62
  // The streak's width on screen as a fraction of the viewport height, held
75
63
  // between the limits; a perspective projection divides by the view depth.
@@ -98,25 +86,11 @@ ${fogVertexGLSL('mvPosition.xyz')}
98
86
  vec2 quadUV = vec2(size.x < 0.0 ? 1.0 - uv.x : uv.x, size.y < 0.0 ? 1.0 - uv.y : uv.y);
99
87
  #ifdef SOFT_PARTICLES
100
88
  projPosition = gl_Position;
101
- linearDepth = -mvPosition.z;
89
+ // View depth is +z ahead of a left-handed camera and -z ahead of a right-handed one.
90
+ linearDepth = abs(mvPosition.z);
102
91
  #endif
103
92
 
104
- #ifdef UV_TILE
105
- vec2 tc = vec2(tileCountX, tileCountY);
106
- float baseTile = floor(uvTile);
107
- float tileU = mod(baseTile, tc.x) / tc.x;
108
- float tileV = 1.0 - floor(baseTile / tc.x) / tc.y - 1.0 / tc.y;
109
- vUV = quadUV / tc + vec2(tileU, tileV);
110
- #ifdef TILE_BLEND
111
- float nextTile = ceil(uvTile);
112
- float nextU = mod(nextTile, tc.x) / tc.x;
113
- float nextV = 1.0 - floor(nextTile / tc.x) / tc.y - 1.0 / tc.y;
114
- vUV2 = quadUV / tc + vec2(nextU, nextV);
115
- vTileBlend = fract(uvTile);
116
- #endif
117
- #else
118
- vUV = quadUV;
119
- #endif
93
+ ${sheetVertexGLSL('quadUV')}
120
94
 
121
95
  #ifdef UV1
122
96
  vUV1 = quadUV;
@@ -1,4 +1,5 @@
1
1
  import {fogVertexDeclarationWGSL, fogVertexWGSL} from './chunks/fog';
2
+ import {sheetVertexDeclarationWGSL, sheetVertexWGSL} from './chunks/sheet';
2
3
 
3
4
  export default /* wgsl */ `
4
5
  // Per-vertex attributes
@@ -17,12 +18,7 @@ attribute velocity: vec4f;
17
18
  uniform world: mat4x4f;
18
19
  uniform view: mat4x4f;
19
20
  uniform projection: mat4x4f;
20
- uniform speedFactor: f32;
21
-
22
- #ifdef UV_TILE
23
- uniform tileCountX: f32;
24
- uniform tileCountY: f32;
25
- #endif
21
+ ${sheetVertexDeclarationWGSL}
26
22
 
27
23
  #ifdef PIVOT
28
24
  // Streak offset in particle-size units: x from head to tail, y across.
@@ -36,10 +32,6 @@ varying vColor: vec4f;
36
32
  // The particle's own UV, never moved by the sheet (UV channel 1).
37
33
  varying vUV1: vec2f;
38
34
  #endif
39
- #ifdef TILE_BLEND
40
- varying vUV2: vec2f;
41
- varying vTileBlend: f32;
42
- #endif
43
35
  #ifdef SOFT_PARTICLES
44
36
  varying projPosition: vec4f;
45
37
  varying linearDepth: f32;
@@ -64,21 +56,17 @@ fn main(input: VertexInputs) -> FragmentInputs {
64
56
  let vlength = length(viewVelocity);
65
57
  // Stretch direction is the velocity direction; only a genuinely motionless particle has none.
66
58
  // Deriving it via normalize keeps the stretch aligned even when the speed contribution is ~0
67
- // (e.g. speedFactor 0), instead of collapsing the whole burst onto a fixed screen axis.
59
+ // (e.g. a speed factor of 0), instead of collapsing the whole burst onto a fixed screen axis.
68
60
  var vdir = vec3f(0.0, 0.0, 1.0);
69
61
  if (vlength > 0.000001) {
70
62
  vdir = viewVelocity / vlength;
71
63
  }
72
- #ifdef BEAM
73
- // Seen straight along its length a beam has no side to face; any will do.
64
+ // Seen straight along its length a streak has no side to face; any will do.
74
65
  let sideRaw = cross(mvPosition.xyz, vdir);
75
66
  var side = vec3f(1.0, 0.0, 0.0);
76
67
  if (dot(sideRaw, sideRaw) > 1e-12) {
77
68
  side = normalize(sideRaw);
78
69
  }
79
- #else
80
- let side = normalize(cross(mvPosition.xyz, vdir));
81
- #endif
82
70
  #ifdef SIZE_LIMITS
83
71
  // The streak's width on screen as a fraction of the viewport height, held
84
72
  // between the limits; a perspective projection divides by the view depth.
@@ -113,25 +101,11 @@ ${fogVertexWGSL('mvPosition.xyz')}
113
101
  let quadUV = select(vertexInputs.uv, 1.0 - vertexInputs.uv, vertexInputs.size.xy < vec2f(0.0));
114
102
  #ifdef SOFT_PARTICLES
115
103
  vertexOutputs.projPosition = clipPosition;
116
- vertexOutputs.linearDepth = -mvPosition.z;
104
+ // View depth is +z ahead of a left-handed camera and -z ahead of a right-handed one.
105
+ vertexOutputs.linearDepth = abs(mvPosition.z);
117
106
  #endif
118
107
 
119
- #ifdef UV_TILE
120
- let tc = vec2f(uniforms.tileCountX, uniforms.tileCountY);
121
- let baseTile = floor(vertexInputs.uvTile);
122
- let tileU = (baseTile % tc.x) / tc.x;
123
- let tileV = 1.0 - floor(baseTile / tc.x) / tc.y - 1.0 / tc.y;
124
- vertexOutputs.vUV = quadUV / tc + vec2f(tileU, tileV);
125
- #ifdef TILE_BLEND
126
- let nextTile = ceil(vertexInputs.uvTile);
127
- let nextU = (nextTile % tc.x) / tc.x;
128
- let nextV = 1.0 - floor(nextTile / tc.x) / tc.y - 1.0 / tc.y;
129
- vertexOutputs.vUV2 = quadUV / tc + vec2f(nextU, nextV);
130
- vertexOutputs.vTileBlend = fract(vertexInputs.uvTile);
131
- #endif
132
- #else
133
- vertexOutputs.vUV = quadUV;
134
- #endif
108
+ ${sheetVertexWGSL('quadUV')}
135
109
 
136
110
  #ifdef UV1
137
111
  vertexOutputs.vUV1 = quadUV;
@@ -1,4 +1,6 @@
1
+ import {blendFragmentGLSL} from './chunks/blend';
1
2
  import {fogFragmentDeclarationGLSL, fogFragmentGLSL} from './chunks/fog';
3
+ import {softFragmentDeclarationGLSL, softFragmentGLSL} from './chunks/soft';
2
4
  import {surfaceColorGLSL, surfaceFragmentDeclarationGLSL} from './chunks/surface';
3
5
 
4
6
  export default /* glsl */ `
@@ -12,13 +14,24 @@ varying vec2 vUV1;
12
14
  uniform sampler2D map;
13
15
  #endif
14
16
 
17
+ #ifdef USE_ALPHATEST
18
+ uniform float alphaTest;
19
+ #endif
20
+
15
21
  ${fogFragmentDeclarationGLSL}
22
+ ${softFragmentDeclarationGLSL}
16
23
  ${surfaceFragmentDeclarationGLSL}
17
24
  void main() {
18
25
  ${surfaceColorGLSL(false)}
26
+ #ifdef USE_ALPHATEST
27
+ if (baseColor.a < alphaTest) discard;
28
+ #else
19
29
  if (baseColor.a < 0.01) discard;
30
+ #endif
20
31
 
21
32
  ${fogFragmentGLSL('baseColor.rgb')}
33
+ ${softFragmentGLSL('baseColor')}
34
+ ${blendFragmentGLSL('baseColor')}
22
35
  gl_FragColor = baseColor;
23
36
  }
24
37
  `;
@@ -1,4 +1,6 @@
1
+ import {blendFragmentWGSL} from './chunks/blend';
1
2
  import {fogFragmentDeclarationWGSL, fogFragmentWGSL} from './chunks/fog';
3
+ import {softFragmentDeclarationWGSL, softFragmentWGSL} from './chunks/soft';
2
4
  import {surfaceColorWGSL, surfaceFragmentDeclarationWGSL} from './chunks/surface';
3
5
 
4
6
  export default /* wgsl */ `
@@ -13,14 +15,25 @@ var mapSampler: sampler;
13
15
  var map: texture_2d<f32>;
14
16
  #endif
15
17
 
18
+ #ifdef USE_ALPHATEST
19
+ uniform alphaTest: f32;
20
+ #endif
21
+
16
22
  ${fogFragmentDeclarationWGSL}
23
+ ${softFragmentDeclarationWGSL}
17
24
  ${surfaceFragmentDeclarationWGSL}
18
25
  @fragment
19
26
  fn main(input: FragmentInputs) -> FragmentOutputs {
20
27
  ${surfaceColorWGSL(false)}
28
+ #ifdef USE_ALPHATEST
29
+ if (baseColor.a < uniforms.alphaTest) { discard; }
30
+ #else
21
31
  if (baseColor.a < 0.01) { discard; }
32
+ #endif
22
33
 
23
34
  ${fogFragmentWGSL('baseColor')}
35
+ ${softFragmentWGSL('baseColor')}
36
+ ${blendFragmentWGSL('baseColor')}
24
37
  fragmentOutputs.color = baseColor;
25
38
  }
26
39
  `;