babylon.quarks 0.25.0 → 0.27.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/CHANGELOG.md +854 -8
- package/README.md +10 -8
- package/dist/babylon.quarks.cjs +1 -1
- package/dist/babylon.quarks.cjs.map +1 -1
- package/dist/babylon.quarks.esm.js +1 -1
- package/dist/babylon.quarks.esm.js.map +1 -1
- package/dist/babylon.quarks.umd.min.js +1 -1
- package/dist/babylon.quarks.umd.min.js.map +1 -1
- package/dist/types/index.d.cts +6683 -0
- package/dist/types/index.d.ts +2210 -613
- package/package.json +12 -6
- package/src/BatchedRenderer.ts +215 -106
- package/src/EffectPool.ts +4 -1
- package/src/MeshSurfaceEmitter.ts +29 -4
- package/src/ParticleEmitter.ts +45 -15
- package/src/ParticleSystem.ts +1012 -1962
- package/src/QuarksLoader.ts +463 -75
- package/src/QuarksPrefab.ts +91 -4
- package/src/QuarksSerializer.ts +484 -0
- package/src/QuarksUtil.ts +15 -0
- package/src/SpriteBatch.ts +149 -238
- package/src/TrailBatch.ts +586 -286
- package/src/VFXBatch.ts +517 -153
- package/src/batchKey.ts +237 -0
- package/src/effectResources.ts +79 -0
- package/src/envAtlas.ts +119 -17
- package/src/index.ts +51 -35
- package/src/nodeId.ts +13 -0
- package/src/shaderProgram.ts +325 -0
- package/src/shaderVariants.ts +225 -0
- package/src/shaders/chunks/fog.ts +4 -2
- package/src/shaders/chunks/sheet.ts +111 -0
- package/src/shaders/chunks/soft.ts +84 -0
- package/src/shaders/chunks/surface.ts +132 -42
- package/src/shaders/local_particle_physics_vert.glsl.ts +28 -27
- package/src/shaders/local_particle_physics_vert.wgsl.ts +30 -28
- package/src/shaders/particle_frag.glsl.ts +6 -22
- package/src/shaders/particle_frag.wgsl.ts +6 -23
- package/src/shaders/particle_physics_frag.glsl.ts +22 -29
- package/src/shaders/particle_physics_frag.wgsl.ts +22 -30
- package/src/shaders/particle_vert.glsl.ts +11 -26
- package/src/shaders/particle_vert.wgsl.ts +11 -25
- package/src/shaders/stretched_bb_particle_vert.glsl.ts +21 -39
- package/src/shaders/stretched_bb_particle_vert.wgsl.ts +22 -40
- package/src/shaders/trail_frag.glsl.ts +14 -1
- package/src/shaders/trail_frag.wgsl.ts +14 -0
- package/src/shaders/trail_vert.glsl.ts +53 -36
- package/src/shaders/trail_vert.wgsl.ts +54 -40
- package/src/softDepth.ts +136 -0
- package/src/system/BehaviorPlan.ts +85 -0
- package/src/system/BoundsTracker.ts +181 -0
- package/src/system/EmissionController.ts +360 -0
- package/src/system/EventDispatcher.ts +44 -0
- package/src/system/ParticleSpawner.ts +274 -0
- package/src/system/SimulationClock.ts +130 -0
- package/src/system/geometry.ts +111 -0
- package/src/system/integrate.ts +428 -0
- package/src/system/materialResolve.ts +116 -0
- package/src/system/normalize.ts +95 -0
- package/src/system/serialization.ts +401 -0
- package/src/system/settingsSchema.ts +317 -0
- package/src/system/types.ts +410 -0
- package/src/textureSource.ts +30 -0
- package/src/trailSettings.ts +51 -0
- package/src/BatchedParticleRenderer.ts +0 -3
- package/src/materials/ParticleMaterials.ts +0 -23
- package/src/materials/index.ts +0 -1
- package/src/shaders/chunks/index.ts +0 -1
- package/src/shaders/chunks/register-shader-chunks.ts +0 -32
- package/src/shaders/chunks/soft_fragment.glsl.ts +0 -13
- package/src/shaders/chunks/soft_pars_fragment.glsl.ts +0 -20
- package/src/shaders/chunks/soft_pars_vertex.glsl.ts +0 -6
- package/src/shaders/chunks/soft_vertex.glsl.ts +0 -6
- package/src/shaders/chunks/tile_fragment.glsl.ts +0 -9
- package/src/shaders/chunks/tile_pars_fragment.glsl.ts +0 -9
- package/src/shaders/chunks/tile_pars_vertex.glsl.ts +0 -28
- package/src/shaders/chunks/tile_vertex.glsl.ts +0 -18
- package/src/shaders/index.ts +0 -9
- package/src/shaders/local_particle_vert.glsl.ts +0 -50
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import {fogFragmentDeclarationGLSL, fogFragmentGLSL} from './chunks/fog';
|
|
2
|
+
import {softFragmentDeclarationGLSL, softFragmentGLSL} from './chunks/soft';
|
|
2
3
|
import {surfaceColorGLSL, surfaceFragmentDeclarationGLSL} from './chunks/surface';
|
|
3
4
|
|
|
4
5
|
export default /* glsl */ `
|
|
5
6
|
varying vec2 vUV;
|
|
6
7
|
varying vec4 vColor;
|
|
8
|
+
#ifdef UV1
|
|
9
|
+
varying vec2 vUV1;
|
|
10
|
+
#endif
|
|
7
11
|
varying vec3 vNormal;
|
|
8
12
|
varying vec3 vWorldPos;
|
|
9
13
|
|
|
@@ -76,29 +80,18 @@ vec3 sampleEnvAtlas(vec3 r) {
|
|
|
76
80
|
}
|
|
77
81
|
#endif
|
|
78
82
|
|
|
79
|
-
#ifdef SOFT_PARTICLES
|
|
80
|
-
uniform sampler2D depthTexture;
|
|
81
|
-
uniform vec2 softParams;
|
|
82
|
-
uniform vec4 projParams;
|
|
83
|
-
varying vec4 projPosition;
|
|
84
|
-
varying float linearDepth;
|
|
85
|
-
#endif
|
|
86
83
|
|
|
87
84
|
#ifdef USE_ALPHATEST
|
|
88
85
|
uniform float alphaTest;
|
|
89
86
|
#endif
|
|
90
87
|
|
|
91
88
|
${fogFragmentDeclarationGLSL}
|
|
89
|
+
${softFragmentDeclarationGLSL}
|
|
92
90
|
${surfaceFragmentDeclarationGLSL}
|
|
93
91
|
void main() {
|
|
94
92
|
${surfaceColorGLSL(true)}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
#else
|
|
98
|
-
if (baseColor.a < 0.01) discard;
|
|
99
|
-
#endif
|
|
100
|
-
|
|
101
|
-
vec3 N = normalize(vNormal);
|
|
93
|
+
// A back face lights, reflects and rims as the face the camera sees.
|
|
94
|
+
vec3 N = normalize(vNormal) * (gl_FrontFacing ? 1.0 : -1.0);
|
|
102
95
|
#ifdef MESH_UNLIT
|
|
103
96
|
vec3 color = baseColor.rgb;
|
|
104
97
|
#else
|
|
@@ -118,26 +111,26 @@ ${surfaceColorGLSL(true)}
|
|
|
118
111
|
#ifdef MESH_RIM
|
|
119
112
|
// Fresnel: strongest where the surface turns away from the camera.
|
|
120
113
|
vec3 V = normalize(eyePosition - vWorldPos);
|
|
121
|
-
float
|
|
122
|
-
#
|
|
123
|
-
|
|
114
|
+
float edgeTerm = pow(1.0 - abs(dot(N, V)), rimParams.x);
|
|
115
|
+
#if defined(MESH_RIM_FADE)
|
|
116
|
+
// Faces turned to the camera fade by the strength; edges stay.
|
|
117
|
+
baseColor.a *= clamp(1.0 - rimParams.y * (1.0 - edgeTerm), 0.0, 1.0);
|
|
118
|
+
#elif defined(MESH_RIM_MIX)
|
|
119
|
+
color = mix(color, rimColor, clamp(edgeTerm * rimParams.y, 0.0, 1.0));
|
|
124
120
|
#else
|
|
125
|
-
color += rimColor *
|
|
121
|
+
color += rimColor * edgeTerm * rimParams.y;
|
|
126
122
|
#endif
|
|
127
123
|
#endif
|
|
128
124
|
|
|
125
|
+
// After the rim, so a fade that empties a face can discard it.
|
|
126
|
+
#ifdef USE_ALPHATEST
|
|
127
|
+
if (baseColor.a < alphaTest) discard;
|
|
128
|
+
#else
|
|
129
|
+
if (baseColor.a < 0.01) discard;
|
|
130
|
+
#endif
|
|
131
|
+
|
|
129
132
|
${fogFragmentGLSL('color')}
|
|
130
133
|
gl_FragColor = vec4(color, baseColor.a);
|
|
131
|
-
|
|
132
|
-
#ifdef SOFT_PARTICLES
|
|
133
|
-
vec2 p2 = projPosition.xy / projPosition.w;
|
|
134
|
-
p2 = 0.5 * p2 + 0.5;
|
|
135
|
-
float readDepth = texture2D(depthTexture, p2.xy).r;
|
|
136
|
-
float zNear = projParams.x;
|
|
137
|
-
float zFar = projParams.y;
|
|
138
|
-
float viewDepth = (zFar * zNear) / (zFar - readDepth * (zFar - zNear));
|
|
139
|
-
float fade = clamp(softParams.y * ((viewDepth - softParams.x) - linearDepth), 0.0, 1.0);
|
|
140
|
-
gl_FragColor *= fade;
|
|
141
|
-
#endif
|
|
134
|
+
${softFragmentGLSL('gl_FragColor')}
|
|
142
135
|
}
|
|
143
136
|
`;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import {fogFragmentDeclarationWGSL, fogFragmentWGSL} from './chunks/fog';
|
|
2
|
+
import {softFragmentDeclarationWGSL, softFragmentWGSL} from './chunks/soft';
|
|
2
3
|
import {surfaceColorWGSL, surfaceFragmentDeclarationWGSL} from './chunks/surface';
|
|
3
4
|
|
|
4
5
|
export default /* wgsl */ `
|
|
5
6
|
varying vUV: vec2f;
|
|
6
7
|
varying vColor: vec4f;
|
|
8
|
+
#ifdef UV1
|
|
9
|
+
varying vUV1: vec2f;
|
|
10
|
+
#endif
|
|
7
11
|
varying vNormal: vec3f;
|
|
8
12
|
varying vWorldPos: vec3f;
|
|
9
13
|
|
|
@@ -75,31 +79,19 @@ fn sampleEnvAtlas(r: vec3f) -> vec3f {
|
|
|
75
79
|
}
|
|
76
80
|
#endif
|
|
77
81
|
|
|
78
|
-
#ifdef SOFT_PARTICLES
|
|
79
|
-
var depthTextureSampler: sampler;
|
|
80
|
-
var depthTexture: texture_2d<f32>;
|
|
81
|
-
uniform softParams: vec2f;
|
|
82
|
-
uniform projParams: vec4f;
|
|
83
|
-
varying projPosition: vec4f;
|
|
84
|
-
varying linearDepth: f32;
|
|
85
|
-
#endif
|
|
86
82
|
|
|
87
83
|
#ifdef USE_ALPHATEST
|
|
88
84
|
uniform alphaTest: f32;
|
|
89
85
|
#endif
|
|
90
86
|
|
|
91
87
|
${fogFragmentDeclarationWGSL}
|
|
88
|
+
${softFragmentDeclarationWGSL}
|
|
92
89
|
${surfaceFragmentDeclarationWGSL}
|
|
93
90
|
@fragment
|
|
94
91
|
fn main(input: FragmentInputs) -> FragmentOutputs {
|
|
95
92
|
${surfaceColorWGSL(true)}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
#else
|
|
99
|
-
if (baseColor.a < 0.01) { discard; }
|
|
100
|
-
#endif
|
|
101
|
-
|
|
102
|
-
let N = normalize(fragmentInputs.vNormal);
|
|
93
|
+
// A back face lights, reflects and rims as the face the camera sees.
|
|
94
|
+
let N = normalize(fragmentInputs.vNormal) * select(-1.0, 1.0, fragmentInputs.frontFacing);
|
|
103
95
|
#ifdef MESH_UNLIT
|
|
104
96
|
var color = baseColor.rgb;
|
|
105
97
|
#else
|
|
@@ -119,28 +111,28 @@ ${surfaceColorWGSL(true)}
|
|
|
119
111
|
#ifdef MESH_RIM
|
|
120
112
|
// Fresnel: strongest where the surface turns away from the camera.
|
|
121
113
|
let V = normalize(uniforms.eyePosition - fragmentInputs.vWorldPos);
|
|
122
|
-
let
|
|
123
|
-
#
|
|
124
|
-
|
|
114
|
+
let edgeTerm = pow(1.0 - abs(dot(N, V)), uniforms.rimParams.x);
|
|
115
|
+
#if defined(MESH_RIM_FADE)
|
|
116
|
+
// Faces turned to the camera fade by the strength; edges stay.
|
|
117
|
+
baseColor.a *= clamp(1.0 - uniforms.rimParams.y * (1.0 - edgeTerm), 0.0, 1.0);
|
|
118
|
+
#elif defined(MESH_RIM_MIX)
|
|
119
|
+
color = mix(color, uniforms.rimColor, clamp(edgeTerm * uniforms.rimParams.y, 0.0, 1.0));
|
|
125
120
|
#else
|
|
126
|
-
color += uniforms.rimColor *
|
|
121
|
+
color += uniforms.rimColor * edgeTerm * uniforms.rimParams.y;
|
|
127
122
|
#endif
|
|
128
123
|
#endif
|
|
129
124
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
let readDepth = textureSample(depthTexture, depthTextureSampler, p2).r;
|
|
136
|
-
let zNear = uniforms.projParams.x;
|
|
137
|
-
let zFar = uniforms.projParams.y;
|
|
138
|
-
let viewDepth = (zFar * zNear) / (zFar - readDepth * (zFar - zNear));
|
|
139
|
-
let fade = clamp(uniforms.softParams.y * ((viewDepth - uniforms.softParams.x) - fragmentInputs.linearDepth), 0.0, 1.0);
|
|
140
|
-
finalColor *= fade;
|
|
125
|
+
// After the rim, so a fade that empties a face can discard it.
|
|
126
|
+
#ifdef USE_ALPHATEST
|
|
127
|
+
if (baseColor.a < uniforms.alphaTest) { discard; }
|
|
128
|
+
#else
|
|
129
|
+
if (baseColor.a < 0.01) { discard; }
|
|
141
130
|
#endif
|
|
142
131
|
|
|
132
|
+
var finalColor = vec4f(color, baseColor.a);
|
|
133
|
+
|
|
143
134
|
${fogFragmentWGSL('finalColor')}
|
|
135
|
+
${softFragmentWGSL('finalColor')}
|
|
144
136
|
fragmentOutputs.color = finalColor;
|
|
145
137
|
}
|
|
146
138
|
`;
|
|
@@ -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
|
-
|
|
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.
|
|
@@ -31,9 +27,9 @@ uniform vec3 pivot;
|
|
|
31
27
|
// Varyings
|
|
32
28
|
varying vec2 vUV;
|
|
33
29
|
varying vec4 vColor;
|
|
34
|
-
#ifdef
|
|
35
|
-
|
|
36
|
-
varying
|
|
30
|
+
#ifdef UV1
|
|
31
|
+
// The particle's own UV, never moved by the sheet (UV channel 1).
|
|
32
|
+
varying vec2 vUV1;
|
|
37
33
|
#endif
|
|
38
34
|
#ifdef SOFT_PARTICLES
|
|
39
35
|
varying vec4 projPosition;
|
|
@@ -99,26 +95,15 @@ void main() {
|
|
|
99
95
|
${fogVertexGLSL('mvPosition.xyz')}
|
|
100
96
|
#ifdef SOFT_PARTICLES
|
|
101
97
|
projPosition = gl_Position;
|
|
102
|
-
|
|
98
|
+
// View depth is +z ahead of a left-handed camera and -z ahead of a right-handed one.
|
|
99
|
+
linearDepth = abs(mvPosition.z);
|
|
103
100
|
#endif
|
|
104
101
|
|
|
105
|
-
|
|
106
|
-
vec2 tc = vec2(tileCountX, tileCountY);
|
|
107
|
-
float baseTile = floor(uvTile);
|
|
108
|
-
float tileU = mod(baseTile, tc.x) / tc.x;
|
|
109
|
-
float tileV = 1.0 - floor(baseTile / tc.x) / tc.y - 1.0 / tc.y;
|
|
110
|
-
vUV = uv / tc + vec2(tileU, tileV);
|
|
111
|
-
#ifdef TILE_BLEND
|
|
112
|
-
float nextTile = ceil(uvTile);
|
|
113
|
-
float nextU = mod(nextTile, tc.x) / tc.x;
|
|
114
|
-
float nextV = 1.0 - floor(nextTile / tc.x) / tc.y - 1.0 / tc.y;
|
|
115
|
-
vUV2 = uv / tc + vec2(nextU, nextV);
|
|
116
|
-
vTileBlend = fract(uvTile);
|
|
117
|
-
#endif
|
|
118
|
-
#else
|
|
119
|
-
vUV = uv;
|
|
120
|
-
#endif
|
|
102
|
+
${sheetVertexGLSL('uv')}
|
|
121
103
|
|
|
104
|
+
#ifdef UV1
|
|
105
|
+
vUV1 = uv;
|
|
106
|
+
#endif
|
|
122
107
|
vColor = color;
|
|
123
108
|
}
|
|
124
109
|
`;
|
|
@@ -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.
|
|
@@ -30,9 +27,9 @@ uniform pivot: vec3f;
|
|
|
30
27
|
// Varyings
|
|
31
28
|
varying vUV: vec2f;
|
|
32
29
|
varying vColor: vec4f;
|
|
33
|
-
#ifdef
|
|
34
|
-
|
|
35
|
-
varying
|
|
30
|
+
#ifdef UV1
|
|
31
|
+
// The particle's own UV, never moved by the sheet (UV channel 1).
|
|
32
|
+
varying vUV1: vec2f;
|
|
36
33
|
#endif
|
|
37
34
|
#ifdef SOFT_PARTICLES
|
|
38
35
|
varying projPosition: vec4f;
|
|
@@ -101,26 +98,15 @@ fn main(input: VertexInputs) -> FragmentInputs {
|
|
|
101
98
|
${fogVertexWGSL('mvPosition.xyz')}
|
|
102
99
|
#ifdef SOFT_PARTICLES
|
|
103
100
|
vertexOutputs.projPosition = clipPosition;
|
|
104
|
-
|
|
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);
|
|
105
103
|
#endif
|
|
106
104
|
|
|
107
|
-
|
|
108
|
-
let tc = vec2f(uniforms.tileCountX, uniforms.tileCountY);
|
|
109
|
-
let baseTile = floor(vertexInputs.uvTile);
|
|
110
|
-
let tileU = (baseTile % tc.x) / tc.x;
|
|
111
|
-
let tileV = 1.0 - floor(baseTile / tc.x) / tc.y - 1.0 / tc.y;
|
|
112
|
-
vertexOutputs.vUV = vertexInputs.uv / tc + vec2f(tileU, tileV);
|
|
113
|
-
#ifdef TILE_BLEND
|
|
114
|
-
let nextTile = ceil(vertexInputs.uvTile);
|
|
115
|
-
let nextU = (nextTile % tc.x) / tc.x;
|
|
116
|
-
let nextV = 1.0 - floor(nextTile / tc.x) / tc.y - 1.0 / tc.y;
|
|
117
|
-
vertexOutputs.vUV2 = vertexInputs.uv / tc + vec2f(nextU, nextV);
|
|
118
|
-
vertexOutputs.vTileBlend = fract(vertexInputs.uvTile);
|
|
119
|
-
#endif
|
|
120
|
-
#else
|
|
121
|
-
vertexOutputs.vUV = vertexInputs.uv;
|
|
122
|
-
#endif
|
|
105
|
+
${sheetVertexWGSL('vertexInputs.uv')}
|
|
123
106
|
|
|
107
|
+
#ifdef UV1
|
|
108
|
+
vertexOutputs.vUV1 = vertexInputs.uv;
|
|
109
|
+
#endif
|
|
124
110
|
vertexOutputs.vColor = vertexInputs.color;
|
|
125
111
|
}
|
|
126
112
|
`;
|
|
@@ -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
|
-
|
|
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.
|
|
@@ -32,9 +28,9 @@ uniform vec3 pivot;
|
|
|
32
28
|
// Varyings
|
|
33
29
|
varying vec2 vUV;
|
|
34
30
|
varying vec4 vColor;
|
|
35
|
-
#ifdef
|
|
36
|
-
|
|
37
|
-
varying
|
|
31
|
+
#ifdef UV1
|
|
32
|
+
// The particle's own UV, never moved by the sheet (UV channel 1).
|
|
33
|
+
varying vec2 vUV1;
|
|
38
34
|
#endif
|
|
39
35
|
#ifdef SOFT_PARTICLES
|
|
40
36
|
varying vec4 projPosition;
|
|
@@ -45,6 +41,7 @@ varying float linearDepth;
|
|
|
45
41
|
// Smallest and largest size a particle may have on screen, as fractions of the viewport height.
|
|
46
42
|
uniform vec2 sizeLimits;
|
|
47
43
|
#endif
|
|
44
|
+
|
|
48
45
|
${fogVertexDeclarationGLSL}
|
|
49
46
|
void main() {
|
|
50
47
|
float lengthFactor = velocity.w;
|
|
@@ -52,6 +49,15 @@ void main() {
|
|
|
52
49
|
// extent and mirrors its texture instead (see quadUV below).
|
|
53
50
|
float avgSize = (abs(size.x) + abs(size.y)) * 0.5;
|
|
54
51
|
vec4 mvPosition = view * world * vec4(offset, 1.0);
|
|
52
|
+
vec3 viewVelocity = mat3(view * world) * velocity.xyz;
|
|
53
|
+
float vlength = length(viewVelocity);
|
|
54
|
+
// Stretch direction is the velocity direction; only a genuinely motionless particle has none.
|
|
55
|
+
// Deriving it via normalize keeps the stretch aligned even when the speed contribution is ~0
|
|
56
|
+
// (e.g. a speed factor of 0), instead of collapsing the whole burst onto a fixed screen axis.
|
|
57
|
+
vec3 vdir = vlength > 0.000001 ? viewVelocity / vlength : vec3(0.0, 0.0, 1.0);
|
|
58
|
+
// Seen straight along its length a streak has no side to face; any will do.
|
|
59
|
+
vec3 sideRaw = cross(mvPosition.xyz, vdir);
|
|
60
|
+
vec3 side = dot(sideRaw, sideRaw) > 1e-12 ? normalize(sideRaw) : vec3(1.0, 0.0, 0.0);
|
|
55
61
|
#ifdef SIZE_LIMITS
|
|
56
62
|
// The streak's width on screen as a fraction of the viewport height, held
|
|
57
63
|
// between the limits; a perspective projection divides by the view depth.
|
|
@@ -60,19 +66,6 @@ void main() {
|
|
|
60
66
|
if (screenSize > 0.0) {
|
|
61
67
|
avgSize *= clamp(screenSize, sizeLimits.x, sizeLimits.y) / screenSize;
|
|
62
68
|
}
|
|
63
|
-
#endif
|
|
64
|
-
vec3 viewVelocity = mat3(view * world) * velocity.xyz;
|
|
65
|
-
float vlength = length(viewVelocity);
|
|
66
|
-
// Stretch direction is the velocity direction; only a genuinely motionless particle has none.
|
|
67
|
-
// Deriving it via normalize keeps the stretch aligned even when the speed contribution is ~0
|
|
68
|
-
// (e.g. speedFactor 0), instead of collapsing the whole burst onto a fixed screen axis.
|
|
69
|
-
vec3 vdir = vlength > 0.000001 ? viewVelocity / vlength : vec3(0.0, 0.0, 1.0);
|
|
70
|
-
#ifdef BEAM
|
|
71
|
-
// Seen straight along its length a beam has no side to face; any will do.
|
|
72
|
-
vec3 sideRaw = cross(mvPosition.xyz, vdir);
|
|
73
|
-
vec3 side = dot(sideRaw, sideRaw) > 1e-12 ? normalize(sideRaw) : vec3(1.0, 0.0, 0.0);
|
|
74
|
-
#else
|
|
75
|
-
vec3 side = normalize(cross(mvPosition.xyz, vdir));
|
|
76
69
|
#endif
|
|
77
70
|
mvPosition.xyz += position.y * side * avgSize;
|
|
78
71
|
#ifdef BEAM
|
|
@@ -93,26 +86,15 @@ ${fogVertexGLSL('mvPosition.xyz')}
|
|
|
93
86
|
vec2 quadUV = vec2(size.x < 0.0 ? 1.0 - uv.x : uv.x, size.y < 0.0 ? 1.0 - uv.y : uv.y);
|
|
94
87
|
#ifdef SOFT_PARTICLES
|
|
95
88
|
projPosition = gl_Position;
|
|
96
|
-
|
|
89
|
+
// View depth is +z ahead of a left-handed camera and -z ahead of a right-handed one.
|
|
90
|
+
linearDepth = abs(mvPosition.z);
|
|
97
91
|
#endif
|
|
98
92
|
|
|
99
|
-
|
|
100
|
-
vec2 tc = vec2(tileCountX, tileCountY);
|
|
101
|
-
float baseTile = floor(uvTile);
|
|
102
|
-
float tileU = mod(baseTile, tc.x) / tc.x;
|
|
103
|
-
float tileV = 1.0 - floor(baseTile / tc.x) / tc.y - 1.0 / tc.y;
|
|
104
|
-
vUV = quadUV / tc + vec2(tileU, tileV);
|
|
105
|
-
#ifdef TILE_BLEND
|
|
106
|
-
float nextTile = ceil(uvTile);
|
|
107
|
-
float nextU = mod(nextTile, tc.x) / tc.x;
|
|
108
|
-
float nextV = 1.0 - floor(nextTile / tc.x) / tc.y - 1.0 / tc.y;
|
|
109
|
-
vUV2 = quadUV / tc + vec2(nextU, nextV);
|
|
110
|
-
vTileBlend = fract(uvTile);
|
|
111
|
-
#endif
|
|
112
|
-
#else
|
|
113
|
-
vUV = quadUV;
|
|
114
|
-
#endif
|
|
93
|
+
${sheetVertexGLSL('quadUV')}
|
|
115
94
|
|
|
95
|
+
#ifdef UV1
|
|
96
|
+
vUV1 = quadUV;
|
|
97
|
+
#endif
|
|
116
98
|
vColor = color;
|
|
117
99
|
}
|
|
118
100
|
`;
|
|
@@ -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
|
-
|
|
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.
|
|
@@ -32,9 +28,9 @@ uniform pivot: vec3f;
|
|
|
32
28
|
// Varyings
|
|
33
29
|
varying vUV: vec2f;
|
|
34
30
|
varying vColor: vec4f;
|
|
35
|
-
#ifdef
|
|
36
|
-
|
|
37
|
-
varying
|
|
31
|
+
#ifdef UV1
|
|
32
|
+
// The particle's own UV, never moved by the sheet (UV channel 1).
|
|
33
|
+
varying vUV1: vec2f;
|
|
38
34
|
#endif
|
|
39
35
|
#ifdef SOFT_PARTICLES
|
|
40
36
|
varying projPosition: vec4f;
|
|
@@ -45,6 +41,7 @@ varying linearDepth: f32;
|
|
|
45
41
|
// Smallest and largest size a particle may have on screen, as fractions of the viewport height.
|
|
46
42
|
uniform sizeLimits: vec2f;
|
|
47
43
|
#endif
|
|
44
|
+
|
|
48
45
|
${fogVertexDeclarationWGSL}
|
|
49
46
|
@vertex
|
|
50
47
|
fn main(input: VertexInputs) -> FragmentInputs {
|
|
@@ -53,35 +50,31 @@ fn main(input: VertexInputs) -> FragmentInputs {
|
|
|
53
50
|
// extent and mirrors its texture instead (see quadUV below).
|
|
54
51
|
var avgSize = (abs(vertexInputs.size.x) + abs(vertexInputs.size.y)) * 0.5;
|
|
55
52
|
var mvPosition = uniforms.view * uniforms.world * vec4f(vertexInputs.offset, 1.0);
|
|
56
|
-
#ifdef SIZE_LIMITS
|
|
57
|
-
// The streak's width on screen as a fraction of the viewport height, held
|
|
58
|
-
// between the limits; a perspective projection divides by the view depth.
|
|
59
|
-
let limitDepth = select(1.0, abs(mvPosition.z), abs(uniforms.projection[2][3]) > 0.0);
|
|
60
|
-
let screenSize = avgSize * uniforms.projection[1][1] / (2.0 * limitDepth);
|
|
61
|
-
if (screenSize > 0.0) {
|
|
62
|
-
avgSize *= clamp(screenSize, uniforms.sizeLimits.x, uniforms.sizeLimits.y) / screenSize;
|
|
63
|
-
}
|
|
64
|
-
#endif
|
|
65
53
|
let viewWorld = uniforms.view * uniforms.world;
|
|
66
54
|
let viewWorld3 = mat3x3f(viewWorld[0].xyz, viewWorld[1].xyz, viewWorld[2].xyz);
|
|
67
55
|
let viewVelocity = viewWorld3 * vertexInputs.velocity.xyz;
|
|
68
56
|
let vlength = length(viewVelocity);
|
|
69
57
|
// Stretch direction is the velocity direction; only a genuinely motionless particle has none.
|
|
70
58
|
// Deriving it via normalize keeps the stretch aligned even when the speed contribution is ~0
|
|
71
|
-
// (e.g.
|
|
59
|
+
// (e.g. a speed factor of 0), instead of collapsing the whole burst onto a fixed screen axis.
|
|
72
60
|
var vdir = vec3f(0.0, 0.0, 1.0);
|
|
73
61
|
if (vlength > 0.000001) {
|
|
74
62
|
vdir = viewVelocity / vlength;
|
|
75
63
|
}
|
|
76
|
-
|
|
77
|
-
// 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.
|
|
78
65
|
let sideRaw = cross(mvPosition.xyz, vdir);
|
|
79
66
|
var side = vec3f(1.0, 0.0, 0.0);
|
|
80
67
|
if (dot(sideRaw, sideRaw) > 1e-12) {
|
|
81
68
|
side = normalize(sideRaw);
|
|
82
69
|
}
|
|
83
|
-
#
|
|
84
|
-
|
|
70
|
+
#ifdef SIZE_LIMITS
|
|
71
|
+
// The streak's width on screen as a fraction of the viewport height, held
|
|
72
|
+
// between the limits; a perspective projection divides by the view depth.
|
|
73
|
+
let limitDepth = select(1.0, abs(mvPosition.z), abs(uniforms.projection[2][3]) > 0.0);
|
|
74
|
+
let screenSize = avgSize * uniforms.projection[1][1] / (2.0 * limitDepth);
|
|
75
|
+
if (screenSize > 0.0) {
|
|
76
|
+
avgSize *= clamp(screenSize, uniforms.sizeLimits.x, uniforms.sizeLimits.y) / screenSize;
|
|
77
|
+
}
|
|
85
78
|
#endif
|
|
86
79
|
let widthOffset = vertexInputs.position.y * side * avgSize;
|
|
87
80
|
// Equivalent to viewVelocity * (1.0 + lengthFactor / vlength) for moving particles, but the
|
|
@@ -108,26 +101,15 @@ ${fogVertexWGSL('mvPosition.xyz')}
|
|
|
108
101
|
let quadUV = select(vertexInputs.uv, 1.0 - vertexInputs.uv, vertexInputs.size.xy < vec2f(0.0));
|
|
109
102
|
#ifdef SOFT_PARTICLES
|
|
110
103
|
vertexOutputs.projPosition = clipPosition;
|
|
111
|
-
|
|
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);
|
|
112
106
|
#endif
|
|
113
107
|
|
|
114
|
-
|
|
115
|
-
let tc = vec2f(uniforms.tileCountX, uniforms.tileCountY);
|
|
116
|
-
let baseTile = floor(vertexInputs.uvTile);
|
|
117
|
-
let tileU = (baseTile % tc.x) / tc.x;
|
|
118
|
-
let tileV = 1.0 - floor(baseTile / tc.x) / tc.y - 1.0 / tc.y;
|
|
119
|
-
vertexOutputs.vUV = quadUV / tc + vec2f(tileU, tileV);
|
|
120
|
-
#ifdef TILE_BLEND
|
|
121
|
-
let nextTile = ceil(vertexInputs.uvTile);
|
|
122
|
-
let nextU = (nextTile % tc.x) / tc.x;
|
|
123
|
-
let nextV = 1.0 - floor(nextTile / tc.x) / tc.y - 1.0 / tc.y;
|
|
124
|
-
vertexOutputs.vUV2 = quadUV / tc + vec2f(nextU, nextV);
|
|
125
|
-
vertexOutputs.vTileBlend = fract(vertexInputs.uvTile);
|
|
126
|
-
#endif
|
|
127
|
-
#else
|
|
128
|
-
vertexOutputs.vUV = quadUV;
|
|
129
|
-
#endif
|
|
108
|
+
${sheetVertexWGSL('quadUV')}
|
|
130
109
|
|
|
110
|
+
#ifdef UV1
|
|
111
|
+
vertexOutputs.vUV1 = quadUV;
|
|
112
|
+
#endif
|
|
131
113
|
vertexOutputs.vColor = vertexInputs.color;
|
|
132
114
|
}
|
|
133
115
|
`;
|
|
@@ -1,21 +1,34 @@
|
|
|
1
1
|
import {fogFragmentDeclarationGLSL, fogFragmentGLSL} from './chunks/fog';
|
|
2
|
+
import {softFragmentDeclarationGLSL, softFragmentGLSL} from './chunks/soft';
|
|
2
3
|
import {surfaceColorGLSL, surfaceFragmentDeclarationGLSL} from './chunks/surface';
|
|
3
4
|
|
|
4
5
|
export default /* glsl */ `
|
|
5
6
|
varying vec2 vUV;
|
|
6
7
|
varying vec4 vColor;
|
|
8
|
+
#ifdef UV1
|
|
9
|
+
varying vec2 vUV1;
|
|
10
|
+
#endif
|
|
7
11
|
|
|
8
12
|
#ifdef USE_MAP
|
|
9
13
|
uniform sampler2D map;
|
|
10
14
|
#endif
|
|
11
15
|
|
|
16
|
+
#ifdef USE_ALPHATEST
|
|
17
|
+
uniform float alphaTest;
|
|
18
|
+
#endif
|
|
19
|
+
|
|
12
20
|
${fogFragmentDeclarationGLSL}
|
|
21
|
+
${softFragmentDeclarationGLSL}
|
|
13
22
|
${surfaceFragmentDeclarationGLSL}
|
|
14
23
|
void main() {
|
|
15
24
|
${surfaceColorGLSL(false)}
|
|
25
|
+
#ifdef USE_ALPHATEST
|
|
26
|
+
if (baseColor.a < alphaTest) discard;
|
|
27
|
+
#else
|
|
16
28
|
if (baseColor.a < 0.01) discard;
|
|
29
|
+
#endif
|
|
17
30
|
|
|
18
31
|
${fogFragmentGLSL('baseColor.rgb')}
|
|
19
32
|
gl_FragColor = baseColor;
|
|
20
|
-
}
|
|
33
|
+
${softFragmentGLSL('gl_FragColor')}}
|
|
21
34
|
`;
|
|
@@ -1,23 +1,37 @@
|
|
|
1
1
|
import {fogFragmentDeclarationWGSL, fogFragmentWGSL} from './chunks/fog';
|
|
2
|
+
import {softFragmentDeclarationWGSL, softFragmentWGSL} from './chunks/soft';
|
|
2
3
|
import {surfaceColorWGSL, surfaceFragmentDeclarationWGSL} from './chunks/surface';
|
|
3
4
|
|
|
4
5
|
export default /* wgsl */ `
|
|
5
6
|
varying vUV: vec2f;
|
|
6
7
|
varying vColor: vec4f;
|
|
8
|
+
#ifdef UV1
|
|
9
|
+
varying vUV1: vec2f;
|
|
10
|
+
#endif
|
|
7
11
|
|
|
8
12
|
#ifdef USE_MAP
|
|
9
13
|
var mapSampler: sampler;
|
|
10
14
|
var map: texture_2d<f32>;
|
|
11
15
|
#endif
|
|
12
16
|
|
|
17
|
+
#ifdef USE_ALPHATEST
|
|
18
|
+
uniform alphaTest: f32;
|
|
19
|
+
#endif
|
|
20
|
+
|
|
13
21
|
${fogFragmentDeclarationWGSL}
|
|
22
|
+
${softFragmentDeclarationWGSL}
|
|
14
23
|
${surfaceFragmentDeclarationWGSL}
|
|
15
24
|
@fragment
|
|
16
25
|
fn main(input: FragmentInputs) -> FragmentOutputs {
|
|
17
26
|
${surfaceColorWGSL(false)}
|
|
27
|
+
#ifdef USE_ALPHATEST
|
|
28
|
+
if (baseColor.a < uniforms.alphaTest) { discard; }
|
|
29
|
+
#else
|
|
18
30
|
if (baseColor.a < 0.01) { discard; }
|
|
31
|
+
#endif
|
|
19
32
|
|
|
20
33
|
${fogFragmentWGSL('baseColor')}
|
|
34
|
+
${softFragmentWGSL('baseColor')}
|
|
21
35
|
fragmentOutputs.color = baseColor;
|
|
22
36
|
}
|
|
23
37
|
`;
|