@driftengine/core 4.11.1 → 4.13.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.json +102 -0
- package/README.md +18 -9
- package/dist/geometry/meshBuilder.d.ts +10 -0
- package/dist/geometry/meshBuilder.js +11 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +3 -2
- package/dist/math/color.d.ts +25 -0
- package/dist/math/color.js +37 -0
- package/dist/render/backend/webgl2/renderer.d.ts +33 -5
- package/dist/render/backend/webgl2/renderer.js +123 -49
- package/dist/render/backend/webgl2/skinScatter.d.ts +3 -1
- package/dist/render/backend/webgl2/skinScatter.js +5 -1
- package/dist/render/backend/webgpu/boltPass.d.ts +1 -1
- package/dist/render/backend/webgpu/causticsPass.d.ts +1 -1
- package/dist/render/backend/webgpu/filmPass.d.ts +1 -1
- package/dist/render/backend/webgpu/flockPass.d.ts +1 -1
- package/dist/render/backend/webgpu/giFieldPass.d.ts +3 -1
- package/dist/render/backend/webgpu/gpuDrivenPass.d.ts +10 -1
- package/dist/render/backend/webgpu/gpuDrivenPass.js +28 -11
- package/dist/render/backend/webgpu/panelPass.d.ts +1 -1
- package/dist/render/backend/webgpu/postPass.d.ts +2 -2
- package/dist/render/backend/webgpu/renderer.d.ts +21 -8
- package/dist/render/backend/webgpu/renderer.js +103 -38
- package/dist/render/backend/webgpu/scatterPass.d.ts +1 -1
- package/dist/render/backend/webgpu/skinScatterPass.d.ts +5 -1
- package/dist/render/backend/webgpu/skinScatterPass.js +9 -3
- package/dist/render/backend/webgpu/skyPass.d.ts +11 -1
- package/dist/render/backend/webgpu/waterPass.d.ts +1 -1
- package/dist/render/backend/webgpu/windStreakPass.d.ts +1 -1
- package/dist/render/causticsRenderer.d.ts +3 -1
- package/dist/render/causticsRenderer.js +5 -1
- package/dist/render/decalPass.d.ts +3 -1
- package/dist/render/decalPass.js +4 -1
- package/dist/render/flockRenderer.d.ts +1 -1
- package/dist/render/flockRenderer.js +4 -1
- package/dist/render/globalMediumPass.d.ts +3 -1
- package/dist/render/globalMediumPass.js +5 -1
- package/dist/render/gradeColor.d.ts +21 -0
- package/dist/render/gradeColor.js +64 -0
- package/dist/render/lightMatrix.d.ts +13 -0
- package/dist/render/lightMatrix.js +17 -0
- package/dist/render/passGrade.d.ts +13 -0
- package/dist/render/passGrade.js +47 -0
- package/dist/render/plumeRenderer.d.ts +1 -1
- package/dist/render/plumeRenderer.js +4 -1
- package/dist/render/renderQuality.d.ts +57 -18
- package/dist/render/renderQuality.js +3 -3
- package/dist/render/sceneTarget.d.ts +2 -0
- package/dist/render/sceneTarget.js +1 -0
- package/dist/render/sdfTextRenderer.d.ts +1 -1
- package/dist/render/sdfTextRenderer.js +1 -1
- package/dist/render/shaders/arcane.d.ts +1 -1
- package/dist/render/shaders/arcane.js +5 -1
- package/dist/render/shaders/bolt.d.ts +1 -1
- package/dist/render/shaders/bolt.js +4 -1
- package/dist/render/shaders/caustics.d.ts +1 -1
- package/dist/render/shaders/caustics.js +4 -1
- package/dist/render/shaders/decalProject.js +12 -2
- package/dist/render/shaders/film.d.ts +1 -1
- package/dist/render/shaders/film.js +22 -9
- package/dist/render/shaders/fire.d.ts +1 -1
- package/dist/render/shaders/fire.js +4 -1
- package/dist/render/shaders/flat/areaLight.d.ts +1 -1
- package/dist/render/shaders/flat/areaLight.js +1 -1
- package/dist/render/shaders/flat/glassTint.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.js +1 -0
- package/dist/render/shaders/flat/index.d.ts +5 -0
- package/dist/render/shaders/flat/index.js +1 -1
- package/dist/render/shaders/flat/layerLooks.d.ts +16 -0
- package/dist/render/shaders/flat/layerLooks.js +108 -0
- package/dist/render/shaders/flat/layered.d.ts +6 -4
- package/dist/render/shaders/flat/layered.js +77 -13
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +7 -2
- package/dist/render/shaders/flat/models.js +1 -1
- package/dist/render/shaders/flat/preamble.js +6 -0
- package/dist/render/shaders/flock.d.ts +1 -1
- package/dist/render/shaders/flock.js +4 -1
- package/dist/render/shaders/generated/arcane.wgsl.d.ts +11 -1
- package/dist/render/shaders/generated/arcane.wgsl.js +11 -1
- package/dist/render/shaders/generated/bolt.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/bolt.wgsl.js +12 -2
- package/dist/render/shaders/generated/caustics.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/caustics.wgsl.js +12 -2
- package/dist/render/shaders/generated/decalProject.wgsl.d.ts +6 -1
- package/dist/render/shaders/generated/decalProject.wgsl.js +6 -1
- package/dist/render/shaders/generated/film.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/film.wgsl.js +12 -2
- package/dist/render/shaders/generated/fire.wgsl.d.ts +11 -1
- package/dist/render/shaders/generated/fire.wgsl.js +11 -1
- package/dist/render/shaders/generated/flat.wgsl.d.ts +144 -16
- package/dist/render/shaders/generated/flat.wgsl.js +183 -55
- package/dist/render/shaders/generated/flock.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/flock.wgsl.js +12 -2
- package/dist/render/shaders/generated/globalMedium.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/globalMedium.wgsl.js +12 -2
- package/dist/render/shaders/generated/lightVolume.wgsl.d.ts +36 -16
- package/dist/render/shaders/generated/lightVolume.wgsl.js +39 -19
- package/dist/render/shaders/generated/panel.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/panel.wgsl.js +12 -2
- package/dist/render/shaders/generated/rush.wgsl.d.ts +31 -26
- package/dist/render/shaders/generated/rush.wgsl.js +31 -26
- package/dist/render/shaders/generated/scatter.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/scatter.wgsl.js +12 -2
- package/dist/render/shaders/generated/skinBlur.wgsl.d.ts +11 -1
- package/dist/render/shaders/generated/skinBlur.wgsl.js +11 -1
- package/dist/render/shaders/generated/sky.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/sky.wgsl.js +12 -2
- package/dist/render/shaders/generated/smoke.wgsl.d.ts +11 -1
- package/dist/render/shaders/generated/smoke.wgsl.js +11 -1
- package/dist/render/shaders/generated/text.wgsl.d.ts +11 -1
- package/dist/render/shaders/generated/text.wgsl.js +11 -1
- package/dist/render/shaders/generated/water.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/water.wgsl.js +12 -2
- package/dist/render/shaders/generated/windStreaks.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/windStreaks.wgsl.js +12 -2
- package/dist/render/shaders/globalMedium.js +14 -1
- package/dist/render/shaders/gpudriven/present.wgsl.d.ts +15 -6
- package/dist/render/shaders/gpudriven/present.wgsl.js +71 -8
- package/dist/render/shaders/lightVolume.js +4 -1
- package/dist/render/shaders/line.d.ts +1 -1
- package/dist/render/shaders/outputTransform.d.ts +8 -2
- package/dist/render/shaders/outputTransform.js +18 -11
- package/dist/render/shaders/panel.d.ts +1 -1
- package/dist/render/shaders/panel.js +5 -1
- package/dist/render/shaders/particle.d.ts +3 -3
- package/dist/render/shaders/rush.js +8 -0
- package/dist/render/shaders/scatter.d.ts +1 -1
- package/dist/render/shaders/scatter.js +4 -1
- package/dist/render/shaders/sdfText.d.ts +1 -1
- package/dist/render/shaders/skinBlur.js +5 -1
- package/dist/render/shaders/sky.d.ts +1 -1
- package/dist/render/shaders/sky.js +5 -1
- package/dist/render/shaders/smoke.d.ts +1 -1
- package/dist/render/shaders/smoke.js +4 -1
- package/dist/render/shaders/text.d.ts +1 -1
- package/dist/render/shaders/text.js +4 -1
- package/dist/render/shaders/water.d.ts +1 -1
- package/dist/render/shaders/water.js +12 -2
- package/dist/render/shaders/windStreaks.d.ts +1 -1
- package/dist/render/shaders/windStreaks.js +4 -1
- package/dist/render/surfaceLayerLooks.d.ts +92 -0
- package/dist/render/surfaceLayerLooks.js +102 -0
- package/dist/render/surfaceLayers.d.ts +47 -6
- package/dist/render/surfaceLayers.js +5 -1
- package/dist/render/textRenderer.d.ts +3 -1
- package/dist/render/textRenderer.js +7 -1
- package/dist/render/vertexDefaults.d.ts +1 -1
- package/dist/render/vertexDefaults.js +1 -1
- package/dist/render/waterRenderer.d.ts +1 -1
- package/dist/render/waterRenderer.js +4 -1
- package/dist/render/windStreakRenderer.d.ts +3 -1
- package/dist/render/windStreakRenderer.js +5 -1
- package/package.json +6 -6
- package/scripts/browser.d.mts +5 -0
- package/scripts/browser.mjs +68 -14
- package/scripts/look.d.mts +81 -0
- package/scripts/look.mjs +380 -0
- package/src/geometry/meshBuilder.ts +21 -2
- package/src/index.ts +13 -2
- package/src/math/color.ts +39 -0
- package/src/render/backend/webgl2/renderer.ts +174 -46
- package/src/render/backend/webgl2/skinScatter.ts +5 -0
- package/src/render/backend/webgpu/giFieldPass.ts +3 -1
- package/src/render/backend/webgpu/gpuDrivenPass.ts +29 -13
- package/src/render/backend/webgpu/renderer.ts +112 -37
- package/src/render/backend/webgpu/skinScatterPass.ts +17 -1
- package/src/render/causticsRenderer.ts +5 -0
- package/src/render/decalPass.ts +3 -0
- package/src/render/flockRenderer.ts +5 -0
- package/src/render/globalMediumPass.ts +10 -1
- package/src/render/gradeColor.ts +90 -0
- package/src/render/lightMatrix.ts +32 -0
- package/src/render/passGrade.ts +58 -0
- package/src/render/plumeRenderer.ts +5 -0
- package/src/render/renderQuality.ts +60 -21
- package/src/render/sceneTarget.ts +3 -0
- package/src/render/sdfTextRenderer.ts +1 -1
- package/src/render/shaders/arcane.ts +5 -1
- package/src/render/shaders/bolt.ts +4 -1
- package/src/render/shaders/caustics.ts +4 -1
- package/src/render/shaders/decalProject.ts +12 -2
- package/src/render/shaders/film.ts +22 -9
- package/src/render/shaders/fire.ts +4 -1
- package/src/render/shaders/flat/areaLight.ts +1 -1
- package/src/render/shaders/flat/glassTint.ts +3 -1
- package/src/render/shaders/flat/index.ts +6 -1
- package/src/render/shaders/flat/layerLooks.ts +108 -0
- package/src/render/shaders/flat/layered.ts +78 -13
- package/src/render/shaders/flat/main.ts +7 -2
- package/src/render/shaders/flat/models.ts +1 -1
- package/src/render/shaders/flat/preamble.ts +6 -0
- package/src/render/shaders/flock.ts +4 -1
- package/src/render/shaders/generated/arcane.wgsl.ts +11 -1
- package/src/render/shaders/generated/bolt.wgsl.ts +12 -2
- package/src/render/shaders/generated/caustics.wgsl.ts +12 -2
- package/src/render/shaders/generated/decalProject.wgsl.ts +6 -1
- package/src/render/shaders/generated/film.wgsl.ts +12 -2
- package/src/render/shaders/generated/fire.wgsl.ts +11 -1
- package/src/render/shaders/generated/flat.wgsl.ts +183 -55
- package/src/render/shaders/generated/flock.wgsl.ts +12 -2
- package/src/render/shaders/generated/globalMedium.wgsl.ts +12 -2
- package/src/render/shaders/generated/lightVolume.wgsl.ts +39 -19
- package/src/render/shaders/generated/panel.wgsl.ts +12 -2
- package/src/render/shaders/generated/rush.wgsl.ts +31 -26
- package/src/render/shaders/generated/scatter.wgsl.ts +12 -2
- package/src/render/shaders/generated/skinBlur.wgsl.ts +11 -1
- package/src/render/shaders/generated/sky.wgsl.ts +12 -2
- package/src/render/shaders/generated/smoke.wgsl.ts +11 -1
- package/src/render/shaders/generated/text.wgsl.ts +11 -1
- package/src/render/shaders/generated/water.wgsl.ts +12 -2
- package/src/render/shaders/generated/windStreaks.wgsl.ts +12 -2
- package/src/render/shaders/globalMedium.ts +14 -1
- package/src/render/shaders/gpudriven/present.wgsl.ts +72 -8
- package/src/render/shaders/lightVolume.ts +4 -1
- package/src/render/shaders/outputTransform.ts +19 -11
- package/src/render/shaders/panel.ts +5 -1
- package/src/render/shaders/rush.ts +8 -0
- package/src/render/shaders/scatter.ts +4 -1
- package/src/render/shaders/skinBlur.ts +5 -1
- package/src/render/shaders/sky.ts +5 -1
- package/src/render/shaders/smoke.ts +4 -1
- package/src/render/shaders/text.ts +4 -1
- package/src/render/shaders/water.ts +12 -2
- package/src/render/shaders/windStreaks.ts +4 -1
- package/src/render/surfaceLayerLooks.ts +186 -0
- package/src/render/surfaceLayers.ts +52 -7
- package/src/render/textRenderer.ts +6 -0
- package/src/render/vertexDefaults.ts +1 -1
- package/src/render/waterRenderer.ts +5 -0
- package/src/render/windStreakRenderer.ts +5 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which layer of the shared arrays each of a layered material's layers reads, and how each looks:
|
|
3
|
+
* `uLayerLooks`, packed by `surfaceLayerLooks.ts`, read by `layered.ts`.
|
|
4
|
+
*
|
|
5
|
+
* **Every helper is the identity where the switch is off**, written as a branch on `LAYER_LOOKS`
|
|
6
|
+
* itself because the generated WGSL carries one string for both values of an override: layer `i`
|
|
7
|
+
* reads layer `i`, the maps beyond the layers start at the layer count, a tint is white, a range is
|
|
8
|
+
* 0 to 1, a normal is as stored, a specular is the surface's own, a repeat down is the repeat
|
|
9
|
+
* across, and nothing is occluded — exactly what `layered.ts` did before this existed, which is what
|
|
10
|
+
* a layered material that asks for none of it has to keep drawing.
|
|
11
|
+
*
|
|
12
|
+
* **A lit switch, `LAYER_LOOKS`**, off until a material first asks and declared after `LAYERED`, so
|
|
13
|
+
* every switch before it keeps its id. It is only ever compiled beside `LAYERED`, whose `uLayers`
|
|
14
|
+
* it reads.
|
|
15
|
+
*/
|
|
16
|
+
export function layerLooksGlsl(on) {
|
|
17
|
+
if (!on) {
|
|
18
|
+
return /* glsl */ `
|
|
19
|
+
const bool LAYER_LOOKS = false; // wgsl:override
|
|
20
|
+
float layerArray(int i) { return float(i); }
|
|
21
|
+
float layerExtras() { return uLayers[1].y; }
|
|
22
|
+
vec3 layerTint(int i) { return vec3(1.0); }
|
|
23
|
+
vec2 layerRanges(int i, vec2 roughMetal) { return roughMetal; }
|
|
24
|
+
vec3 layerStrengthen(int i, vec3 texel) { return texel; }
|
|
25
|
+
float layerNamedSpecular(int i) { return -1.0; }
|
|
26
|
+
float layerRepeatDown(int i, float across) { return across; }
|
|
27
|
+
vec2 layerOcclusionStrengths() { return vec2(0.0); }
|
|
28
|
+
vec2 layerOcclusionRange() { return vec2(0.0, 1.0); }
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
31
|
+
return /* glsl */ `
|
|
32
|
+
/* Whether layers are picked from shared arrays and given looks of their own: layerLooks.ts. */
|
|
33
|
+
const bool LAYER_LOOKS = true; // wgsl:override
|
|
34
|
+
/*
|
|
35
|
+
* Fifteen vectors, as surfaceLayerLooks.ts packs them: the array layer each of the five reads, base
|
|
36
|
+
* first (floats 0 to 4); where the maps beyond the layers start (5), the mesh occlusion's strength
|
|
37
|
+
* on the colour, from 0 up (6), and on the ambient light (7); then two vectors a
|
|
38
|
+
* layer, base first: its tint (x y z) and normal strength (w), then its roughness range (x to y)
|
|
39
|
+
* and metalness range (z to w); then each layer's specular, -1 for the surface's own (48 to 52), its
|
|
40
|
+
* repeat down (53 to 57), and the occlusion's range (58 to 59).
|
|
41
|
+
*/
|
|
42
|
+
uniform vec4 uLayerLooks[15]; // wgsl:material
|
|
43
|
+
|
|
44
|
+
/* Float k of the fifteen vectors. */
|
|
45
|
+
float layerLook(int k) {
|
|
46
|
+
return uLayerLooks[k / 4][k % 4];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* The layer of the albedo, normal and ORM arrays a material's layer i reads. */
|
|
50
|
+
float layerArray(int i) {
|
|
51
|
+
if (LAYER_LOOKS) return layerLook(i);
|
|
52
|
+
return float(i);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* Where the maps beyond the layers start in each array. */
|
|
56
|
+
float layerExtras() {
|
|
57
|
+
if (LAYER_LOOKS) return uLayerLooks[1].y;
|
|
58
|
+
return uLayers[1].y;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
vec3 layerTint(int i) {
|
|
62
|
+
if (LAYER_LOOKS) return uLayerLooks[2 + i * 2].xyz;
|
|
63
|
+
return vec3(1.0);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* The ORM's roughness and metalness, each spread over the layer's own range. */
|
|
67
|
+
vec2 layerRanges(int i, vec2 roughMetal) {
|
|
68
|
+
if (LAYER_LOOKS) {
|
|
69
|
+
vec4 range = uLayerLooks[3 + i * 2];
|
|
70
|
+
return vec2(mix(range.x, range.y, roughMetal.x), mix(range.z, range.w, roughMetal.y));
|
|
71
|
+
}
|
|
72
|
+
return roughMetal;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/*
|
|
76
|
+
* A tangent-space texel bent further or less by the layer's strength: its x and y scaled, its z
|
|
77
|
+
* kept, so 0 lies flat and a strength above 1 steepens every slope the map holds. z is held above
|
|
78
|
+
* zero so a texel lying exactly flat on its surface cannot normalise to nothing at strength 0.
|
|
79
|
+
*/
|
|
80
|
+
vec3 layerStrengthen(int i, vec3 texel) {
|
|
81
|
+
if (LAYER_LOOKS) return normalize(vec3(texel.xy * uLayerLooks[2 + i * 2].w, max(texel.z, 1e-4)));
|
|
82
|
+
return texel;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* The specular the layer names, or -1 where it names none and the surface's own stands. */
|
|
86
|
+
float layerNamedSpecular(int i) {
|
|
87
|
+
if (LAYER_LOOKS) return layerLook(48 + i);
|
|
88
|
+
return -1.0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* The layer's repeat down, which is its repeat across unless it gave two. */
|
|
92
|
+
float layerRepeatDown(int i, float across) {
|
|
93
|
+
if (LAYER_LOOKS) return layerLook(53 + i);
|
|
94
|
+
return across;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* The mesh occlusion's strength on the colour (x), from 0 up, and on the ambient light (y). */
|
|
98
|
+
vec2 layerOcclusionStrengths() {
|
|
99
|
+
if (LAYER_LOOKS) return uLayerLooks[1].zw;
|
|
100
|
+
return vec2(0.0);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
vec2 layerOcclusionRange() {
|
|
104
|
+
if (LAYER_LOOKS) return uLayerLooks[14].zw;
|
|
105
|
+
return vec2(0.0, 1.0);
|
|
106
|
+
}
|
|
107
|
+
`;
|
|
108
|
+
}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* A material blended from layers by a mask: `SurfaceMaterial.layers`, packed into `uLayers` by
|
|
3
3
|
* `surfaceLayers.ts`.
|
|
4
4
|
*
|
|
5
|
-
* **Layer `i` is layer `i` of the material's arrays
|
|
5
|
+
* **Layer `i` is layer `i` of the material's arrays** — or the layer `layerLooks.ts` picks, with the
|
|
6
|
+
* tint, ranges and normal strength it gives each — each read at its own repeat of where the
|
|
6
7
|
* layers are laid: the mesh's coordinates, or the world's horizontal plane where the material has a
|
|
7
8
|
* projection (`worldUv.ts`). The mask's channels weigh layers 1 to 4 — red, green, blue, alpha — and
|
|
8
9
|
* come from a map read where a shading model's would be, from the ORM array's layer past the layers,
|
|
@@ -21,7 +22,8 @@
|
|
|
21
22
|
* in uniform control flow (AGENTS.md 2026-08-07), so the loop is bounded by the layer count, a
|
|
22
23
|
* uniform, and never skips on a share, which is the pixel's own.
|
|
23
24
|
*
|
|
24
|
-
* **A lit switch, `LAYERED`**, off until a material first asks, declared
|
|
25
|
-
* it keeps its id. Compiled out, its four vectors are not declared and its calls are
|
|
25
|
+
* **A lit switch, `LAYERED`**, off until a material first asks, declared after every switch before
|
|
26
|
+
* it so each keeps its id. Compiled out, its four vectors are not declared and its calls are
|
|
27
|
+
* constants. `looks` compiles `LAYER_LOOKS` in beside it, and means nothing without it.
|
|
26
28
|
*/
|
|
27
|
-
export declare function layeredGlsl(on: boolean): string;
|
|
29
|
+
export declare function layeredGlsl(on: boolean, looks?: boolean): string;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { layerLooksGlsl } from './layerLooks.js';
|
|
1
2
|
/**
|
|
2
3
|
* A material blended from layers by a mask: `SurfaceMaterial.layers`, packed into `uLayers` by
|
|
3
4
|
* `surfaceLayers.ts`.
|
|
4
5
|
*
|
|
5
|
-
* **Layer `i` is layer `i` of the material's arrays
|
|
6
|
+
* **Layer `i` is layer `i` of the material's arrays** — or the layer `layerLooks.ts` picks, with the
|
|
7
|
+
* tint, ranges and normal strength it gives each — each read at its own repeat of where the
|
|
6
8
|
* layers are laid: the mesh's coordinates, or the world's horizontal plane where the material has a
|
|
7
9
|
* projection (`worldUv.ts`). The mask's channels weigh layers 1 to 4 — red, green, blue, alpha — and
|
|
8
10
|
* come from a map read where a shading model's would be, from the ORM array's layer past the layers,
|
|
@@ -21,10 +23,11 @@
|
|
|
21
23
|
* in uniform control flow (AGENTS.md 2026-08-07), so the loop is bounded by the layer count, a
|
|
22
24
|
* uniform, and never skips on a share, which is the pixel's own.
|
|
23
25
|
*
|
|
24
|
-
* **A lit switch, `LAYERED`**, off until a material first asks, declared
|
|
25
|
-
* it keeps its id. Compiled out, its four vectors are not declared and its calls are
|
|
26
|
+
* **A lit switch, `LAYERED`**, off until a material first asks, declared after every switch before
|
|
27
|
+
* it so each keeps its id. Compiled out, its four vectors are not declared and its calls are
|
|
28
|
+
* constants. `looks` compiles `LAYER_LOOKS` in beside it, and means nothing without it.
|
|
26
29
|
*/
|
|
27
|
-
export function layeredGlsl(on) {
|
|
30
|
+
export function layeredGlsl(on, looks = false) {
|
|
28
31
|
if (!on) {
|
|
29
32
|
return /* glsl */ `
|
|
30
33
|
const bool LAYERED = false; // wgsl:override
|
|
@@ -38,6 +41,8 @@ bool layeredMeshNormal() { return false; }
|
|
|
38
41
|
vec3 layeredMeshTexel() { return vec3(0.0, 0.0, 1.0); }
|
|
39
42
|
bool layeredGlows() { return false; }
|
|
40
43
|
vec3 layeredEmissive() { return vec3(0.0); }
|
|
44
|
+
float layeredAmbient() { return 1.0; }
|
|
45
|
+
float layeredSpecular(float own) { return own; }
|
|
41
46
|
`;
|
|
42
47
|
}
|
|
43
48
|
return /* glsl */ `
|
|
@@ -51,10 +56,16 @@ const bool LAYERED = true; // wgsl:override
|
|
|
51
56
|
* layer or -1 (y), its bias (z) and its sharpness (w).
|
|
52
57
|
*/
|
|
53
58
|
uniform vec4 uLayers[4]; // wgsl:material
|
|
54
|
-
|
|
59
|
+
${layerLooksGlsl(looks)}
|
|
55
60
|
/* Each layer's share of this point, the base's and layers 1 to 4's: worked out once, in layeredBegin. */
|
|
56
61
|
float lShareBase;
|
|
57
62
|
vec4 lShare;
|
|
63
|
+
/*
|
|
64
|
+
* What an occlusion read at the mesh's coordinates leaves of this point's colour and of its ambient
|
|
65
|
+
* light, 1 where none: layeredBegin.
|
|
66
|
+
*/
|
|
67
|
+
float lColorOcclusion;
|
|
68
|
+
float lAmbientOcclusion;
|
|
58
69
|
|
|
59
70
|
bool layered() {
|
|
60
71
|
return uLayers[1].y > 0.5;
|
|
@@ -71,14 +82,15 @@ vec2 layerPlace() {
|
|
|
71
82
|
}
|
|
72
83
|
|
|
73
84
|
vec3 layerAt(int i) {
|
|
74
|
-
|
|
85
|
+
float across = layerRepeat(i);
|
|
86
|
+
return vec3(layerPlace() * vec2(across, layerRepeatDown(i, across)), layerArray(i));
|
|
75
87
|
}
|
|
76
88
|
|
|
77
89
|
/* The weights as the material keeps them: the mask's channels, at the mesh's own coordinates. */
|
|
78
90
|
vec4 layerWeights() {
|
|
79
91
|
float source = uLayers[1].w;
|
|
80
92
|
if (source > 1.5) return vec4(vColor, 0.0);
|
|
81
|
-
if (source > 0.5) return texture(uOrmMap, vec3(vUv.xy,
|
|
93
|
+
if (source > 0.5) return texture(uOrmMap, vec3(vUv.xy, layerExtras()));
|
|
82
94
|
return texture(uModelMap, vec3(vUv.xy, 0.0));
|
|
83
95
|
}
|
|
84
96
|
|
|
@@ -92,10 +104,25 @@ vec4 layerPick(float layer) {
|
|
|
92
104
|
* Under a branch on uniforms, as its reads are.
|
|
93
105
|
*/
|
|
94
106
|
void layeredBegin() {
|
|
107
|
+
/*
|
|
108
|
+
* The occlusion at the mesh's coordinates, once: the ORM array's layer past the layers and past
|
|
109
|
+
* any mask and added mask it carries, spread over its range and taken at each strength. The
|
|
110
|
+
* colour's may pass 1, darkening faster than the occlusion does, and is held at black.
|
|
111
|
+
*/
|
|
112
|
+
lColorOcclusion = 1.0;
|
|
113
|
+
lAmbientOcclusion = 1.0;
|
|
114
|
+
vec2 strength = layerOcclusionStrengths();
|
|
115
|
+
if (strength.x > 0.0 || strength.y > 0.0) {
|
|
116
|
+
float at = layerExtras() + (abs(uLayers[1].w - 1.0) < 0.5 ? 1.0 : 0.0) + (uLayers[2].z > 0.5 ? 1.0 : 0.0);
|
|
117
|
+
vec2 range = layerOcclusionRange();
|
|
118
|
+
float bare = 1.0 - mix(range.x, range.y, texture(uOrmMap, vec3(vUv.xy, at)).r);
|
|
119
|
+
lColorOcclusion = max(0.0, 1.0 - strength.x * bare);
|
|
120
|
+
lAmbientOcclusion = 1.0 - strength.y * bare;
|
|
121
|
+
}
|
|
95
122
|
vec4 m = layerWeights();
|
|
96
123
|
if (uLayers[2].z > 0.5) {
|
|
97
124
|
/* The ORM array's layer past the layers, and past the mask where the array carries that too. */
|
|
98
|
-
float at =
|
|
125
|
+
float at = layerExtras() + (abs(uLayers[1].w - 1.0) < 0.5 ? 1.0 : 0.0);
|
|
99
126
|
float added = texture(uOrmMap, vec3(layerPlace() * uLayers[2].w, at)).r * uLayers[3].x;
|
|
100
127
|
m = mix(m, clamp(m + added, 0.0, 1.0), layerPick(uLayers[2].z));
|
|
101
128
|
}
|
|
@@ -135,23 +162,60 @@ vec3 layeredColor(vec3 color) {
|
|
|
135
162
|
return uLayers[1].w > 1.5 ? vec3(1.0) : color;
|
|
136
163
|
}
|
|
137
164
|
|
|
138
|
-
/*
|
|
165
|
+
/*
|
|
166
|
+
* Colour by the shares, each layer's tinted, and the base layer's coverage, which a cutout reads;
|
|
167
|
+
* then darkened by the occlusion at the mesh's coordinates, at the colour's strength.
|
|
168
|
+
*/
|
|
139
169
|
vec4 layeredAlbedo() {
|
|
140
170
|
vec4 sum = vec4(0.0);
|
|
141
171
|
for (int i = 0; i < 5; i++) {
|
|
142
172
|
if (float(i) >= uLayers[1].y) break;
|
|
143
173
|
vec4 t = texture(uAlbedo, layerAt(i));
|
|
144
|
-
sum.rgb += t.rgb * layerShare(i);
|
|
174
|
+
sum.rgb += t.rgb * layerTint(i) * layerShare(i);
|
|
145
175
|
if (i == 0) sum.a = t.a;
|
|
146
176
|
}
|
|
177
|
+
sum.rgb *= lColorOcclusion;
|
|
147
178
|
return sum;
|
|
148
179
|
}
|
|
149
180
|
|
|
181
|
+
/* What the ambient light keeps: the occlusion at the mesh's coordinates, at the ambient's strength. */
|
|
182
|
+
float layeredAmbient() {
|
|
183
|
+
return lAmbientOcclusion;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/*
|
|
187
|
+
* The specular by the shares: each layer's named one at its share, and the surface's own over the
|
|
188
|
+
* layers naming none, once at most. Under a summed blend the shares add past 1 where the weights
|
|
189
|
+
* do, and a surface whose layers leave the specular to it reflects its own, not its own times that
|
|
190
|
+
* sum; under a blend laid over, the shares never pass 1 and this is the sum it always was. What it
|
|
191
|
+
* gives up: named speculars still add as their colours do, so a summed blend that names them
|
|
192
|
+
* reflects their sum. The surface's own, untouched, where no material has asked for looks: shares
|
|
193
|
+
* summing to one in floating point are not quite one, and a layered material that names nothing
|
|
194
|
+
* must draw exactly as before.
|
|
195
|
+
*/
|
|
196
|
+
float layeredSpecular(float own) {
|
|
197
|
+
if (LAYER_LOOKS) {
|
|
198
|
+
float named = 0.0;
|
|
199
|
+
float unnamed = 0.0;
|
|
200
|
+
for (int i = 0; i < 5; i++) {
|
|
201
|
+
if (float(i) >= uLayers[1].y) break;
|
|
202
|
+
float specular = layerNamedSpecular(i);
|
|
203
|
+
if (specular < 0.0) unnamed += layerShare(i);
|
|
204
|
+
else named += specular * layerShare(i);
|
|
205
|
+
}
|
|
206
|
+
return named + own * min(unnamed, 1.0);
|
|
207
|
+
}
|
|
208
|
+
return own;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/* Occlusion, roughness and metalness by the shares, each layer's spread over its own ranges. */
|
|
150
212
|
vec3 layeredOrm() {
|
|
151
213
|
vec3 sum = vec3(0.0);
|
|
152
214
|
for (int i = 0; i < 5; i++) {
|
|
153
215
|
if (float(i) >= uLayers[1].y) break;
|
|
154
|
-
|
|
216
|
+
vec3 t = texture(uOrmMap, layerAt(i)).rgb;
|
|
217
|
+
t.yz = layerRanges(i, t.yz);
|
|
218
|
+
sum += t * layerShare(i);
|
|
155
219
|
}
|
|
156
220
|
return sum;
|
|
157
221
|
}
|
|
@@ -168,7 +232,7 @@ vec3 layeredTexel() {
|
|
|
168
232
|
vec3 sum = vec3(0.0);
|
|
169
233
|
for (int i = 0; i < 5; i++) {
|
|
170
234
|
if (float(i) >= uLayers[1].y) break;
|
|
171
|
-
sum += layerNormalTexel(layerAt(i)) * layerShare(i);
|
|
235
|
+
sum += layerStrengthen(i, layerNormalTexel(layerAt(i))) * layerShare(i);
|
|
172
236
|
}
|
|
173
237
|
float len = length(sum);
|
|
174
238
|
return len > 1e-5 ? sum / len : vec3(0.0, 0.0, 1.0);
|
|
@@ -181,7 +245,7 @@ bool layeredMeshNormal() {
|
|
|
181
245
|
|
|
182
246
|
/* That normal's texel: the normal array's layer past the layers, at the mesh's coordinates. */
|
|
183
247
|
vec3 layeredMeshTexel() {
|
|
184
|
-
return layerNormalTexel(vec3(vUv.xy,
|
|
248
|
+
return layerNormalTexel(vec3(vUv.xy, layerExtras()));
|
|
185
249
|
}
|
|
186
250
|
|
|
187
251
|
/* Whether the emissive map belongs to one layer rather than to the whole surface. */
|