babylon.quarks 0.26.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 +769 -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 +1959 -588
- package/package.json +12 -6
- package/src/BatchedRenderer.ts +204 -101
- package/src/EffectPool.ts +4 -1
- package/src/MeshSurfaceEmitter.ts +29 -4
- package/src/ParticleEmitter.ts +45 -15
- package/src/ParticleSystem.ts +909 -2061
- package/src/QuarksLoader.ts +421 -67
- package/src/QuarksPrefab.ts +91 -4
- package/src/QuarksSerializer.ts +484 -0
- package/src/QuarksUtil.ts +15 -0
- package/src/SpriteBatch.ts +106 -246
- package/src/TrailBatch.ts +533 -342
- package/src/VFXBatch.ts +236 -136
- package/src/batchKey.ts +237 -0
- package/src/effectResources.ts +79 -0
- package/src/envAtlas.ts +119 -17
- package/src/index.ts +32 -33
- 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 +10 -0
- package/src/shaders/local_particle_physics_vert.glsl.ts +14 -28
- package/src/shaders/local_particle_physics_vert.wgsl.ts +16 -29
- package/src/shaders/particle_frag.glsl.ts +3 -22
- package/src/shaders/particle_frag.wgsl.ts +3 -23
- package/src/shaders/particle_physics_frag.glsl.ts +12 -25
- package/src/shaders/particle_physics_frag.wgsl.ts +12 -26
- package/src/shaders/particle_vert.glsl.ts +5 -27
- package/src/shaders/particle_vert.wgsl.ts +5 -26
- package/src/shaders/stretched_bb_particle_vert.glsl.ts +7 -33
- package/src/shaders/stretched_bb_particle_vert.wgsl.ts +7 -33
- package/src/shaders/trail_frag.glsl.ts +11 -1
- package/src/shaders/trail_frag.wgsl.ts +11 -0
- package/src/shaders/trail_vert.glsl.ts +45 -36
- package/src/shaders/trail_vert.wgsl.ts +46 -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
|
+
}
|
|
@@ -108,6 +108,7 @@ export function surfaceColorGLSL(tileBlend: boolean): string {
|
|
|
108
108
|
baseColor.a = 1.0;
|
|
109
109
|
float erosionMaskValue = 1.0;
|
|
110
110
|
#endif
|
|
111
|
+
#if defined(USE_MAP) || defined(GRADIENT_MAP)
|
|
111
112
|
#ifdef USE_MAP
|
|
112
113
|
vec4 texColor = texture2D(map, mapUV);
|
|
113
114
|
${
|
|
@@ -130,6 +131,10 @@ export function surfaceColorGLSL(tileBlend: boolean): string {
|
|
|
130
131
|
#endif`
|
|
131
132
|
: ''
|
|
132
133
|
}
|
|
134
|
+
#else
|
|
135
|
+
// No map: the ramp is looked up at white, its far end.
|
|
136
|
+
vec4 texColor = vec4(1.0);
|
|
137
|
+
#endif
|
|
133
138
|
#ifdef GRADIENT_MAP
|
|
134
139
|
float rampAt = clamp(dot(texColor, gradientMapChannel), 0.0, 1.0);
|
|
135
140
|
vec4 ramp = texture2D(gradientMap, vec2(mix(gradientMapRange.x, gradientMapRange.y, rampAt), 0.5));
|
|
@@ -221,6 +226,7 @@ export function surfaceColorWGSL(tileBlend: boolean): string {
|
|
|
221
226
|
baseColor.a = 1.0;
|
|
222
227
|
var erosionMaskValue = 1.0;
|
|
223
228
|
#endif
|
|
229
|
+
#if defined(USE_MAP) || defined(GRADIENT_MAP)
|
|
224
230
|
#ifdef USE_MAP
|
|
225
231
|
var texColor = textureSample(map, mapSampler, mapUV);
|
|
226
232
|
${
|
|
@@ -243,6 +249,10 @@ export function surfaceColorWGSL(tileBlend: boolean): string {
|
|
|
243
249
|
#endif`
|
|
244
250
|
: ''
|
|
245
251
|
}
|
|
252
|
+
#else
|
|
253
|
+
// No map: the ramp is looked up at white, its far end.
|
|
254
|
+
var texColor = vec4f(1.0);
|
|
255
|
+
#endif
|
|
246
256
|
#ifdef GRADIENT_MAP
|
|
247
257
|
let rampAt = clamp(dot(texColor, uniforms.gradientMapChannel), 0.0, 1.0);
|
|
248
258
|
let ramp = textureSample(gradientMap, gradientMapSampler, vec2f(mix(uniforms.gradientMapRange.x, uniforms.gradientMapRange.y, rampAt), 0.5));
|
|
@@ -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,11 +14,7 @@ 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;
|
|
@@ -32,11 +29,6 @@ varying vec2 vUV1;
|
|
|
32
29
|
varying vec3 vNormal;
|
|
33
30
|
varying vec3 vWorldPos;
|
|
34
31
|
|
|
35
|
-
#ifdef TILE_BLEND
|
|
36
|
-
varying vec2 vUV2;
|
|
37
|
-
varying float vTileBlend;
|
|
38
|
-
#endif
|
|
39
|
-
|
|
40
32
|
#ifdef SOFT_PARTICLES
|
|
41
33
|
varying vec4 projPosition;
|
|
42
34
|
varying float linearDepth;
|
|
@@ -53,7 +45,15 @@ ${fogVertexDeclarationGLSL}
|
|
|
53
45
|
void main() {
|
|
54
46
|
vec3 scaledPosition = position * size;
|
|
55
47
|
vec3 rotatedPosition = applyQuaternion(scaledPosition, rotation);
|
|
56
|
-
|
|
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);
|
|
57
57
|
vec3 localPos = rotatedPosition + offset;
|
|
58
58
|
|
|
59
59
|
vec4 worldPos = world * vec4(localPos, 1.0);
|
|
@@ -66,25 +66,11 @@ ${fogVertexGLSL('viewPos.xyz')}
|
|
|
66
66
|
|
|
67
67
|
#ifdef SOFT_PARTICLES
|
|
68
68
|
projPosition = gl_Position;
|
|
69
|
-
|
|
69
|
+
// View depth is +z ahead of a left-handed camera and -z ahead of a right-handed one.
|
|
70
|
+
linearDepth = abs(viewPos.z);
|
|
70
71
|
#endif
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
vec2 tc = vec2(tileCountX, tileCountY);
|
|
74
|
-
float baseTile = floor(uvTile);
|
|
75
|
-
float tileU = mod(baseTile, tc.x) / tc.x;
|
|
76
|
-
float tileV = 1.0 - floor(baseTile / tc.x) / tc.y - 1.0 / tc.y;
|
|
77
|
-
vUV = uv / tc + vec2(tileU, tileV);
|
|
78
|
-
#ifdef TILE_BLEND
|
|
79
|
-
float nextTile = ceil(uvTile);
|
|
80
|
-
float nextU = mod(nextTile, tc.x) / tc.x;
|
|
81
|
-
float nextV = 1.0 - floor(nextTile / tc.x) / tc.y - 1.0 / tc.y;
|
|
82
|
-
vUV2 = uv / tc + vec2(nextU, nextV);
|
|
83
|
-
vTileBlend = fract(uvTile);
|
|
84
|
-
#endif
|
|
85
|
-
#else
|
|
86
|
-
vUV = uv;
|
|
87
|
-
#endif
|
|
73
|
+
${sheetVertexGLSL('uv')}
|
|
88
74
|
|
|
89
75
|
#ifdef UV1
|
|
90
76
|
#ifdef MESH_UV2
|
|
@@ -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
|
|
47
|
+
let size = vertexInputs.size;
|
|
48
|
+
let scaledPosition = vertexInputs.position * size;
|
|
56
49
|
let rotatedPosition = applyQuaternion(scaledPosition, vertexInputs.rotation);
|
|
57
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,5 @@
|
|
|
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 */ `
|
|
@@ -17,26 +18,16 @@ varying float vTileBlend;
|
|
|
17
18
|
uniform sampler2D map;
|
|
18
19
|
#endif
|
|
19
20
|
|
|
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
21
|
|
|
28
22
|
#ifdef USE_ALPHATEST
|
|
29
23
|
uniform float alphaTest;
|
|
30
24
|
#endif
|
|
31
25
|
|
|
32
26
|
${fogFragmentDeclarationGLSL}
|
|
27
|
+
${softFragmentDeclarationGLSL}
|
|
33
28
|
${surfaceFragmentDeclarationGLSL}
|
|
34
29
|
void main() {
|
|
35
30
|
${surfaceColorGLSL(true)}
|
|
36
|
-
#ifdef USE_COLOR_AS_ALPHA
|
|
37
|
-
baseColor.a *= (baseColor.r + baseColor.g + baseColor.b) / 3.0;
|
|
38
|
-
#endif
|
|
39
|
-
|
|
40
31
|
#ifdef USE_ALPHATEST
|
|
41
32
|
if (baseColor.a < alphaTest) discard;
|
|
42
33
|
#else
|
|
@@ -45,16 +36,6 @@ ${surfaceColorGLSL(true)}
|
|
|
45
36
|
|
|
46
37
|
${fogFragmentGLSL('baseColor.rgb')}
|
|
47
38
|
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
|
|
39
|
+
${softFragmentGLSL('gl_FragColor')}
|
|
59
40
|
}
|
|
60
41
|
`;
|
|
@@ -1,4 +1,5 @@
|
|
|
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 */ `
|
|
@@ -18,46 +19,25 @@ var mapSampler: sampler;
|
|
|
18
19
|
var map: texture_2d<f32>;
|
|
19
20
|
#endif
|
|
20
21
|
|
|
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
22
|
|
|
30
23
|
#ifdef USE_ALPHATEST
|
|
31
24
|
uniform alphaTest: f32;
|
|
32
25
|
#endif
|
|
33
26
|
|
|
34
27
|
${fogFragmentDeclarationWGSL}
|
|
28
|
+
${softFragmentDeclarationWGSL}
|
|
35
29
|
${surfaceFragmentDeclarationWGSL}
|
|
36
30
|
@fragment
|
|
37
31
|
fn main(input: FragmentInputs) -> FragmentOutputs {
|
|
38
32
|
${surfaceColorWGSL(true)}
|
|
39
|
-
#ifdef USE_COLOR_AS_ALPHA
|
|
40
|
-
baseColor.a *= (baseColor.r + baseColor.g + baseColor.b) / 3.0;
|
|
41
|
-
#endif
|
|
42
|
-
|
|
43
33
|
#ifdef USE_ALPHATEST
|
|
44
34
|
if (baseColor.a < uniforms.alphaTest) { discard; }
|
|
45
35
|
#else
|
|
46
36
|
if (baseColor.a < 0.01) { discard; }
|
|
47
37
|
#endif
|
|
48
38
|
|
|
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
39
|
${fogFragmentWGSL('baseColor')}
|
|
40
|
+
${softFragmentWGSL('baseColor')}
|
|
61
41
|
fragmentOutputs.color = baseColor;
|
|
62
42
|
}
|
|
63
43
|
`;
|
|
@@ -1,4 +1,5 @@
|
|
|
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 */ `
|
|
@@ -79,29 +80,18 @@ vec3 sampleEnvAtlas(vec3 r) {
|
|
|
79
80
|
}
|
|
80
81
|
#endif
|
|
81
82
|
|
|
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
83
|
|
|
90
84
|
#ifdef USE_ALPHATEST
|
|
91
85
|
uniform float alphaTest;
|
|
92
86
|
#endif
|
|
93
87
|
|
|
94
88
|
${fogFragmentDeclarationGLSL}
|
|
89
|
+
${softFragmentDeclarationGLSL}
|
|
95
90
|
${surfaceFragmentDeclarationGLSL}
|
|
96
91
|
void main() {
|
|
97
92
|
${surfaceColorGLSL(true)}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
#else
|
|
101
|
-
if (baseColor.a < 0.01) discard;
|
|
102
|
-
#endif
|
|
103
|
-
|
|
104
|
-
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);
|
|
105
95
|
#ifdef MESH_UNLIT
|
|
106
96
|
vec3 color = baseColor.rgb;
|
|
107
97
|
#else
|
|
@@ -132,18 +122,15 @@ ${surfaceColorGLSL(true)}
|
|
|
132
122
|
#endif
|
|
133
123
|
#endif
|
|
134
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
|
+
|
|
135
132
|
${fogFragmentGLSL('color')}
|
|
136
133
|
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;
|
|
147
|
-
#endif
|
|
134
|
+
${softFragmentGLSL('gl_FragColor')}
|
|
148
135
|
}
|
|
149
136
|
`;
|
|
@@ -1,4 +1,5 @@
|
|
|
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 */ `
|
|
@@ -78,31 +79,19 @@ fn sampleEnvAtlas(r: vec3f) -> vec3f {
|
|
|
78
79
|
}
|
|
79
80
|
#endif
|
|
80
81
|
|
|
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
82
|
|
|
90
83
|
#ifdef USE_ALPHATEST
|
|
91
84
|
uniform alphaTest: f32;
|
|
92
85
|
#endif
|
|
93
86
|
|
|
94
87
|
${fogFragmentDeclarationWGSL}
|
|
88
|
+
${softFragmentDeclarationWGSL}
|
|
95
89
|
${surfaceFragmentDeclarationWGSL}
|
|
96
90
|
@fragment
|
|
97
91
|
fn main(input: FragmentInputs) -> FragmentOutputs {
|
|
98
92
|
${surfaceColorWGSL(true)}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
#else
|
|
102
|
-
if (baseColor.a < 0.01) { discard; }
|
|
103
|
-
#endif
|
|
104
|
-
|
|
105
|
-
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);
|
|
106
95
|
#ifdef MESH_UNLIT
|
|
107
96
|
var color = baseColor.rgb;
|
|
108
97
|
#else
|
|
@@ -133,20 +122,17 @@ ${surfaceColorWGSL(true)}
|
|
|
133
122
|
#endif
|
|
134
123
|
#endif
|
|
135
124
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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;
|
|
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; }
|
|
147
130
|
#endif
|
|
148
131
|
|
|
132
|
+
var finalColor = vec4f(color, baseColor.a);
|
|
133
|
+
|
|
149
134
|
${fogFragmentWGSL('finalColor')}
|
|
135
|
+
${softFragmentWGSL('finalColor')}
|
|
150
136
|
fragmentOutputs.color = finalColor;
|
|
151
137
|
}
|
|
152
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.
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|