@vitreajs/vitrea 0.15.0 → 0.16.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.
@@ -1,4 +1,4 @@
1
- import { DEFAULT_GROUP_UNION, LowPassHysteresisDriver, WGSL_RSUPN, WGSL_RSUP, resolveFromChannels, resolveConcentric, governorFieldParams, fieldParams, DEFAULT_MOTION_PROFILE } from './chunk-WM2DV3ZD.js';
1
+ import { DEFAULT_GROUP_UNION, LowPassHysteresisDriver, WGSL_RSUPN, WGSL_RSUP, resolveFromChannels, resolveConcentric, governorFieldParams, fieldParams, DEFAULT_MOTION_PROFILE } from './chunk-IOTISK2R.js';
2
2
 
3
3
  // ../renderer-webgpu/dist/wgsl/analysis.js
4
4
  var ANALYSIS_WORKGROUP = 64;
@@ -1212,6 +1212,12 @@ function withMaterialOverrides(base, patch) {
1212
1212
  tintShadeDark: patch.tintShadeDark ?? base.tintShadeDark,
1213
1213
  tintShadeLight: patch.tintShadeLight ?? base.tintShadeLight,
1214
1214
  tintShadeStrength: patch.tintShadeStrength ?? base.tintShadeStrength,
1215
+ ...(patch.tintChromaScale ?? base.tintChromaScale ?? 1) === 1 ? {} : {
1216
+ tintChromaScale: patch.tintChromaScale ?? base.tintChromaScale
1217
+ },
1218
+ ...(patch.tintShadeCollapseRetention ?? base.tintShadeCollapseRetention ?? 0) === 0 ? {} : {
1219
+ tintShadeCollapseRetention: patch.tintShadeCollapseRetention ?? base.tintShadeCollapseRetention
1220
+ },
1215
1221
  backdropToneMax: patch.backdropToneMax ?? base.backdropToneMax,
1216
1222
  backdropToneLow: patch.backdropToneLow ?? base.backdropToneLow,
1217
1223
  backdropToneHigh: patch.backdropToneHigh ?? base.backdropToneHigh,
@@ -1300,7 +1306,15 @@ function tintShade(materialLuminance, grip, profile = DEFAULT_MATERIAL_PROFILE)
1300
1306
  }
1301
1307
  function tintShadeLayer(seed, materialLuminance, grip, profile = DEFAULT_MATERIAL_PROFILE) {
1302
1308
  const shade = tintShade(materialLuminance, grip, profile);
1303
- return [seed[0] * shade, seed[1] * shade, seed[2] * shade];
1309
+ const chroma = Math.min(1, Math.max(0, profile.tintChromaScale ?? 1));
1310
+ if (chroma === 1)
1311
+ return [seed[0] * shade, seed[1] * shade, seed[2] * shade];
1312
+ const neutral = Math.max(...seed);
1313
+ return [
1314
+ (neutral + (seed[0] - neutral) * chroma) * shade,
1315
+ (neutral + (seed[1] - neutral) * chroma) * shade,
1316
+ (neutral + (seed[2] - neutral) * chroma) * shade
1317
+ ];
1304
1318
  }
1305
1319
  function tintedMaterialColour(material, tint, grip, profile = DEFAULT_MATERIAL_PROFILE) {
1306
1320
  if (tint === void 0 || tint.strength <= 0)
@@ -2498,9 +2512,17 @@ var poolKey = {
2498
2512
  backdropHeavy: (sourceId) => `backdrop:${sourceId}:heavy`,
2499
2513
  backdropHeavyScratch: (sourceId) => `backdrop:${sourceId}:heavy-scratch`,
2500
2514
  backdropUpload: (sourceId) => `backdrop:${sourceId}:upload`,
2501
- groupField: (groupId) => `group:${groupId}:field`,
2502
- groupAux: (groupId) => `group:${groupId}:aux`,
2503
- groupAux2: (groupId) => `group:${groupId}:aux2`
2515
+ /*
2516
+ * The four field targets. Their key is a group's RESOURCE identity — the id
2517
+ * qualified by the plane it draws on (`groupResourceId`) — and not the group
2518
+ * id, because one group can draw on two planes in one frame and each plane's
2519
+ * field is its own size.
2520
+ */
2521
+ groupField: (resourceId) => `group:${resourceId}:field`,
2522
+ groupAux: (resourceId) => `group:${resourceId}:aux`,
2523
+ groupAux2: (resourceId) => `group:${resourceId}:aux2`,
2524
+ /** The surface's presence per pixel (W27d) — the field pass's fourth target. */
2525
+ groupPresence: (resourceId) => `group:${resourceId}:presence`
2504
2526
  };
2505
2527
 
2506
2528
  // ../renderer-webgpu/dist/gpu-context.js
@@ -2589,12 +2611,32 @@ var IDLE_CHANNELS = {
2589
2611
  glow: 0,
2590
2612
  sweep: 0,
2591
2613
  shimmer: 0,
2592
- lensStrength: 1
2614
+ lensStrength: 1,
2615
+ // 1 rather than 0, for `lensStrength`'s reason: a surface nobody is driving is
2616
+ // a surface that is fully there, and 0 is a distinct claim a driver can make.
2617
+ materialization: 1
2593
2618
  };
2594
2619
 
2595
2620
  // ../renderer-webgpu/dist/instances.js
2596
2621
  var INSTANCE_FLOATS = 18;
2597
2622
  var INSTANCE_BYTES = INSTANCE_FLOATS * 4;
2623
+ var LENS_STRENGTH_MAX = 4;
2624
+ function boundedLensStrength(strength) {
2625
+ if (Number.isNaN(strength))
2626
+ return IDLE_CHANNELS.lensStrength;
2627
+ return Math.min(LENS_STRENGTH_MAX, Math.max(0, strength));
2628
+ }
2629
+ function boundedMaterialization(value) {
2630
+ if (Number.isNaN(value))
2631
+ return IDLE_CHANNELS.materialization;
2632
+ return Math.min(1, Math.max(0, value));
2633
+ }
2634
+ function drawsMaterial(surface) {
2635
+ if (surface.fieldReferenceOnly === true)
2636
+ return false;
2637
+ const presence = surface.channels?.materialization ?? IDLE_CHANNELS.materialization;
2638
+ return boundedMaterialization(presence) > 0;
2639
+ }
2598
2640
  var channelsOf = (input) => ({
2599
2641
  ...IDLE_CHANNELS,
2600
2642
  ...input.channels
@@ -2643,7 +2685,7 @@ function resolveSurfaces(group, family, profile = DEFAULT_MATERIAL_PROFILE, poli
2643
2685
  return shape;
2644
2686
  };
2645
2687
  const paramsFor = (shape) => family === "rsup" ? governorFieldParams(shape) : fieldParams(shape);
2646
- return group.surfaces.filter((surface) => surface.fieldReferenceOnly !== true).map((surface) => {
2688
+ return group.surfaces.filter(drawsMaterial).map((surface) => {
2647
2689
  const channels = channelsOf(surface);
2648
2690
  const shape = resolveShapeOf(surface);
2649
2691
  const fieldSource = surface.concentricOf === void 0 ? shape : resolveShapeOf(byId.get(surface.concentricOf.nodeId));
@@ -2660,6 +2702,7 @@ function resolveSurfaces(group, family, profile = DEFAULT_MATERIAL_PROFILE, poli
2660
2702
  spanPx,
2661
2703
  lensDepthPx: lensDepthPx(shape.channels.thickness, spanPx, profile, profile.refractionScale[accessibilityRefractionCap(policy)]),
2662
2704
  sizeThickness: thickness,
2705
+ materialization: boundedMaterialization(channels.materialization),
2663
2706
  tintStrength: Math.min(1, Math.max(0, surface.tint?.strength ?? 0))
2664
2707
  };
2665
2708
  });
@@ -2723,10 +2766,10 @@ function packInstances(surfaces, origin, into) {
2723
2766
  data[o + 11] = s.shape.channels.thickness;
2724
2767
  data[o + 12] = s.channels.press;
2725
2768
  data[o + 13] = s.channels.glow;
2726
- data[o + 14] = Math.max(s.shape.channels.thickness, 0) * Math.min(1, Math.max(0, s.channels.lensStrength));
2769
+ data[o + 14] = Math.max(s.shape.channels.thickness, 0) * boundedLensStrength(s.channels.lensStrength);
2727
2770
  data[o + 15] = s.tintStrength;
2728
2771
  data[o + 16] = s.spanPx;
2729
- data[o + 17] = 0;
2772
+ data[o + 17] = s.materialization;
2730
2773
  }
2731
2774
  return { data, count: surfaces.length };
2732
2775
  }
@@ -3004,7 +3047,7 @@ var WGSL_INSTANCE_STRUCT = `struct Instance {
3004
3047
  lensThick : f32, // 56 authored thickness in CSS px times the lensStrength channel (W12 G2): both depths are evaluated from it per pixel
3005
3048
  tintK : f32, // 60 author tint strength, 0..1 \u2014 the seed itself is a group uniform
3006
3049
  span : f32, // 64 the surface's shorter extent, CSS px \u2014 the size law's input, both curves (W11c)
3007
- _pad : f32, // 68 stride padding: vec2f aligns the struct to 8, so 72 is the next legal size
3050
+ mat : f32, // 68 presence, 0..1 (W27d): the slot the 8-byte alignment already required
3008
3051
  };`;
3009
3052
  var WGSL_FIELD_SAMPLE = `struct FieldSample {
3010
3053
  d : f32,
@@ -3214,6 +3257,17 @@ var WGSL_FIELD_PASS = `struct FieldUniforms {
3214
3257
  // two merged members share one oval there \u2014 a value nothing measured either.
3215
3258
  // For a concentric child the box is the parent's (the child is the parent's
3216
3259
  // level set), which is the same centre and a slightly larger oval.
3260
+ //
3261
+ // 'presence' (W27d) is the fourth target and carries one number: the surface's
3262
+ // materialization, blended through the union on the same weight as everything
3263
+ // else. It is a target of its own rather than a component of one of the three
3264
+ // above because all three are full \u2014 the field carries the distance, the normal
3265
+ // and the coverage, 'aux' the four optical scalars, 'aux2' the surface's own box
3266
+ // \u2014 and repurposing a component would mean re-deriving a value the fragment
3267
+ // stages read, which is how a golden moves for a reason nobody named. It is
3268
+ // r16float rather than the working rgba16float for the same honesty: one scalar
3269
+ // costs one channel, and a wave that needs a second widens the format in the one
3270
+ // place it is declared ('passes.ts').
3217
3271
 
3218
3272
  @group(0) @binding(0) var<uniform> fu : FieldUniforms;
3219
3273
  @group(0) @binding(1) var<storage, read> instances : array<Instance>;
@@ -3223,6 +3277,7 @@ struct Member {
3223
3277
  g : vec2f,
3224
3278
  aux : vec4f,
3225
3279
  aux2 : vec4f,
3280
+ mat : f32,
3226
3281
  };
3227
3282
 
3228
3283
  fn eval_instance(i : u32, p : vec2f) -> Member {
@@ -3239,6 +3294,7 @@ fn eval_instance(i : u32, p : vec2f) -> Member {
3239
3294
  // The pixel relative to the surface's centre, and the half-extents: what the
3240
3295
  // oval's gradient needs, written here where the group-local position is exact.
3241
3296
  m.aux2 = vec4f(p - s.centre, s.half);
3297
+ m.mat = s.mat;
3242
3298
  return m;
3243
3299
  }
3244
3300
 
@@ -3246,6 +3302,7 @@ struct FieldOut {
3246
3302
  @location(0) field : vec4f,
3247
3303
  @location(1) aux : vec4f,
3248
3304
  @location(2) aux2 : vec4f,
3305
+ @location(3) presence : vec4f,
3249
3306
  };
3250
3307
 
3251
3308
  @fragment
@@ -3264,6 +3321,10 @@ fn fs_field(in : FullscreenOut) -> FieldOut {
3264
3321
  out.field = vec4f(65000.0, 0.0, -1.0, 0.0);
3265
3322
  out.aux = vec4f(0.0);
3266
3323
  out.aux2 = vec4f(0.0);
3324
+ // The idle, not zero: no surface here means nothing to be absent, and a
3325
+ // reader that walks off the instances (the outer shadow's offset read) must
3326
+ // not find a material it has to fade.
3327
+ out.presence = vec4f(1.0, 0.0, 0.0, 0.0);
3267
3328
  return out;
3268
3329
  }
3269
3330
 
@@ -3277,6 +3338,7 @@ fn fs_field(in : FullscreenOut) -> FieldOut {
3277
3338
  acc.g = mix(s.g, acc.g, h);
3278
3339
  acc.aux = mix(s.aux, acc.aux, h);
3279
3340
  acc.aux2 = mix(s.aux2, acc.aux2, h);
3341
+ acc.mat = mix(s.mat, acc.mat, h);
3280
3342
  nearest = min(nearest, s.d);
3281
3343
  }
3282
3344
  // One clamp at the end of the fold, so |union - min| <= maxBulge holds for any
@@ -3290,6 +3352,7 @@ fn fs_field(in : FullscreenOut) -> FieldOut {
3290
3352
  out.field = vec4f(acc.d, normal.x, normal.y, coverage);
3291
3353
  out.aux = acc.aux;
3292
3354
  out.aux2 = acc.aux2;
3355
+ out.presence = vec4f(acc.mat, 0.0, 0.0, 0.0);
3293
3356
  return out;
3294
3357
  }`;
3295
3358
  function fieldPassSource(family) {
@@ -3349,6 +3412,10 @@ var WGSL_HIGHLIGHT_PASS = `struct HighlightUniforms {
3349
3412
  @group(0) @binding(1) var fieldTexture : texture_2d<f32>;
3350
3413
  @group(0) @binding(2) var auxTexture : texture_2d<f32>;
3351
3414
  @group(0) @binding(3) var fieldSampler : sampler;
3415
+ /// The surface's presence per pixel (W27d) \u2014 the field pass's fourth target,
3416
+ /// bound here for the same reason the optics pass binds it: a highlight is the
3417
+ /// material catching light, and a material that is not there catches none.
3418
+ @group(0) @binding(4) var presenceTexture : texture_2d<f32>;
3352
3419
 
3353
3420
  const TAU = 6.283185307179586;
3354
3421
 
@@ -3367,14 +3434,18 @@ fn fs_highlight(in : FullscreenOut) -> @location(0) vec4f {
3367
3434
  let fieldUv = in.uv * hu.fieldFit.xy + hu.fieldFit.zw;
3368
3435
  var field : vec4f;
3369
3436
  var aux : vec4f;
3437
+ var presence : vec4f;
3370
3438
  if (hu.flags.z > 0.5) {
3371
3439
  field = textureSampleLevel(fieldTexture, fieldSampler, fieldUv, 0.0);
3372
3440
  aux = textureSampleLevel(auxTexture, fieldSampler, fieldUv, 0.0);
3441
+ presence = textureSampleLevel(presenceTexture, fieldSampler, fieldUv, 0.0);
3373
3442
  } else {
3374
3443
  let texel = vec2i(fieldUv * hu.flags.xy);
3375
3444
  field = textureLoad(fieldTexture, texel, 0);
3376
3445
  aux = textureLoad(auxTexture, texel, 0);
3446
+ presence = textureLoad(presenceTexture, texel, 0);
3377
3447
  }
3448
+ let mat = clamp(presence.x, 0.0, 1.0);
3378
3449
  let d = field.x;
3379
3450
  let normal = field.yz;
3380
3451
  let coverage = field.w;
@@ -3432,7 +3503,15 @@ fn fs_highlight(in : FullscreenOut) -> @location(0) vec4f {
3432
3503
  toneAdapt = clamp(hu.toneAdapt.w, 0.0, 1.0) * (1.0 - toneT * toneT * (3.0 - 2.0 * toneT));
3433
3504
  }
3434
3505
 
3435
- let intensity = clamp(sweep + press, 0.0, 1.0) * coverage * (1.0 - toneAdapt);
3506
+ /*
3507
+ * The presence (W27d) fades both lights on one factor, exactly as the collapse
3508
+ * above fades them: the sweep is the material's own rim catching a travelling
3509
+ * light and the glow is the material lit from a press, so neither survives a
3510
+ * surface that is not there. It is applied to the composed intensity rather
3511
+ * than to each term, because a highlight that fades on two statements of one
3512
+ * rule is a highlight that will one day fade on one of them.
3513
+ */
3514
+ let intensity = clamp(sweep + press, 0.0, 1.0) * coverage * (1.0 - toneAdapt) * mat;
3436
3515
  if (intensity <= 0.0) {
3437
3516
  return vec4f(0.0);
3438
3517
  }
@@ -3460,9 +3539,8 @@ var WGSL_OPTICS_PASS = `struct OpticsUniforms {
3460
3539
  /// accessibility fold \u2014 the refraction ladder read at the preference's cap,
3461
3540
  /// which every facet's span-dependent rise is multiplied by (W11c)
3462
3541
  tone : vec4f,
3463
- /// rimWidthPx, rimAlpha; (z) and (w) carried specularPower and specularGain
3464
- /// until W24 retired the one-sided specular from the rim (claims 5.108
3465
- /// section 1) and are written but unread
3542
+ /// rimWidthPx, rimAlpha; the slots retired by W24 now carry W27c's
3543
+ /// tintChromaScale (z) and tintShadeCollapseRetention (w).
3466
3544
  rim : vec4f,
3467
3545
  /// light direction, unit (xy), shadowDepth (z), shadowAlpha (w)
3468
3546
  light : vec4f,
@@ -3578,7 +3656,9 @@ var WGSL_OPTICS_PASS = `struct OpticsUniforms {
3578
3656
  /// carries a heavy texture, 0 where it does not. The WIDTH is not here: the
3579
3657
  /// pyramid blurred it into 'backdropHeavy' before any group was drawn, so all
3580
3658
  /// this pass decides is which of two textures the deep sample comes from.
3581
- /// (y) (z) (w) free.
3659
+ /// (y) is the DOM material mode (0 off, 1 unknown tone, 2 measured tone);
3660
+ /// (z) and (w) carry its reference level and minimum tint contrast.
3661
+ /// Texture draws keep those lanes zero, so their input bytes do not move.
3582
3662
  heavyTap : vec4f,
3583
3663
  };
3584
3664
 
@@ -3598,6 +3678,11 @@ var WGSL_OPTICS_PASS = `struct OpticsUniforms {
3598
3678
  /// from. Bound at every draw; read only where 'heavyTap.x' says there is one.
3599
3679
  @group(0) @binding(8) var backdropHeavy : texture_2d<f32>;
3600
3680
 
3681
+ /// The surface's PRESENCE per pixel (W27d; contract X6): the 'materialization'
3682
+ /// channel, unioned in the field pass like every other per-surface scalar. One
3683
+ /// channel, in the field pass's fourth target \u2014 see 'wgsl/field.ts'.
3684
+ @group(0) @binding(9) var presenceTexture : texture_2d<f32>;
3685
+
3601
3686
  /// One encoded sRGB channel from a linear one \u2014 the space the backdrop tone
3602
3687
  /// response's anchors live in (W9). Mirrors material.ts's 'linearToSrgbChannel'.
3603
3688
  fn srgb_encode(c : f32) -> f32 {
@@ -3672,6 +3757,12 @@ struct ShadowSample {
3672
3757
  alpha : f32,
3673
3758
  falloff : f32,
3674
3759
  castSpanCss : f32,
3760
+ /// The presence of the surface that CAST the shadow (W27d), read at the offset
3761
+ /// position beside its span. A shadow belongs to the surface above it, so it
3762
+ /// fades with that surface's materialization and not with the one under this
3763
+ /// pixel \u2014 which is a real difference wherever a dissolving surface's shadow
3764
+ /// falls across a present one.
3765
+ castMat : f32,
3675
3766
  };
3676
3767
 
3677
3768
  /// The composite's peak linear occlusion above the knee, at a casting span \u2014
@@ -3702,6 +3793,7 @@ fn outer_shadow(uv : vec2f, upsampled : f32, fieldSize : vec2f) -> ShadowSample
3702
3793
  out.alpha = 0.0;
3703
3794
  out.falloff = 0.0;
3704
3795
  out.castSpanCss = 0.0;
3796
+ out.castMat = 1.0;
3705
3797
  if (ou.shadow.x <= 0.0 && ou.shadowThick.x <= 0.0) {
3706
3798
  return out;
3707
3799
  }
@@ -3729,14 +3821,18 @@ fn outer_shadow(uv : vec2f, upsampled : f32, fieldSize : vec2f) -> ShadowSample
3729
3821
  let shadowUv = clamp(vec2f(uv.x, shiftedY), vec2f(0.0), vec2f(1.0));
3730
3822
  var shadowField : vec4f;
3731
3823
  var shadowAux : vec4f;
3824
+ var shadowPresence : vec4f;
3732
3825
  if (upsampled > 0.5) {
3733
3826
  shadowField = textureSampleLevel(fieldTexture, fieldSampler, shadowUv, 0.0);
3734
3827
  shadowAux = textureSampleLevel(auxTexture, fieldSampler, shadowUv, 0.0);
3828
+ shadowPresence = textureSampleLevel(presenceTexture, fieldSampler, shadowUv, 0.0);
3735
3829
  } else {
3736
3830
  let texel = clamp(vec2i(shadowUv * fieldSize), vec2i(0), vec2i(fieldSize) - vec2i(1));
3737
3831
  shadowField = textureLoad(fieldTexture, texel, 0);
3738
3832
  shadowAux = textureLoad(auxTexture, texel, 0);
3833
+ shadowPresence = textureLoad(presenceTexture, texel, 0);
3739
3834
  }
3835
+ let castMat = clamp(shadowPresence.x, 0.0, 1.0);
3740
3836
 
3741
3837
  // The size law reaches the amplitude and nothing else \u2014 the reference's three
3742
3838
  // lengths are span-invariant across 32\u2026160 px. Every span-keyed quantity here
@@ -3766,9 +3862,12 @@ fn outer_shadow(uv : vec2f, upsampled : f32, fieldSize : vec2f) -> ShadowSample
3766
3862
  // LINEAR light; then the one conversion to the canvas's compositing space,
3767
3863
  // which is where the black term is actually composited.
3768
3864
  let occ = clamp(regime + ou.shadowSize.x * sizeK * (1.0 - regime), 0.0, 1.0);
3769
- out.alpha = 1.0 - pow(1.0 - occ, 1.0 / 2.4);
3865
+ // Times the casting surface's presence (W27d): a material that is not there
3866
+ // occludes nothing. At presence 1 this is the alpha the bed measures.
3867
+ out.alpha = (1.0 - pow(1.0 - occ, 1.0 / 2.4)) * castMat;
3770
3868
  out.falloff = outer_shadow_falloff(shadowField.x + clampedOffCss - ou.shadow.z, ou.shadow.y);
3771
3869
  out.castSpanCss = shadowAux.z;
3870
+ out.castMat = castMat;
3772
3871
  return out;
3773
3872
  }
3774
3873
 
@@ -3788,7 +3887,8 @@ fn outer_shadow(uv : vec2f, upsampled : f32, fieldSize : vec2f) -> ShadowSample
3788
3887
  /// zero where the group has no backdrop to copy \u2014 so 'dark-solid', 'impulse',
3789
3888
  /// every thin cell and every unsampled group stay byte-for-byte what they were.
3790
3889
  fn outer_shadow_lift(viewport01 : vec2f, shadow : ShadowSample) -> vec3f {
3791
- if (ou.flags.x <= 0.5 || ou.shadowLift.x <= 0.0 || shadow.falloff <= 0.0) {
3890
+ if ((ou.flags.x <= 0.5 && ou.heavyTap.y < 1.5) ||
3891
+ ou.shadowLift.x <= 0.0 || shadow.falloff <= 0.0) {
3792
3892
  return vec3f(0.0);
3793
3893
  }
3794
3894
  // Written out rather than through WGSL's 'smoothstep', which is undefined
@@ -3804,13 +3904,53 @@ fn outer_shadow_lift(viewport01 : vec2f, shadow : ShadowSample) -> vec3f {
3804
3904
  if (rise <= 0.0) {
3805
3905
  return vec3f(0.0);
3806
3906
  }
3907
+ if (ou.flags.x <= 0.5) {
3908
+ // A DOM page has no exterior texture: this is the law at the stated tone,
3909
+ // not a claim to reproduce the colour or structure beyond the silhouette.
3910
+ return ou.toneColour.rgb * (ou.shadowLift.x * rise * shadow.falloff);
3911
+ }
3807
3912
  let uv = clamp(viewport01 * ou.fit.xy + ou.fit.zw, vec2f(0.0), vec2f(1.0));
3808
3913
  let chainSample = textureSampleLevel(backdropChain, backdropSampler, uv, ou.shadowLift.w);
3809
3914
  // Premultiplied linear in, straight colour out \u2014 the same unpremultiply the
3810
3915
  // body's own samples take, for the same reason: a partially transparent
3811
3916
  // backdrop must not darken what the material adds back.
3812
3917
  let v = chainSample.rgb / max(chainSample.a, 1e-6);
3813
- return v * (ou.shadowLift.x * rise * shadow.falloff);
3918
+ // The black term's presence, on the shadow's second term: the two are one
3919
+ // shadow with one falloff (W14 G0), so one channel fades both.
3920
+ return v * (ou.shadowLift.x * rise * shadow.falloff * shadow.castMat);
3921
+ }
3922
+
3923
+ /// The DOM branch is the per-pixel mirror of platform-web's materialAtBackdrop.
3924
+ /// It evaluates the linear response, collapse, paint and rim at the stated tone,
3925
+ /// then solves the encoded layer the browser composites. A union's span stays
3926
+ /// per pixel, and the conversion reference never enables an unknown tone.
3927
+ fn dom_material_backdrop() -> vec3f {
3928
+ if (ou.heavyTap.y > 1.5) { return ou.toneColour.rgb; }
3929
+ return vec3f(ou.heavyTap.z);
3930
+ }
3931
+
3932
+ /// The cssTintAlpha secant, at the actual tone rather than before the response.
3933
+ fn dom_material_alpha(composite : vec3f, backdrop : vec3f, alpha : f32) -> f32 {
3934
+ if (alpha <= 1e-6) { return 0.0; }
3935
+ let weights = vec3f(0.2126, 0.7152, 0.0722);
3936
+ let neutral = max((composite - backdrop * (1.0 - alpha)) / alpha, vec3f(0.0));
3937
+ let b = srgb_encode(dot(backdrop, weights));
3938
+ let span = srgb_encode(dot(neutral, weights)) - b;
3939
+ if (abs(span) < ou.heavyTap.w) { return alpha; }
3940
+ return clamp((srgb_encode(dot(composite, weights)) - b) / span, 0.0, 1.0);
3941
+ }
3942
+
3943
+ /// The final encoded solve, including paint and contour light. The least opacity
3944
+ /// needed to keep every channel in gamut is an algebraic constraint, not a fit.
3945
+ /// At the reference B this returns E(C) exactly after browser source-over; away
3946
+ /// from B the scalar layer cannot reproduce the sampled path's local structure.
3947
+ fn dom_material_output(encodedComposite : vec3f, encodedBackdrop : vec3f, alpha : f32) -> vec4f {
3948
+ let c = clamp(encodedComposite, vec3f(0.0), vec3f(1.0));
3949
+ let b = clamp(encodedBackdrop, vec3f(0.0), vec3f(1.0));
3950
+ let need = select((b - c) / max(b, vec3f(1e-6)),
3951
+ (c - b) / max(vec3f(1.0) - b, vec3f(1e-6)), c >= b);
3952
+ let a = clamp(max(alpha, max(need.x, max(need.y, need.z))), 0.0, 1.0);
3953
+ return vec4f(clamp(c - b * (1.0 - a), vec3f(0.0), vec3f(a)), a);
3814
3954
  }
3815
3955
 
3816
3956
  @fragment
@@ -3823,20 +3963,48 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
3823
3963
  var field : vec4f;
3824
3964
  var aux : vec4f;
3825
3965
  var aux2 : vec4f;
3966
+ var presence : vec4f;
3826
3967
  if (ou.flags.w > 0.5) {
3827
3968
  field = textureSampleLevel(fieldTexture, fieldSampler, in.uv, 0.0);
3828
3969
  aux = textureSampleLevel(auxTexture, fieldSampler, in.uv, 0.0);
3829
3970
  aux2 = textureSampleLevel(aux2Texture, fieldSampler, in.uv, 0.0);
3971
+ presence = textureSampleLevel(presenceTexture, fieldSampler, in.uv, 0.0);
3830
3972
  } else {
3831
3973
  let texel = vec2i(in.uv * ou.flags.yz);
3832
3974
  field = textureLoad(fieldTexture, texel, 0);
3833
3975
  aux = textureLoad(auxTexture, texel, 0);
3834
3976
  aux2 = textureLoad(aux2Texture, texel, 0);
3977
+ presence = textureLoad(presenceTexture, texel, 0);
3835
3978
  }
3836
3979
 
3837
3980
  let d = field.x;
3838
3981
  let normal = field.yz;
3839
3982
  let coverage = field.w;
3983
+ /*
3984
+ * The surface's PRESENCE at this pixel (W27d; contract X6) \u2014 the
3985
+ * 'materialization' channel, 1 on a surface nobody is driving.
3986
+ *
3987
+ * It multiplies every term the material ADDS to what is behind it: the lens's
3988
+ * depth and magnitude, the body's mix away from the unblurred backdrop, the
3989
+ * material's own alpha, the author tint's coverage, the inner shadow, the rim,
3990
+ * the outer shadow and the highlight pass's light. It does NOT multiply the
3991
+ * coverage: a presence spent there would be a crossfade of the whole composite,
3992
+ * which is the alpha Apple's rule rules out ("prefer setting the effect
3993
+ * property over the alpha") and which the runtime cannot afford either \u2014 the
3994
+ * host that wrote it would form a Backdrop Root and lose the group's sampling.
3995
+ *
3996
+ * Not to be confused with 'present' below, which is what survives the backdrop
3997
+ * COLLAPSE. The two multiply many of the same terms and mean different things:
3998
+ * one is the author's presence, the other is the material having taken its
3999
+ * backdrop's tone. Both are one multiplication by one on the resting bed.
4000
+ *
4001
+ * The channel is strictly ABOVE zero here. Exactly 0 is 'Glass.identity' and is
4002
+ * resolved on the CPU by dropping the member before this pass ever runs
4003
+ * ('instances.ts'), so a surface that is not there has no silhouette to draw a
4004
+ * faded material into and no shape to union with its neighbours. What this
4005
+ * shader owns is the continuum between the endpoints.
4006
+ */
4007
+ let mat = clamp(presence.x, 0.0, 1.0);
3840
4008
 
3841
4009
  /*
3842
4010
  * The outer shadow (W8) sits UNDER the material, so it is resolved before the
@@ -3892,7 +4060,13 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
3892
4060
  // Per-pixel, unioned through the field pass. See the module note. 'aux.x' is
3893
4061
  // the authored thickness times the lensStrength channel (W12 G2); the lens's
3894
4062
  // depth and the inner shadow's are both evaluated from it and the span below.
3895
- let lensThick = max(aux.x, 0.0);
4063
+ //
4064
+ // Times the presence (W27d), because this is the one number Apple's own
4065
+ // description of materializing names \u2014 "by gradually modulating the light
4066
+ // bending and lensing" \u2014 and both depths are functions of it, so the lens
4067
+ // shallows and weakens together and the inner shadow's depth follows the same
4068
+ // channel rather than a second statement of it.
4069
+ let lensThick = max(aux.x, 0.0) * mat;
3896
4070
  // The thickness curve off the span of whichever surface owns this pixel
3897
4071
  // (W11c). 'sizeK' is the thickness factor, 0..1: zero on anything at or below
3898
4072
  // the profile's 'sizeSpanMin', saturated at 'sizeSpanMax', folded under the
@@ -4070,6 +4244,8 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
4070
4244
  let scatterLod = clamp(ou.size.w + log2(max(gainEff, 1e-4)), 0.0, ou.lens.w);
4071
4245
 
4072
4246
  var backdrop = vec3f(0.0);
4247
+ let domMaterial = ou.heavyTap.y > 0.5;
4248
+ if (domMaterial) { backdrop = dom_material_backdrop(); }
4073
4249
  if (ou.flags.x > 0.5) {
4074
4250
  // Both components at the refracted position (W11c G2): the band and the
4075
4251
  // interior are one body, and the displacement alone is the lens.
@@ -4105,6 +4281,26 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
4105
4281
  // the glass.
4106
4282
  let scatterColour = scatterSample.rgb / max(scatterSample.a, 1e-6);
4107
4283
  backdrop = mix(bodySample.rgb / max(bodySample.a, 1e-6), scatterColour, kScatter);
4284
+ /*
4285
+ * The body's own half of the presence (W27d): a material at half presence
4286
+ * shows half the BLUR, not half the surface. What a surface at presence 0
4287
+ * stands over is the page as it is, so the two components' composite lerps
4288
+ * back to the unblurred backdrop \u2014 the chain's own level 0, which is the
4289
+ * texture before any of the pyramid's widths were applied.
4290
+ *
4291
+ * Read at 'refractedUv' rather than at this pixel's own position: the lens is
4292
+ * scaled by the same channel, so the sample walks back to the pixel as the
4293
+ * presence falls and arrives exactly there at 0. One uv, one read, and no
4294
+ * discontinuity between the two ends.
4295
+ *
4296
+ * The branch is what keeps the resting material byte-identical \u2014 at presence
4297
+ * 1 the extra tap is not taken at all \u2014 and it is also what keeps a present
4298
+ * surface from paying for a channel it is not using.
4299
+ */
4300
+ if (mat < 1.0) {
4301
+ let sharpSample = textureSampleLevel(backdropChain, backdropSampler, refractedUv, 0.0);
4302
+ backdrop = mix(sharpSample.rgb / max(sharpSample.a, 1e-6), backdrop, mat);
4303
+ }
4108
4304
  }
4109
4305
 
4110
4306
  // Adaptive tint. 'adapt.w' is the strength the accessibility policy and the
@@ -4255,7 +4451,7 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
4255
4451
  * There the CSS tier's own 'backdrop-filter' is what carries the transmission.
4256
4452
  */
4257
4453
  var toneTarget = ou.toneColour.rgb;
4258
- if (ou.flags.x > 0.5) {
4454
+ if (ou.flags.x > 0.5 || domMaterial) {
4259
4455
  toneTarget = mix(toneTarget, backdrop, clamp(ou.toneRowThick.w, 0.0, 1.0));
4260
4456
  }
4261
4457
 
@@ -4273,7 +4469,15 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
4273
4469
  // opaque" is a statement about how much material there is), and the backdrop
4274
4470
  // adaptation moved it above. The author's colour never touches it \u2014 but not
4275
4471
  // for the reason the composition contract first gave (claims \xA75.36).
4276
- var colour = mix(backdrop, adapted, adaptedAlpha);
4472
+ /*
4473
+ * The material's alpha, times the presence (W27d) \u2014 and applied HERE rather
4474
+ * than to 'adaptedAlpha' above, which is load-bearing: that alpha is the
4475
+ * divisor the collapse's own composite is un-premultiplied by, so scaling it
4476
+ * there would move the adapted COLOUR as well as the amount of it. Presence is
4477
+ * how much of the material is there, not what the material is.
4478
+ */
4479
+ let presentAlpha = adaptedAlpha * mat;
4480
+ var colour = mix(backdrop, adapted, presentAlpha);
4277
4481
  /*
4278
4482
  * How much of this pixel the SURFACE owns, as the canvas will composite it.
4279
4483
  *
@@ -4295,10 +4499,41 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
4295
4499
  * in encoded sRGB, so the alpha is the CSS tier's, not the linear profile's.
4296
4500
  */
4297
4501
  var bodyAlpha = 1.0;
4298
- if (ou.flags.x <= 0.5) {
4502
+ var domAlpha = 1.0;
4503
+ if (domMaterial) {
4504
+ // The collapse transmits k*c of the DOM proxy as well. Solve the secant
4505
+ // after the linear material, never feed its encoded alpha back into R.
4506
+ /*
4507
+ * Times the presence (W27d), on the same factor 'presentAlpha' carries into
4508
+ * 'colour' just above \u2014 this branch's body is a SOLVED layer rather than a
4509
+ * composite, so the secant's own input is where the channel reaches it.
4510
+ *
4511
+ * It has to be here rather than on the result. The secant divides the
4512
+ * composite by this alpha to recover the material's own neutral, so scaling
4513
+ * both together leaves that neutral (and the span it spans) at exactly what
4514
+ * presence 1 solves, and only the returned coverage travels. Left unscaled,
4515
+ * the neutral would walk toward the backdrop as the surface thins, the span
4516
+ * would fall under 'heavyTap.w', and the guard would hand back the FULL
4517
+ * alpha \u2014 a flat tone painted over a page the surface has left.
4518
+ *
4519
+ * At presence 1 the factor is exactly 1.0 and the expression is bit-identical
4520
+ * to the resting one; at 0 the secant's own '<= 1e-6' guard returns 0.
4521
+ */
4522
+ let transmission = toneAdapt * clamp(ou.toneRowThick.w, 0.0, 1.0);
4523
+ domAlpha = dom_material_alpha(colour, backdrop,
4524
+ clamp(adaptedAlpha - transmission, 0.0, 1.0) * mat);
4525
+ } else if (ou.flags.x <= 0.5) {
4299
4526
  colour = adapted;
4300
- bodyAlpha = adaptedAlpha;
4527
+ bodyAlpha = presentAlpha;
4301
4528
  }
4529
+ /*
4530
+ * One gap this tier cannot close from here, named rather than left to be
4531
+ * discovered (W27d): on an unsampled group the blurred backdrop is a DOM proxy
4532
+ * beneath this canvas, so the body's mix toward the unblurred backdrop above
4533
+ * has no texture to mix with. A layer that fades to alpha 0 there reveals the
4534
+ * PROXY's blur rather than the page \u2014 presence takes the tint, the rim and the
4535
+ * shadows out, and the blur is the host's to fade with it.
4536
+ */
4302
4537
 
4303
4538
  // The author tint (W10). 'aux.w' is the per-pixel strength, unioned in the
4304
4539
  // field pass, so a toolbar can carry one tinted control among plain ones; the
@@ -4360,16 +4595,40 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
4360
4595
  * reach painted pixels only (W23 S10).
4361
4596
  */
4362
4597
  var rimTintColour = vec3f(1.0);
4363
- if (aux.w > 0.0) {
4598
+ /*
4599
+ * The author tint's coverage at this pixel, times the presence (W27d). The
4600
+ * paint is part of the material and not a thing painted onto the page, so a
4601
+ * dissolving surface takes its colour with it \u2014 at presence 0 the pixel is the
4602
+ * backdrop and not a flat orange over it. At presence 1 this is
4603
+ * 'clamp(aux.w, 0, 1)' exactly, which is what the tint's own law was fitted on.
4604
+ */
4605
+ let tintK = clamp(aux.w, 0.0, 1.0) * mat;
4606
+ if (tintK > 0.0) {
4364
4607
  // The untinted material's luminance at this pixel. Over a backdrop that is
4365
4608
  // the composite; as a layer it is the layer over the tone the host measured
4366
4609
  // for the group \u2014 zero where nothing was measured, the same reference-level
4367
4610
  // convention the CSS tier's 'materialLuminance' takes (within its 0.02).
4368
4611
  let u = bodyAlpha * dot(colour, vec3f(0.2126, 0.7152, 0.0722)) + (1.0 - bodyAlpha) * ou.toneColour.w;
4369
- let grip = clamp(ou.seed.w, 0.0, 1.0) * clamp(ou.tone.z, 0.0, 1.0) * (1.0 - toneAdapt);
4612
+ let grip = clamp(ou.seed.w, 0.0, 1.0) * clamp(ou.tone.z, 0.0, 1.0) *
4613
+ (1.0 - toneAdapt * (1.0 - clamp(ou.rim.w, 0.0, 1.0)));
4370
4614
  let shade = mix(1.0, clamp(mix(ou.tone.x, ou.tone.y, clamp(u, 0.0, 1.0)), 0.0, 1.0), grip);
4371
- let layer = ou.seed.rgb * shade;
4372
- let s = clamp(aux.w, 0.0, 1.0);
4615
+ // The identity branch preserves the active seed's arithmetic bit for bit.
4616
+ var seed = ou.seed.rgb;
4617
+ if (ou.rim.z < 1.0) {
4618
+ let neutral = max(seed.r, max(seed.g, seed.b));
4619
+ seed = mix(vec3f(neutral), seed, clamp(ou.rim.z, 0.0, 1.0));
4620
+ }
4621
+ let layer = seed * shade;
4622
+ /*
4623
+ * The recede's chroma collapse (W27c) shapes WHAT the paint is; presence
4624
+ * (W27d) is how much of it is there. They compose on this one strength and
4625
+ * each reaches it once: the collapse through 'seed', the presence through
4626
+ * 'tintK'. 's' is the coverage every consumer below reads \u2014 the rim's tint
4627
+ * mix, the encoded fold, and the DOM branch's own alpha \u2014 so folding the
4628
+ * presence in here is what keeps it from being applied twice downstream.
4629
+ */
4630
+ let s = tintK;
4631
+ if (domMaterial) { domAlpha = 1.0 - (1.0 - s) * (1.0 - domAlpha); }
4373
4632
  let layerLuma = max(dot(layer, vec3f(0.2126, 0.7152, 0.0722)), 0.05);
4374
4633
  rimTintColour = mix(vec3f(1.0), layer / layerLuma, clamp(ou.rimLaw.w, 0.0, 1.0) * s);
4375
4634
  let encodedMaterial = linear_to_srgb(clamp(colour, vec3f(0.0), vec3f(1.0)));
@@ -4412,7 +4671,11 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
4412
4671
  // A multiplicative occlusion of the whole composite. As a layer that is the
4413
4672
  // colour scaled and the alpha raised \u2014 (k\xB7a\xB7c, 1 \u2212 k\xB7(1 \u2212 a)) composites to
4414
4673
  // k times what (a\xB7c, a) would \u2014 and at bodyAlpha 1 it is the plain product.
4415
- let shadowKeep = 1.0 - shadowProfile * shadowDepth * ou.light.w * present;
4674
+ // Times the presence (W27d) on the AMPLITUDE, beside the depth the same channel
4675
+ // already shallowed through 'lensThick': the occlusion is the material's own,
4676
+ // and a material that is half there occludes half as much of what is behind it.
4677
+ let shadowKeep = 1.0 - shadowProfile * shadowDepth * ou.light.w * present * mat;
4678
+ if (domMaterial) { domAlpha = 1.0 - shadowKeep * (1.0 - domAlpha); }
4416
4679
  let shadowedAlpha = 1.0 - shadowKeep * (1.0 - bodyAlpha);
4417
4680
  colour = colour * (shadowKeep * bodyAlpha / max(shadowedAlpha, 1e-6));
4418
4681
  bodyAlpha = shadowedAlpha;
@@ -4464,7 +4727,7 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
4464
4727
  let rimLuma = materialAlpha * dot(materialColour, vec3f(0.2126, 0.7152, 0.0722))
4465
4728
  + (1.0 - materialAlpha) * ou.toneColour.w;
4466
4729
  let rimAmplitude = ou.rim.y + ou.rimLaw.x * rimLuma;
4467
- let rimCollapsed = mix(ou.rimLaw.y, ou.rimLaw.z, clamp(aux.w, 0.0, 1.0));
4730
+ let rimCollapsed = mix(ou.rimLaw.y, ou.rimLaw.z, tintK);
4468
4731
  /*
4469
4732
  * The lit edge (W24; claims \xA75.107) \u2014 the directional factor the whole rim is
4470
4733
  * multiplied by, symmetric about 'rimLit.xy'.
@@ -4524,10 +4787,15 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
4524
4787
  */
4525
4788
  let alongSide = clamp((rel.x / halfExt.x) * (rel.y / halfExt.y), -1.0, 1.0);
4526
4789
  let alongFactor = max(1.0 + ou.rimLit.w * sizeThick * alongSide, 0.0);
4527
- let rim = rw * lit * alongFactor * (rimAmplitude * present + rimCollapsed * toneAdapt);
4790
+ // The whole rim \u2014 both the appearance's own and the one the collapse keeps \u2014
4791
+ // times the presence (W27d). The rim is the mark that says a surface is HERE,
4792
+ // which is the first thing a surface that is not there stops saying; the same
4793
+ // argument the collapse's 'present' makes, from the author's side.
4794
+ let rim = rw * lit * alongFactor * (rimAmplitude * present + rimCollapsed * toneAdapt) * mat;
4528
4795
  let rimLight = rim * rimTintColour;
4529
- if (ou.flags.x > 0.5) {
4796
+ if (ou.flags.x > 0.5 || domMaterial) {
4530
4797
  colour = colour + rimLight;
4798
+ if (domMaterial) { domAlpha = clamp(domAlpha + rim, 0.0, 1.0); }
4531
4799
  } else {
4532
4800
  // Added light has no premultiplied form of its own \u2014 a canvas colour may
4533
4801
  // not exceed its alpha \u2014 so the layer carries the light in its opacity:
@@ -4555,6 +4823,17 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
4555
4823
  // translucent surface shows the page through it, not its own shadow. (With
4556
4824
  // an opaque body the two are the same quantity, which is how the shadow was
4557
4825
  // first written and why the difference only surfaced with the layer form.)
4826
+ if (domMaterial) {
4827
+ // Coverage precedes the gamut solve. The sampled rim may exceed white
4828
+ // before antialiasing; clipping it first would dim the half-covered edge.
4829
+ // Include the exterior shadow in the same target so its light and opacity
4830
+ // remain one valid premultiplied layer at that edge too.
4831
+ let b = linear_to_srgb(backdrop);
4832
+ let compositeEncoded = linear_to_srgb(max(colour, vec3f(0.0))) * coverage
4833
+ + (b * (1.0 - shadowAlpha) + liftEncoded) * (1.0 - coverage);
4834
+ let alpha = domAlpha * coverage + shadowAlpha * (1.0 - coverage);
4835
+ return dom_material_output(compositeEncoded, b, alpha);
4836
+ }
4558
4837
  let body = encode_output(max(colour, vec3f(0.0)), coverage * bodyAlpha);
4559
4838
  return vec4f(
4560
4839
  body.rgb + liftEncoded * (1.0 - coverage),
@@ -4647,10 +4926,12 @@ function allShaderSource() {
4647
4926
 
4648
4927
  // ../renderer-webgpu/dist/passes.js
4649
4928
  var fieldUsage = () => GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING;
4929
+ var PRESENCE_TEXTURE_FORMAT = "r16float";
4650
4930
  var PREMULTIPLIED_OVER = {
4651
4931
  color: { srcFactor: "one", dstFactor: "one-minus-src-alpha", operation: "add" },
4652
4932
  alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha", operation: "add" }
4653
4933
  };
4934
+ var groupResourceId = (plane, groupId) => plane === "" ? groupId : `${plane}/${groupId}`;
4654
4935
  function createPassRunner(context) {
4655
4936
  const { device, pool, cache } = context;
4656
4937
  const uniforms = /* @__PURE__ */ new Map();
@@ -4690,7 +4971,8 @@ function createPassRunner(context) {
4690
4971
  targets: [
4691
4972
  { format: WORKING_TEXTURE_FORMAT },
4692
4973
  { format: WORKING_TEXTURE_FORMAT },
4693
- { format: WORKING_TEXTURE_FORMAT }
4974
+ { format: WORKING_TEXTURE_FORMAT },
4975
+ { format: PRESENCE_TEXTURE_FORMAT }
4694
4976
  ]
4695
4977
  },
4696
4978
  primitive: { topology: "triangle-list" }
@@ -4741,28 +5023,35 @@ function createPassRunner(context) {
4741
5023
  const rectHeight = Math.max(1, Math.round(args.rectDevice.height));
4742
5024
  const width = Math.max(1, Math.round(args.rectDevice.width * args.renderScale));
4743
5025
  const height = Math.max(1, Math.round(args.rectDevice.height * args.renderScale));
4744
- const field = pool.acquire(poolKey.groupField(args.groupId), {
5026
+ const field = pool.acquire(poolKey.groupField(args.resourceId), {
4745
5027
  width,
4746
5028
  height,
4747
5029
  format: WORKING_TEXTURE_FORMAT,
4748
5030
  usage: fieldUsage(),
4749
- label: `vitrea:group:${args.groupId}:field`
5031
+ label: `vitrea:group:${args.resourceId}:field`
4750
5032
  });
4751
- const aux = pool.acquire(poolKey.groupAux(args.groupId), {
5033
+ const aux = pool.acquire(poolKey.groupAux(args.resourceId), {
4752
5034
  width,
4753
5035
  height,
4754
5036
  format: WORKING_TEXTURE_FORMAT,
4755
5037
  usage: fieldUsage(),
4756
- label: `vitrea:group:${args.groupId}:aux`
5038
+ label: `vitrea:group:${args.resourceId}:aux`
4757
5039
  });
4758
- const aux2 = pool.acquire(poolKey.groupAux2(args.groupId), {
5040
+ const aux2 = pool.acquire(poolKey.groupAux2(args.resourceId), {
4759
5041
  width,
4760
5042
  height,
4761
5043
  format: WORKING_TEXTURE_FORMAT,
4762
5044
  usage: fieldUsage(),
4763
- label: `vitrea:group:${args.groupId}:aux2`
5045
+ label: `vitrea:group:${args.resourceId}:aux2`
5046
+ });
5047
+ const presence = pool.acquire(poolKey.groupPresence(args.resourceId), {
5048
+ width,
5049
+ height,
5050
+ format: PRESENCE_TEXTURE_FORMAT,
5051
+ usage: fieldUsage(),
5052
+ label: `vitrea:group:${args.resourceId}:presence`
4764
5053
  });
4765
- const slot = uniformSlot(`field:${args.groupId}`, 12);
5054
+ const slot = uniformSlot(`field:${args.resourceId}`, 12);
4766
5055
  slot.data[0] = rectWidth;
4767
5056
  slot.data[1] = rectHeight;
4768
5057
  slot.data[2] = args.cssPerDevice;
@@ -4776,12 +5065,12 @@ function createPassRunner(context) {
4776
5065
  slot.data[11] = 0;
4777
5066
  new Uint32Array(slot.data.buffer, slot.data.byteOffset + 32, 1)[0] = args.instanceCount;
4778
5067
  slot.write();
4779
- const instances = storageSlot(args.groupId);
5068
+ const instances = storageSlot(args.resourceId);
4780
5069
  instances.ensure(Math.max(args.instanceCount, 1) * INSTANCE_BYTES);
4781
5070
  instances.write(args.instances, Math.max(args.instanceCount, 1) * (INSTANCE_BYTES / 4));
4782
5071
  const pipeline = fieldPipeline(args.family);
4783
5072
  const pass = encoder.beginRenderPass({
4784
- label: `vitrea:pass:field:${args.groupId}`,
5073
+ label: `vitrea:pass:field:${args.resourceId}`,
4785
5074
  ...timed(PASS_LABEL.field),
4786
5075
  colorAttachments: [
4787
5076
  {
@@ -4801,6 +5090,15 @@ function createPassRunner(context) {
4801
5090
  loadOp: "clear",
4802
5091
  storeOp: "store",
4803
5092
  clearValue: { r: 0, g: 0, b: 0, a: 0 }
5093
+ },
5094
+ {
5095
+ view: presence.createView(),
5096
+ loadOp: "clear",
5097
+ // Cleared to the IDLE presence rather than to zero: a texel the
5098
+ // fullscreen triangle never wrote must not read as a material that
5099
+ // has been asked to disappear.
5100
+ storeOp: "store",
5101
+ clearValue: { r: 1, g: 0, b: 0, a: 0 }
4804
5102
  }
4805
5103
  ]
4806
5104
  });
@@ -4818,13 +5116,14 @@ function createPassRunner(context) {
4818
5116
  field,
4819
5117
  aux,
4820
5118
  aux2,
5119
+ presence,
4821
5120
  width,
4822
5121
  height,
4823
5122
  upsampled: width !== rectWidth || height !== rectHeight
4824
5123
  };
4825
5124
  },
4826
5125
  opticsPass(encoder, args) {
4827
- const slot = uniformSlot(`optics:${args.groupId}`, 112);
5126
+ const slot = uniformSlot(`optics:${args.resourceId}`, 112);
4828
5127
  const d = slot.data;
4829
5128
  d[0] = args.viewportDevice[0];
4830
5129
  d[1] = args.viewportDevice[1];
@@ -4856,8 +5155,8 @@ function createPassRunner(context) {
4856
5155
  d[27] = args.sizeFold;
4857
5156
  d[28] = args.rimWidth;
4858
5157
  d[29] = args.rimAlpha;
4859
- d[30] = args.specularPower;
4860
- d[31] = args.specularGain;
5158
+ d[30] = args.tintChromaScale ?? 1;
5159
+ d[31] = args.tintShadeCollapseRetention ?? 0;
4861
5160
  d[32] = args.lightDirection[0];
4862
5161
  d[33] = args.lightDirection[1];
4863
5162
  d[34] = args.shadowDepth;
@@ -4935,16 +5234,16 @@ function createPassRunner(context) {
4935
5234
  d[106] = 0;
4936
5235
  d[107] = 0;
4937
5236
  d[108] = args.heavyTapEnabled ? 1 : 0;
4938
- d[109] = 0;
4939
- d[110] = 0;
4940
- d[111] = 0;
5237
+ d[109] = args.domMaterial?.mode ?? 0;
5238
+ d[110] = args.domMaterial?.referenceBackdropLuminance ?? 0;
5239
+ d[111] = args.domMaterial?.minimumTintContrast ?? 0;
4941
5240
  slot.write();
4942
5241
  const chain = args.backdrop?.chain ?? placeholderView;
4943
5242
  const body = args.backdrop?.body ?? placeholderView;
4944
5243
  const heavy = args.backdrop?.heavy ?? placeholderView;
4945
5244
  const pipeline = opticsPipeline(args.targetFormat);
4946
5245
  const pass = encoder.beginRenderPass({
4947
- label: `vitrea:pass:optics:${args.groupId}`,
5246
+ label: `vitrea:pass:optics:${args.resourceId}`,
4948
5247
  ...timed(PASS_LABEL.optics),
4949
5248
  colorAttachments: [{ view: args.target, loadOp: "load", storeOp: "store" }]
4950
5249
  });
@@ -4963,14 +5262,15 @@ function createPassRunner(context) {
4963
5262
  // read at all when the governor shrank them below the group's rect.
4964
5263
  { binding: 6, resource: context.flatSampler },
4965
5264
  { binding: 7, resource: args.fields.aux2.createView() },
4966
- { binding: 8, resource: heavy }
5265
+ { binding: 8, resource: heavy },
5266
+ { binding: 9, resource: args.fields.presence.createView() }
4967
5267
  ]
4968
5268
  }));
4969
5269
  pass.draw(3);
4970
5270
  pass.end();
4971
5271
  },
4972
5272
  highlightPass(encoder, args) {
4973
- const slot = uniformSlot(`highlight:${args.groupId}`, 32);
5273
+ const slot = uniformSlot(`highlight:${args.resourceId}`, 32);
4974
5274
  const d = slot.data;
4975
5275
  d[0] = args.viewportDevice[0];
4976
5276
  d[1] = args.viewportDevice[1];
@@ -5008,7 +5308,7 @@ function createPassRunner(context) {
5008
5308
  slot.write();
5009
5309
  const pipeline = highlightPipeline(args.targetFormat);
5010
5310
  const pass = encoder.beginRenderPass({
5011
- label: `vitrea:pass:highlight:${args.groupId}`,
5311
+ label: `vitrea:pass:highlight:${args.resourceId}`,
5012
5312
  ...timed(PASS_LABEL.highlight),
5013
5313
  colorAttachments: [{ view: args.target, loadOp: "load", storeOp: "store" }]
5014
5314
  });
@@ -5020,7 +5320,8 @@ function createPassRunner(context) {
5020
5320
  { binding: 0, resource: { buffer: slot.buffer } },
5021
5321
  { binding: 1, resource: args.fields.field.createView() },
5022
5322
  { binding: 2, resource: args.fields.aux.createView() },
5023
- { binding: 3, resource: context.flatSampler }
5323
+ { binding: 3, resource: context.flatSampler },
5324
+ { binding: 4, resource: args.fields.presence.createView() }
5024
5325
  ]
5025
5326
  }));
5026
5327
  pass.draw(3);
@@ -5043,13 +5344,15 @@ function createPassRunner(context) {
5043
5344
  setTimeline(next) {
5044
5345
  timeline = next;
5045
5346
  },
5046
- forget(groupId) {
5047
- pool.release(poolKey.groupField(groupId));
5048
- pool.release(poolKey.groupAux(groupId));
5049
- pool.release(poolKey.groupAux2(groupId));
5050
- storages.get(groupId)?.destroy();
5051
- storages.delete(groupId);
5052
- for (const key of [`field:${groupId}`, `optics:${groupId}`, `highlight:${groupId}`]) {
5347
+ forget(resourceId) {
5348
+ pool.release(poolKey.groupField(resourceId));
5349
+ pool.release(poolKey.groupAux(resourceId));
5350
+ pool.release(poolKey.groupAux2(resourceId));
5351
+ pool.release(poolKey.groupPresence(resourceId));
5352
+ storages.get(resourceId)?.destroy();
5353
+ storages.delete(resourceId);
5354
+ for (const pass of ["field", "optics", "highlight"]) {
5355
+ const key = `${pass}:${resourceId}`;
5053
5356
  uniforms.get(key)?.buffer.destroy();
5054
5357
  uniforms.delete(key);
5055
5358
  }
@@ -5710,6 +6013,7 @@ function createWebGPURenderer(options = {}) {
5710
6013
  let generations = 0;
5711
6014
  let lastFrameTimeMs;
5712
6015
  let targets;
6016
+ const planesDrawn = /* @__PURE__ */ new Set();
5713
6017
  let pendingEncoder;
5714
6018
  let pendingRebuilds = 0;
5715
6019
  let pendingUnbuilt = [];
@@ -5831,7 +6135,7 @@ function createWebGPURenderer(options = {}) {
5831
6135
  return 0;
5832
6136
  return heavyTapSigmaAtScale(material, viewport.devicePixelRatio) / Math.max(viewport.devicePixelRatio, 1e-3);
5833
6137
  };
5834
- const groupTintSeed = (input) => input.surfaces.find((surface) => surface.fieldReferenceOnly !== true && (surface.tint?.strength ?? 0) > 0)?.tint?.color;
6138
+ const groupTintSeed = (input) => input.surfaces.find((surface) => drawsMaterial(surface) && (surface.tint?.strength ?? 0) > 0)?.tint?.color;
5835
6139
  const stateOf = (input, resolution) => {
5836
6140
  const resolved = resolution?.groups.find((group) => group.groupId === input.groupId);
5837
6141
  if (resolved === void 0) {
@@ -5933,10 +6237,15 @@ function createWebGPURenderer(options = {}) {
5933
6237
  ];
5934
6238
  const skipped = [];
5935
6239
  let drawn = 0;
6240
+ planesDrawn.add(active.plane);
6241
+ const resourceOf = (groupId) => groupResourceId(active.plane, groupId);
6242
+ const releaseIdle = (groupId) => passes.forget(resourceOf(groupId));
5936
6243
  for (const entry of groups.values()) {
5937
6244
  const input = entry.input;
5938
- if (input.surfaces.length === 0)
6245
+ if (input.surfaces.length === 0) {
6246
+ releaseIdle(input.groupId);
5939
6247
  continue;
6248
+ }
5940
6249
  const policy = resolution?.accessibility.material ?? accessibility;
5941
6250
  let surfaces;
5942
6251
  try {
@@ -5946,6 +6255,7 @@ function createWebGPURenderer(options = {}) {
5946
6255
  groupId: input.groupId,
5947
6256
  reason: error instanceof Error ? error.message : String(error)
5948
6257
  });
6258
+ releaseIdle(input.groupId);
5949
6259
  continue;
5950
6260
  }
5951
6261
  const union = unionOf(input);
@@ -5958,15 +6268,17 @@ function createWebGPURenderer(options = {}) {
5958
6268
  const shadowReachPx = outerShadowReachPx(shadow, reachOcclusion);
5959
6269
  const snapped = snapRectToDevicePixels(groupFieldRect(surfaces, union, void 0, shadowReachPx), dpr);
5960
6270
  const rectDevice = clipFieldRectToCanvas(snapped, dpr, viewportDevice);
5961
- if (rectDevice === void 0)
6271
+ if (rectDevice === void 0) {
6272
+ releaseIdle(input.groupId);
5962
6273
  continue;
6274
+ }
5963
6275
  const surfaceRectDevice = shadowReachPx === 0 ? rectDevice : clipFieldRectToCanvas(snapRectToDevicePixels(groupFieldRect(surfaces, union), dpr), dpr, viewportDevice) ?? rectDevice;
5964
6276
  const packed = packInstances(surfaces, [
5965
6277
  rectDevice.x * cssPerDevice,
5966
6278
  rectDevice.y * cssPerDevice
5967
6279
  ]);
5968
6280
  const fields = passes.fieldPass(encoder, {
5969
- groupId: input.groupId,
6281
+ resourceId: resourceOf(input.groupId),
5970
6282
  family: governor.knobs.fieldFamily,
5971
6283
  rectDevice,
5972
6284
  cssPerDevice,
@@ -5984,11 +6296,7 @@ function createWebGPURenderer(options = {}) {
5984
6296
  const pyramid = sourceId === void 0 ? void 0 : pyramids.resources(sourceId);
5985
6297
  const adapt = sourceId === void 0 ? void 0 : adaptationFor(sourceId).values;
5986
6298
  const nominalOptics = material.optics[variant];
5987
- const optics = opticsUnderPolicy(pyramid === void 0 && input.unsampledMaterial !== void 0 ? {
5988
- ...nominalOptics,
5989
- tint: input.unsampledMaterial.tint,
5990
- tintAlpha: input.unsampledMaterial.tintAlpha
5991
- } : nominalOptics, policy, material);
6299
+ const optics = opticsUnderPolicy(nominalOptics, policy, material);
5992
6300
  const backdropTone = [
5993
6301
  material.backdropToneLow,
5994
6302
  material.backdropToneHigh,
@@ -5999,7 +6307,7 @@ function createWebGPURenderer(options = {}) {
5999
6307
  const refraction = effectiveRefraction(accessibilityRefractionCap(policy), state.refraction);
6000
6308
  const refractionScale = material.refractionScale[refraction];
6001
6309
  passes.opticsPass(encoder, {
6002
- groupId: input.groupId,
6310
+ resourceId: resourceOf(input.groupId),
6003
6311
  target: active.optics,
6004
6312
  targetFormat: active.format,
6005
6313
  rectDevice,
@@ -6043,6 +6351,8 @@ function createWebGPURenderer(options = {}) {
6043
6351
  tintSeed: (policy.glass === "none" ? void 0 : groupTintSeed(input)) ?? optics.tint,
6044
6352
  tintToneAdaptation: tintToneAdaptation(policy, material),
6045
6353
  tintShade: [material.tintShadeDark, material.tintShadeLight, material.tintShadeStrength],
6354
+ tintChromaScale: material.tintChromaScale ?? 1,
6355
+ tintShadeCollapseRetention: material.tintShadeCollapseRetention ?? 0,
6046
6356
  // The band's half-width is a per-scale reading since W23: the reference's
6047
6357
  // rim narrows between the scales where vitrea's widened (claims §5.100
6048
6358
  // §5). At dpr 1, and on any variant whose two anchors are equal, this is
@@ -6091,6 +6401,10 @@ function createWebGPURenderer(options = {}) {
6091
6401
  // itself is already in the texture, so this pass only chooses which of
6092
6402
  // two textures the deep sample comes from.
6093
6403
  heavyTapEnabled: pyramid?.heavy !== void 0,
6404
+ ...pyramid === void 0 && input.unsampledMaterial !== void 0 ? { domMaterial: {
6405
+ ...input.unsampledMaterial,
6406
+ mode: input.backdropTone === void 0 ? 1 : 2
6407
+ } } : {},
6094
6408
  shadowDepth: optics.shadowDepth,
6095
6409
  shadowAlpha: optics.shadowAlpha,
6096
6410
  // The size law's gains, per group (W2); the per-pixel factor they
@@ -6196,9 +6510,9 @@ function createWebGPURenderer(options = {}) {
6196
6510
  shadow.thickOcclusionAt160
6197
6511
  ],
6198
6512
  outerShadowLift: [
6199
- // The lift needs a chain to copy; without one there is nothing to add,
6200
- // and `hasBackdrop` in the shader says the same thing a second time.
6201
- pyramid === void 0 || policy.glass === "none" ? 0 : shadow.liftAmplitude,
6513
+ // A DOM layer can evaluate the lift at its stated tone, but not at
6514
+ // unknown exterior pixels. No tone still means no light to add.
6515
+ policy.glass === "none" || pyramid === void 0 && (input.unsampledMaterial === void 0 || input.backdropTone === void 0) ? 0 : shadow.liftAmplitude,
6202
6516
  shadow.liftSpanMin,
6203
6517
  shadow.liftSpanFull,
6204
6518
  liftChainLod(shadow.liftBlurSigmaCss, pyramid)
@@ -6214,7 +6528,7 @@ function createWebGPURenderer(options = {}) {
6214
6528
  if (active.highlight !== void 0) {
6215
6529
  const lead = surfaces.reduce((best, surface) => surface.channels.glow > best.channels.glow ? surface : best, surfaces[0]);
6216
6530
  passes.highlightPass(encoder, {
6217
- groupId: input.groupId,
6531
+ resourceId: resourceOf(input.groupId),
6218
6532
  target: active.highlight,
6219
6533
  targetFormat: active.format,
6220
6534
  // The surface's own rect, not the shadow's — see `surfaceRectDevice`.
@@ -6361,7 +6675,8 @@ function createWebGPURenderer(options = {}) {
6361
6675
  },
6362
6676
  removeGroup(groupId) {
6363
6677
  groups.delete(groupId);
6364
- runner?.forget(groupId);
6678
+ for (const plane of planesDrawn)
6679
+ runner?.forget(groupResourceId(plane, groupId));
6365
6680
  },
6366
6681
  setAccessibility(policy) {
6367
6682
  accessibility = policy;
@@ -6377,7 +6692,8 @@ function createWebGPURenderer(options = {}) {
6377
6692
  targets = {
6378
6693
  optics: next.optics,
6379
6694
  ...next.highlight === void 0 ? {} : { highlight: next.highlight },
6380
- format: next.format ?? OUTPUT_TEXTURE_FORMAT
6695
+ format: next.format ?? OUTPUT_TEXTURE_FORMAT,
6696
+ plane: next.plane ?? ""
6381
6697
  };
6382
6698
  },
6383
6699
  drawFrame(args) {
@@ -6385,7 +6701,8 @@ function createWebGPURenderer(options = {}) {
6385
6701
  targets = {
6386
6702
  optics: args.optics,
6387
6703
  ...args.highlight === void 0 ? {} : { highlight: args.highlight },
6388
- format: args.format ?? OUTPUT_TEXTURE_FORMAT
6704
+ format: args.format ?? OUTPUT_TEXTURE_FORMAT,
6705
+ plane: args.plane ?? ""
6389
6706
  };
6390
6707
  pyramids.beginFrame(args.frame.id);
6391
6708
  pyramids.setTimeline(args.timing);
@@ -6503,5 +6820,5 @@ function createWebGPURenderer(options = {}) {
6503
6820
  }
6504
6821
 
6505
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 };
6506
- //# sourceMappingURL=dist-PT4PUS4K.js.map
6507
- //# sourceMappingURL=dist-PT4PUS4K.js.map
6823
+ //# sourceMappingURL=dist-C43H3RKY.js.map
6824
+ //# sourceMappingURL=dist-C43H3RKY.js.map