@vitreajs/vitrea 0.16.0 → 0.18.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/README.md +4 -3
- package/dist/{dist-C43H3RKY.js → dist-VQPRX7BX.js} +620 -50
- package/dist/dist-VQPRX7BX.js.map +1 -0
- package/dist/index.d.ts +58 -7
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/dist-C43H3RKY.js.map +0 -1
|
@@ -220,6 +220,12 @@ function occlusionAlphaUnderPolicy(nominal, occlusion, lift = INCREASED_OCCLUSIO
|
|
|
220
220
|
return 1;
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
|
+
function occlusionLiftForPolicy(policy, profile = DEFAULT_MATERIAL_PROFILE) {
|
|
224
|
+
if (policy.occlusion !== "increased")
|
|
225
|
+
return profile.increasedOcclusionLift;
|
|
226
|
+
const levels = profile.increasedOcclusionLiftByPolicy;
|
|
227
|
+
return policy.ambientTint === "reduced" ? levels?.increaseContrast ?? profile.increasedOcclusionLift : levels?.reduceTransparency ?? profile.increasedOcclusionLift;
|
|
228
|
+
}
|
|
223
229
|
var DEFAULT_MATERIAL_PROFILE = {
|
|
224
230
|
optics: {
|
|
225
231
|
// σ = 8 for the regular variant, which keeps this package's blur and
|
|
@@ -1152,8 +1158,26 @@ function rejectRetiredOuterShadowLeaves(patch) {
|
|
|
1152
1158
|
throw new Error(`outerShadow.${leaf} was retired by W14 G1 (claims \xA75.62) and is replaced by ${replacement}. Applying this patch would have rendered the default shadow while recording itself as configured. It is refused rather than mapped: a single span-flat amplitude is the material the measurement retired.`);
|
|
1153
1159
|
}
|
|
1154
1160
|
}
|
|
1161
|
+
function rejectMixedBackdropToneArity(anchorX, thin, thick) {
|
|
1162
|
+
for (const [name, row] of [
|
|
1163
|
+
["backdropToneAnchorX", anchorX],
|
|
1164
|
+
["backdropToneResponseThin", thin],
|
|
1165
|
+
["backdropToneResponseThick", thick]
|
|
1166
|
+
]) {
|
|
1167
|
+
if (Array.isArray(row) && (row.length === 3 || row.length === 4))
|
|
1168
|
+
continue;
|
|
1169
|
+
throw new Error(`The backdrop tone response's ${name} is ${JSON.stringify(row) ?? String(row)}, which is not an array of three or four knots. The curve has exactly those two forms, and anything else is read as a different one by each tier: the CPU curve and the CSS mirror take the four-knot branch for any length but three, where the shader takes the three-knot branch for any length but four.`);
|
|
1170
|
+
}
|
|
1171
|
+
if (anchorX.length === thin.length && thin.length === thick.length)
|
|
1172
|
+
return;
|
|
1173
|
+
throw new Error(`The backdrop tone response's three rows resolved to different knot counts \u2014 backdropToneAnchorX ${anchorX.length}, backdropToneResponseThin ${thin.length}, backdropToneResponseThick ${thick.length}. They are one curve's knots and that curve's levels at its two thickness ends, and the shader reads the knot count off the anchors alone, so a mixed triplet renders as NaN on the CPU curve and as a fabricated segment on the GPU. A patch moving the response to a new knot count has to name all three rows.`);
|
|
1174
|
+
}
|
|
1155
1175
|
function withMaterialOverrides(base, patch) {
|
|
1156
1176
|
rejectRetiredOuterShadowLeaves(patch.outerShadow);
|
|
1177
|
+
const backdropToneAbscissa = patch.backdropToneAbscissa === void 0 ? base.backdropToneAbscissa : patch.backdropToneAbscissa;
|
|
1178
|
+
if (backdropToneAbscissa !== void 0 && backdropToneAbscissa !== "source" && (backdropToneAbscissa === null || typeof backdropToneAbscissa !== "object" || backdropToneAbscissa.kind !== "silhouette" || Object.keys(backdropToneAbscissa).some((key) => key !== "kind"))) {
|
|
1179
|
+
throw new TypeError("backdropToneAbscissa must be source or { kind: silhouette }");
|
|
1180
|
+
}
|
|
1157
1181
|
const optics = {};
|
|
1158
1182
|
for (const variant of MATERIAL_VARIANTS) {
|
|
1159
1183
|
optics[variant] = { ...base.optics[variant], ...patch.optics?.[variant] };
|
|
@@ -1162,6 +1186,10 @@ function withMaterialOverrides(base, patch) {
|
|
|
1162
1186
|
for (const rung of REFRACTION_LADDER) {
|
|
1163
1187
|
refractionScale[rung] = patch.refractionScale?.[rung] ?? base.refractionScale[rung];
|
|
1164
1188
|
}
|
|
1189
|
+
const backdropToneAnchorX = patch.backdropToneAnchorX ?? base.backdropToneAnchorX;
|
|
1190
|
+
const backdropToneResponseThin = patch.backdropToneResponseThin ?? base.backdropToneResponseThin;
|
|
1191
|
+
const backdropToneResponseThick = patch.backdropToneResponseThick ?? base.backdropToneResponseThick;
|
|
1192
|
+
rejectMixedBackdropToneArity(backdropToneAnchorX, backdropToneResponseThin, backdropToneResponseThick);
|
|
1165
1193
|
return {
|
|
1166
1194
|
optics,
|
|
1167
1195
|
adaptiveTintDark: patch.adaptiveTintDark ?? base.adaptiveTintDark,
|
|
@@ -1207,6 +1235,10 @@ function withMaterialOverrides(base, patch) {
|
|
|
1207
1235
|
lensOvalizationSpanMax: patch.lensOvalizationSpanMax ?? base.lensOvalizationSpanMax,
|
|
1208
1236
|
reducedTransparencyFrost: patch.reducedTransparencyFrost ?? base.reducedTransparencyFrost,
|
|
1209
1237
|
increasedOcclusionLift: patch.increasedOcclusionLift ?? base.increasedOcclusionLift,
|
|
1238
|
+
...(patch.increasedOcclusionLiftByPolicy ?? base.increasedOcclusionLiftByPolicy) === void 0 ? {} : { increasedOcclusionLiftByPolicy: {
|
|
1239
|
+
...base.increasedOcclusionLiftByPolicy,
|
|
1240
|
+
...patch.increasedOcclusionLiftByPolicy
|
|
1241
|
+
} },
|
|
1210
1242
|
strongBorderRim: { ...base.strongBorderRim, ...patch.strongBorderRim },
|
|
1211
1243
|
reducedTintAdaptation: patch.reducedTintAdaptation ?? base.reducedTintAdaptation,
|
|
1212
1244
|
tintShadeDark: patch.tintShadeDark ?? base.tintShadeDark,
|
|
@@ -1227,9 +1259,10 @@ function withMaterialOverrides(base, patch) {
|
|
|
1227
1259
|
rimCollapsed: patch.rimCollapsed ?? base.rimCollapsed,
|
|
1228
1260
|
rimCollapsedTinted: patch.rimCollapsedTinted ?? base.rimCollapsedTinted,
|
|
1229
1261
|
rimTintChroma: patch.rimTintChroma ?? base.rimTintChroma,
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1262
|
+
...backdropToneAbscissa === void 0 ? {} : { backdropToneAbscissa },
|
|
1263
|
+
backdropToneAnchorX,
|
|
1264
|
+
backdropToneResponseThin,
|
|
1265
|
+
backdropToneResponseThick,
|
|
1233
1266
|
backdropToneResponseStrength: patch.backdropToneResponseStrength ?? base.backdropToneResponseStrength,
|
|
1234
1267
|
outerShadow: { ...base.outerShadow, ...patch.outerShadow },
|
|
1235
1268
|
lightDirection: patch.lightDirection ?? base.lightDirection,
|
|
@@ -1249,7 +1282,7 @@ function opticsUnderPolicy(optics, policy, profile = DEFAULT_MATERIAL_PROFILE) {
|
|
|
1249
1282
|
}
|
|
1250
1283
|
next = {
|
|
1251
1284
|
...next,
|
|
1252
|
-
tintAlpha: occlusionAlphaUnderPolicy(next.tintAlpha, policy.occlusion, profile
|
|
1285
|
+
tintAlpha: occlusionAlphaUnderPolicy(next.tintAlpha, policy.occlusion, occlusionLiftForPolicy(policy, profile))
|
|
1253
1286
|
};
|
|
1254
1287
|
if (policy.border === "strong") {
|
|
1255
1288
|
next = {
|
|
@@ -1373,19 +1406,45 @@ function backdropToneResponse(encodedInput, thickness, profile = DEFAULT_MATERIA
|
|
|
1373
1406
|
const xs = profile.backdropToneAnchorX;
|
|
1374
1407
|
const f = smoothstep(0, 1, thickness);
|
|
1375
1408
|
const ys = [0, 1, 2].map((i) => (profile.backdropToneResponseThin[i] ?? 0) + ((profile.backdropToneResponseThick[i] ?? 0) - (profile.backdropToneResponseThin[i] ?? 0)) * f);
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1409
|
+
let x, h, t, y0, y1, s0, s1;
|
|
1410
|
+
if (xs.length === 3) {
|
|
1411
|
+
x = Math.min(xs[2], Math.max(xs[0], encodedInput));
|
|
1412
|
+
const h0 = xs[1] - xs[0];
|
|
1413
|
+
const h1 = xs[2] - xs[1];
|
|
1414
|
+
const d0 = (ys[1] - ys[0]) / h0;
|
|
1415
|
+
const d1 = (ys[2] - ys[1]) / h1;
|
|
1416
|
+
const m1 = d0 * d1 <= 0 ? 0 : 2 * d0 * d1 / (d0 + d1);
|
|
1417
|
+
const seg = x <= xs[1] ? 0 : 1;
|
|
1418
|
+
h = seg === 0 ? h0 : h1;
|
|
1419
|
+
t = (x - (seg === 0 ? xs[0] : xs[1])) / h;
|
|
1420
|
+
y0 = seg === 0 ? ys[0] : ys[1];
|
|
1421
|
+
y1 = seg === 0 ? ys[1] : ys[2];
|
|
1422
|
+
s0 = seg === 0 ? d0 : m1;
|
|
1423
|
+
s1 = seg === 0 ? m1 : d1;
|
|
1424
|
+
} else {
|
|
1425
|
+
const ys4 = [
|
|
1426
|
+
ys[0],
|
|
1427
|
+
ys[1],
|
|
1428
|
+
ys[2],
|
|
1429
|
+
profile.backdropToneResponseThin[3] + (profile.backdropToneResponseThick[3] - profile.backdropToneResponseThin[3]) * f
|
|
1430
|
+
];
|
|
1431
|
+
x = Math.min(xs[3], Math.max(xs[0], encodedInput));
|
|
1432
|
+
const h0 = xs[1] - xs[0], h1 = xs[2] - xs[1], h2 = xs[3] - xs[2];
|
|
1433
|
+
const d0 = (ys4[1] - ys4[0]) / h0;
|
|
1434
|
+
const d1 = (ys4[2] - ys4[1]) / h1;
|
|
1435
|
+
const d2 = (ys4[3] - ys4[2]) / h2;
|
|
1436
|
+
const m1 = d0 * d1 <= 0 ? 0 : 2 * d0 * d1 / (d0 + d1);
|
|
1437
|
+
const m2 = d1 * d2 <= 0 ? 0 : 2 * d1 * d2 / (d1 + d2);
|
|
1438
|
+
const seg = x <= xs[1] ? 0 : x <= xs[2] ? 1 : 2;
|
|
1439
|
+
const hs = [h0, h1, h2];
|
|
1440
|
+
const slopes = [d0, m1, m2, d2];
|
|
1441
|
+
h = hs[seg];
|
|
1442
|
+
t = (x - xs[seg]) / h;
|
|
1443
|
+
y0 = ys4[seg];
|
|
1444
|
+
y1 = ys4[seg + 1];
|
|
1445
|
+
s0 = slopes[seg];
|
|
1446
|
+
s1 = slopes[seg + 1];
|
|
1447
|
+
}
|
|
1389
1448
|
return y0 * (1 + 2 * t) * (1 - t) * (1 - t) + s0 * h * t * (1 - t) * (1 - t) + y1 * t * t * (3 - 2 * t) + s1 * h * t * t * (t - 1) + levelFar;
|
|
1390
1449
|
}
|
|
1391
1450
|
function backdropToneSolveWeight(encodedInput, profile = DEFAULT_MATERIAL_PROFILE) {
|
|
@@ -3386,7 +3445,7 @@ var WGSL_HIGHLIGHT_PASS = `struct HighlightUniforms {
|
|
|
3386
3445
|
glow : vec4f,
|
|
3387
3446
|
/// highlight colour, linear light (xyz), unused (w)
|
|
3388
3447
|
colour : vec4f,
|
|
3389
|
-
/// fieldSize.xy, fieldUpsampled (z),
|
|
3448
|
+
/// fieldSize.xy, fieldUpsampled (z), local tone field present (w, W28)
|
|
3390
3449
|
flags : vec4f,
|
|
3391
3450
|
/// backdrop tone adaptation (W7), exactly as the optics pass takes it:
|
|
3392
3451
|
/// backdropToneLow, backdropToneHigh, the size bias already divided by the
|
|
@@ -3416,6 +3475,7 @@ var WGSL_HIGHLIGHT_PASS = `struct HighlightUniforms {
|
|
|
3416
3475
|
/// bound here for the same reason the optics pass binds it: a highlight is the
|
|
3417
3476
|
/// material catching light, and a material that is not there catches none.
|
|
3418
3477
|
@group(0) @binding(4) var presenceTexture : texture_2d<f32>;
|
|
3478
|
+
@group(0) @binding(5) var localToneTexture : texture_2d<f32>;
|
|
3419
3479
|
|
|
3420
3480
|
const TAU = 6.283185307179586;
|
|
3421
3481
|
|
|
@@ -3445,6 +3505,16 @@ fn fs_highlight(in : FullscreenOut) -> @location(0) vec4f {
|
|
|
3445
3505
|
aux = textureLoad(auxTexture, texel, 0);
|
|
3446
3506
|
presence = textureLoad(presenceTexture, texel, 0);
|
|
3447
3507
|
}
|
|
3508
|
+
var toneStrength = hu.toneAdapt.w;
|
|
3509
|
+
var toneLevel = hu.toneLevel.x;
|
|
3510
|
+
if (hu.flags.w > 0.5) {
|
|
3511
|
+
if (hu.flags.z > 0.5) {
|
|
3512
|
+
toneLevel = textureSampleLevel(localToneTexture, fieldSampler, fieldUv, 0.0).w;
|
|
3513
|
+
} else {
|
|
3514
|
+
toneLevel = textureLoad(localToneTexture, vec2i(fieldUv * hu.flags.xy), 0).w;
|
|
3515
|
+
}
|
|
3516
|
+
}
|
|
3517
|
+
if (toneLevel < 0.0) { toneStrength = 0.0; }
|
|
3448
3518
|
let mat = clamp(presence.x, 0.0, 1.0);
|
|
3449
3519
|
let d = field.x;
|
|
3450
3520
|
let normal = field.yz;
|
|
@@ -3493,14 +3563,14 @@ fn fs_highlight(in : FullscreenOut) -> @location(0) vec4f {
|
|
|
3493
3563
|
);
|
|
3494
3564
|
let sizeK = clamp(spanT * spanT * (3.0 - 2.0 * spanT) * hu.toneLevel.w, 0.0, 1.0);
|
|
3495
3565
|
var toneAdapt = 0.0;
|
|
3496
|
-
if (
|
|
3497
|
-
let toneX =
|
|
3566
|
+
if (toneStrength > 0.0) {
|
|
3567
|
+
let toneX = toneLevel + hu.toneAdapt.z * sizeK;
|
|
3498
3568
|
let toneT = clamp(
|
|
3499
3569
|
(toneX - hu.toneAdapt.x) / max(hu.toneAdapt.y - hu.toneAdapt.x, 1e-6),
|
|
3500
3570
|
0.0,
|
|
3501
3571
|
1.0,
|
|
3502
3572
|
);
|
|
3503
|
-
toneAdapt = clamp(
|
|
3573
|
+
toneAdapt = clamp(toneStrength, 0.0, 1.0) * (1.0 - toneT * toneT * (3.0 - 2.0 * toneT));
|
|
3504
3574
|
}
|
|
3505
3575
|
|
|
3506
3576
|
/*
|
|
@@ -3660,6 +3730,12 @@ var WGSL_OPTICS_PASS = `struct OpticsUniforms {
|
|
|
3660
3730
|
/// (z) and (w) carry its reference level and minimum tint contrast.
|
|
3661
3731
|
/// Texture draws keep those lanes zero, so their input bytes do not move.
|
|
3662
3732
|
heavyTap : vec4f,
|
|
3733
|
+
/// Decision Log 18's optional fourth response knot: encoded x, thin y,
|
|
3734
|
+
/// thick z, and a length gate w. Appended so every three-knot field keeps its
|
|
3735
|
+
/// byte offset and its original shader branch.
|
|
3736
|
+
toneExtra : vec4f,
|
|
3737
|
+
/// W28: whether the per-surface reference field is present (x).
|
|
3738
|
+
localTone : vec4f,
|
|
3663
3739
|
};
|
|
3664
3740
|
|
|
3665
3741
|
@group(0) @binding(0) var<uniform> ou : OpticsUniforms;
|
|
@@ -3682,6 +3758,7 @@ var WGSL_OPTICS_PASS = `struct OpticsUniforms {
|
|
|
3682
3758
|
/// channel, unioned in the field pass like every other per-surface scalar. One
|
|
3683
3759
|
/// channel, in the field pass's fourth target \u2014 see 'wgsl/field.ts'.
|
|
3684
3760
|
@group(0) @binding(9) var presenceTexture : texture_2d<f32>;
|
|
3761
|
+
@group(0) @binding(10) var localToneTexture : texture_2d<f32>;
|
|
3685
3762
|
|
|
3686
3763
|
/// One encoded sRGB channel from a linear one \u2014 the space the backdrop tone
|
|
3687
3764
|
/// response's anchors live in (W9). Mirrors material.ts's 'linearToSrgbChannel'.
|
|
@@ -3698,6 +3775,35 @@ fn tone_response(x : f32, sizeK : f32, levelFar : f32) -> f32 {
|
|
|
3698
3775
|
let f = sizeK * sizeK * (3.0 - 2.0 * sizeK);
|
|
3699
3776
|
let ys = mix(ou.toneRowThin.xyz, ou.toneRowThick.xyz, vec3f(f));
|
|
3700
3777
|
let xs = ou.toneAnchor.xyz;
|
|
3778
|
+
if (ou.toneExtra.w > 0.5) {
|
|
3779
|
+
let ys4 = vec4f(ys, mix(ou.toneExtra.y, ou.toneExtra.z, f));
|
|
3780
|
+
let xs4 = vec4f(xs, ou.toneExtra.x);
|
|
3781
|
+
let xc4 = clamp(x, xs4.x, xs4.w);
|
|
3782
|
+
let h0 = max(xs4.y - xs4.x, 1e-4);
|
|
3783
|
+
let h1 = max(xs4.z - xs4.y, 1e-4);
|
|
3784
|
+
let h2 = max(xs4.w - xs4.z, 1e-4);
|
|
3785
|
+
let d0 = (ys4.y - ys4.x) / h0;
|
|
3786
|
+
let d1 = (ys4.z - ys4.y) / h1;
|
|
3787
|
+
let d2 = (ys4.w - ys4.z) / h2;
|
|
3788
|
+
var m1 = 0.0; var m2 = 0.0;
|
|
3789
|
+
if (d0 * d1 > 0.0) { m1 = 2.0 * d0 * d1 / (d0 + d1); }
|
|
3790
|
+
if (d1 * d2 > 0.0) { m2 = 2.0 * d1 * d2 / (d1 + d2); }
|
|
3791
|
+
var h = h0; var t = (xc4 - xs4.x) / h0;
|
|
3792
|
+
var y0 = ys4.x; var y1 = ys4.y; var s0 = d0; var s1 = m1;
|
|
3793
|
+
if (xc4 > xs4.y) {
|
|
3794
|
+
h = h1; t = (xc4 - xs4.y) / h1;
|
|
3795
|
+
y0 = ys4.y; y1 = ys4.z; s0 = m1; s1 = m2;
|
|
3796
|
+
}
|
|
3797
|
+
if (xc4 > xs4.z) {
|
|
3798
|
+
h = h2; t = (xc4 - xs4.z) / h2;
|
|
3799
|
+
y0 = ys4.z; y1 = ys4.w; s0 = m2; s1 = d2;
|
|
3800
|
+
}
|
|
3801
|
+
return y0 * (1.0 + 2.0 * t) * (1.0 - t) * (1.0 - t)
|
|
3802
|
+
+ s0 * h * t * (1.0 - t) * (1.0 - t)
|
|
3803
|
+
+ y1 * t * t * (3.0 - 2.0 * t)
|
|
3804
|
+
+ s1 * h * t * t * (t - 1.0)
|
|
3805
|
+
+ levelFar;
|
|
3806
|
+
}
|
|
3701
3807
|
let xc = clamp(x, xs.x, xs.z);
|
|
3702
3808
|
let h0 = max(xs.y - xs.x, 1e-4);
|
|
3703
3809
|
let h1 = max(xs.z - xs.y, 1e-4);
|
|
@@ -3977,6 +4083,27 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
|
|
|
3977
4083
|
presence = textureLoad(presenceTexture, texel, 0);
|
|
3978
4084
|
}
|
|
3979
4085
|
|
|
4086
|
+
// The complete reference changes together: response, collapse colour and
|
|
4087
|
+
// compensation, nominal composition, opacity solve, and the tint/rim readouts.
|
|
4088
|
+
// The source branch retains the old uniforms and arithmetic exactly.
|
|
4089
|
+
var toneStrength = ou.toneAdapt.w;
|
|
4090
|
+
var toneColour = ou.toneColour;
|
|
4091
|
+
var toneLinearMean = ou.toneAnchor.w;
|
|
4092
|
+
if (ou.localTone.x > 0.5) {
|
|
4093
|
+
if (ou.flags.w > 0.5) {
|
|
4094
|
+
toneColour = textureSampleLevel(localToneTexture, fieldSampler, in.uv, 0.0);
|
|
4095
|
+
} else {
|
|
4096
|
+
toneColour = textureLoad(localToneTexture, vec2i(in.uv * ou.flags.yz), 0);
|
|
4097
|
+
}
|
|
4098
|
+
toneLinearMean = dot(toneColour.rgb, vec3f(0.2126, 0.7152, 0.0722));
|
|
4099
|
+
// A fully transparent mask measured no colour and has no local authority.
|
|
4100
|
+
if (toneColour.w < 0.0) {
|
|
4101
|
+
toneStrength = 0.0;
|
|
4102
|
+
toneColour = ou.toneColour;
|
|
4103
|
+
toneLinearMean = ou.toneAnchor.w;
|
|
4104
|
+
}
|
|
4105
|
+
}
|
|
4106
|
+
|
|
3980
4107
|
let d = field.x;
|
|
3981
4108
|
let normal = field.yz;
|
|
3982
4109
|
let coverage = field.w;
|
|
@@ -4338,13 +4465,13 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
|
|
|
4338
4465
|
*/
|
|
4339
4466
|
var toneAdapt = 0.0;
|
|
4340
4467
|
if (ou.toneAdapt.w > 0.0) {
|
|
4341
|
-
let toneX =
|
|
4468
|
+
let toneX = toneColour.w + ou.toneAdapt.z * sizeK;
|
|
4342
4469
|
let toneT = clamp(
|
|
4343
4470
|
(toneX - ou.toneAdapt.x) / max(ou.toneAdapt.y - ou.toneAdapt.x, 1e-6),
|
|
4344
4471
|
0.0,
|
|
4345
4472
|
1.0,
|
|
4346
4473
|
);
|
|
4347
|
-
toneAdapt = clamp(
|
|
4474
|
+
toneAdapt = clamp(toneStrength, 0.0, 1.0) * (1.0 - toneT * toneT * (3.0 - 2.0 * toneT));
|
|
4348
4475
|
}
|
|
4349
4476
|
/*
|
|
4350
4477
|
* Both the colour and the alpha move, together and not separately. What the
|
|
@@ -4384,9 +4511,9 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
|
|
|
4384
4511
|
*/
|
|
4385
4512
|
var solvedNeutral = neutral;
|
|
4386
4513
|
var solvedAlpha = sizedAlpha;
|
|
4387
|
-
if (
|
|
4514
|
+
if (toneStrength > 0.0 && ou.toneRowThin.w > 0.0 &&
|
|
4388
4515
|
sizedAlpha > 1e-3 && toneAdapt < 0.995) {
|
|
4389
|
-
let encodedInput = srgb_encode(
|
|
4516
|
+
let encodedInput = srgb_encode(toneColour.w);
|
|
4390
4517
|
let anchor = max(ou.toneAnchor.x, 1e-4);
|
|
4391
4518
|
let authority =
|
|
4392
4519
|
smoothstep(anchor * 0.5, anchor, encodedInput) * clamp(ou.toneRowThin.w, 0.0, 1.0);
|
|
@@ -4394,10 +4521,10 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
|
|
|
4394
4521
|
let response = tone_response(encodedInput, sizeK, toneLevelFar);
|
|
4395
4522
|
// The collapse's mean pull is toward L(toneColour.rgb) \u2014 the LINEAR
|
|
4396
4523
|
// mean, which toneAnchor.w carries \u2014 not toward the encoded level.
|
|
4397
|
-
let preCollapse = (response - toneAdapt *
|
|
4524
|
+
let preCollapse = (response - toneAdapt * toneLinearMean) / (1.0 - toneAdapt);
|
|
4398
4525
|
let neutralLuma = dot(neutral, vec3f(0.2126, 0.7152, 0.0722));
|
|
4399
|
-
let nominal = (1.0 - sizedAlpha) *
|
|
4400
|
-
let shift = (preCollapse - nominal) / sizedAlpha * authority *
|
|
4526
|
+
let nominal = (1.0 - sizedAlpha) * toneLinearMean + sizedAlpha * neutralLuma;
|
|
4527
|
+
let shift = (preCollapse - nominal) / sizedAlpha * authority * toneStrength;
|
|
4401
4528
|
solvedNeutral = clamp(neutral + vec3f(shift), vec3f(0.0), vec3f(1.0));
|
|
4402
4529
|
/*
|
|
4403
4530
|
* The light attractor needs OPACITY. The light scheme's neutral is
|
|
@@ -4410,14 +4537,14 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
|
|
|
4410
4537
|
* collapse's own axis with its own fitted constants.
|
|
4411
4538
|
*/
|
|
4412
4539
|
let solvedLuma = dot(solvedNeutral, vec3f(0.2126, 0.7152, 0.0722));
|
|
4413
|
-
let achieved = (1.0 - sizedAlpha) *
|
|
4414
|
-
if (preCollapse > achieved + 1e-4 && solvedLuma >
|
|
4540
|
+
let achieved = (1.0 - sizedAlpha) * toneLinearMean + sizedAlpha * solvedLuma;
|
|
4541
|
+
if (preCollapse > achieved + 1e-4 && solvedLuma > toneLinearMean + 1e-3) {
|
|
4415
4542
|
let alphaTarget = clamp(
|
|
4416
|
-
(preCollapse -
|
|
4543
|
+
(preCollapse - toneLinearMean) / (solvedLuma - toneLinearMean),
|
|
4417
4544
|
sizedAlpha,
|
|
4418
4545
|
1.0,
|
|
4419
4546
|
);
|
|
4420
|
-
solvedAlpha = mix(sizedAlpha, alphaTarget, authority *
|
|
4547
|
+
solvedAlpha = mix(sizedAlpha, alphaTarget, authority * toneStrength);
|
|
4421
4548
|
}
|
|
4422
4549
|
}
|
|
4423
4550
|
}
|
|
@@ -4450,7 +4577,7 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
|
|
|
4450
4577
|
* lerped toward it would be a black surface rather than a transmitting one.
|
|
4451
4578
|
* There the CSS tier's own 'backdrop-filter' is what carries the transmission.
|
|
4452
4579
|
*/
|
|
4453
|
-
var toneTarget =
|
|
4580
|
+
var toneTarget = toneColour.rgb;
|
|
4454
4581
|
if (ou.flags.x > 0.5 || domMaterial) {
|
|
4455
4582
|
toneTarget = mix(toneTarget, backdrop, clamp(ou.toneRowThick.w, 0.0, 1.0));
|
|
4456
4583
|
}
|
|
@@ -4608,7 +4735,7 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
|
|
|
4608
4735
|
// the composite; as a layer it is the layer over the tone the host measured
|
|
4609
4736
|
// for the group \u2014 zero where nothing was measured, the same reference-level
|
|
4610
4737
|
// convention the CSS tier's 'materialLuminance' takes (within its 0.02).
|
|
4611
|
-
let u = bodyAlpha * dot(colour, vec3f(0.2126, 0.7152, 0.0722)) + (1.0 - bodyAlpha) *
|
|
4738
|
+
let u = bodyAlpha * dot(colour, vec3f(0.2126, 0.7152, 0.0722)) + (1.0 - bodyAlpha) * toneColour.w;
|
|
4612
4739
|
let grip = clamp(ou.seed.w, 0.0, 1.0) * clamp(ou.tone.z, 0.0, 1.0) *
|
|
4613
4740
|
(1.0 - toneAdapt * (1.0 - clamp(ou.rim.w, 0.0, 1.0)));
|
|
4614
4741
|
let shade = mix(1.0, clamp(mix(ou.tone.x, ou.tone.y, clamp(u, 0.0, 1.0)), 0.0, 1.0), grip);
|
|
@@ -4725,7 +4852,7 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
|
|
|
4725
4852
|
* author tint layer composites with sixty lines above.
|
|
4726
4853
|
*/
|
|
4727
4854
|
let rimLuma = materialAlpha * dot(materialColour, vec3f(0.2126, 0.7152, 0.0722))
|
|
4728
|
-
+ (1.0 - materialAlpha) *
|
|
4855
|
+
+ (1.0 - materialAlpha) * toneColour.w;
|
|
4729
4856
|
let rimAmplitude = ou.rim.y + ou.rimLaw.x * rimLuma;
|
|
4730
4857
|
let rimCollapsed = mix(ou.rimLaw.y, ou.rimLaw.z, tintK);
|
|
4731
4858
|
/*
|
|
@@ -4899,6 +5026,112 @@ fn vs_fullscreen(@builtin(vertex_index) index : u32) -> FullscreenOut {
|
|
|
4899
5026
|
}
|
|
4900
5027
|
`;
|
|
4901
5028
|
|
|
5029
|
+
// ../renderer-webgpu/dist/wgsl/silhouette-tone.js
|
|
5030
|
+
var silhouetteReductionModule = () => `${WGSL_PRELUDE}
|
|
5031
|
+
struct ToneShape { rect : vec4f, radius : vec4f };
|
|
5032
|
+
struct ToneStat { colour : vec4f, stats : vec4f };
|
|
5033
|
+
struct ToneUniforms { viewport : vec4f, fit : vec4f };
|
|
5034
|
+
@group(0) @binding(0) var<uniform> u : ToneUniforms;
|
|
5035
|
+
@group(0) @binding(1) var source : texture_2d<f32>;
|
|
5036
|
+
@group(0) @binding(3) var<storage, read> shapes : array<ToneShape>;
|
|
5037
|
+
@group(0) @binding(4) var<storage, read_write> tones : array<ToneStat>;
|
|
5038
|
+
var<workgroup> sums : array<vec4f, 256>;
|
|
5039
|
+
var<workgroup> counts : array<f32, 256>;
|
|
5040
|
+
var<workgroup> weights : array<f32, 256>;
|
|
5041
|
+
struct RawTone { value : vec4f, alpha : f32 };
|
|
5042
|
+
|
|
5043
|
+
fn raw_tone(texel : vec2i) -> RawTone {
|
|
5044
|
+
let dims = vec2i(textureDimensions(source));
|
|
5045
|
+
let rgba = textureLoad(source, clamp(texel, vec2i(0), dims - 1), 0);
|
|
5046
|
+
let rgb = rgba.rgb / max(rgba.a, 1e-6);
|
|
5047
|
+
return RawTone(vec4f(rgb, dot(linear_to_srgb(rgb), vec3f(0.2126, 0.7152, 0.0722))) * rgba.a, rgba.a);
|
|
5048
|
+
}
|
|
5049
|
+
|
|
5050
|
+
@compute @workgroup_size(256)
|
|
5051
|
+
fn reduce_tone(@builtin(local_invocation_index) lane : u32,
|
|
5052
|
+
@builtin(workgroup_id) group : vec3u) {
|
|
5053
|
+
let shape = shapes[group.x];
|
|
5054
|
+
// G0 clips to the capture raster. Clip BEFORE deriving the iteration area so
|
|
5055
|
+
// offscreen geometry cannot create unbounded work or overflow its u32 product.
|
|
5056
|
+
// In-bounds rectangles retain exactly the same lane assignment and arithmetic.
|
|
5057
|
+
let lo = vec2i(clamp(floor(shape.rect.xy), vec2f(0.0), u.viewport.xy));
|
|
5058
|
+
let hi = vec2i(clamp(ceil(shape.rect.xy + shape.rect.zw), vec2f(0.0), u.viewport.xy));
|
|
5059
|
+
let extent = vec2u(max(hi - lo, vec2i(0)));
|
|
5060
|
+
let half = shape.rect.zw * 0.5;
|
|
5061
|
+
let centre = shape.rect.xy + half;
|
|
5062
|
+
let radius = min(shape.radius.x, min(half.x, half.y));
|
|
5063
|
+
var sum = vec4f(0.0);
|
|
5064
|
+
var count = 0.0;
|
|
5065
|
+
var weight = 0.0;
|
|
5066
|
+
for (var i = lane; i < extent.x * extent.y; i += 256u) {
|
|
5067
|
+
let pixel = lo + vec2i(vec2u(i % extent.x, i / extent.x));
|
|
5068
|
+
let p = vec2f(pixel) + 0.5;
|
|
5069
|
+
let q = abs(p - centre) - half + radius;
|
|
5070
|
+
let distance = length(max(q, vec2f(0.0))) + min(max(q.x, q.y), 0.0) - radius;
|
|
5071
|
+
if (distance > 0.0) { continue; }
|
|
5072
|
+
let uv = (p / u.viewport.xy) * u.fit.xy + u.fit.zw;
|
|
5073
|
+
// Interpolate encoded and linear statistics separately. Encoding after
|
|
5074
|
+
// bilinear filtering would reintroduce a Jensen gap on a scaled source.
|
|
5075
|
+
let at = uv * vec2f(textureDimensions(source)) - 0.5;
|
|
5076
|
+
let base = vec2i(floor(at));
|
|
5077
|
+
let f = fract(at);
|
|
5078
|
+
let a = raw_tone(base);
|
|
5079
|
+
let b = raw_tone(base + vec2i(1, 0));
|
|
5080
|
+
let c = raw_tone(base + vec2i(0, 1));
|
|
5081
|
+
let d = raw_tone(base + vec2i(1, 1));
|
|
5082
|
+
sum += mix(mix(a.value, b.value, f.x), mix(c.value, d.value, f.x), f.y);
|
|
5083
|
+
weight += mix(mix(a.alpha, b.alpha, f.x), mix(c.alpha, d.alpha, f.x), f.y);
|
|
5084
|
+
count += 1.0;
|
|
5085
|
+
}
|
|
5086
|
+
sums[lane] = sum;
|
|
5087
|
+
counts[lane] = count;
|
|
5088
|
+
weights[lane] = weight;
|
|
5089
|
+
workgroupBarrier();
|
|
5090
|
+
for (var stride = 128u; stride > 0u; stride /= 2u) {
|
|
5091
|
+
if (lane < stride) {
|
|
5092
|
+
sums[lane] += sums[lane + stride];
|
|
5093
|
+
counts[lane] += counts[lane + stride];
|
|
5094
|
+
weights[lane] += weights[lane + stride];
|
|
5095
|
+
}
|
|
5096
|
+
workgroupBarrier();
|
|
5097
|
+
}
|
|
5098
|
+
if (lane == 0u) {
|
|
5099
|
+
let mean = sums[0] / max(weights[0], 1e-6);
|
|
5100
|
+
let level = srgb_to_linear(vec3f(mean.w)).x;
|
|
5101
|
+
tones[group.x].colour = vec4f(mean.rgb, level);
|
|
5102
|
+
tones[group.x].stats = vec4f(mean.w, luminance(mean.rgb), counts[0], weights[0]);
|
|
5103
|
+
}
|
|
5104
|
+
}
|
|
5105
|
+
`;
|
|
5106
|
+
var silhouetteFieldModule = (family) => `${WGSL_PRELUDE}
|
|
5107
|
+
${WGSL_FIELD_KERNELS}
|
|
5108
|
+
struct FieldUniforms { screen : vec4f, unionP : vec4f, counts : vec4u, fallback : vec4f };
|
|
5109
|
+
struct ToneStat { colour : vec4f, stats : vec4f };
|
|
5110
|
+
@group(0) @binding(0) var<uniform> u : FieldUniforms;
|
|
5111
|
+
@group(0) @binding(1) var<storage, read> instances : array<Instance>;
|
|
5112
|
+
@group(0) @binding(2) var<storage, read> tones : array<ToneStat>;
|
|
5113
|
+
fn member_distance(i : u32, p : vec2f) -> f32 {
|
|
5114
|
+
let s = instances[i];
|
|
5115
|
+
return ${family === "rsupn" ? "sd_rsupn_grad" : "sd_rsup_grad"}(
|
|
5116
|
+
p - s.centre, s.half, s.re, vec4f(s.k0, s.k1, s.k2, s.k3), s.k4).d + s.inset;
|
|
5117
|
+
}
|
|
5118
|
+
fn member_tone(i : u32) -> vec4f {
|
|
5119
|
+
return select(u.fallback, tones[i].colour, tones[i].stats.w > 0.0);
|
|
5120
|
+
}
|
|
5121
|
+
@fragment
|
|
5122
|
+
fn fs_tone(in : FullscreenOut) -> @location(0) vec4f {
|
|
5123
|
+
let p = in.uv * u.screen.xy * u.screen.z;
|
|
5124
|
+
var distance = member_distance(0u, p);
|
|
5125
|
+
var colour = member_tone(0u);
|
|
5126
|
+
for (var i = 1u; i < u.counts.x; i += 1u) {
|
|
5127
|
+
let blend = union_blend(distance, member_distance(i, p), u.unionP.xyz);
|
|
5128
|
+
distance = blend.x;
|
|
5129
|
+
colour = mix(member_tone(i), colour, blend.y);
|
|
5130
|
+
}
|
|
5131
|
+
return colour;
|
|
5132
|
+
}
|
|
5133
|
+
`;
|
|
5134
|
+
|
|
4902
5135
|
// ../renderer-webgpu/dist/wgsl/index.js
|
|
4903
5136
|
var withPrelude = (pass) => `${WGSL_PRELUDE}
|
|
4904
5137
|
${pass}
|
|
@@ -4919,6 +5152,9 @@ function allShaderSource() {
|
|
|
4919
5152
|
importPassSource("external"),
|
|
4920
5153
|
WGSL_DOWNSAMPLE_PASS,
|
|
4921
5154
|
WGSL_ANALYSIS_PASS,
|
|
5155
|
+
silhouetteReductionModule(),
|
|
5156
|
+
silhouetteFieldModule("rsupn"),
|
|
5157
|
+
silhouetteFieldModule("rsup"),
|
|
4922
5158
|
WGSL_OPTICS_PASS,
|
|
4923
5159
|
WGSL_HIGHLIGHT_PASS
|
|
4924
5160
|
].join("\n\n");
|
|
@@ -5123,7 +5359,7 @@ function createPassRunner(context) {
|
|
|
5123
5359
|
};
|
|
5124
5360
|
},
|
|
5125
5361
|
opticsPass(encoder, args) {
|
|
5126
|
-
const slot = uniformSlot(`optics:${args.resourceId}`,
|
|
5362
|
+
const slot = uniformSlot(`optics:${args.resourceId}`, 120);
|
|
5127
5363
|
const d = slot.data;
|
|
5128
5364
|
d[0] = args.viewportDevice[0];
|
|
5129
5365
|
d[1] = args.viewportDevice[1];
|
|
@@ -5237,6 +5473,11 @@ function createPassRunner(context) {
|
|
|
5237
5473
|
d[109] = args.domMaterial?.mode ?? 0;
|
|
5238
5474
|
d[110] = args.domMaterial?.referenceBackdropLuminance ?? 0;
|
|
5239
5475
|
d[111] = args.domMaterial?.minimumTintContrast ?? 0;
|
|
5476
|
+
d[112] = args.backdropToneAnchorX[3] ?? args.backdropToneAnchorX[2];
|
|
5477
|
+
d[113] = args.backdropToneResponseThin[3] ?? args.backdropToneResponseThin[2];
|
|
5478
|
+
d[114] = args.backdropToneResponseThick[3] ?? args.backdropToneResponseThick[2];
|
|
5479
|
+
d[115] = args.backdropToneAnchorX.length === 4 ? 1 : 0;
|
|
5480
|
+
d[116] = args.localTone === void 0 ? 0 : 1;
|
|
5240
5481
|
slot.write();
|
|
5241
5482
|
const chain = args.backdrop?.chain ?? placeholderView;
|
|
5242
5483
|
const body = args.backdrop?.body ?? placeholderView;
|
|
@@ -5263,7 +5504,8 @@ function createPassRunner(context) {
|
|
|
5263
5504
|
{ binding: 6, resource: context.flatSampler },
|
|
5264
5505
|
{ binding: 7, resource: args.fields.aux2.createView() },
|
|
5265
5506
|
{ binding: 8, resource: heavy },
|
|
5266
|
-
{ binding: 9, resource: args.fields.presence.createView() }
|
|
5507
|
+
{ binding: 9, resource: args.fields.presence.createView() },
|
|
5508
|
+
{ binding: 10, resource: args.localTone ?? placeholderView }
|
|
5267
5509
|
]
|
|
5268
5510
|
}));
|
|
5269
5511
|
pass.draw(3);
|
|
@@ -5291,7 +5533,7 @@ function createPassRunner(context) {
|
|
|
5291
5533
|
d[16] = args.fields.width;
|
|
5292
5534
|
d[17] = args.fields.height;
|
|
5293
5535
|
d[18] = args.fields.upsampled ? 1 : 0;
|
|
5294
|
-
d[19] = 0;
|
|
5536
|
+
d[19] = args.localTone === void 0 ? 0 : 1;
|
|
5295
5537
|
d[20] = args.backdropTone[0];
|
|
5296
5538
|
d[21] = Math.max(args.backdropTone[1], args.backdropTone[0] + 1e-4);
|
|
5297
5539
|
d[22] = args.backdropTone[2];
|
|
@@ -5321,7 +5563,8 @@ function createPassRunner(context) {
|
|
|
5321
5563
|
{ binding: 1, resource: args.fields.field.createView() },
|
|
5322
5564
|
{ binding: 2, resource: args.fields.aux.createView() },
|
|
5323
5565
|
{ binding: 3, resource: context.flatSampler },
|
|
5324
|
-
{ binding: 4, resource: args.fields.presence.createView() }
|
|
5566
|
+
{ binding: 4, resource: args.fields.presence.createView() },
|
|
5567
|
+
{ binding: 5, resource: args.localTone ?? placeholderView }
|
|
5325
5568
|
]
|
|
5326
5569
|
}));
|
|
5327
5570
|
pass.draw(3);
|
|
@@ -5977,6 +6220,263 @@ function createPyramidStore(context) {
|
|
|
5977
6220
|
}
|
|
5978
6221
|
var ANALYSIS_DISPATCH = { workgroupSize: ANALYSIS_WORKGROUP, workgroups: 1 };
|
|
5979
6222
|
|
|
6223
|
+
// ../renderer-webgpu/dist/silhouette-tone.js
|
|
6224
|
+
function packToneShapes(surfaces, dpr) {
|
|
6225
|
+
const data = new Float32Array(surfaces.length * 8);
|
|
6226
|
+
surfaces.forEach((surface, i) => {
|
|
6227
|
+
const [w, h] = surface.shape.channels.size;
|
|
6228
|
+
data.set([
|
|
6229
|
+
(surface.centre[0] - w / 2) * dpr,
|
|
6230
|
+
(surface.centre[1] - h / 2) * dpr,
|
|
6231
|
+
w * dpr,
|
|
6232
|
+
h * dpr,
|
|
6233
|
+
surface.shape.corner.radius * dpr,
|
|
6234
|
+
0,
|
|
6235
|
+
0,
|
|
6236
|
+
0
|
|
6237
|
+
], i * 8);
|
|
6238
|
+
});
|
|
6239
|
+
return data;
|
|
6240
|
+
}
|
|
6241
|
+
function toneReadingsFromBuffer(values, metadata, fallback) {
|
|
6242
|
+
return metadata.flatMap((meta, i) => {
|
|
6243
|
+
if (values[i * 8 + 7] > 0)
|
|
6244
|
+
return [{
|
|
6245
|
+
...meta,
|
|
6246
|
+
kind: "silhouette",
|
|
6247
|
+
level: 0,
|
|
6248
|
+
color: [values[i * 8], values[i * 8 + 1], values[i * 8 + 2]],
|
|
6249
|
+
luminance: values[i * 8 + 3],
|
|
6250
|
+
encodedLuminance: values[i * 8 + 4],
|
|
6251
|
+
linearLuminance: values[i * 8 + 5],
|
|
6252
|
+
sampleCount: values[i * 8 + 6]
|
|
6253
|
+
}];
|
|
6254
|
+
if (fallback === void 0 || fallback[3] < 0)
|
|
6255
|
+
return [];
|
|
6256
|
+
const [r, g, b, luminance] = fallback;
|
|
6257
|
+
return [{
|
|
6258
|
+
surfaceId: meta.surfaceId,
|
|
6259
|
+
kind: "source",
|
|
6260
|
+
color: [r, g, b],
|
|
6261
|
+
luminance,
|
|
6262
|
+
encodedLuminance: linearToSrgbChannel(luminance),
|
|
6263
|
+
// The local optics field derives this channel from RGB, including fallback.
|
|
6264
|
+
linearLuminance: relativeLuminance([r, g, b]),
|
|
6265
|
+
sampleCount: 0,
|
|
6266
|
+
level: 0,
|
|
6267
|
+
sourceWidth: 0,
|
|
6268
|
+
sourceHeight: 0,
|
|
6269
|
+
sampledWidth: 0,
|
|
6270
|
+
sampledHeight: 0
|
|
6271
|
+
}];
|
|
6272
|
+
});
|
|
6273
|
+
}
|
|
6274
|
+
function createSilhouetteTonePass(context) {
|
|
6275
|
+
const { device, cache, pool } = context;
|
|
6276
|
+
const createEntry = (count, groupId) => ({
|
|
6277
|
+
groupId,
|
|
6278
|
+
count,
|
|
6279
|
+
shapes: createStorageSlot(device, count * 32, "vitrea:tone-shapes"),
|
|
6280
|
+
instances: createStorageSlot(device, count * 72, "vitrea:tone-instances"),
|
|
6281
|
+
uniform: createUniformSlot(device, 8, "vitrea:tone-uniform"),
|
|
6282
|
+
fieldUniform: createUniformSlot(device, 16, "vitrea:tone-field-uniform"),
|
|
6283
|
+
tones: device.createBuffer({
|
|
6284
|
+
size: count * 32,
|
|
6285
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
|
|
6286
|
+
}),
|
|
6287
|
+
readback: device.createBuffer({
|
|
6288
|
+
size: count * 32,
|
|
6289
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
6290
|
+
}),
|
|
6291
|
+
reduced: void 0,
|
|
6292
|
+
encodedReduction: false,
|
|
6293
|
+
observation: void 0,
|
|
6294
|
+
fallback: void 0,
|
|
6295
|
+
encodedFallback: void 0,
|
|
6296
|
+
queued: void 0,
|
|
6297
|
+
pending: void 0
|
|
6298
|
+
});
|
|
6299
|
+
const entries = /* @__PURE__ */ new Map();
|
|
6300
|
+
const destroyEntry = (entry) => {
|
|
6301
|
+
entry.shapes.destroy();
|
|
6302
|
+
entry.instances.destroy();
|
|
6303
|
+
entry.uniform.buffer.destroy();
|
|
6304
|
+
entry.fieldUniform.buffer.destroy();
|
|
6305
|
+
entry.tones.destroy();
|
|
6306
|
+
entry.readback.destroy();
|
|
6307
|
+
};
|
|
6308
|
+
const forget = (resourceId) => {
|
|
6309
|
+
const entry = entries.get(resourceId);
|
|
6310
|
+
if (entry !== void 0)
|
|
6311
|
+
destroyEntry(entry);
|
|
6312
|
+
entries.delete(resourceId);
|
|
6313
|
+
pool.release(`tone-field:${resourceId}`);
|
|
6314
|
+
};
|
|
6315
|
+
return {
|
|
6316
|
+
draw(encoder, args) {
|
|
6317
|
+
const { field, pyramid, fields } = args;
|
|
6318
|
+
let entry = entries.get(field.resourceId);
|
|
6319
|
+
if (entry !== void 0 && entry.count !== field.instanceCount) {
|
|
6320
|
+
forget(field.resourceId);
|
|
6321
|
+
entry = void 0;
|
|
6322
|
+
}
|
|
6323
|
+
if (entry === void 0) {
|
|
6324
|
+
entry = createEntry(field.instanceCount, args.groupId);
|
|
6325
|
+
entries.set(field.resourceId, entry);
|
|
6326
|
+
}
|
|
6327
|
+
const shapeData = packToneShapes(args.surfaces, 1 / field.cssPerDevice);
|
|
6328
|
+
const geometryKey = JSON.stringify([
|
|
6329
|
+
pyramid.sourceId,
|
|
6330
|
+
pyramid.sizeEpoch,
|
|
6331
|
+
pyramid.sourceWidth,
|
|
6332
|
+
pyramid.sourceHeight,
|
|
6333
|
+
pyramid.plan.width,
|
|
6334
|
+
pyramid.plan.height,
|
|
6335
|
+
...shapeData,
|
|
6336
|
+
...args.viewportDevice,
|
|
6337
|
+
...args.fit,
|
|
6338
|
+
...args.surfaces.map((surface) => surface.nodeId)
|
|
6339
|
+
]);
|
|
6340
|
+
const previous = entry.reduced;
|
|
6341
|
+
if (previous === void 0 || previous.chain !== pyramid.chain || previous.geometryKey !== geometryKey || previous.builtEpoch !== pyramid.builtEpoch && (!args.liveSource || readbackDue(previous.timeMs, args.timeMs, args.cadenceHz))) {
|
|
6342
|
+
entry.reduced = {
|
|
6343
|
+
chain: pyramid.chain,
|
|
6344
|
+
geometryKey,
|
|
6345
|
+
builtEpoch: pyramid.builtEpoch,
|
|
6346
|
+
timeMs: args.timeMs,
|
|
6347
|
+
metadata: args.surfaces.map((surface) => ({
|
|
6348
|
+
surfaceId: surface.nodeId,
|
|
6349
|
+
sourceWidth: pyramid.sourceWidth,
|
|
6350
|
+
sourceHeight: pyramid.sourceHeight,
|
|
6351
|
+
sampledWidth: pyramid.plan.width,
|
|
6352
|
+
sampledHeight: pyramid.plan.height
|
|
6353
|
+
}))
|
|
6354
|
+
};
|
|
6355
|
+
entry.encodedReduction = true;
|
|
6356
|
+
entry.shapes.write(shapeData, shapeData.length);
|
|
6357
|
+
entry.uniform.data.set([...args.viewportDevice, 0, 0, ...args.fit]);
|
|
6358
|
+
entry.uniform.write();
|
|
6359
|
+
const pipeline = cache.computePipeline("silhouette-reduction", () => ({
|
|
6360
|
+
layout: "auto",
|
|
6361
|
+
compute: {
|
|
6362
|
+
module: cache.module("silhouette-reduction", silhouetteReductionModule),
|
|
6363
|
+
entryPoint: "reduce_tone"
|
|
6364
|
+
}
|
|
6365
|
+
}));
|
|
6366
|
+
const pass = encoder.beginComputePass({ label: "vitrea:silhouette-reduction" });
|
|
6367
|
+
pass.setPipeline(pipeline);
|
|
6368
|
+
pass.setBindGroup(0, device.createBindGroup({
|
|
6369
|
+
layout: pipeline.getBindGroupLayout(0),
|
|
6370
|
+
entries: [
|
|
6371
|
+
{ binding: 0, resource: { buffer: entry.uniform.buffer } },
|
|
6372
|
+
{ binding: 1, resource: pyramid.chain.createView({ baseMipLevel: 0, mipLevelCount: 1 }) },
|
|
6373
|
+
{ binding: 3, resource: { buffer: entry.shapes.buffer } },
|
|
6374
|
+
{ binding: 4, resource: { buffer: entry.tones } }
|
|
6375
|
+
]
|
|
6376
|
+
}));
|
|
6377
|
+
pass.dispatchWorkgroups(field.instanceCount);
|
|
6378
|
+
pass.end();
|
|
6379
|
+
}
|
|
6380
|
+
entry.instances.write(field.instances, field.instanceCount * 18);
|
|
6381
|
+
entry.encodedFallback = args.fallbackTone;
|
|
6382
|
+
if (entry.queued === void 0 && entry.pending === void 0 && entry.observation?.reduction !== entry.reduced) {
|
|
6383
|
+
encoder.copyBufferToBuffer(entry.tones, 0, entry.readback, 0, entry.count * 32);
|
|
6384
|
+
entry.queued = entry.reduced;
|
|
6385
|
+
}
|
|
6386
|
+
const texture = pool.acquire(`tone-field:${field.resourceId}`, {
|
|
6387
|
+
width: fields.width,
|
|
6388
|
+
height: fields.height,
|
|
6389
|
+
format: "rgba16float",
|
|
6390
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
|
|
6391
|
+
});
|
|
6392
|
+
const u = entry.fieldUniform;
|
|
6393
|
+
u.data.set([
|
|
6394
|
+
field.rectDevice.width,
|
|
6395
|
+
field.rectDevice.height,
|
|
6396
|
+
field.cssPerDevice,
|
|
6397
|
+
0,
|
|
6398
|
+
field.union.neckWidth,
|
|
6399
|
+
field.union.maxBulge,
|
|
6400
|
+
field.union.separationThreshold,
|
|
6401
|
+
0
|
|
6402
|
+
]);
|
|
6403
|
+
new Uint32Array(u.data.buffer)[8] = field.instanceCount;
|
|
6404
|
+
u.data.set(args.fallbackTone, 12);
|
|
6405
|
+
u.write();
|
|
6406
|
+
const fieldPipeline = cache.renderPipeline(`silhouette-field:${field.family}`, () => ({
|
|
6407
|
+
layout: "auto",
|
|
6408
|
+
vertex: { module: cache.module(`silhouette-field:${field.family}`, () => silhouetteFieldModule(field.family)), entryPoint: "vs_fullscreen" },
|
|
6409
|
+
fragment: {
|
|
6410
|
+
module: cache.module(`silhouette-field:${field.family}`, () => silhouetteFieldModule(field.family)),
|
|
6411
|
+
entryPoint: "fs_tone",
|
|
6412
|
+
targets: [{ format: "rgba16float" }]
|
|
6413
|
+
},
|
|
6414
|
+
primitive: { topology: "triangle-list" }
|
|
6415
|
+
}));
|
|
6416
|
+
const view = texture.createView();
|
|
6417
|
+
const fieldPass = encoder.beginRenderPass({
|
|
6418
|
+
label: "vitrea:silhouette-field",
|
|
6419
|
+
colorAttachments: [{ view, loadOp: "clear", storeOp: "store" }]
|
|
6420
|
+
});
|
|
6421
|
+
fieldPass.setPipeline(fieldPipeline);
|
|
6422
|
+
fieldPass.setBindGroup(0, device.createBindGroup({
|
|
6423
|
+
layout: fieldPipeline.getBindGroupLayout(0),
|
|
6424
|
+
entries: [
|
|
6425
|
+
{ binding: 0, resource: { buffer: u.buffer } },
|
|
6426
|
+
{ binding: 1, resource: { buffer: entry.instances.buffer } },
|
|
6427
|
+
{ binding: 2, resource: { buffer: entry.tones } }
|
|
6428
|
+
]
|
|
6429
|
+
}));
|
|
6430
|
+
fieldPass.draw(3);
|
|
6431
|
+
fieldPass.end();
|
|
6432
|
+
return view;
|
|
6433
|
+
},
|
|
6434
|
+
afterSubmit() {
|
|
6435
|
+
for (const entry of entries.values()) {
|
|
6436
|
+
entry.encodedReduction = false;
|
|
6437
|
+
if (entry.encodedFallback !== void 0)
|
|
6438
|
+
entry.fallback = entry.encodedFallback;
|
|
6439
|
+
entry.encodedFallback = void 0;
|
|
6440
|
+
const reduction = entry.queued;
|
|
6441
|
+
if (reduction === void 0)
|
|
6442
|
+
continue;
|
|
6443
|
+
entry.queued = void 0;
|
|
6444
|
+
entry.pending = entry.readback.mapAsync(GPUMapMode.READ).then(() => {
|
|
6445
|
+
entry.observation = {
|
|
6446
|
+
reduction,
|
|
6447
|
+
values: new Float32Array(entry.readback.getMappedRange()).slice()
|
|
6448
|
+
};
|
|
6449
|
+
entry.readback.unmap();
|
|
6450
|
+
}).catch(() => {
|
|
6451
|
+
entry.observation = void 0;
|
|
6452
|
+
}).finally(() => {
|
|
6453
|
+
entry.pending = void 0;
|
|
6454
|
+
});
|
|
6455
|
+
}
|
|
6456
|
+
},
|
|
6457
|
+
cancelQueued() {
|
|
6458
|
+
for (const entry of entries.values()) {
|
|
6459
|
+
if (entry.encodedReduction)
|
|
6460
|
+
entry.reduced = void 0;
|
|
6461
|
+
entry.encodedReduction = false;
|
|
6462
|
+
entry.encodedFallback = void 0;
|
|
6463
|
+
entry.queued = void 0;
|
|
6464
|
+
}
|
|
6465
|
+
},
|
|
6466
|
+
async collect() {
|
|
6467
|
+
await Promise.all([...entries.values()].map((entry) => entry.pending));
|
|
6468
|
+
},
|
|
6469
|
+
readings(groupId) {
|
|
6470
|
+
return [...entries.values()].filter((entry) => entry.groupId === groupId).flatMap((entry) => entry.observation === void 0 || entry.observation.reduction !== entry.reduced ? [] : toneReadingsFromBuffer(entry.observation.values, entry.observation.reduction.metadata, entry.fallback));
|
|
6471
|
+
},
|
|
6472
|
+
forget,
|
|
6473
|
+
destroy() {
|
|
6474
|
+
for (const resourceId of entries.keys())
|
|
6475
|
+
forget(resourceId);
|
|
6476
|
+
}
|
|
6477
|
+
};
|
|
6478
|
+
}
|
|
6479
|
+
|
|
5980
6480
|
// ../renderer-webgpu/dist/renderer.js
|
|
5981
6481
|
var OPTICS_PASS_ID = "vitrea.optics";
|
|
5982
6482
|
var HIGHLIGHT_PASS_ID = "vitrea.highlight";
|
|
@@ -5998,6 +6498,7 @@ function createWebGPURenderer(options = {}) {
|
|
|
5998
6498
|
const groups = /* @__PURE__ */ new Map();
|
|
5999
6499
|
const adaptation = /* @__PURE__ */ new Map();
|
|
6000
6500
|
const lastReadbackAt = /* @__PURE__ */ new Map();
|
|
6501
|
+
const hintedTones = /* @__PURE__ */ new Map();
|
|
6001
6502
|
let accessibility = NOMINAL_MATERIAL_POLICY;
|
|
6002
6503
|
let material = withMaterialOverrides(DEFAULT_MATERIAL_PROFILE, options.materialProfile ?? {});
|
|
6003
6504
|
let viewport = options.viewport ?? {
|
|
@@ -6009,6 +6510,7 @@ function createWebGPURenderer(options = {}) {
|
|
|
6009
6510
|
let builtGeneration;
|
|
6010
6511
|
let store;
|
|
6011
6512
|
let runner;
|
|
6513
|
+
let silhouetteTone;
|
|
6012
6514
|
let framesDrawn = 0;
|
|
6013
6515
|
let generations = 0;
|
|
6014
6516
|
let lastFrameTimeMs;
|
|
@@ -6032,6 +6534,9 @@ function createWebGPURenderer(options = {}) {
|
|
|
6032
6534
|
});
|
|
6033
6535
|
const dropContext = () => {
|
|
6034
6536
|
store?.destroy();
|
|
6537
|
+
silhouetteTone?.destroy();
|
|
6538
|
+
silhouetteTone = void 0;
|
|
6539
|
+
hintedTones.clear();
|
|
6035
6540
|
runner?.destroy();
|
|
6036
6541
|
context?.destroy();
|
|
6037
6542
|
store = void 0;
|
|
@@ -6063,6 +6568,7 @@ function createWebGPURenderer(options = {}) {
|
|
|
6063
6568
|
builtGeneration = generation;
|
|
6064
6569
|
store = createPyramidStore(context);
|
|
6065
6570
|
runner = createPassRunner(context);
|
|
6571
|
+
silhouetteTone = createSilhouetteTonePass(context);
|
|
6066
6572
|
if (superseded !== void 0 && superseded !== generation) {
|
|
6067
6573
|
for (const provider of providers.values()) {
|
|
6068
6574
|
if (provider.generation !== generation)
|
|
@@ -6223,7 +6729,7 @@ function createWebGPURenderer(options = {}) {
|
|
|
6223
6729
|
}
|
|
6224
6730
|
return { built, unbuilt };
|
|
6225
6731
|
}
|
|
6226
|
-
function drawGroups(encoder, resolution) {
|
|
6732
|
+
function drawGroups(encoder, resolution, timeMs) {
|
|
6227
6733
|
const { store: pyramids, runner: passes } = ensureContext();
|
|
6228
6734
|
const active = targets;
|
|
6229
6735
|
if (active === void 0) {
|
|
@@ -6239,7 +6745,11 @@ function createWebGPURenderer(options = {}) {
|
|
|
6239
6745
|
let drawn = 0;
|
|
6240
6746
|
planesDrawn.add(active.plane);
|
|
6241
6747
|
const resourceOf = (groupId) => groupResourceId(active.plane, groupId);
|
|
6242
|
-
const releaseIdle = (groupId) =>
|
|
6748
|
+
const releaseIdle = (groupId) => {
|
|
6749
|
+
passes.forget(resourceOf(groupId));
|
|
6750
|
+
silhouetteTone?.forget(resourceOf(groupId));
|
|
6751
|
+
hintedTones.delete(resourceOf(groupId));
|
|
6752
|
+
};
|
|
6243
6753
|
for (const entry of groups.values()) {
|
|
6244
6754
|
const input = entry.input;
|
|
6245
6755
|
if (input.surfaces.length === 0) {
|
|
@@ -6277,7 +6787,7 @@ function createWebGPURenderer(options = {}) {
|
|
|
6277
6787
|
rectDevice.x * cssPerDevice,
|
|
6278
6788
|
rectDevice.y * cssPerDevice
|
|
6279
6789
|
]);
|
|
6280
|
-
const
|
|
6790
|
+
const fieldArgs = {
|
|
6281
6791
|
resourceId: resourceOf(input.groupId),
|
|
6282
6792
|
family: governor.knobs.fieldFamily,
|
|
6283
6793
|
rectDevice,
|
|
@@ -6289,19 +6799,62 @@ function createWebGPURenderer(options = {}) {
|
|
|
6289
6799
|
instances: packed.data,
|
|
6290
6800
|
instanceCount: packed.count,
|
|
6291
6801
|
union
|
|
6292
|
-
}
|
|
6802
|
+
};
|
|
6803
|
+
const fields = passes.fieldPass(encoder, fieldArgs);
|
|
6293
6804
|
const state = stateOf(input, resolution);
|
|
6294
6805
|
const variant = variantOf(input);
|
|
6295
6806
|
const sourceId = input.backdropSourceId;
|
|
6296
6807
|
const pyramid = sourceId === void 0 ? void 0 : pyramids.resources(sourceId);
|
|
6297
6808
|
const adapt = sourceId === void 0 ? void 0 : adaptationFor(sourceId).values;
|
|
6809
|
+
const localTone = typeof material.backdropToneAbscissa === "object" && input.backdropToneHint !== true && pyramid !== void 0 && sourceId !== void 0 && surfaces.length > 0 ? silhouetteTone?.draw(encoder, {
|
|
6810
|
+
groupId: input.groupId,
|
|
6811
|
+
field: fieldArgs,
|
|
6812
|
+
fields,
|
|
6813
|
+
surfaces,
|
|
6814
|
+
pyramid,
|
|
6815
|
+
viewportDevice,
|
|
6816
|
+
fit: fitFor(sourceId, pyramid),
|
|
6817
|
+
timeMs,
|
|
6818
|
+
cadenceHz: governor.knobs.adaptationCadenceHz,
|
|
6819
|
+
liveSource: providers.get(sourceId)?.kind !== "image" && providers.get(sourceId)?.kind !== "gradient",
|
|
6820
|
+
fallbackTone: [
|
|
6821
|
+
input.backdropTone?.[0] ?? 0,
|
|
6822
|
+
input.backdropTone?.[1] ?? 0,
|
|
6823
|
+
input.backdropTone?.[2] ?? 0,
|
|
6824
|
+
input.backdropTone === void 0 ? -1 : input.backdropToneLevel ?? relativeLuminance(input.backdropTone)
|
|
6825
|
+
]
|
|
6826
|
+
}) : void 0;
|
|
6827
|
+
if (localTone === void 0)
|
|
6828
|
+
silhouetteTone?.forget(resourceOf(input.groupId));
|
|
6829
|
+
const hintLevel = input.backdropToneLevel ?? (input.backdropTone === void 0 ? void 0 : relativeLuminance(input.backdropTone));
|
|
6830
|
+
if (typeof material.backdropToneAbscissa === "object" && input.backdropToneHint === true && hintLevel !== void 0 && input.backdropTone !== void 0) {
|
|
6831
|
+
const color = input.backdropTone;
|
|
6832
|
+
hintedTones.set(resourceOf(input.groupId), {
|
|
6833
|
+
groupId: input.groupId,
|
|
6834
|
+
readings: surfaces.map((surface) => ({
|
|
6835
|
+
surfaceId: surface.nodeId,
|
|
6836
|
+
kind: "hint",
|
|
6837
|
+
color,
|
|
6838
|
+
encodedLuminance: linearToSrgbChannel(hintLevel),
|
|
6839
|
+
luminance: hintLevel,
|
|
6840
|
+
linearLuminance: input.backdropToneLinearLuminance ?? hintLevel,
|
|
6841
|
+
sampleCount: 0,
|
|
6842
|
+
level: 0,
|
|
6843
|
+
sourceWidth: 0,
|
|
6844
|
+
sourceHeight: 0,
|
|
6845
|
+
sampledWidth: 0,
|
|
6846
|
+
sampledHeight: 0
|
|
6847
|
+
}))
|
|
6848
|
+
});
|
|
6849
|
+
} else
|
|
6850
|
+
hintedTones.delete(resourceOf(input.groupId));
|
|
6298
6851
|
const nominalOptics = material.optics[variant];
|
|
6299
6852
|
const optics = opticsUnderPolicy(nominalOptics, policy, material);
|
|
6300
6853
|
const backdropTone = [
|
|
6301
6854
|
material.backdropToneLow,
|
|
6302
6855
|
material.backdropToneHigh,
|
|
6303
6856
|
backdropToneSizeBiasUnderPolicy(policy, material),
|
|
6304
|
-
input.backdropTone === void 0 ? 0 : backdropToneUnderPolicy(policy, material) * material.backdropToneMax
|
|
6857
|
+
input.backdropTone === void 0 && localTone === void 0 ? 0 : backdropToneUnderPolicy(policy, material) * material.backdropToneMax
|
|
6305
6858
|
];
|
|
6306
6859
|
const backdropToneLevel = shadowBackdropLuminance ?? 0;
|
|
6307
6860
|
const refraction = effectiveRefraction(accessibilityRefractionCap(policy), state.refraction);
|
|
@@ -6312,6 +6865,7 @@ function createWebGPURenderer(options = {}) {
|
|
|
6312
6865
|
targetFormat: active.format,
|
|
6313
6866
|
rectDevice,
|
|
6314
6867
|
fields,
|
|
6868
|
+
...localTone === void 0 ? {} : { localTone },
|
|
6315
6869
|
viewportDevice,
|
|
6316
6870
|
cssPerDevice,
|
|
6317
6871
|
coverageRampCss: cssPerDevice,
|
|
@@ -6535,6 +7089,7 @@ function createWebGPURenderer(options = {}) {
|
|
|
6535
7089
|
rectDevice: surfaceRectDevice,
|
|
6536
7090
|
fieldRectDevice: rectDevice,
|
|
6537
7091
|
fields,
|
|
7092
|
+
...localTone === void 0 ? {} : { localTone },
|
|
6538
7093
|
viewportDevice,
|
|
6539
7094
|
cssPerDevice,
|
|
6540
7095
|
sweep: lead.channels.sweep,
|
|
@@ -6675,8 +7230,11 @@ function createWebGPURenderer(options = {}) {
|
|
|
6675
7230
|
},
|
|
6676
7231
|
removeGroup(groupId) {
|
|
6677
7232
|
groups.delete(groupId);
|
|
6678
|
-
for (const plane of planesDrawn)
|
|
7233
|
+
for (const plane of planesDrawn) {
|
|
6679
7234
|
runner?.forget(groupResourceId(plane, groupId));
|
|
7235
|
+
silhouetteTone?.forget(groupResourceId(plane, groupId));
|
|
7236
|
+
hintedTones.delete(groupResourceId(plane, groupId));
|
|
7237
|
+
}
|
|
6680
7238
|
},
|
|
6681
7239
|
setAccessibility(policy) {
|
|
6682
7240
|
accessibility = policy;
|
|
@@ -6720,12 +7278,14 @@ function createWebGPURenderer(options = {}) {
|
|
|
6720
7278
|
if (args.highlight !== void 0)
|
|
6721
7279
|
passes.clearPass(encoder, args.highlight);
|
|
6722
7280
|
}
|
|
6723
|
-
result = drawGroups(encoder, args.resolution);
|
|
7281
|
+
result = drawGroups(encoder, args.resolution, args.frame.timeMs);
|
|
6724
7282
|
args.timing?.resolve(encoder);
|
|
6725
7283
|
gpu.device.queue.submit([encoder.finish()]);
|
|
6726
7284
|
pyramids.afterSubmit();
|
|
7285
|
+
silhouetteTone?.afterSubmit();
|
|
6727
7286
|
} finally {
|
|
6728
7287
|
pyramids.releaseAcquired();
|
|
7288
|
+
silhouetteTone?.cancelQueued();
|
|
6729
7289
|
}
|
|
6730
7290
|
const delta = lastFrameTimeMs === void 0 ? 0 : args.frame.timeMs - lastFrameTimeMs;
|
|
6731
7291
|
lastFrameTimeMs = args.frame.timeMs;
|
|
@@ -6758,6 +7318,7 @@ function createWebGPURenderer(options = {}) {
|
|
|
6758
7318
|
} catch (error) {
|
|
6759
7319
|
pendingEncoder = void 0;
|
|
6760
7320
|
pyramids.releaseAcquired();
|
|
7321
|
+
silhouetteTone?.cancelQueued();
|
|
6761
7322
|
throw error;
|
|
6762
7323
|
}
|
|
6763
7324
|
},
|
|
@@ -6773,12 +7334,14 @@ function createWebGPURenderer(options = {}) {
|
|
|
6773
7334
|
passes.clearPass(encoder, targets.optics);
|
|
6774
7335
|
if (targets.highlight !== void 0)
|
|
6775
7336
|
passes.clearPass(encoder, targets.highlight);
|
|
6776
|
-
drawGroups(encoder, frameContext.resolution);
|
|
7337
|
+
drawGroups(encoder, frameContext.resolution, frameContext.frame.timeMs);
|
|
6777
7338
|
}
|
|
6778
7339
|
context.device.queue.submit([encoder.finish()]);
|
|
6779
7340
|
pyramids.afterSubmit();
|
|
7341
|
+
silhouetteTone?.afterSubmit();
|
|
6780
7342
|
} finally {
|
|
6781
7343
|
pyramids.releaseAcquired();
|
|
7344
|
+
silhouetteTone?.cancelQueued();
|
|
6782
7345
|
}
|
|
6783
7346
|
const delta = lastFrameTimeMs === void 0 ? 0 : frameContext.frame.timeMs - lastFrameTimeMs;
|
|
6784
7347
|
lastFrameTimeMs = frameContext.frame.timeMs;
|
|
@@ -6790,7 +7353,14 @@ function createWebGPURenderer(options = {}) {
|
|
|
6790
7353
|
}
|
|
6791
7354
|
};
|
|
6792
7355
|
},
|
|
7356
|
+
backdropToneAbscissae(groupId) {
|
|
7357
|
+
return [
|
|
7358
|
+
...silhouetteTone?.readings(groupId) ?? [],
|
|
7359
|
+
...[...hintedTones.values()].filter((entry) => entry.groupId === groupId).flatMap((entry) => entry.readings)
|
|
7360
|
+
];
|
|
7361
|
+
},
|
|
6793
7362
|
async collectAdaptation() {
|
|
7363
|
+
await silhouetteTone?.collect();
|
|
6794
7364
|
if (store === void 0)
|
|
6795
7365
|
return 0;
|
|
6796
7366
|
const stats = await store.collectStats();
|
|
@@ -6819,6 +7389,6 @@ function createWebGPURenderer(options = {}) {
|
|
|
6819
7389
|
};
|
|
6820
7390
|
}
|
|
6821
7391
|
|
|
6822
|
-
export { ADAPTIVE_LUMINANCE_HIGH, ADAPTIVE_LUMINANCE_LOW, ADAPTIVE_TINT_DARK, ADAPTIVE_TINT_LIGHT, ANALYSIS_DISPATCH, ANALYSIS_GRID, ANALYSIS_PASS_ID, ANALYSIS_STATS_FLOATS, ANALYSIS_TARGET_EXTENT, ANALYSIS_WORKGROUP, BACKDROP_ALPHA_MODES, BACKDROP_COLOR_SPACES, BACKDROP_KINDS, BACKDROP_PASS_ID, BACKDROP_TONE_HIGH, BACKDROP_TONE_LOW, BACKDROP_TONE_MAX, BACKDROP_TONE_SIZE_BIAS, CANVAS_FORMAT, CHAIN_SIGMA_AT_LEVEL_1, CROSS_CHECK_SHAPE_FLOATS, CROSS_CHECK_WORKGROUP, DEFAULT_MATERIAL_PROFILE, FAMILY_C_CROSS_CHECK, FIELD_PASS_ID, GOVERNOR_LADDER, HIGHLIGHT_PASS_ID, IDENTITY_FIT, IDLE_CHANNELS, INCREASED_OCCLUSION_LIFT, INSTANCE_BYTES, INSTANCE_FLOATS, LENS_AMOUNT_MAX, LENS_AMOUNT_PER_SPAN, LENS_EXTENT_GAIN, LENS_HEIGHT_MAX, LENS_HEIGHT_PER_SPAN, LENS_OVALIZATION, LENS_PROFILE_EXPONENT, LENS_REFRACTION_GAIN, LENS_SIZE_GAIN_MAX, LENS_THICKNESS_REFERENCE, LUMINANCE_WEIGHTS, MATERIAL_OPTICS, MATERIAL_VARIANTS, MAX_CHAIN_LEVELS, MIN_LEVEL_EXTENT, NOMINAL_GOVERNOR, NOMINAL_MATERIAL_POLICY, OPTICS_PASS_ID, OUTER_SHADOW, OUTER_SHADOW_THICK_SPANS, OUTER_SHADOW_THIN_L, OUTER_SHADOW_UNMEASURED_BACKDROP_LUMINANCE, OUTPUT_TEXTURE_FORMAT, PASS_LABEL, REFRACTION_LADDER, REFRACTION_SCALE, RENDERER_ERROR_CODES, RENDERER_PASS_IDS, RendererError, SIZE_OCCLUSION_GAIN, SIZE_SCATTER_FLOOR, SIZE_SCATTER_FLOOR_2X, SIZE_SCATTER_GAIN_FAR_2X, SIZE_SCATTER_GAIN_MAX, SIZE_SCATTER_GAIN_MAX_2X, SIZE_SCATTER_RAMP_REACH_1X_PX, SIZE_SCATTER_RAMP_REACH_2X_PX, SIZE_SCATTER_RAMP_START_FAR_1X, SIZE_SCATTER_RAMP_START_FAR_2X, SIZE_SCATTER_RAMP_START_THICK_1X, SIZE_SCATTER_RAMP_START_THICK_2X, SIZE_SCATTER_RAMP_START_THIN_1X, SIZE_SCATTER_RAMP_START_THIN_2X, SIZE_SCATTER_SPAN_MAX, SIZE_SCATTER_SPAN_MAX_2X, SIZE_SHADOW_GAIN_MAX, SIZE_SPAN_MAX, SIZE_SPAN_MIN, SRGB_ENCODING_EXPONENT, SUPPORTED_APP_TEXTURE_FORMATS, WGSL_ANALYSIS_PASS, WGSL_CROSS_CHECK_PASS, WGSL_DOWNSAMPLE_PASS, WGSL_FIELD_KERNELS, WGSL_FIELD_PASS, WGSL_FIELD_SAMPLE, WGSL_HIGHLIGHT_PASS, WGSL_IMPORT_PASS, WGSL_INSTANCE_STRUCT, WGSL_OPTICS_PASS, WGSL_PRELUDE, WGSL_RSUPN_GRAD, WGSL_RSUP_GRAD, WGSL_SMOOTH_UNION, WORKING_TEXTURE_FORMAT, ZERO_STATS, accessibilityRefractionCap, adaptationStrength, adaptedTintAlpha, adaptedTintColour, adaptiveTint, allShaderSource, alphaNormalisationMode, analysisModule, backdropFit, backdropToneAdaptation, backdropToneResponse, backdropToneSizeBiasUnderPolicy, backdropToneSolveWeight, backdropToneUnderPolicy, bodyBlurPlan, chainModule, clipFieldRectToCanvas, collapsedRimUnderPolicy, coverFit, createAdaptationState, createAppTextureProvider, createCopyProvider, createDeviceHost, createGovernor, createGpuContext, createGradientProvider, createPassRunner, createPipelineCache, createPyramidStore, createRebuildLedger, createStorageSlot, createTexturePool, createTimingCollector, createUniformSlot, createVideoProvider, createWebGPURenderer, crossCheckKernelModule, displayP3ToSrgbLinear, effectiveRefraction, encodeOutput, encodeOutputBytes, fieldModule, fieldPassSource, groupFieldRect, heavyTapSigmaAtScale, highlightModule, importColorMatrix, importModule, importPassSource, isUsablePlacement, lensAmountBasePx, lensDepthPx, lensDirection, lensDisplacementPx, lensExtentPx, lensHeightBasePx, lensMagnitudePx, lensOvalizationAt, lensSizeGain, lensSizeGainFromThickness, linearGradientStops, linearToSrgb, linearToSrgbChannel, occlusionAlphaUnderPolicy, opticsModule, opticsUnderPolicy, outerShadowAlpha, outerShadowFalloff, outerShadowLiftRise, outerShadowOcclusionAt, outerShadowReachPx, outerShadowThickOcclusion, outerShadowThinOcclusion, outerShadowUnderPolicy, packInstances, pipelineKey, placementFit, planPyramid, poolKey, readbackDue, refractionRank, relativeLuminance, rendererError, resolveSurfaces, rimAlongSideFactor, rimAlongSideField, samePlacement, scatterDeepThickness, scatterFloorAtScale, scatterGainAt, scatterGainAtScale, scatterGainFarAtScale, scatterHeavyShareThickAtScale, scatterRampAreaMean, scatterRampReachDevicePx, scatterRampStart, scatterSharpShare, scatterSpanMaxAtScale, scatterThickness, shadowDepthPx, sizeOcclusionAlpha, sizeOcclusionAlphaAt, sizeOuterShadowOcclusion, sizeOuterShadowOcclusionAt, sizeScatterSigma, sizeScatterSigmaAt, sizeShadowDepth, sizeShadowDepthAt, sizeThickness, sizeThicknessUnderPolicy, sizeToneLevelFar, snapRectToDevicePixels, srgbToLinear, srgbToLinearChannel, statsFromBuffer, supportsTimestamps, texelsPerCssPx, tintShade, tintShadeLayer, tintToneAdaptation, tintedMaterialColour, validateAppTexture, withMaterialOverrides };
|
|
6823
|
-
//# sourceMappingURL=dist-
|
|
6824
|
-
//# sourceMappingURL=dist-
|
|
7392
|
+
export { ADAPTIVE_LUMINANCE_HIGH, ADAPTIVE_LUMINANCE_LOW, ADAPTIVE_TINT_DARK, ADAPTIVE_TINT_LIGHT, ANALYSIS_DISPATCH, ANALYSIS_GRID, ANALYSIS_PASS_ID, ANALYSIS_STATS_FLOATS, ANALYSIS_TARGET_EXTENT, ANALYSIS_WORKGROUP, BACKDROP_ALPHA_MODES, BACKDROP_COLOR_SPACES, BACKDROP_KINDS, BACKDROP_PASS_ID, BACKDROP_TONE_HIGH, BACKDROP_TONE_LOW, BACKDROP_TONE_MAX, BACKDROP_TONE_SIZE_BIAS, CANVAS_FORMAT, CHAIN_SIGMA_AT_LEVEL_1, CROSS_CHECK_SHAPE_FLOATS, CROSS_CHECK_WORKGROUP, DEFAULT_MATERIAL_PROFILE, FAMILY_C_CROSS_CHECK, FIELD_PASS_ID, GOVERNOR_LADDER, HIGHLIGHT_PASS_ID, IDENTITY_FIT, IDLE_CHANNELS, INCREASED_OCCLUSION_LIFT, INSTANCE_BYTES, INSTANCE_FLOATS, LENS_AMOUNT_MAX, LENS_AMOUNT_PER_SPAN, LENS_EXTENT_GAIN, LENS_HEIGHT_MAX, LENS_HEIGHT_PER_SPAN, LENS_OVALIZATION, LENS_PROFILE_EXPONENT, LENS_REFRACTION_GAIN, LENS_SIZE_GAIN_MAX, LENS_THICKNESS_REFERENCE, LUMINANCE_WEIGHTS, MATERIAL_OPTICS, MATERIAL_VARIANTS, MAX_CHAIN_LEVELS, MIN_LEVEL_EXTENT, NOMINAL_GOVERNOR, NOMINAL_MATERIAL_POLICY, OPTICS_PASS_ID, OUTER_SHADOW, OUTER_SHADOW_THICK_SPANS, OUTER_SHADOW_THIN_L, OUTER_SHADOW_UNMEASURED_BACKDROP_LUMINANCE, OUTPUT_TEXTURE_FORMAT, PASS_LABEL, REFRACTION_LADDER, REFRACTION_SCALE, RENDERER_ERROR_CODES, RENDERER_PASS_IDS, RendererError, SIZE_OCCLUSION_GAIN, SIZE_SCATTER_FLOOR, SIZE_SCATTER_FLOOR_2X, SIZE_SCATTER_GAIN_FAR_2X, SIZE_SCATTER_GAIN_MAX, SIZE_SCATTER_GAIN_MAX_2X, SIZE_SCATTER_RAMP_REACH_1X_PX, SIZE_SCATTER_RAMP_REACH_2X_PX, SIZE_SCATTER_RAMP_START_FAR_1X, SIZE_SCATTER_RAMP_START_FAR_2X, SIZE_SCATTER_RAMP_START_THICK_1X, SIZE_SCATTER_RAMP_START_THICK_2X, SIZE_SCATTER_RAMP_START_THIN_1X, SIZE_SCATTER_RAMP_START_THIN_2X, SIZE_SCATTER_SPAN_MAX, SIZE_SCATTER_SPAN_MAX_2X, SIZE_SHADOW_GAIN_MAX, SIZE_SPAN_MAX, SIZE_SPAN_MIN, SRGB_ENCODING_EXPONENT, SUPPORTED_APP_TEXTURE_FORMATS, WGSL_ANALYSIS_PASS, WGSL_CROSS_CHECK_PASS, WGSL_DOWNSAMPLE_PASS, WGSL_FIELD_KERNELS, WGSL_FIELD_PASS, WGSL_FIELD_SAMPLE, WGSL_HIGHLIGHT_PASS, WGSL_IMPORT_PASS, WGSL_INSTANCE_STRUCT, WGSL_OPTICS_PASS, WGSL_PRELUDE, WGSL_RSUPN_GRAD, WGSL_RSUP_GRAD, WGSL_SMOOTH_UNION, WORKING_TEXTURE_FORMAT, ZERO_STATS, accessibilityRefractionCap, adaptationStrength, adaptedTintAlpha, adaptedTintColour, adaptiveTint, allShaderSource, alphaNormalisationMode, analysisModule, backdropFit, backdropToneAdaptation, backdropToneResponse, backdropToneSizeBiasUnderPolicy, backdropToneSolveWeight, backdropToneUnderPolicy, bodyBlurPlan, chainModule, clipFieldRectToCanvas, collapsedRimUnderPolicy, coverFit, createAdaptationState, createAppTextureProvider, createCopyProvider, createDeviceHost, createGovernor, createGpuContext, createGradientProvider, createPassRunner, createPipelineCache, createPyramidStore, createRebuildLedger, createStorageSlot, createTexturePool, createTimingCollector, createUniformSlot, createVideoProvider, createWebGPURenderer, crossCheckKernelModule, displayP3ToSrgbLinear, effectiveRefraction, encodeOutput, encodeOutputBytes, fieldModule, fieldPassSource, groupFieldRect, heavyTapSigmaAtScale, highlightModule, importColorMatrix, importModule, importPassSource, isUsablePlacement, lensAmountBasePx, lensDepthPx, lensDirection, lensDisplacementPx, lensExtentPx, lensHeightBasePx, lensMagnitudePx, lensOvalizationAt, lensSizeGain, lensSizeGainFromThickness, linearGradientStops, linearToSrgb, linearToSrgbChannel, occlusionAlphaUnderPolicy, occlusionLiftForPolicy, opticsModule, opticsUnderPolicy, outerShadowAlpha, outerShadowFalloff, outerShadowLiftRise, outerShadowOcclusionAt, outerShadowReachPx, outerShadowThickOcclusion, outerShadowThinOcclusion, outerShadowUnderPolicy, packInstances, pipelineKey, placementFit, planPyramid, poolKey, readbackDue, refractionRank, relativeLuminance, rendererError, resolveSurfaces, rimAlongSideFactor, rimAlongSideField, samePlacement, scatterDeepThickness, scatterFloorAtScale, scatterGainAt, scatterGainAtScale, scatterGainFarAtScale, scatterHeavyShareThickAtScale, scatterRampAreaMean, scatterRampReachDevicePx, scatterRampStart, scatterSharpShare, scatterSpanMaxAtScale, scatterThickness, shadowDepthPx, sizeOcclusionAlpha, sizeOcclusionAlphaAt, sizeOuterShadowOcclusion, sizeOuterShadowOcclusionAt, sizeScatterSigma, sizeScatterSigmaAt, sizeShadowDepth, sizeShadowDepthAt, sizeThickness, sizeThicknessUnderPolicy, sizeToneLevelFar, snapRectToDevicePixels, srgbToLinear, srgbToLinearChannel, statsFromBuffer, supportsTimestamps, texelsPerCssPx, tintShade, tintShadeLayer, tintToneAdaptation, tintedMaterialColour, validateAppTexture, withMaterialOverrides };
|
|
7393
|
+
//# sourceMappingURL=dist-VQPRX7BX.js.map
|
|
7394
|
+
//# sourceMappingURL=dist-VQPRX7BX.js.map
|