@driftengine/core 4.11.1 → 4.12.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 +36 -0
- package/README.md +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/render/backend/webgl2/renderer.d.ts +16 -1
- package/dist/render/backend/webgl2/renderer.js +41 -2
- package/dist/render/backend/webgpu/renderer.d.ts +2 -0
- package/dist/render/backend/webgpu/renderer.js +9 -0
- 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 +116 -0
- package/dist/render/shaders/flat/layered.d.ts +6 -4
- package/dist/render/shaders/flat/layered.js +62 -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/generated/flat.wgsl.d.ts +144 -16
- package/dist/render/shaders/generated/flat.wgsl.js +183 -55
- package/dist/render/surfaceLayerLooks.d.ts +80 -0
- package/dist/render/surfaceLayerLooks.js +83 -0
- package/dist/render/surfaceLayers.d.ts +47 -6
- package/dist/render/surfaceLayers.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/index.ts +2 -0
- package/src/render/backend/webgl2/renderer.ts +40 -2
- package/src/render/backend/webgpu/renderer.ts +8 -0
- 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 +116 -0
- package/src/render/shaders/flat/layered.ts +63 -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/generated/flat.wgsl.ts +183 -55
- package/src/render/surfaceLayerLooks.ts +155 -0
- package/src/render/surfaceLayers.ts +52 -7
|
@@ -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,12 @@ 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
|
+
/* What an occlusion read at the mesh's coordinates leaves of this point, 1 where none: layeredBegin. */
|
|
64
|
+
float lMeshOcclusion;
|
|
58
65
|
|
|
59
66
|
bool layered() {
|
|
60
67
|
return uLayers[1].y > 0.5;
|
|
@@ -71,14 +78,15 @@ vec2 layerPlace() {
|
|
|
71
78
|
}
|
|
72
79
|
|
|
73
80
|
vec3 layerAt(int i) {
|
|
74
|
-
|
|
81
|
+
float across = layerRepeat(i);
|
|
82
|
+
return vec3(layerPlace() * vec2(across, layerRepeatDown(i, across)), layerArray(i));
|
|
75
83
|
}
|
|
76
84
|
|
|
77
85
|
/* The weights as the material keeps them: the mask's channels, at the mesh's own coordinates. */
|
|
78
86
|
vec4 layerWeights() {
|
|
79
87
|
float source = uLayers[1].w;
|
|
80
88
|
if (source > 1.5) return vec4(vColor, 0.0);
|
|
81
|
-
if (source > 0.5) return texture(uOrmMap, vec3(vUv.xy,
|
|
89
|
+
if (source > 0.5) return texture(uOrmMap, vec3(vUv.xy, layerExtras()));
|
|
82
90
|
return texture(uModelMap, vec3(vUv.xy, 0.0));
|
|
83
91
|
}
|
|
84
92
|
|
|
@@ -92,10 +100,22 @@ vec4 layerPick(float layer) {
|
|
|
92
100
|
* Under a branch on uniforms, as its reads are.
|
|
93
101
|
*/
|
|
94
102
|
void layeredBegin() {
|
|
103
|
+
/*
|
|
104
|
+
* The occlusion at the mesh's coordinates, once: the ORM array's layer past the layers and past
|
|
105
|
+
* any mask and added mask it carries, spread over its range and taken at its strength.
|
|
106
|
+
*/
|
|
107
|
+
lMeshOcclusion = 1.0;
|
|
108
|
+
float strength = layerOcclusionStrength();
|
|
109
|
+
if (strength > 0.0) {
|
|
110
|
+
float at = layerExtras() + (abs(uLayers[1].w - 1.0) < 0.5 ? 1.0 : 0.0) + (uLayers[2].z > 0.5 ? 1.0 : 0.0);
|
|
111
|
+
vec2 range = layerOcclusionRange();
|
|
112
|
+
float occlusion = mix(range.x, range.y, texture(uOrmMap, vec3(vUv.xy, at)).r);
|
|
113
|
+
lMeshOcclusion = mix(1.0, occlusion, strength);
|
|
114
|
+
}
|
|
95
115
|
vec4 m = layerWeights();
|
|
96
116
|
if (uLayers[2].z > 0.5) {
|
|
97
117
|
/* The ORM array's layer past the layers, and past the mask where the array carries that too. */
|
|
98
|
-
float at =
|
|
118
|
+
float at = layerExtras() + (abs(uLayers[1].w - 1.0) < 0.5 ? 1.0 : 0.0);
|
|
99
119
|
float added = texture(uOrmMap, vec3(layerPlace() * uLayers[2].w, at)).r * uLayers[3].x;
|
|
100
120
|
m = mix(m, clamp(m + added, 0.0, 1.0), layerPick(uLayers[2].z));
|
|
101
121
|
}
|
|
@@ -135,23 +155,52 @@ vec3 layeredColor(vec3 color) {
|
|
|
135
155
|
return uLayers[1].w > 1.5 ? vec3(1.0) : color;
|
|
136
156
|
}
|
|
137
157
|
|
|
138
|
-
/*
|
|
158
|
+
/*
|
|
159
|
+
* Colour by the shares, each layer's tinted, and the base layer's coverage, which a cutout reads;
|
|
160
|
+
* then darkened by the occlusion at the mesh's coordinates, where it is the colour that takes it.
|
|
161
|
+
*/
|
|
139
162
|
vec4 layeredAlbedo() {
|
|
140
163
|
vec4 sum = vec4(0.0);
|
|
141
164
|
for (int i = 0; i < 5; i++) {
|
|
142
165
|
if (float(i) >= uLayers[1].y) break;
|
|
143
166
|
vec4 t = texture(uAlbedo, layerAt(i));
|
|
144
|
-
sum.rgb += t.rgb * layerShare(i);
|
|
167
|
+
sum.rgb += t.rgb * layerTint(i) * layerShare(i);
|
|
145
168
|
if (i == 0) sum.a = t.a;
|
|
146
169
|
}
|
|
170
|
+
if (!layerOcclusionAmbient()) sum.rgb *= lMeshOcclusion;
|
|
147
171
|
return sum;
|
|
148
172
|
}
|
|
149
173
|
|
|
174
|
+
/* What the ambient light keeps: the occlusion at the mesh's coordinates, where it takes it. */
|
|
175
|
+
float layeredAmbient() {
|
|
176
|
+
return layerOcclusionAmbient() ? lMeshOcclusion : 1.0;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/*
|
|
180
|
+
* The specular by the shares, each layer's own or the surface's where it names none. The surface's
|
|
181
|
+
* own, untouched, where no material has asked for looks: shares summing to one in floating point
|
|
182
|
+
* are not quite one, and a layered material that names nothing must draw exactly as before.
|
|
183
|
+
*/
|
|
184
|
+
float layeredSpecular(float own) {
|
|
185
|
+
if (LAYER_LOOKS) {
|
|
186
|
+
float sum = 0.0;
|
|
187
|
+
for (int i = 0; i < 5; i++) {
|
|
188
|
+
if (float(i) >= uLayers[1].y) break;
|
|
189
|
+
sum += layerSpecular(i, own) * layerShare(i);
|
|
190
|
+
}
|
|
191
|
+
return sum;
|
|
192
|
+
}
|
|
193
|
+
return own;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* Occlusion, roughness and metalness by the shares, each layer's spread over its own ranges. */
|
|
150
197
|
vec3 layeredOrm() {
|
|
151
198
|
vec3 sum = vec3(0.0);
|
|
152
199
|
for (int i = 0; i < 5; i++) {
|
|
153
200
|
if (float(i) >= uLayers[1].y) break;
|
|
154
|
-
|
|
201
|
+
vec3 t = texture(uOrmMap, layerAt(i)).rgb;
|
|
202
|
+
t.yz = layerRanges(i, t.yz);
|
|
203
|
+
sum += t * layerShare(i);
|
|
155
204
|
}
|
|
156
205
|
return sum;
|
|
157
206
|
}
|
|
@@ -168,7 +217,7 @@ vec3 layeredTexel() {
|
|
|
168
217
|
vec3 sum = vec3(0.0);
|
|
169
218
|
for (int i = 0; i < 5; i++) {
|
|
170
219
|
if (float(i) >= uLayers[1].y) break;
|
|
171
|
-
sum += layerNormalTexel(layerAt(i)) * layerShare(i);
|
|
220
|
+
sum += layerStrengthen(i, layerNormalTexel(layerAt(i))) * layerShare(i);
|
|
172
221
|
}
|
|
173
222
|
float len = length(sum);
|
|
174
223
|
return len > 1e-5 ? sum / len : vec3(0.0, 0.0, 1.0);
|
|
@@ -181,7 +230,7 @@ bool layeredMeshNormal() {
|
|
|
181
230
|
|
|
182
231
|
/* That normal's texel: the normal array's layer past the layers, at the mesh's coordinates. */
|
|
183
232
|
vec3 layeredMeshTexel() {
|
|
184
|
-
return layerNormalTexel(vec3(vUv.xy,
|
|
233
|
+
return layerNormalTexel(vec3(vUv.xy, layerExtras()));
|
|
185
234
|
}
|
|
186
235
|
|
|
187
236
|
/* Whether the emissive map belongs to one layer rather than to the whole surface. */
|