babylon.quarks 0.25.0 → 0.26.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 +85 -0
- 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.ts +279 -53
- package/package.json +1 -1
- package/src/BatchedRenderer.ts +23 -17
- package/src/ParticleSystem.ts +240 -38
- package/src/QuarksLoader.ts +42 -8
- package/src/SpriteBatch.ts +52 -1
- package/src/TrailBatch.ts +129 -20
- package/src/VFXBatch.ts +325 -61
- package/src/index.ts +19 -2
- package/src/shaders/chunks/surface.ts +122 -42
- package/src/shaders/local_particle_physics_vert.glsl.ts +15 -0
- package/src/shaders/local_particle_physics_vert.wgsl.ts +15 -0
- package/src/shaders/particle_frag.glsl.ts +3 -0
- package/src/shaders/particle_frag.wgsl.ts +3 -0
- package/src/shaders/particle_physics_frag.glsl.ts +10 -4
- package/src/shaders/particle_physics_frag.wgsl.ts +10 -4
- package/src/shaders/particle_vert.glsl.ts +7 -0
- package/src/shaders/particle_vert.wgsl.ts +7 -0
- package/src/shaders/stretched_bb_particle_vert.glsl.ts +17 -9
- package/src/shaders/stretched_bb_particle_vert.wgsl.ts +17 -9
- package/src/shaders/trail_frag.glsl.ts +3 -0
- package/src/shaders/trail_frag.wgsl.ts +3 -0
- package/src/shaders/trail_vert.glsl.ts +8 -0
- package/src/shaders/trail_vert.wgsl.ts +8 -0
|
@@ -1,43 +1,65 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Texture effects shared by the sprite, mesh and trail fragment shaders, in
|
|
3
|
-
* both shader languages: UV scrolling, a gradient map and
|
|
3
|
+
* both shader languages: UV scrolling, UV distortion, a gradient map and
|
|
4
|
+
* alpha erosion.
|
|
4
5
|
*
|
|
5
|
-
* - `
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
6
|
+
* - `UV1`: the vertex shader passes `vUV1`, the particle's own UV that the
|
|
7
|
+
* sprite sheet never moves (see `UVChannel`). The distortion noise and the
|
|
8
|
+
* erosion mask read it under `UV_DISTORTION_UV1` / `EROSION_MASK_UV1`, the
|
|
9
|
+
* map's UV (`vUV`) otherwise.
|
|
10
|
+
* - Each texture can be laid by a transform, `(tiling u, tiling v, offset u,
|
|
11
|
+
* offset v)`: sampled at `uv * transform.xy + transform.zw`, the offset
|
|
12
|
+
* holding its scroll, wrapped on the CPU so it never loses precision (see
|
|
13
|
+
* `TextureUV`).
|
|
14
|
+
* - `MAP_TRANSFORM`: the map is laid by `mapTransform`, on `vUV1` under
|
|
15
|
+
* `MAP_UV1` (where the sheet's second tile is not blended, the sheet not
|
|
16
|
+
* applying), on the sheet's UV otherwise, where a scroll runs into the
|
|
17
|
+
* neighbouring tiles.
|
|
18
|
+
* - `UV_DISTORTION`: the map's UV is pushed about by a noise texture
|
|
19
|
+
* (`distortionMap`, red and green around 0.5, laid by `distortionTransform`)
|
|
20
|
+
* by up to `distortionStrength` UV units: the heat shimmer, licking and
|
|
21
|
+
* breathing of fire and auras. On a sprite sheet the pushed UV can reach
|
|
22
|
+
* the neighbouring tile.
|
|
23
|
+
* - `GRADIENT_MAP`: the map's texel dotted with `gradientMapChannel` (one
|
|
24
|
+
* channel, or luminance weights) picks a colour along U of `gradientMap`.
|
|
25
|
+
* The ramp's alpha multiplies the map's, or replaces it when the lookup is
|
|
26
|
+
* by alpha (`gradientMapChannel.a` 1). The particle colour still tints the
|
|
27
|
+
* result. `gradientMapRange` keeps the lookup between the first and last
|
|
28
|
+
* texel centres. Make the ramp without mipmaps: the lookup's UV jumps with
|
|
29
|
+
* the map's detail, and the hardware would pick a blurred mip for it.
|
|
14
30
|
* - `EROSION`: the particle's alpha stops being a transparency and becomes how
|
|
15
31
|
* much of the shape is left. A fragment shows where the mask (the red
|
|
16
|
-
* channel of `erosionMask` under `EROSION_MASK`,
|
|
17
|
-
*
|
|
18
|
-
* alpha
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* the edge band just above the cut glows in
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* alpha (one-one, premultiplied) show a hard cut.
|
|
32
|
+
* channel of `erosionMask` under `EROSION_MASK`, laid by
|
|
33
|
+
* `erosionMaskTransform`; the map's alpha otherwise) is above the cut that
|
|
34
|
+
* alpha sets: alpha 1 shows everything the map shows, alpha 0 nothing, and
|
|
35
|
+
* on the way down the shape eats away from its lowest mask values first — a
|
|
36
|
+
* noise mask dissolves it, a gradient mask wipes it. `erosionParams` is
|
|
37
|
+
* (softness, edge width); the edge band just above the cut glows in
|
|
38
|
+
* `erosionEdgeColor`. Erosion only changes alpha, so blend modes that
|
|
39
|
+
* ignore alpha (one-one, premultiplied) show a hard cut.
|
|
25
40
|
*/
|
|
26
41
|
|
|
27
42
|
/** Fragment-side declarations, GLSL. */
|
|
28
43
|
export const surfaceFragmentDeclarationGLSL = /* glsl */ `
|
|
29
|
-
#ifdef
|
|
30
|
-
uniform
|
|
44
|
+
#ifdef MAP_TRANSFORM
|
|
45
|
+
uniform vec4 mapTransform;
|
|
46
|
+
#endif
|
|
47
|
+
#ifdef UV_DISTORTION
|
|
48
|
+
uniform sampler2D distortionMap;
|
|
49
|
+
uniform vec4 distortionTransform;
|
|
50
|
+
uniform float distortionStrength;
|
|
31
51
|
#endif
|
|
32
52
|
#ifdef GRADIENT_MAP
|
|
33
53
|
uniform sampler2D gradientMap;
|
|
34
54
|
uniform vec2 gradientMapRange;
|
|
55
|
+
uniform vec4 gradientMapChannel;
|
|
35
56
|
#endif
|
|
36
57
|
#ifdef EROSION
|
|
37
|
-
uniform
|
|
58
|
+
uniform vec2 erosionParams;
|
|
38
59
|
uniform vec3 erosionEdgeColor;
|
|
39
60
|
#ifdef EROSION_MASK
|
|
40
61
|
uniform sampler2D erosionMask;
|
|
62
|
+
uniform vec4 erosionMaskTransform;
|
|
41
63
|
#endif
|
|
42
64
|
|
|
43
65
|
vec4 quarksErode(vec4 color, float level, float mask) {
|
|
@@ -65,11 +87,22 @@ vec4 quarksErode(vec4 color, float level, float mask) {
|
|
|
65
87
|
export function surfaceColorGLSL(tileBlend: boolean): string {
|
|
66
88
|
return /* glsl */ `
|
|
67
89
|
vec4 baseColor = vColor;
|
|
68
|
-
#
|
|
69
|
-
vec2 mapUV =
|
|
90
|
+
#if defined(MAP_TRANSFORM) && defined(MAP_UV1)
|
|
91
|
+
vec2 mapUV = vUV1 * mapTransform.xy + mapTransform.zw;
|
|
92
|
+
#elif defined(MAP_TRANSFORM)
|
|
93
|
+
vec2 mapUV = vUV * mapTransform.xy + mapTransform.zw;
|
|
70
94
|
#else
|
|
71
95
|
vec2 mapUV = vUV;
|
|
72
96
|
#endif
|
|
97
|
+
#ifdef UV_DISTORTION
|
|
98
|
+
#ifdef UV_DISTORTION_UV1
|
|
99
|
+
vec2 distortionUV = vUV1;
|
|
100
|
+
#else
|
|
101
|
+
vec2 distortionUV = vUV;
|
|
102
|
+
#endif
|
|
103
|
+
vec2 distortion = (texture2D(distortionMap, distortionUV * distortionTransform.xy + distortionTransform.zw).rg - 0.5) * 2.0 * distortionStrength;
|
|
104
|
+
mapUV += distortion;
|
|
105
|
+
#endif
|
|
73
106
|
#ifdef EROSION
|
|
74
107
|
float erosionLevel = baseColor.a;
|
|
75
108
|
baseColor.a = 1.0;
|
|
@@ -80,18 +113,27 @@ export function surfaceColorGLSL(tileBlend: boolean): string {
|
|
|
80
113
|
${
|
|
81
114
|
tileBlend
|
|
82
115
|
? `#ifdef TILE_BLEND
|
|
83
|
-
#
|
|
84
|
-
|
|
116
|
+
#if defined(MAP_TRANSFORM) && defined(MAP_UV1)
|
|
117
|
+
vec2 mapUV2 = mapUV;
|
|
85
118
|
#else
|
|
86
|
-
|
|
119
|
+
#ifdef MAP_TRANSFORM
|
|
120
|
+
vec2 mapUV2 = vUV2 * mapTransform.xy + mapTransform.zw;
|
|
121
|
+
#else
|
|
122
|
+
vec2 mapUV2 = vUV2;
|
|
123
|
+
#endif
|
|
124
|
+
#ifdef UV_DISTORTION
|
|
125
|
+
mapUV2 += distortion;
|
|
126
|
+
#endif
|
|
87
127
|
#endif
|
|
128
|
+
vec4 texColor2 = texture2D(map, mapUV2);
|
|
88
129
|
texColor = mix(texColor, texColor2, vTileBlend);
|
|
89
130
|
#endif`
|
|
90
131
|
: ''
|
|
91
132
|
}
|
|
92
133
|
#ifdef GRADIENT_MAP
|
|
93
|
-
|
|
94
|
-
|
|
134
|
+
float rampAt = clamp(dot(texColor, gradientMapChannel), 0.0, 1.0);
|
|
135
|
+
vec4 ramp = texture2D(gradientMap, vec2(mix(gradientMapRange.x, gradientMapRange.y, rampAt), 0.5));
|
|
136
|
+
texColor = vec4(ramp.rgb, ramp.a * mix(texColor.a, 1.0, gradientMapChannel.a));
|
|
95
137
|
#endif
|
|
96
138
|
#ifdef EROSION
|
|
97
139
|
erosionMaskValue = texColor.a;
|
|
@@ -100,7 +142,12 @@ export function surfaceColorGLSL(tileBlend: boolean): string {
|
|
|
100
142
|
#endif
|
|
101
143
|
#ifdef EROSION
|
|
102
144
|
#ifdef EROSION_MASK
|
|
103
|
-
|
|
145
|
+
#ifdef EROSION_MASK_UV1
|
|
146
|
+
vec2 erosionUV = vUV1;
|
|
147
|
+
#else
|
|
148
|
+
vec2 erosionUV = vUV;
|
|
149
|
+
#endif
|
|
150
|
+
erosionMaskValue = texture2D(erosionMask, erosionUV * erosionMaskTransform.xy + erosionMaskTransform.zw).r;
|
|
104
151
|
#endif
|
|
105
152
|
baseColor = quarksErode(baseColor, erosionLevel, erosionMaskValue);
|
|
106
153
|
#endif
|
|
@@ -109,20 +156,28 @@ export function surfaceColorGLSL(tileBlend: boolean): string {
|
|
|
109
156
|
|
|
110
157
|
/** Fragment-side declarations, WGSL. */
|
|
111
158
|
export const surfaceFragmentDeclarationWGSL = /* wgsl */ `
|
|
112
|
-
#ifdef
|
|
113
|
-
uniform
|
|
159
|
+
#ifdef MAP_TRANSFORM
|
|
160
|
+
uniform mapTransform: vec4f;
|
|
161
|
+
#endif
|
|
162
|
+
#ifdef UV_DISTORTION
|
|
163
|
+
var distortionMapSampler: sampler;
|
|
164
|
+
var distortionMap: texture_2d<f32>;
|
|
165
|
+
uniform distortionTransform: vec4f;
|
|
166
|
+
uniform distortionStrength: f32;
|
|
114
167
|
#endif
|
|
115
168
|
#ifdef GRADIENT_MAP
|
|
116
169
|
var gradientMapSampler: sampler;
|
|
117
170
|
var gradientMap: texture_2d<f32>;
|
|
118
171
|
uniform gradientMapRange: vec2f;
|
|
172
|
+
uniform gradientMapChannel: vec4f;
|
|
119
173
|
#endif
|
|
120
174
|
#ifdef EROSION
|
|
121
|
-
uniform erosionParams:
|
|
175
|
+
uniform erosionParams: vec2f;
|
|
122
176
|
uniform erosionEdgeColor: vec3f;
|
|
123
177
|
#ifdef EROSION_MASK
|
|
124
178
|
var erosionMaskSampler: sampler;
|
|
125
179
|
var erosionMask: texture_2d<f32>;
|
|
180
|
+
uniform erosionMaskTransform: vec4f;
|
|
126
181
|
#endif
|
|
127
182
|
|
|
128
183
|
fn quarksErode(colorIn: vec4f, level: f32, mask: f32) -> vec4f {
|
|
@@ -145,10 +200,21 @@ fn quarksErode(colorIn: vec4f, level: f32, mask: f32) -> vec4f {
|
|
|
145
200
|
export function surfaceColorWGSL(tileBlend: boolean): string {
|
|
146
201
|
return /* wgsl */ `
|
|
147
202
|
var baseColor = fragmentInputs.vColor;
|
|
148
|
-
#
|
|
149
|
-
|
|
203
|
+
#if defined(MAP_TRANSFORM) && defined(MAP_UV1)
|
|
204
|
+
var mapUV = fragmentInputs.vUV1 * uniforms.mapTransform.xy + uniforms.mapTransform.zw;
|
|
205
|
+
#elif defined(MAP_TRANSFORM)
|
|
206
|
+
var mapUV = fragmentInputs.vUV * uniforms.mapTransform.xy + uniforms.mapTransform.zw;
|
|
150
207
|
#else
|
|
151
|
-
|
|
208
|
+
var mapUV = fragmentInputs.vUV;
|
|
209
|
+
#endif
|
|
210
|
+
#ifdef UV_DISTORTION
|
|
211
|
+
#ifdef UV_DISTORTION_UV1
|
|
212
|
+
let distortionUV = fragmentInputs.vUV1;
|
|
213
|
+
#else
|
|
214
|
+
let distortionUV = fragmentInputs.vUV;
|
|
215
|
+
#endif
|
|
216
|
+
let distortion = (textureSample(distortionMap, distortionMapSampler, distortionUV * uniforms.distortionTransform.xy + uniforms.distortionTransform.zw).rg - 0.5) * 2.0 * uniforms.distortionStrength;
|
|
217
|
+
mapUV += distortion;
|
|
152
218
|
#endif
|
|
153
219
|
#ifdef EROSION
|
|
154
220
|
let erosionLevel = baseColor.a;
|
|
@@ -160,18 +226,27 @@ export function surfaceColorWGSL(tileBlend: boolean): string {
|
|
|
160
226
|
${
|
|
161
227
|
tileBlend
|
|
162
228
|
? `#ifdef TILE_BLEND
|
|
163
|
-
#
|
|
164
|
-
let
|
|
229
|
+
#if defined(MAP_TRANSFORM) && defined(MAP_UV1)
|
|
230
|
+
let mapUV2 = mapUV;
|
|
165
231
|
#else
|
|
166
|
-
|
|
232
|
+
#ifdef MAP_TRANSFORM
|
|
233
|
+
var mapUV2 = fragmentInputs.vUV2 * uniforms.mapTransform.xy + uniforms.mapTransform.zw;
|
|
234
|
+
#else
|
|
235
|
+
var mapUV2 = fragmentInputs.vUV2;
|
|
236
|
+
#endif
|
|
237
|
+
#ifdef UV_DISTORTION
|
|
238
|
+
mapUV2 += distortion;
|
|
239
|
+
#endif
|
|
167
240
|
#endif
|
|
241
|
+
let texColor2 = textureSample(map, mapSampler, mapUV2);
|
|
168
242
|
texColor = mix(texColor, texColor2, fragmentInputs.vTileBlend);
|
|
169
243
|
#endif`
|
|
170
244
|
: ''
|
|
171
245
|
}
|
|
172
246
|
#ifdef GRADIENT_MAP
|
|
173
|
-
let
|
|
174
|
-
|
|
247
|
+
let rampAt = clamp(dot(texColor, uniforms.gradientMapChannel), 0.0, 1.0);
|
|
248
|
+
let ramp = textureSample(gradientMap, gradientMapSampler, vec2f(mix(uniforms.gradientMapRange.x, uniforms.gradientMapRange.y, rampAt), 0.5));
|
|
249
|
+
texColor = vec4f(ramp.rgb, ramp.a * mix(texColor.a, 1.0, uniforms.gradientMapChannel.a));
|
|
175
250
|
#endif
|
|
176
251
|
#ifdef EROSION
|
|
177
252
|
erosionMaskValue = texColor.a;
|
|
@@ -180,7 +255,12 @@ export function surfaceColorWGSL(tileBlend: boolean): string {
|
|
|
180
255
|
#endif
|
|
181
256
|
#ifdef EROSION
|
|
182
257
|
#ifdef EROSION_MASK
|
|
183
|
-
|
|
258
|
+
#ifdef EROSION_MASK_UV1
|
|
259
|
+
let erosionUV = fragmentInputs.vUV1;
|
|
260
|
+
#else
|
|
261
|
+
let erosionUV = fragmentInputs.vUV;
|
|
262
|
+
#endif
|
|
263
|
+
erosionMaskValue = textureSample(erosionMask, erosionMaskSampler, erosionUV * uniforms.erosionMaskTransform.xy + uniforms.erosionMaskTransform.zw).r;
|
|
184
264
|
#endif
|
|
185
265
|
baseColor = quarksErode(baseColor, erosionLevel, erosionMaskValue);
|
|
186
266
|
#endif
|
|
@@ -21,6 +21,14 @@ uniform float tileCountY;
|
|
|
21
21
|
|
|
22
22
|
varying vec2 vUV;
|
|
23
23
|
varying vec4 vColor;
|
|
24
|
+
#ifdef UV1
|
|
25
|
+
#ifdef MESH_UV2
|
|
26
|
+
// The mesh's second UV set.
|
|
27
|
+
attribute vec2 uv2;
|
|
28
|
+
#endif
|
|
29
|
+
// UV channel 1: the mesh's second UV set, or its first when it has none.
|
|
30
|
+
varying vec2 vUV1;
|
|
31
|
+
#endif
|
|
24
32
|
varying vec3 vNormal;
|
|
25
33
|
varying vec3 vWorldPos;
|
|
26
34
|
|
|
@@ -78,6 +86,13 @@ ${fogVertexGLSL('viewPos.xyz')}
|
|
|
78
86
|
vUV = uv;
|
|
79
87
|
#endif
|
|
80
88
|
|
|
89
|
+
#ifdef UV1
|
|
90
|
+
#ifdef MESH_UV2
|
|
91
|
+
vUV1 = uv2;
|
|
92
|
+
#else
|
|
93
|
+
vUV1 = uv;
|
|
94
|
+
#endif
|
|
95
|
+
#endif
|
|
81
96
|
vColor = color;
|
|
82
97
|
}
|
|
83
98
|
`;
|
|
@@ -21,6 +21,14 @@ uniform tileCountY: f32;
|
|
|
21
21
|
|
|
22
22
|
varying vUV: vec2f;
|
|
23
23
|
varying vColor: vec4f;
|
|
24
|
+
#ifdef UV1
|
|
25
|
+
#ifdef MESH_UV2
|
|
26
|
+
// The mesh's second UV set.
|
|
27
|
+
attribute uv2: vec2f;
|
|
28
|
+
#endif
|
|
29
|
+
// UV channel 1: the mesh's second UV set, or its first when it has none.
|
|
30
|
+
varying vUV1: vec2f;
|
|
31
|
+
#endif
|
|
24
32
|
varying vNormal: vec3f;
|
|
25
33
|
varying vWorldPos: vec3f;
|
|
26
34
|
|
|
@@ -80,6 +88,13 @@ ${fogVertexWGSL('viewPos.xyz')}
|
|
|
80
88
|
vertexOutputs.vUV = vertexInputs.uv;
|
|
81
89
|
#endif
|
|
82
90
|
|
|
91
|
+
#ifdef UV1
|
|
92
|
+
#ifdef MESH_UV2
|
|
93
|
+
vertexOutputs.vUV1 = vertexInputs.uv2;
|
|
94
|
+
#else
|
|
95
|
+
vertexOutputs.vUV1 = vertexInputs.uv;
|
|
96
|
+
#endif
|
|
97
|
+
#endif
|
|
83
98
|
vertexOutputs.vColor = vertexInputs.color;
|
|
84
99
|
}
|
|
85
100
|
`;
|
|
@@ -4,6 +4,9 @@ import {surfaceColorGLSL, surfaceFragmentDeclarationGLSL} from './chunks/surface
|
|
|
4
4
|
export default /* glsl */ `
|
|
5
5
|
varying vec2 vUV;
|
|
6
6
|
varying vec4 vColor;
|
|
7
|
+
#ifdef UV1
|
|
8
|
+
varying vec2 vUV1;
|
|
9
|
+
#endif
|
|
7
10
|
varying vec3 vNormal;
|
|
8
11
|
varying vec3 vWorldPos;
|
|
9
12
|
|
|
@@ -118,11 +121,14 @@ ${surfaceColorGLSL(true)}
|
|
|
118
121
|
#ifdef MESH_RIM
|
|
119
122
|
// Fresnel: strongest where the surface turns away from the camera.
|
|
120
123
|
vec3 V = normalize(eyePosition - vWorldPos);
|
|
121
|
-
float
|
|
122
|
-
#
|
|
123
|
-
|
|
124
|
+
float edgeTerm = pow(1.0 - abs(dot(N, V)), rimParams.x);
|
|
125
|
+
#if defined(MESH_RIM_FADE)
|
|
126
|
+
// Faces turned to the camera fade by the strength; edges stay.
|
|
127
|
+
baseColor.a *= clamp(1.0 - rimParams.y * (1.0 - edgeTerm), 0.0, 1.0);
|
|
128
|
+
#elif defined(MESH_RIM_MIX)
|
|
129
|
+
color = mix(color, rimColor, clamp(edgeTerm * rimParams.y, 0.0, 1.0));
|
|
124
130
|
#else
|
|
125
|
-
color += rimColor *
|
|
131
|
+
color += rimColor * edgeTerm * rimParams.y;
|
|
126
132
|
#endif
|
|
127
133
|
#endif
|
|
128
134
|
|
|
@@ -4,6 +4,9 @@ import {surfaceColorWGSL, surfaceFragmentDeclarationWGSL} from './chunks/surface
|
|
|
4
4
|
export default /* wgsl */ `
|
|
5
5
|
varying vUV: vec2f;
|
|
6
6
|
varying vColor: vec4f;
|
|
7
|
+
#ifdef UV1
|
|
8
|
+
varying vUV1: vec2f;
|
|
9
|
+
#endif
|
|
7
10
|
varying vNormal: vec3f;
|
|
8
11
|
varying vWorldPos: vec3f;
|
|
9
12
|
|
|
@@ -119,11 +122,14 @@ ${surfaceColorWGSL(true)}
|
|
|
119
122
|
#ifdef MESH_RIM
|
|
120
123
|
// Fresnel: strongest where the surface turns away from the camera.
|
|
121
124
|
let V = normalize(uniforms.eyePosition - fragmentInputs.vWorldPos);
|
|
122
|
-
let
|
|
123
|
-
#
|
|
124
|
-
|
|
125
|
+
let edgeTerm = pow(1.0 - abs(dot(N, V)), uniforms.rimParams.x);
|
|
126
|
+
#if defined(MESH_RIM_FADE)
|
|
127
|
+
// Faces turned to the camera fade by the strength; edges stay.
|
|
128
|
+
baseColor.a *= clamp(1.0 - uniforms.rimParams.y * (1.0 - edgeTerm), 0.0, 1.0);
|
|
129
|
+
#elif defined(MESH_RIM_MIX)
|
|
130
|
+
color = mix(color, uniforms.rimColor, clamp(edgeTerm * uniforms.rimParams.y, 0.0, 1.0));
|
|
125
131
|
#else
|
|
126
|
-
color += uniforms.rimColor *
|
|
132
|
+
color += uniforms.rimColor * edgeTerm * uniforms.rimParams.y;
|
|
127
133
|
#endif
|
|
128
134
|
#endif
|
|
129
135
|
|
|
@@ -31,6 +31,10 @@ uniform vec3 pivot;
|
|
|
31
31
|
// Varyings
|
|
32
32
|
varying vec2 vUV;
|
|
33
33
|
varying vec4 vColor;
|
|
34
|
+
#ifdef UV1
|
|
35
|
+
// The particle's own UV, never moved by the sheet (UV channel 1).
|
|
36
|
+
varying vec2 vUV1;
|
|
37
|
+
#endif
|
|
34
38
|
#ifdef TILE_BLEND
|
|
35
39
|
varying vec2 vUV2;
|
|
36
40
|
varying float vTileBlend;
|
|
@@ -119,6 +123,9 @@ ${fogVertexGLSL('mvPosition.xyz')}
|
|
|
119
123
|
vUV = uv;
|
|
120
124
|
#endif
|
|
121
125
|
|
|
126
|
+
#ifdef UV1
|
|
127
|
+
vUV1 = uv;
|
|
128
|
+
#endif
|
|
122
129
|
vColor = color;
|
|
123
130
|
}
|
|
124
131
|
`;
|
|
@@ -30,6 +30,10 @@ uniform pivot: vec3f;
|
|
|
30
30
|
// Varyings
|
|
31
31
|
varying vUV: vec2f;
|
|
32
32
|
varying vColor: vec4f;
|
|
33
|
+
#ifdef UV1
|
|
34
|
+
// The particle's own UV, never moved by the sheet (UV channel 1).
|
|
35
|
+
varying vUV1: vec2f;
|
|
36
|
+
#endif
|
|
33
37
|
#ifdef TILE_BLEND
|
|
34
38
|
varying vUV2: vec2f;
|
|
35
39
|
varying vTileBlend: f32;
|
|
@@ -121,6 +125,9 @@ ${fogVertexWGSL('mvPosition.xyz')}
|
|
|
121
125
|
vertexOutputs.vUV = vertexInputs.uv;
|
|
122
126
|
#endif
|
|
123
127
|
|
|
128
|
+
#ifdef UV1
|
|
129
|
+
vertexOutputs.vUV1 = vertexInputs.uv;
|
|
130
|
+
#endif
|
|
124
131
|
vertexOutputs.vColor = vertexInputs.color;
|
|
125
132
|
}
|
|
126
133
|
`;
|
|
@@ -32,6 +32,10 @@ uniform vec3 pivot;
|
|
|
32
32
|
// Varyings
|
|
33
33
|
varying vec2 vUV;
|
|
34
34
|
varying vec4 vColor;
|
|
35
|
+
#ifdef UV1
|
|
36
|
+
// The particle's own UV, never moved by the sheet (UV channel 1).
|
|
37
|
+
varying vec2 vUV1;
|
|
38
|
+
#endif
|
|
35
39
|
#ifdef TILE_BLEND
|
|
36
40
|
varying vec2 vUV2;
|
|
37
41
|
varying float vTileBlend;
|
|
@@ -45,6 +49,7 @@ varying float linearDepth;
|
|
|
45
49
|
// Smallest and largest size a particle may have on screen, as fractions of the viewport height.
|
|
46
50
|
uniform vec2 sizeLimits;
|
|
47
51
|
#endif
|
|
52
|
+
|
|
48
53
|
${fogVertexDeclarationGLSL}
|
|
49
54
|
void main() {
|
|
50
55
|
float lengthFactor = velocity.w;
|
|
@@ -52,15 +57,6 @@ void main() {
|
|
|
52
57
|
// extent and mirrors its texture instead (see quadUV below).
|
|
53
58
|
float avgSize = (abs(size.x) + abs(size.y)) * 0.5;
|
|
54
59
|
vec4 mvPosition = view * world * vec4(offset, 1.0);
|
|
55
|
-
#ifdef SIZE_LIMITS
|
|
56
|
-
// The streak's width on screen as a fraction of the viewport height, held
|
|
57
|
-
// between the limits; a perspective projection divides by the view depth.
|
|
58
|
-
float limitDepth = abs(projection[2][3]) > 0.0 ? abs(mvPosition.z) : 1.0;
|
|
59
|
-
float screenSize = avgSize * projection[1][1] / (2.0 * limitDepth);
|
|
60
|
-
if (screenSize > 0.0) {
|
|
61
|
-
avgSize *= clamp(screenSize, sizeLimits.x, sizeLimits.y) / screenSize;
|
|
62
|
-
}
|
|
63
|
-
#endif
|
|
64
60
|
vec3 viewVelocity = mat3(view * world) * velocity.xyz;
|
|
65
61
|
float vlength = length(viewVelocity);
|
|
66
62
|
// Stretch direction is the velocity direction; only a genuinely motionless particle has none.
|
|
@@ -73,6 +69,15 @@ void main() {
|
|
|
73
69
|
vec3 side = dot(sideRaw, sideRaw) > 1e-12 ? normalize(sideRaw) : vec3(1.0, 0.0, 0.0);
|
|
74
70
|
#else
|
|
75
71
|
vec3 side = normalize(cross(mvPosition.xyz, vdir));
|
|
72
|
+
#endif
|
|
73
|
+
#ifdef SIZE_LIMITS
|
|
74
|
+
// The streak's width on screen as a fraction of the viewport height, held
|
|
75
|
+
// between the limits; a perspective projection divides by the view depth.
|
|
76
|
+
float limitDepth = abs(projection[2][3]) > 0.0 ? abs(mvPosition.z) : 1.0;
|
|
77
|
+
float screenSize = avgSize * projection[1][1] / (2.0 * limitDepth);
|
|
78
|
+
if (screenSize > 0.0) {
|
|
79
|
+
avgSize *= clamp(screenSize, sizeLimits.x, sizeLimits.y) / screenSize;
|
|
80
|
+
}
|
|
76
81
|
#endif
|
|
77
82
|
mvPosition.xyz += position.y * side * avgSize;
|
|
78
83
|
#ifdef BEAM
|
|
@@ -113,6 +118,9 @@ ${fogVertexGLSL('mvPosition.xyz')}
|
|
|
113
118
|
vUV = quadUV;
|
|
114
119
|
#endif
|
|
115
120
|
|
|
121
|
+
#ifdef UV1
|
|
122
|
+
vUV1 = quadUV;
|
|
123
|
+
#endif
|
|
116
124
|
vColor = color;
|
|
117
125
|
}
|
|
118
126
|
`;
|
|
@@ -32,6 +32,10 @@ uniform pivot: vec3f;
|
|
|
32
32
|
// Varyings
|
|
33
33
|
varying vUV: vec2f;
|
|
34
34
|
varying vColor: vec4f;
|
|
35
|
+
#ifdef UV1
|
|
36
|
+
// The particle's own UV, never moved by the sheet (UV channel 1).
|
|
37
|
+
varying vUV1: vec2f;
|
|
38
|
+
#endif
|
|
35
39
|
#ifdef TILE_BLEND
|
|
36
40
|
varying vUV2: vec2f;
|
|
37
41
|
varying vTileBlend: f32;
|
|
@@ -45,6 +49,7 @@ varying linearDepth: f32;
|
|
|
45
49
|
// Smallest and largest size a particle may have on screen, as fractions of the viewport height.
|
|
46
50
|
uniform sizeLimits: vec2f;
|
|
47
51
|
#endif
|
|
52
|
+
|
|
48
53
|
${fogVertexDeclarationWGSL}
|
|
49
54
|
@vertex
|
|
50
55
|
fn main(input: VertexInputs) -> FragmentInputs {
|
|
@@ -53,15 +58,6 @@ fn main(input: VertexInputs) -> FragmentInputs {
|
|
|
53
58
|
// extent and mirrors its texture instead (see quadUV below).
|
|
54
59
|
var avgSize = (abs(vertexInputs.size.x) + abs(vertexInputs.size.y)) * 0.5;
|
|
55
60
|
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
61
|
let viewWorld = uniforms.view * uniforms.world;
|
|
66
62
|
let viewWorld3 = mat3x3f(viewWorld[0].xyz, viewWorld[1].xyz, viewWorld[2].xyz);
|
|
67
63
|
let viewVelocity = viewWorld3 * vertexInputs.velocity.xyz;
|
|
@@ -82,6 +78,15 @@ fn main(input: VertexInputs) -> FragmentInputs {
|
|
|
82
78
|
}
|
|
83
79
|
#else
|
|
84
80
|
let side = normalize(cross(mvPosition.xyz, vdir));
|
|
81
|
+
#endif
|
|
82
|
+
#ifdef SIZE_LIMITS
|
|
83
|
+
// The streak's width on screen as a fraction of the viewport height, held
|
|
84
|
+
// between the limits; a perspective projection divides by the view depth.
|
|
85
|
+
let limitDepth = select(1.0, abs(mvPosition.z), abs(uniforms.projection[2][3]) > 0.0);
|
|
86
|
+
let screenSize = avgSize * uniforms.projection[1][1] / (2.0 * limitDepth);
|
|
87
|
+
if (screenSize > 0.0) {
|
|
88
|
+
avgSize *= clamp(screenSize, uniforms.sizeLimits.x, uniforms.sizeLimits.y) / screenSize;
|
|
89
|
+
}
|
|
85
90
|
#endif
|
|
86
91
|
let widthOffset = vertexInputs.position.y * side * avgSize;
|
|
87
92
|
// Equivalent to viewVelocity * (1.0 + lengthFactor / vlength) for moving particles, but the
|
|
@@ -128,6 +133,9 @@ ${fogVertexWGSL('mvPosition.xyz')}
|
|
|
128
133
|
vertexOutputs.vUV = quadUV;
|
|
129
134
|
#endif
|
|
130
135
|
|
|
136
|
+
#ifdef UV1
|
|
137
|
+
vertexOutputs.vUV1 = quadUV;
|
|
138
|
+
#endif
|
|
131
139
|
vertexOutputs.vColor = vertexInputs.color;
|
|
132
140
|
}
|
|
133
141
|
`;
|
|
@@ -17,6 +17,11 @@ uniform float sizeAttenuation;
|
|
|
17
17
|
|
|
18
18
|
varying vec2 vUV;
|
|
19
19
|
varying vec4 vColor;
|
|
20
|
+
#ifdef UV1
|
|
21
|
+
// Along the trail and across it, without the sheet's cell (UV channel 1).
|
|
22
|
+
attribute vec2 uv2;
|
|
23
|
+
varying vec2 vUV1;
|
|
24
|
+
#endif
|
|
20
25
|
|
|
21
26
|
vec2 fix(vec4 i, float aspect) {
|
|
22
27
|
vec2 res = i.xy / i.w;
|
|
@@ -57,6 +62,9 @@ void main() {
|
|
|
57
62
|
gl_Position = finalPosition;
|
|
58
63
|
${fogVertexGLSL('(view * vec4(position, 1.0)).xyz')}
|
|
59
64
|
vUV = uv;
|
|
65
|
+
#ifdef UV1
|
|
66
|
+
vUV1 = uv2;
|
|
67
|
+
#endif
|
|
60
68
|
vColor = color;
|
|
61
69
|
}
|
|
62
70
|
`;
|
|
@@ -17,6 +17,11 @@ uniform sizeAttenuation: f32;
|
|
|
17
17
|
|
|
18
18
|
varying vUV: vec2f;
|
|
19
19
|
varying vColor: vec4f;
|
|
20
|
+
#ifdef UV1
|
|
21
|
+
// Along the trail and across it, without the sheet's cell (UV channel 1).
|
|
22
|
+
attribute uv2: vec2f;
|
|
23
|
+
varying vUV1: vec2f;
|
|
24
|
+
#endif
|
|
20
25
|
|
|
21
26
|
fn fix(i: vec4f, aspect: f32) -> vec2f {
|
|
22
27
|
var res = i.xy / i.w;
|
|
@@ -62,6 +67,9 @@ fn main(input: VertexInputs) -> FragmentInputs {
|
|
|
62
67
|
vertexOutputs.position = finalPosition;
|
|
63
68
|
${fogVertexWGSL('(uniforms.view * vec4f(vertexInputs.position, 1.0)).xyz')}
|
|
64
69
|
vertexOutputs.vUV = vertexInputs.uv;
|
|
70
|
+
#ifdef UV1
|
|
71
|
+
vertexOutputs.vUV1 = vertexInputs.uv2;
|
|
72
|
+
#endif
|
|
65
73
|
vertexOutputs.vColor = vertexInputs.color;
|
|
66
74
|
}
|
|
67
75
|
`;
|