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
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Soft particles for the particle shaders, in both shader languages.
|
|
3
|
+
*
|
|
4
|
+
* The fragment reads the scene depth behind it from `depthTexture`, turns it into view depth with
|
|
5
|
+
* the coefficients in `projParams` (see `softDepthParams`), and fades out over the distance in
|
|
6
|
+
* `softParams` as it nears the scene, as Unity's soft particles and Unreal's Depth Fade do. The
|
|
7
|
+
* fade runs last, after fog, so both languages produce the same colour.
|
|
8
|
+
*
|
|
9
|
+
* `SOFT_DEPTH_PACKED` reads a depth packed into four 8-bit channels, as a Babylon
|
|
10
|
+
* `DepthRenderer` of type `UNSIGNED_BYTE` writes it.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Fragment-side declaration and depth decode, GLSL. */
|
|
14
|
+
export const softFragmentDeclarationGLSL = /* glsl */ `
|
|
15
|
+
#ifdef SOFT_PARTICLES
|
|
16
|
+
uniform sampler2D depthTexture;
|
|
17
|
+
uniform vec2 softParams;
|
|
18
|
+
uniform vec4 projParams;
|
|
19
|
+
varying vec4 projPosition;
|
|
20
|
+
varying float linearDepth;
|
|
21
|
+
|
|
22
|
+
float quarksSceneDepth(vec4 texel) {
|
|
23
|
+
#ifdef SOFT_DEPTH_PACKED
|
|
24
|
+
float d = dot(texel, vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0));
|
|
25
|
+
#else
|
|
26
|
+
float d = texel.r;
|
|
27
|
+
#endif
|
|
28
|
+
float denominator = projParams.z * d + projParams.w;
|
|
29
|
+
float depth = abs(denominator) > 1e-8 ? abs((projParams.x * d + projParams.y) / denominator) : 0.0;
|
|
30
|
+
// Nothing drawn there reads as infinitely far.
|
|
31
|
+
return depth > 0.0 ? depth : 1e30;
|
|
32
|
+
}
|
|
33
|
+
#endif
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
/** Fades `target` as the fragment nears the scene behind it, GLSL. */
|
|
37
|
+
export function softFragmentGLSL(target: string): string {
|
|
38
|
+
return /* glsl */ `
|
|
39
|
+
#ifdef SOFT_PARTICLES
|
|
40
|
+
{
|
|
41
|
+
vec2 softUV = 0.5 * (projPosition.xy / projPosition.w) + 0.5;
|
|
42
|
+
float sceneDepth = quarksSceneDepth(texture2D(depthTexture, softUV));
|
|
43
|
+
${target} *= clamp(softParams.y * ((sceneDepth - softParams.x) - linearDepth), 0.0, 1.0);
|
|
44
|
+
}
|
|
45
|
+
#endif
|
|
46
|
+
`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Fragment-side declaration and depth decode, WGSL. */
|
|
50
|
+
export const softFragmentDeclarationWGSL = /* wgsl */ `
|
|
51
|
+
#ifdef SOFT_PARTICLES
|
|
52
|
+
var depthTextureSampler: sampler;
|
|
53
|
+
var depthTexture: texture_2d<f32>;
|
|
54
|
+
uniform softParams: vec2f;
|
|
55
|
+
uniform projParams: vec4f;
|
|
56
|
+
varying projPosition: vec4f;
|
|
57
|
+
varying linearDepth: f32;
|
|
58
|
+
|
|
59
|
+
fn quarksSceneDepth(texel: vec4f) -> f32 {
|
|
60
|
+
#ifdef SOFT_DEPTH_PACKED
|
|
61
|
+
let d = dot(texel, vec4f(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0));
|
|
62
|
+
#else
|
|
63
|
+
let d = texel.r;
|
|
64
|
+
#endif
|
|
65
|
+
let denominator = uniforms.projParams.z * d + uniforms.projParams.w;
|
|
66
|
+
let depth = select(0.0, abs((uniforms.projParams.x * d + uniforms.projParams.y) / denominator), abs(denominator) > 1e-8);
|
|
67
|
+
// Nothing drawn there reads as infinitely far.
|
|
68
|
+
return select(1e30, depth, depth > 0.0);
|
|
69
|
+
}
|
|
70
|
+
#endif
|
|
71
|
+
`;
|
|
72
|
+
|
|
73
|
+
/** Fades `target` as the fragment nears the scene behind it, WGSL. */
|
|
74
|
+
export function softFragmentWGSL(target: string): string {
|
|
75
|
+
return /* wgsl */ `
|
|
76
|
+
#ifdef SOFT_PARTICLES
|
|
77
|
+
{
|
|
78
|
+
let softUV = 0.5 * (fragmentInputs.projPosition.xy / fragmentInputs.projPosition.w) + 0.5;
|
|
79
|
+
let sceneDepth = quarksSceneDepth(textureSample(depthTexture, depthTextureSampler, softUV));
|
|
80
|
+
${target} *= clamp(uniforms.softParams.y * ((sceneDepth - uniforms.softParams.x) - fragmentInputs.linearDepth), 0.0, 1.0);
|
|
81
|
+
}
|
|
82
|
+
#endif
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
@@ -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,33 +87,58 @@ 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;
|
|
76
109
|
float erosionMaskValue = 1.0;
|
|
77
110
|
#endif
|
|
111
|
+
#if defined(USE_MAP) || defined(GRADIENT_MAP)
|
|
78
112
|
#ifdef USE_MAP
|
|
79
113
|
vec4 texColor = texture2D(map, mapUV);
|
|
80
114
|
${
|
|
81
115
|
tileBlend
|
|
82
116
|
? `#ifdef TILE_BLEND
|
|
83
|
-
#
|
|
84
|
-
|
|
117
|
+
#if defined(MAP_TRANSFORM) && defined(MAP_UV1)
|
|
118
|
+
vec2 mapUV2 = mapUV;
|
|
85
119
|
#else
|
|
86
|
-
|
|
120
|
+
#ifdef MAP_TRANSFORM
|
|
121
|
+
vec2 mapUV2 = vUV2 * mapTransform.xy + mapTransform.zw;
|
|
122
|
+
#else
|
|
123
|
+
vec2 mapUV2 = vUV2;
|
|
124
|
+
#endif
|
|
125
|
+
#ifdef UV_DISTORTION
|
|
126
|
+
mapUV2 += distortion;
|
|
127
|
+
#endif
|
|
87
128
|
#endif
|
|
129
|
+
vec4 texColor2 = texture2D(map, mapUV2);
|
|
88
130
|
texColor = mix(texColor, texColor2, vTileBlend);
|
|
89
131
|
#endif`
|
|
90
132
|
: ''
|
|
91
133
|
}
|
|
134
|
+
#else
|
|
135
|
+
// No map: the ramp is looked up at white, its far end.
|
|
136
|
+
vec4 texColor = vec4(1.0);
|
|
137
|
+
#endif
|
|
92
138
|
#ifdef GRADIENT_MAP
|
|
93
|
-
|
|
94
|
-
|
|
139
|
+
float rampAt = clamp(dot(texColor, gradientMapChannel), 0.0, 1.0);
|
|
140
|
+
vec4 ramp = texture2D(gradientMap, vec2(mix(gradientMapRange.x, gradientMapRange.y, rampAt), 0.5));
|
|
141
|
+
texColor = vec4(ramp.rgb, ramp.a * mix(texColor.a, 1.0, gradientMapChannel.a));
|
|
95
142
|
#endif
|
|
96
143
|
#ifdef EROSION
|
|
97
144
|
erosionMaskValue = texColor.a;
|
|
@@ -100,7 +147,12 @@ export function surfaceColorGLSL(tileBlend: boolean): string {
|
|
|
100
147
|
#endif
|
|
101
148
|
#ifdef EROSION
|
|
102
149
|
#ifdef EROSION_MASK
|
|
103
|
-
|
|
150
|
+
#ifdef EROSION_MASK_UV1
|
|
151
|
+
vec2 erosionUV = vUV1;
|
|
152
|
+
#else
|
|
153
|
+
vec2 erosionUV = vUV;
|
|
154
|
+
#endif
|
|
155
|
+
erosionMaskValue = texture2D(erosionMask, erosionUV * erosionMaskTransform.xy + erosionMaskTransform.zw).r;
|
|
104
156
|
#endif
|
|
105
157
|
baseColor = quarksErode(baseColor, erosionLevel, erosionMaskValue);
|
|
106
158
|
#endif
|
|
@@ -109,20 +161,28 @@ export function surfaceColorGLSL(tileBlend: boolean): string {
|
|
|
109
161
|
|
|
110
162
|
/** Fragment-side declarations, WGSL. */
|
|
111
163
|
export const surfaceFragmentDeclarationWGSL = /* wgsl */ `
|
|
112
|
-
#ifdef
|
|
113
|
-
uniform
|
|
164
|
+
#ifdef MAP_TRANSFORM
|
|
165
|
+
uniform mapTransform: vec4f;
|
|
166
|
+
#endif
|
|
167
|
+
#ifdef UV_DISTORTION
|
|
168
|
+
var distortionMapSampler: sampler;
|
|
169
|
+
var distortionMap: texture_2d<f32>;
|
|
170
|
+
uniform distortionTransform: vec4f;
|
|
171
|
+
uniform distortionStrength: f32;
|
|
114
172
|
#endif
|
|
115
173
|
#ifdef GRADIENT_MAP
|
|
116
174
|
var gradientMapSampler: sampler;
|
|
117
175
|
var gradientMap: texture_2d<f32>;
|
|
118
176
|
uniform gradientMapRange: vec2f;
|
|
177
|
+
uniform gradientMapChannel: vec4f;
|
|
119
178
|
#endif
|
|
120
179
|
#ifdef EROSION
|
|
121
|
-
uniform erosionParams:
|
|
180
|
+
uniform erosionParams: vec2f;
|
|
122
181
|
uniform erosionEdgeColor: vec3f;
|
|
123
182
|
#ifdef EROSION_MASK
|
|
124
183
|
var erosionMaskSampler: sampler;
|
|
125
184
|
var erosionMask: texture_2d<f32>;
|
|
185
|
+
uniform erosionMaskTransform: vec4f;
|
|
126
186
|
#endif
|
|
127
187
|
|
|
128
188
|
fn quarksErode(colorIn: vec4f, level: f32, mask: f32) -> vec4f {
|
|
@@ -145,33 +205,58 @@ fn quarksErode(colorIn: vec4f, level: f32, mask: f32) -> vec4f {
|
|
|
145
205
|
export function surfaceColorWGSL(tileBlend: boolean): string {
|
|
146
206
|
return /* wgsl */ `
|
|
147
207
|
var baseColor = fragmentInputs.vColor;
|
|
148
|
-
#
|
|
149
|
-
|
|
208
|
+
#if defined(MAP_TRANSFORM) && defined(MAP_UV1)
|
|
209
|
+
var mapUV = fragmentInputs.vUV1 * uniforms.mapTransform.xy + uniforms.mapTransform.zw;
|
|
210
|
+
#elif defined(MAP_TRANSFORM)
|
|
211
|
+
var mapUV = fragmentInputs.vUV * uniforms.mapTransform.xy + uniforms.mapTransform.zw;
|
|
150
212
|
#else
|
|
151
|
-
|
|
213
|
+
var mapUV = fragmentInputs.vUV;
|
|
214
|
+
#endif
|
|
215
|
+
#ifdef UV_DISTORTION
|
|
216
|
+
#ifdef UV_DISTORTION_UV1
|
|
217
|
+
let distortionUV = fragmentInputs.vUV1;
|
|
218
|
+
#else
|
|
219
|
+
let distortionUV = fragmentInputs.vUV;
|
|
220
|
+
#endif
|
|
221
|
+
let distortion = (textureSample(distortionMap, distortionMapSampler, distortionUV * uniforms.distortionTransform.xy + uniforms.distortionTransform.zw).rg - 0.5) * 2.0 * uniforms.distortionStrength;
|
|
222
|
+
mapUV += distortion;
|
|
152
223
|
#endif
|
|
153
224
|
#ifdef EROSION
|
|
154
225
|
let erosionLevel = baseColor.a;
|
|
155
226
|
baseColor.a = 1.0;
|
|
156
227
|
var erosionMaskValue = 1.0;
|
|
157
228
|
#endif
|
|
229
|
+
#if defined(USE_MAP) || defined(GRADIENT_MAP)
|
|
158
230
|
#ifdef USE_MAP
|
|
159
231
|
var texColor = textureSample(map, mapSampler, mapUV);
|
|
160
232
|
${
|
|
161
233
|
tileBlend
|
|
162
234
|
? `#ifdef TILE_BLEND
|
|
163
|
-
#
|
|
164
|
-
let
|
|
235
|
+
#if defined(MAP_TRANSFORM) && defined(MAP_UV1)
|
|
236
|
+
let mapUV2 = mapUV;
|
|
165
237
|
#else
|
|
166
|
-
|
|
238
|
+
#ifdef MAP_TRANSFORM
|
|
239
|
+
var mapUV2 = fragmentInputs.vUV2 * uniforms.mapTransform.xy + uniforms.mapTransform.zw;
|
|
240
|
+
#else
|
|
241
|
+
var mapUV2 = fragmentInputs.vUV2;
|
|
242
|
+
#endif
|
|
243
|
+
#ifdef UV_DISTORTION
|
|
244
|
+
mapUV2 += distortion;
|
|
245
|
+
#endif
|
|
167
246
|
#endif
|
|
247
|
+
let texColor2 = textureSample(map, mapSampler, mapUV2);
|
|
168
248
|
texColor = mix(texColor, texColor2, fragmentInputs.vTileBlend);
|
|
169
249
|
#endif`
|
|
170
250
|
: ''
|
|
171
251
|
}
|
|
252
|
+
#else
|
|
253
|
+
// No map: the ramp is looked up at white, its far end.
|
|
254
|
+
var texColor = vec4f(1.0);
|
|
255
|
+
#endif
|
|
172
256
|
#ifdef GRADIENT_MAP
|
|
173
|
-
let
|
|
174
|
-
|
|
257
|
+
let rampAt = clamp(dot(texColor, uniforms.gradientMapChannel), 0.0, 1.0);
|
|
258
|
+
let ramp = textureSample(gradientMap, gradientMapSampler, vec2f(mix(uniforms.gradientMapRange.x, uniforms.gradientMapRange.y, rampAt), 0.5));
|
|
259
|
+
texColor = vec4f(ramp.rgb, ramp.a * mix(texColor.a, 1.0, uniforms.gradientMapChannel.a));
|
|
175
260
|
#endif
|
|
176
261
|
#ifdef EROSION
|
|
177
262
|
erosionMaskValue = texColor.a;
|
|
@@ -180,7 +265,12 @@ export function surfaceColorWGSL(tileBlend: boolean): string {
|
|
|
180
265
|
#endif
|
|
181
266
|
#ifdef EROSION
|
|
182
267
|
#ifdef EROSION_MASK
|
|
183
|
-
|
|
268
|
+
#ifdef EROSION_MASK_UV1
|
|
269
|
+
let erosionUV = fragmentInputs.vUV1;
|
|
270
|
+
#else
|
|
271
|
+
let erosionUV = fragmentInputs.vUV;
|
|
272
|
+
#endif
|
|
273
|
+
erosionMaskValue = textureSample(erosionMask, erosionMaskSampler, erosionUV * uniforms.erosionMaskTransform.xy + uniforms.erosionMaskTransform.zw).r;
|
|
184
274
|
#endif
|
|
185
275
|
baseColor = quarksErode(baseColor, erosionLevel, erosionMaskValue);
|
|
186
276
|
#endif
|
|
@@ -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
|
attribute vec3 position;
|
|
@@ -13,22 +14,21 @@ attribute float uvTile;
|
|
|
13
14
|
uniform mat4 world;
|
|
14
15
|
uniform mat4 view;
|
|
15
16
|
uniform mat4 projection;
|
|
16
|
-
|
|
17
|
-
#ifdef UV_TILE
|
|
18
|
-
uniform float tileCountX;
|
|
19
|
-
uniform float tileCountY;
|
|
20
|
-
#endif
|
|
17
|
+
${sheetVertexDeclarationGLSL}
|
|
21
18
|
|
|
22
19
|
varying vec2 vUV;
|
|
23
20
|
varying vec4 vColor;
|
|
21
|
+
#ifdef UV1
|
|
22
|
+
#ifdef MESH_UV2
|
|
23
|
+
// The mesh's second UV set.
|
|
24
|
+
attribute vec2 uv2;
|
|
25
|
+
#endif
|
|
26
|
+
// UV channel 1: the mesh's second UV set, or its first when it has none.
|
|
27
|
+
varying vec2 vUV1;
|
|
28
|
+
#endif
|
|
24
29
|
varying vec3 vNormal;
|
|
25
30
|
varying vec3 vWorldPos;
|
|
26
31
|
|
|
27
|
-
#ifdef TILE_BLEND
|
|
28
|
-
varying vec2 vUV2;
|
|
29
|
-
varying float vTileBlend;
|
|
30
|
-
#endif
|
|
31
|
-
|
|
32
32
|
#ifdef SOFT_PARTICLES
|
|
33
33
|
varying vec4 projPosition;
|
|
34
34
|
varying float linearDepth;
|
|
@@ -45,7 +45,15 @@ ${fogVertexDeclarationGLSL}
|
|
|
45
45
|
void main() {
|
|
46
46
|
vec3 scaledPosition = position * size;
|
|
47
47
|
vec3 rotatedPosition = applyQuaternion(scaledPosition, rotation);
|
|
48
|
-
|
|
48
|
+
// A normal scales by the inverse of the size, so a stretched mesh keeps its normals
|
|
49
|
+
// perpendicular; a flat size counts as a sliver rather than dividing by zero.
|
|
50
|
+
vec3 safeSize = vec3(
|
|
51
|
+
abs(size.x) > 1e-6 ? size.x : 1e-6,
|
|
52
|
+
abs(size.y) > 1e-6 ? size.y : 1e-6,
|
|
53
|
+
abs(size.z) > 1e-6 ? size.z : 1e-6);
|
|
54
|
+
// A mirrored size (an odd number of negative components) turns the winding inside out, so the
|
|
55
|
+
// normal is turned with it and the fragment's front-face test agrees with the geometry.
|
|
56
|
+
vec3 rotatedNormal = normalize(applyQuaternion(normal / safeSize, rotation)) * sign(safeSize.x * safeSize.y * safeSize.z);
|
|
49
57
|
vec3 localPos = rotatedPosition + offset;
|
|
50
58
|
|
|
51
59
|
vec4 worldPos = world * vec4(localPos, 1.0);
|
|
@@ -58,26 +66,19 @@ ${fogVertexGLSL('viewPos.xyz')}
|
|
|
58
66
|
|
|
59
67
|
#ifdef SOFT_PARTICLES
|
|
60
68
|
projPosition = gl_Position;
|
|
61
|
-
|
|
69
|
+
// View depth is +z ahead of a left-handed camera and -z ahead of a right-handed one.
|
|
70
|
+
linearDepth = abs(viewPos.z);
|
|
62
71
|
#endif
|
|
63
72
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
vUV = uv / tc + vec2(tileU, tileV);
|
|
70
|
-
#ifdef TILE_BLEND
|
|
71
|
-
float nextTile = ceil(uvTile);
|
|
72
|
-
float nextU = mod(nextTile, tc.x) / tc.x;
|
|
73
|
-
float nextV = 1.0 - floor(nextTile / tc.x) / tc.y - 1.0 / tc.y;
|
|
74
|
-
vUV2 = uv / tc + vec2(nextU, nextV);
|
|
75
|
-
vTileBlend = fract(uvTile);
|
|
76
|
-
#endif
|
|
73
|
+
${sheetVertexGLSL('uv')}
|
|
74
|
+
|
|
75
|
+
#ifdef UV1
|
|
76
|
+
#ifdef MESH_UV2
|
|
77
|
+
vUV1 = uv2;
|
|
77
78
|
#else
|
|
78
|
-
|
|
79
|
+
vUV1 = uv;
|
|
80
|
+
#endif
|
|
79
81
|
#endif
|
|
80
|
-
|
|
81
82
|
vColor = color;
|
|
82
83
|
}
|
|
83
84
|
`;
|
|
@@ -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,22 +14,21 @@ 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;
|
|
21
|
+
#ifdef UV1
|
|
22
|
+
#ifdef MESH_UV2
|
|
23
|
+
// The mesh's second UV set.
|
|
24
|
+
attribute uv2: vec2f;
|
|
25
|
+
#endif
|
|
26
|
+
// UV channel 1: the mesh's second UV set, or its first when it has none.
|
|
27
|
+
varying vUV1: vec2f;
|
|
28
|
+
#endif
|
|
24
29
|
varying vNormal: vec3f;
|
|
25
30
|
varying vWorldPos: vec3f;
|
|
26
31
|
|
|
27
|
-
#ifdef TILE_BLEND
|
|
28
|
-
varying vUV2: vec2f;
|
|
29
|
-
varying vTileBlend: f32;
|
|
30
|
-
#endif
|
|
31
|
-
|
|
32
32
|
#ifdef SOFT_PARTICLES
|
|
33
33
|
varying projPosition: vec4f;
|
|
34
34
|
varying linearDepth: f32;
|
|
@@ -44,9 +44,18 @@ fn applyQuaternion(v: vec3f, q: vec4f) -> vec3f {
|
|
|
44
44
|
${fogVertexDeclarationWGSL}
|
|
45
45
|
@vertex
|
|
46
46
|
fn main(input: VertexInputs) -> FragmentInputs {
|
|
47
|
-
let
|
|
47
|
+
let size = vertexInputs.size;
|
|
48
|
+
let scaledPosition = vertexInputs.position * size;
|
|
48
49
|
let rotatedPosition = applyQuaternion(scaledPosition, vertexInputs.rotation);
|
|
49
|
-
|
|
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);
|
|
50
59
|
let localPos = rotatedPosition + vertexInputs.offset;
|
|
51
60
|
|
|
52
61
|
let worldPos = uniforms.world * vec4f(localPos, 1.0);
|
|
@@ -60,26 +69,19 @@ ${fogVertexWGSL('viewPos.xyz')}
|
|
|
60
69
|
|
|
61
70
|
#ifdef SOFT_PARTICLES
|
|
62
71
|
vertexOutputs.projPosition = clipPosition;
|
|
63
|
-
|
|
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);
|
|
64
74
|
#endif
|
|
65
75
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
vertexOutputs.vUV = vertexInputs.uv / tc + vec2f(tileU, tileV);
|
|
72
|
-
#ifdef TILE_BLEND
|
|
73
|
-
let nextTile = ceil(vertexInputs.uvTile);
|
|
74
|
-
let nextU = (nextTile % tc.x) / tc.x;
|
|
75
|
-
let nextV = 1.0 - floor(nextTile / tc.x) / tc.y - 1.0 / tc.y;
|
|
76
|
-
vertexOutputs.vUV2 = vertexInputs.uv / tc + vec2f(nextU, nextV);
|
|
77
|
-
vertexOutputs.vTileBlend = fract(vertexInputs.uvTile);
|
|
78
|
-
#endif
|
|
76
|
+
${sheetVertexWGSL('vertexInputs.uv')}
|
|
77
|
+
|
|
78
|
+
#ifdef UV1
|
|
79
|
+
#ifdef MESH_UV2
|
|
80
|
+
vertexOutputs.vUV1 = vertexInputs.uv2;
|
|
79
81
|
#else
|
|
80
|
-
vertexOutputs.
|
|
82
|
+
vertexOutputs.vUV1 = vertexInputs.uv;
|
|
83
|
+
#endif
|
|
81
84
|
#endif
|
|
82
|
-
|
|
83
85
|
vertexOutputs.vColor = vertexInputs.color;
|
|
84
86
|
}
|
|
85
87
|
`;
|
|
@@ -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
|
|
|
8
12
|
#ifdef TILE_BLEND
|
|
9
13
|
varying vec2 vUV2;
|
|
@@ -14,26 +18,16 @@ varying float vTileBlend;
|
|
|
14
18
|
uniform sampler2D map;
|
|
15
19
|
#endif
|
|
16
20
|
|
|
17
|
-
#ifdef SOFT_PARTICLES
|
|
18
|
-
uniform sampler2D depthTexture;
|
|
19
|
-
uniform vec2 softParams;
|
|
20
|
-
uniform vec4 projParams;
|
|
21
|
-
varying vec4 projPosition;
|
|
22
|
-
varying float linearDepth;
|
|
23
|
-
#endif
|
|
24
21
|
|
|
25
22
|
#ifdef USE_ALPHATEST
|
|
26
23
|
uniform float alphaTest;
|
|
27
24
|
#endif
|
|
28
25
|
|
|
29
26
|
${fogFragmentDeclarationGLSL}
|
|
27
|
+
${softFragmentDeclarationGLSL}
|
|
30
28
|
${surfaceFragmentDeclarationGLSL}
|
|
31
29
|
void main() {
|
|
32
30
|
${surfaceColorGLSL(true)}
|
|
33
|
-
#ifdef USE_COLOR_AS_ALPHA
|
|
34
|
-
baseColor.a *= (baseColor.r + baseColor.g + baseColor.b) / 3.0;
|
|
35
|
-
#endif
|
|
36
|
-
|
|
37
31
|
#ifdef USE_ALPHATEST
|
|
38
32
|
if (baseColor.a < alphaTest) discard;
|
|
39
33
|
#else
|
|
@@ -42,16 +36,6 @@ ${surfaceColorGLSL(true)}
|
|
|
42
36
|
|
|
43
37
|
${fogFragmentGLSL('baseColor.rgb')}
|
|
44
38
|
gl_FragColor = baseColor;
|
|
45
|
-
|
|
46
|
-
#ifdef SOFT_PARTICLES
|
|
47
|
-
vec2 p2 = projPosition.xy / projPosition.w;
|
|
48
|
-
p2 = 0.5 * p2 + 0.5;
|
|
49
|
-
float readDepth = texture2D(depthTexture, p2.xy).r;
|
|
50
|
-
float zNear = projParams.x;
|
|
51
|
-
float zFar = projParams.y;
|
|
52
|
-
float viewDepth = (zFar * zNear) / (zFar - readDepth * (zFar - zNear));
|
|
53
|
-
float fade = clamp(softParams.y * ((viewDepth - softParams.x) - linearDepth), 0.0, 1.0);
|
|
54
|
-
gl_FragColor *= fade;
|
|
55
|
-
#endif
|
|
39
|
+
${softFragmentGLSL('gl_FragColor')}
|
|
56
40
|
}
|
|
57
41
|
`;
|
|
@@ -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
|
|
|
8
12
|
#ifdef TILE_BLEND
|
|
9
13
|
varying vUV2: vec2f;
|
|
@@ -15,46 +19,25 @@ var mapSampler: sampler;
|
|
|
15
19
|
var map: texture_2d<f32>;
|
|
16
20
|
#endif
|
|
17
21
|
|
|
18
|
-
#ifdef SOFT_PARTICLES
|
|
19
|
-
var depthTextureSampler: sampler;
|
|
20
|
-
var depthTexture: texture_2d<f32>;
|
|
21
|
-
uniform softParams: vec2f;
|
|
22
|
-
uniform projParams: vec4f;
|
|
23
|
-
varying projPosition: vec4f;
|
|
24
|
-
varying linearDepth: f32;
|
|
25
|
-
#endif
|
|
26
22
|
|
|
27
23
|
#ifdef USE_ALPHATEST
|
|
28
24
|
uniform alphaTest: f32;
|
|
29
25
|
#endif
|
|
30
26
|
|
|
31
27
|
${fogFragmentDeclarationWGSL}
|
|
28
|
+
${softFragmentDeclarationWGSL}
|
|
32
29
|
${surfaceFragmentDeclarationWGSL}
|
|
33
30
|
@fragment
|
|
34
31
|
fn main(input: FragmentInputs) -> FragmentOutputs {
|
|
35
32
|
${surfaceColorWGSL(true)}
|
|
36
|
-
#ifdef USE_COLOR_AS_ALPHA
|
|
37
|
-
baseColor.a *= (baseColor.r + baseColor.g + baseColor.b) / 3.0;
|
|
38
|
-
#endif
|
|
39
|
-
|
|
40
33
|
#ifdef USE_ALPHATEST
|
|
41
34
|
if (baseColor.a < uniforms.alphaTest) { discard; }
|
|
42
35
|
#else
|
|
43
36
|
if (baseColor.a < 0.01) { discard; }
|
|
44
37
|
#endif
|
|
45
38
|
|
|
46
|
-
#ifdef SOFT_PARTICLES
|
|
47
|
-
var p2 = fragmentInputs.projPosition.xy / fragmentInputs.projPosition.w;
|
|
48
|
-
p2 = 0.5 * p2 + 0.5;
|
|
49
|
-
let readDepth = textureSample(depthTexture, depthTextureSampler, p2).r;
|
|
50
|
-
let zNear = uniforms.projParams.x;
|
|
51
|
-
let zFar = uniforms.projParams.y;
|
|
52
|
-
let viewDepth = (zFar * zNear) / (zFar - readDepth * (zFar - zNear));
|
|
53
|
-
let fade = clamp(uniforms.softParams.y * ((viewDepth - uniforms.softParams.x) - fragmentInputs.linearDepth), 0.0, 1.0);
|
|
54
|
-
baseColor *= fade;
|
|
55
|
-
#endif
|
|
56
|
-
|
|
57
39
|
${fogFragmentWGSL('baseColor')}
|
|
40
|
+
${softFragmentWGSL('baseColor')}
|
|
58
41
|
fragmentOutputs.color = baseColor;
|
|
59
42
|
}
|
|
60
43
|
`;
|