@vitreajs/vitrea 0.1.1 → 0.3.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 +89 -19
- package/dist/{dist-FGJI5LQM.js → dist-MVSXUP3K.js} +1440 -140
- package/dist/dist-MVSXUP3K.js.map +1 -0
- package/dist/index.d.ts +897 -182
- package/dist/index.js +129 -18
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/dist/dist-FGJI5LQM.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -180,13 +180,40 @@ type InteractionState = (typeof INTERACTION_STATES)[number];
|
|
|
180
180
|
* source — are *not* diagnostics. Those throw `GlassSceneError`, because
|
|
181
181
|
* continuing past them would leave a half-built scene. Diagnostics carry the
|
|
182
182
|
* recoverable, per-frame, policy-level findings instead.
|
|
183
|
+
*
|
|
184
|
+
* ## One channel, several code spaces
|
|
185
|
+
*
|
|
186
|
+
* The channel is generic over its code union and core's own union is only its
|
|
187
|
+
* default instantiation. That is what lets the browser layer — which detects
|
|
188
|
+
* things core cannot name, like a host placed outside its plane — have a code
|
|
189
|
+
* space of its own without a second copy of the machinery, and it is why the
|
|
190
|
+
* dedupe rule, the retention rule and the key separator have exactly one
|
|
191
|
+
* definition in the workspace (Decision Log #21(b), #23(c)).
|
|
192
|
+
*
|
|
193
|
+
* Two properties are load-bearing and deliberately *not* generalised:
|
|
194
|
+
*
|
|
195
|
+
* - **A diagnostic carries no origin tag.** Which code space a finding came
|
|
196
|
+
* from is the channel's business, added on the way out to a host's sink, not
|
|
197
|
+
* a field every emitter has to write. `platform-web`'s `layer-model.ts` is
|
|
198
|
+
* the proof: it is a pure function that takes a bare `report` callback, and
|
|
199
|
+
* an origin tag in the payload would have rewritten every emitter in it.
|
|
200
|
+
* - **`report` stays assignable to `(d) => void`.** Checkers take the
|
|
201
|
+
* capability to report, never the channel, so a module that emits findings
|
|
202
|
+
* knows nothing about retention or dedupe.
|
|
183
203
|
*/
|
|
184
204
|
type DiagnosticSeverity = "warning" | "error";
|
|
185
205
|
/** Everything core can report. Owned here so a host can switch exhaustively. */
|
|
186
|
-
declare const DIAGNOSTIC_CODES: readonly ["same-plane-overlap", "variant-mixing", "merge-distance-below-padding", "group-proxy-overlap", "clear-variant-needs-dimming", "foreground-mode-illegal", "foreground-rate-clamped", "backdrop-hint-out-of-range", "backdrop-hint-redundant-estimator", "reduced-transparency-undetectable", "frame-phase-violation"];
|
|
206
|
+
declare const DIAGNOSTIC_CODES: readonly ["same-plane-overlap", "variant-mixing", "tint-mixing", "merge-distance-below-padding", "group-proxy-overlap", "clear-variant-needs-dimming", "foreground-mode-illegal", "foreground-rate-clamped", "backdrop-hint-out-of-range", "backdrop-hint-redundant-estimator", "reduced-transparency-undetectable", "frame-phase-violation"];
|
|
187
207
|
type DiagnosticCode = (typeof DIAGNOSTIC_CODES)[number];
|
|
188
|
-
|
|
189
|
-
|
|
208
|
+
/**
|
|
209
|
+
* One finding, over whichever code space the channel was opened on.
|
|
210
|
+
*
|
|
211
|
+
* `Code` defaults to core's own union, so `Diagnostic` unqualified still means
|
|
212
|
+
* exactly what it meant before the channel became generic and every existing
|
|
213
|
+
* annotation of it still reads.
|
|
214
|
+
*/
|
|
215
|
+
interface Diagnostic<Code extends string = DiagnosticCode> {
|
|
216
|
+
readonly code: Code;
|
|
190
217
|
readonly severity: DiagnosticSeverity;
|
|
191
218
|
/**
|
|
192
219
|
* The ids this finding is about — group, node, or source. Together with
|
|
@@ -196,21 +223,21 @@ interface Diagnostic {
|
|
|
196
223
|
readonly subjects: readonly string[];
|
|
197
224
|
readonly message: string;
|
|
198
225
|
}
|
|
199
|
-
type DiagnosticSink = (diagnostic: Diagnostic) => void;
|
|
200
|
-
interface DiagnosticsChannel {
|
|
201
|
-
report(diagnostic: Diagnostic): void;
|
|
226
|
+
type DiagnosticSink<Code extends string = DiagnosticCode> = (diagnostic: Diagnostic<Code>) => void;
|
|
227
|
+
interface DiagnosticsChannel<Code extends string = DiagnosticCode> {
|
|
228
|
+
report(diagnostic: Diagnostic<Code>): void;
|
|
202
229
|
/** Findings retained since construction or the last `clear()`. */
|
|
203
|
-
readonly reported: readonly Diagnostic[];
|
|
230
|
+
readonly reported: readonly Diagnostic<Code>[];
|
|
204
231
|
/** Forget what was seen, so a condition that returns is reported again. */
|
|
205
232
|
clear(): void;
|
|
206
233
|
}
|
|
207
|
-
interface DiagnosticsChannelOptions {
|
|
234
|
+
interface DiagnosticsChannelOptions<Code extends string = DiagnosticCode> {
|
|
208
235
|
/** Where findings go. Omitted in tests and in hosts that only read `reported`. */
|
|
209
|
-
readonly sink?: DiagnosticSink
|
|
236
|
+
readonly sink?: DiagnosticSink<Code>;
|
|
210
237
|
/** Collapse repeats of the same code+subjects. Default true. */
|
|
211
238
|
readonly dedupe?: boolean;
|
|
212
239
|
}
|
|
213
|
-
declare function createDiagnosticsChannel(options?: DiagnosticsChannelOptions): DiagnosticsChannel
|
|
240
|
+
declare function createDiagnosticsChannel<Code extends string = DiagnosticCode>(options?: DiagnosticsChannelOptions<Code>): DiagnosticsChannel<Code>;
|
|
214
241
|
|
|
215
242
|
/**
|
|
216
243
|
* Accessibility policy (§Accessibility policy, plus the Reduced Motion
|
|
@@ -415,6 +442,26 @@ declare const ACCESSIBILITY_PRECEDENCE: readonly ["reducedMotion", "reducedTrans
|
|
|
415
442
|
*/
|
|
416
443
|
declare function resolveAccessibilityPolicy(system: SystemAccessibilityPreferences, overrides?: AccessibilityOverrides, diagnostics?: DiagnosticsChannel): ResolvedAccessibilityPolicy;
|
|
417
444
|
|
|
445
|
+
/**
|
|
446
|
+
* The refraction ladder, weakest rung first.
|
|
447
|
+
*
|
|
448
|
+
* Two independent things cap refraction: the accessibility policy's ceiling
|
|
449
|
+
* (core's `ResolvedMaterialPolicy.refraction`, a regime — `nominal | reduced |
|
|
450
|
+
* none`) and the group's resolved capability state (X2's `RefractionQuality` —
|
|
451
|
+
* `true | approximate | none`, what the sampling backend can actually deliver).
|
|
452
|
+
* **Renderers honour the lower of the two** (Decision Log #19), which is only a
|
|
453
|
+
* meaningful sentence against an ordering — this one.
|
|
454
|
+
*
|
|
455
|
+
* Written out rather than derived from `RefractionQuality`, because that type's
|
|
456
|
+
* own declaration order is not an ordering.
|
|
457
|
+
*/
|
|
458
|
+
declare const REFRACTION_LADDER: readonly ["none", "approximate", "true"];
|
|
459
|
+
/**
|
|
460
|
+
* X2's capability-derived refraction level (`core/src/state.ts` re-exports this
|
|
461
|
+
* name). Derived from the ladder so the rungs and the type cannot drift apart.
|
|
462
|
+
*/
|
|
463
|
+
type RefractionQuality = (typeof REFRACTION_LADDER)[number];
|
|
464
|
+
|
|
418
465
|
/**
|
|
419
466
|
* X2 — the resolved-state model (§Backdrop & analysis contracts).
|
|
420
467
|
*
|
|
@@ -425,10 +472,10 @@ declare function resolveAccessibilityPolicy(system: SystemAccessibilityPreferenc
|
|
|
425
472
|
*
|
|
426
473
|
* C1 ships the shape; C4 ships the resolver.
|
|
427
474
|
*/
|
|
475
|
+
|
|
428
476
|
type ConfiguredSource = "texture" | "dom";
|
|
429
477
|
type ActiveRenderer = "webgpu" | "css";
|
|
430
478
|
type SamplingBackend = "gpu-texture" | "css-backdrop" | "none";
|
|
431
|
-
type RefractionQuality$1 = "true" | "approximate" | "none";
|
|
432
479
|
type AnalysisQuality = "exact" | "hint" | "none";
|
|
433
480
|
type GroupHealth = "ok" | "demoted";
|
|
434
481
|
declare const DEMOTION_REASONS: readonly ["no-webgpu", "no-backdrop-filter", "tainted-source", "incompatible-texture", "no-texture-supplied", "device-lost", "probe-failed", "governor"];
|
|
@@ -439,7 +486,7 @@ interface GlassGroupState {
|
|
|
439
486
|
/** What is actually drawing. */
|
|
440
487
|
readonly activeRenderer: ActiveRenderer;
|
|
441
488
|
readonly samplingBackend: SamplingBackend;
|
|
442
|
-
readonly refraction: RefractionQuality
|
|
489
|
+
readonly refraction: RefractionQuality;
|
|
443
490
|
readonly analysis: AnalysisQuality;
|
|
444
491
|
readonly health: GroupHealth;
|
|
445
492
|
readonly demotionReason?: DemotionReason;
|
|
@@ -797,6 +844,53 @@ interface FrameInfo {
|
|
|
797
844
|
|
|
798
845
|
declare const MATERIAL_VARIANTS$1: readonly ["regular", "clear"];
|
|
799
846
|
type MaterialVariant$1 = (typeof MATERIAL_VARIANTS$1)[number];
|
|
847
|
+
/**
|
|
848
|
+
* An author's tint seed, sRGB-encoded, 0..1 per channel.
|
|
849
|
+
*
|
|
850
|
+
* Encoded rather than linear because this is the number the author wrote: a CSS
|
|
851
|
+
* colour, parsed. The conversion into the working space belongs to whichever
|
|
852
|
+
* tier is drawing, and core carries no colour maths.
|
|
853
|
+
*/
|
|
854
|
+
type TintColor = readonly [r: number, g: number, b: number];
|
|
855
|
+
/**
|
|
856
|
+
* §Material tint — the author-facing half of Apple's `Glass.tint(_:)`.
|
|
857
|
+
*
|
|
858
|
+
* **A tint is a seed, not a fill.** Apple states the mechanism plainly:
|
|
859
|
+
* "selecting a color generates a range of tones that are **mapped to content
|
|
860
|
+
* brightness underneath** the tinted element… changing its hue, brightness and
|
|
861
|
+
* saturation depending on what's behind without deviating too much from the
|
|
862
|
+
* intended color" (WWDC25 session 219). A flat overlay of the seed is the
|
|
863
|
+
* failure Apple names in the same session — "completely opaque and breaks the
|
|
864
|
+
* visual character of Liquid Glass" — so this value is carried to the renderers
|
|
865
|
+
* as a seed and tone-mapped there, per pixel, against the backdrop the material
|
|
866
|
+
* is already sampling.
|
|
867
|
+
*
|
|
868
|
+
* Two axes, kept apart on purpose, because Apple's own vocabulary overloads the
|
|
869
|
+
* word:
|
|
870
|
+
*
|
|
871
|
+
* - **This is the colour axis.** It says what colour the material's tint layer
|
|
872
|
+
* is. It never changes how much of that layer there is.
|
|
873
|
+
* - The **alpha axis** — how opaque the tint layer is — is the material's
|
|
874
|
+
* calibrated `tintAlpha`, the same quantity reduced transparency lifts. That
|
|
875
|
+
* is where the *user's* system preference lives (iOS 26.1's Clear/Tinted
|
|
876
|
+
* toggle "increases the opacity of Liquid Glass and adds more contrast"; OS
|
|
877
|
+
* 27's slider runs the same axis continuously, "ultra clear to fully
|
|
878
|
+
* tinted"). A future reference migration therefore lands on the occlusion
|
|
879
|
+
* axis and cannot collide with an author's tint.
|
|
880
|
+
*
|
|
881
|
+
* `strength` is the author's own subtlety knob and comes from the seed colour's
|
|
882
|
+
* alpha — `rgba(255, 149, 0, 0.5)` is a half-strength orange, exactly as
|
|
883
|
+
* `Color.orange.opacity(0.5)` is in SwiftUI. It says how far the material's tint
|
|
884
|
+
* colour moves from its neutral (profile) tint toward the tone, and at 0 the
|
|
885
|
+
* material is byte-identical to an untinted one.
|
|
886
|
+
*/
|
|
887
|
+
interface GlassTint {
|
|
888
|
+
readonly color: TintColor;
|
|
889
|
+
/** How far the material's tint moves toward the tone, 0..1. */
|
|
890
|
+
readonly strength: number;
|
|
891
|
+
}
|
|
892
|
+
/** A tint with its channels clamped into range. `strength` defaults to fully tinted. */
|
|
893
|
+
declare function glassTint(color: TintColor, strength?: number): GlassTint;
|
|
800
894
|
/** The scrim laid beneath clear glass so foreground content stays legible. */
|
|
801
895
|
interface DimmingPolicy {
|
|
802
896
|
/** Scrim opacity, 0..1. */
|
|
@@ -810,11 +904,13 @@ interface DimmingPolicy {
|
|
|
810
904
|
* satisfy, not to be correct.
|
|
811
905
|
*/
|
|
812
906
|
declare const DEFAULT_CLEAR_DIMMING: DimmingPolicy;
|
|
813
|
-
/** A group's material defaults. A node inherits `variant` when it declares none. */
|
|
907
|
+
/** A group's material defaults. A node inherits `variant` and `tint` when it declares none. */
|
|
814
908
|
interface MaterialProfile$1 {
|
|
815
909
|
readonly variant: MaterialVariant$1;
|
|
816
910
|
/** Required for any clear surface in the group. */
|
|
817
911
|
readonly dimming?: DimmingPolicy;
|
|
912
|
+
/** Group-wide tint seed. A node overrides it, or clears it with `null`. */
|
|
913
|
+
readonly tint?: GlassTint;
|
|
818
914
|
}
|
|
819
915
|
interface ResolvedMaterial {
|
|
820
916
|
readonly variant: MaterialVariant$1;
|
|
@@ -822,15 +918,45 @@ interface ResolvedMaterial {
|
|
|
822
918
|
readonly adaptation: "adaptive" | "constrained";
|
|
823
919
|
/** Present exactly when `variant` is `"clear"`. */
|
|
824
920
|
readonly dimming?: DimmingPolicy;
|
|
921
|
+
/** Absent when the surface is untinted, or when its tint has no strength. */
|
|
922
|
+
readonly tint?: GlassTint;
|
|
825
923
|
}
|
|
826
924
|
interface MaterialRequest {
|
|
827
925
|
readonly variant: MaterialVariant$1;
|
|
828
926
|
readonly dimming?: DimmingPolicy;
|
|
927
|
+
/** The tint this surface resolved to — its own, or the group's. */
|
|
928
|
+
readonly tint?: GlassTint | null;
|
|
829
929
|
/** Named in diagnostics; also the dedupe subject. */
|
|
830
930
|
readonly nodeId?: string;
|
|
831
931
|
readonly diagnostics?: DiagnosticsChannel;
|
|
832
932
|
}
|
|
833
933
|
declare function resolveMaterial(request: MaterialRequest): ResolvedMaterial;
|
|
934
|
+
interface TintMixingCheck {
|
|
935
|
+
readonly groupId: string;
|
|
936
|
+
readonly members: readonly {
|
|
937
|
+
readonly nodeId: string;
|
|
938
|
+
readonly tint?: GlassTint;
|
|
939
|
+
}[];
|
|
940
|
+
readonly diagnostics?: DiagnosticsChannel;
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* Report a group whose members ask for **different** tint seeds.
|
|
944
|
+
*
|
|
945
|
+
* A group is one sampling region and one optics pass, so the GPU tier carries
|
|
946
|
+
* one seed per group and a per-pixel strength — which is exactly enough for the
|
|
947
|
+
* composition Apple's guidance describes ("apply color to the background rather
|
|
948
|
+
* than to symbols… refrain from adding color to the background of multiple
|
|
949
|
+
* controls"): one emphasised control inside a toolbar of plain ones. Two
|
|
950
|
+
* different hues in one group is outside that, and the two tiers would then
|
|
951
|
+
* disagree — the CSS tier styles each host element on its own and can honour
|
|
952
|
+
* both. So it warns and changes nothing, on the same reasoning as
|
|
953
|
+
* `checkVariantMixing`: coercing one of the two would silently discard an
|
|
954
|
+
* author's intent.
|
|
955
|
+
*
|
|
956
|
+
* Untinted members are not a mix. They are the ordinary case the mechanism is
|
|
957
|
+
* for, and their strength is simply zero.
|
|
958
|
+
*/
|
|
959
|
+
declare function checkTintMixing(check: TintMixingCheck): boolean;
|
|
834
960
|
interface VariantMixingCheck {
|
|
835
961
|
readonly groupId: string;
|
|
836
962
|
readonly members: readonly {
|
|
@@ -871,7 +997,7 @@ interface ZSlot {
|
|
|
871
997
|
readonly order: number;
|
|
872
998
|
}
|
|
873
999
|
/** Viewport-space rectangle in CSS px, measured by platform-web and handed in as data. */
|
|
874
|
-
interface Rect {
|
|
1000
|
+
interface Rect$1 {
|
|
875
1001
|
readonly x: number;
|
|
876
1002
|
readonly y: number;
|
|
877
1003
|
readonly width: number;
|
|
@@ -880,15 +1006,38 @@ interface Rect {
|
|
|
880
1006
|
/** Back-to-front ordering: every base node before every overlay node, then by `order`. */
|
|
881
1007
|
declare function compareZSlot(a: ZSlot, b: ZSlot): number;
|
|
882
1008
|
/** Smallest rect containing both. */
|
|
883
|
-
declare function unionRect(a: Rect, b: Rect): Rect;
|
|
1009
|
+
declare function unionRect(a: Rect$1, b: Rect$1): Rect$1;
|
|
884
1010
|
/** Grow a rect outwards on every side — how a group's proxy gets its padding. */
|
|
885
|
-
declare function inflateRect(rect: Rect, by: number): Rect;
|
|
1011
|
+
declare function inflateRect(rect: Rect$1, by: number): Rect$1;
|
|
1012
|
+
/**
|
|
1013
|
+
* The part of `rect` that survives every clip in the chain.
|
|
1014
|
+
*
|
|
1015
|
+
* A surface's border box is measured unclipped — `getBoundingClientRect` reports
|
|
1016
|
+
* the box wherever it is, whether or not an `overflow: scroll` ancestor is
|
|
1017
|
+
* actually showing it — so the box alone says nothing about what is visible. The
|
|
1018
|
+
* clip chain, measured alongside it, is what turns the box into the region the
|
|
1019
|
+
* surface can paint in (Decision Log #41(k)).
|
|
1020
|
+
*
|
|
1021
|
+
* A fully scrolled-out surface intersects to zero extent, and every consumer in
|
|
1022
|
+
* here already treats a zero-extent rect as "contributes nothing": `rectsOverlap`
|
|
1023
|
+
* refuses it, and the proxy geometry skips it as unmeasured. That is deliberate
|
|
1024
|
+
* — it means "scrolled out of view" needs no special case anywhere downstream.
|
|
1025
|
+
*
|
|
1026
|
+
* Rects only, and the approximation is stated rather than implied: a rounded
|
|
1027
|
+
* clipping ancestor is carried as its bounding box, so a surface tucked into a
|
|
1028
|
+
* rounded scroller's corner is treated as slightly more visible than it is. The
|
|
1029
|
+
* error is bounded by the ancestor's corner radius and always errs towards
|
|
1030
|
+
* reporting *more* surface, which is the safe direction for every consumer here
|
|
1031
|
+
* — an overlap check that over-reports warns about something real-ish, one that
|
|
1032
|
+
* under-reports misses a genuine double-filter.
|
|
1033
|
+
*/
|
|
1034
|
+
declare function clipRect(rect: Rect$1, clip: readonly Rect$1[] | undefined): Rect$1;
|
|
886
1035
|
/**
|
|
887
1036
|
* Positive-area intersection. Touching edges are not an overlap — adjacent
|
|
888
1037
|
* surfaces in a toolbar are the common case and are legal. A degenerate rect
|
|
889
1038
|
* (an unmeasured or collapsed host) overlaps nothing.
|
|
890
1039
|
*/
|
|
891
|
-
declare function rectsOverlap(a: Rect, b: Rect): boolean;
|
|
1040
|
+
declare function rectsOverlap(a: Rect$1, b: Rect$1): boolean;
|
|
892
1041
|
|
|
893
1042
|
/**
|
|
894
1043
|
* The scene model (§Core model): the three registries and everything that
|
|
@@ -1024,6 +1173,28 @@ interface GlassGroupRecord {
|
|
|
1024
1173
|
readonly state?: GlassGroupState;
|
|
1025
1174
|
/** Per-group governor override; falls back to the scene-wide pressure. */
|
|
1026
1175
|
readonly governor?: GovernorPressure;
|
|
1176
|
+
/**
|
|
1177
|
+
* Per-group platform probe override; falls back to the scene-wide probe.
|
|
1178
|
+
*
|
|
1179
|
+
* Most of `PlatformProbe` genuinely is scene-wide — there is one device per
|
|
1180
|
+
* root, and whether the engine has `backdrop-filter` is a fact about the
|
|
1181
|
+
* engine. `backdropProxyConformance` is the exception, and S1 measured why:
|
|
1182
|
+
* the backdrop-root audit is per group, "not per document, because different
|
|
1183
|
+
* groups can sit under different ancestors". A group whose proxy chain is
|
|
1184
|
+
* re-rooted must demote alone.
|
|
1185
|
+
*/
|
|
1186
|
+
readonly platform?: PlatformProbe;
|
|
1187
|
+
}
|
|
1188
|
+
/**
|
|
1189
|
+
* X8 rider 2: this surface is a level set of another surface's field, inset by a
|
|
1190
|
+
* fixed distance — a segmented control's indicator inside its track, drawn as
|
|
1191
|
+
* one field rather than two shapes that happen to nest.
|
|
1192
|
+
*/
|
|
1193
|
+
interface ConcentricParent {
|
|
1194
|
+
/** The parent surface. Must be registered, and must share this node's group. */
|
|
1195
|
+
readonly nodeId: string;
|
|
1196
|
+
/** CSS px inward from the parent's contour. */
|
|
1197
|
+
readonly inset: number;
|
|
1027
1198
|
}
|
|
1028
1199
|
interface GlassNodeDescriptor {
|
|
1029
1200
|
readonly id: string;
|
|
@@ -1031,8 +1202,33 @@ interface GlassNodeDescriptor {
|
|
|
1031
1202
|
readonly shapeFamily: ShapeFamily;
|
|
1032
1203
|
readonly shape: ShapeChannels;
|
|
1033
1204
|
readonly zSlot: ZSlot;
|
|
1205
|
+
/**
|
|
1206
|
+
* Which of geometry's two corner references this shape is fit against
|
|
1207
|
+
* (Decision Log #22(a) — two separate fits, not two points on one axis).
|
|
1208
|
+
* Defaults to `"apple-continuous"` at the renderer.
|
|
1209
|
+
*
|
|
1210
|
+
* A scene-model field since Decision Log #23(c). In v1 it was a render input
|
|
1211
|
+
* the browser layer never set, so a shape authored on the Figma smoothing axis
|
|
1212
|
+
* was silently resolved against the Apple fit, and a binding that wanted to
|
|
1213
|
+
* refuse a cross-reference morph had to mirror geometry's private mapping to
|
|
1214
|
+
* do it. The reference travels with the shape now.
|
|
1215
|
+
*/
|
|
1216
|
+
readonly reference?: CornerReference;
|
|
1217
|
+
/**
|
|
1218
|
+
* X8 rider 2's parent edge, likewise a scene-model field since #23(c).
|
|
1219
|
+
*
|
|
1220
|
+
* The link is validated here rather than at draw time: an unknown parent, a
|
|
1221
|
+
* parent in another group and a cycle are all refusals at registration, where
|
|
1222
|
+
* the caller that made the mistake is still on the stack.
|
|
1223
|
+
*/
|
|
1224
|
+
readonly concentricOf?: ConcentricParent;
|
|
1034
1225
|
/** Inherits the group's material profile when absent. */
|
|
1035
1226
|
readonly variant?: MaterialVariant$1;
|
|
1227
|
+
/**
|
|
1228
|
+
* Overrides the group's tint seed. `null` clears an inherited one, the way
|
|
1229
|
+
* `Glass.tint(nil)` does; absent inherits.
|
|
1230
|
+
*/
|
|
1231
|
+
readonly tint?: GlassTint | null;
|
|
1036
1232
|
readonly interaction?: InteractionState;
|
|
1037
1233
|
/** Overrides the group's adaptation for this surface. */
|
|
1038
1234
|
readonly foreground?: ForegroundAdaptation;
|
|
@@ -1040,9 +1236,9 @@ interface GlassNodeDescriptor {
|
|
|
1040
1236
|
interface GlassNodeRecord {
|
|
1041
1237
|
readonly descriptor: GlassNodeDescriptor;
|
|
1042
1238
|
/** Measured by platform-web in the read phase; absent until then. */
|
|
1043
|
-
readonly bounds?: Rect;
|
|
1239
|
+
readonly bounds?: Rect$1;
|
|
1044
1240
|
/** Ancestor clip chain, viewport space. */
|
|
1045
|
-
readonly clip?: readonly Rect[];
|
|
1241
|
+
readonly clip?: readonly Rect$1[];
|
|
1046
1242
|
}
|
|
1047
1243
|
/** One pyramid rebuild. `groupIds` is why there is one request and not one per group. */
|
|
1048
1244
|
interface BackdropRebuildRequest {
|
|
@@ -1090,7 +1286,10 @@ interface PlaneOverlap {
|
|
|
1090
1286
|
readonly plane: GlassPlane;
|
|
1091
1287
|
readonly nodeIds: readonly [string, string];
|
|
1092
1288
|
}
|
|
1093
|
-
/**
|
|
1289
|
+
/**
|
|
1290
|
+
* Two groups close enough in one plane that one group's padded proxy would
|
|
1291
|
+
* sample the pixels the other one paints (X1).
|
|
1292
|
+
*/
|
|
1094
1293
|
interface ProxyOverlap {
|
|
1095
1294
|
readonly plane: GlassPlane;
|
|
1096
1295
|
readonly groupIds: readonly [string, string];
|
|
@@ -1136,8 +1335,26 @@ interface GlassScene {
|
|
|
1136
1335
|
glassNode(id: string): GlassNodeRecord | undefined;
|
|
1137
1336
|
nodesOfGroup(groupId: string): readonly GlassNodeRecord[];
|
|
1138
1337
|
/** Measured viewport geometry, from the read phase. */
|
|
1139
|
-
setNodeBounds(id: string, bounds: Rect, clip?: readonly Rect[]): void;
|
|
1140
|
-
|
|
1338
|
+
setNodeBounds(id: string, bounds: Rect$1, clip?: readonly Rect$1[]): void;
|
|
1339
|
+
/**
|
|
1340
|
+
* Scene-wide by default; per group when `groupId` is given.
|
|
1341
|
+
*
|
|
1342
|
+
* The per-group form exists for `backdropProxyConformance` (Decision Log
|
|
1343
|
+
* #21(a), #23(c)). S1's backdrop-root audit is per group — different groups
|
|
1344
|
+
* sit under different ancestors — so a scene-wide-only probe forced the
|
|
1345
|
+
* browser layer either to demote every group when one failed, or to bypass
|
|
1346
|
+
* `resolve()` and call the pure resolver itself with the verdict folded in.
|
|
1347
|
+
* It chose the second, honestly and in the open, and this setter is what
|
|
1348
|
+
* retires it: with the verdict in the scene, `ResolvedGroup.state` and the
|
|
1349
|
+
* host's per-group answer are the same answer again.
|
|
1350
|
+
*
|
|
1351
|
+
* A per-group probe REPLACES the scene-wide one for that group rather than
|
|
1352
|
+
* merging with it, exactly as `setGovernorPressure` does. Merging would be a
|
|
1353
|
+
* second precedence rule sitting beside `REASON_PRECEDENCE`, and the caller
|
|
1354
|
+
* that knows the group's verdict is the same caller that holds the scene-wide
|
|
1355
|
+
* probe it was derived from.
|
|
1356
|
+
*/
|
|
1357
|
+
setPlatformProbe(probe: PlatformProbe, groupId?: string): void;
|
|
1141
1358
|
setSourceProbe(sourceId: string, probe: SourceProbe): void;
|
|
1142
1359
|
/** Scene-wide by default; per group when `groupId` is given. */
|
|
1143
1360
|
setGovernorPressure(pressure: GovernorPressure, groupId?: string): void;
|
|
@@ -1171,8 +1388,8 @@ interface GlassScene {
|
|
|
1171
1388
|
checkSamePlaneOverlap(): readonly PlaneOverlap[];
|
|
1172
1389
|
/**
|
|
1173
1390
|
* The cross-group half of X1's proxy geometry. `mergeDistance` only unions
|
|
1174
|
-
* members *within* a group, so
|
|
1175
|
-
*
|
|
1391
|
+
* members *within* a group, so a neighbouring group's proxy can still sample
|
|
1392
|
+
* the pixels this one paints — which S1 measured double-filtering.
|
|
1176
1393
|
*/
|
|
1177
1394
|
checkGroupProxyOverlap(): readonly ProxyOverlap[];
|
|
1178
1395
|
}
|
|
@@ -1353,15 +1570,15 @@ type Rgb = readonly [r: number, g: number, b: number];
|
|
|
1353
1570
|
* **The lower of the two wins**, and this module folds them into one scalar before
|
|
1354
1571
|
* anything reaches a uniform, so the shader has no way to honour the wrong one.
|
|
1355
1572
|
*
|
|
1356
|
-
* The ordering
|
|
1357
|
-
*
|
|
1358
|
-
*
|
|
1359
|
-
*
|
|
1573
|
+
* The ordering is `@vitrea/policy`'s, and so is the fold. It used to be restated
|
|
1574
|
+
* here — this package sits *below* core in the dependency graph and platform-web
|
|
1575
|
+
* sits above it, so for most of v1 there was no module both tiers could see and
|
|
1576
|
+
* the CSS tier carried a second copy. Decision Log #23(d) closed that seam by
|
|
1577
|
+
* putting the ladder in a pure leaf underneath everything, which the renderer can
|
|
1578
|
+
* depend on directly (alongside `@vitrea/geometry`) with no cycle to close. The
|
|
1579
|
+
* two copies can no longer disagree because there is only one.
|
|
1360
1580
|
*/
|
|
1361
1581
|
|
|
1362
|
-
/** X2's `RefractionQuality`, restated. Weakest first — the declaration order IS the ladder. */
|
|
1363
|
-
declare const REFRACTION_LADDER: readonly ["none", "approximate", "true"];
|
|
1364
|
-
type RefractionQuality = (typeof REFRACTION_LADDER)[number];
|
|
1365
1582
|
/**
|
|
1366
1583
|
* The slice of core's `ResolvedAccessibilityPolicy["material"]` the renderer
|
|
1367
1584
|
* reads. core's type is assignable to this; a test pins that.
|
|
@@ -1401,6 +1618,96 @@ interface MaterialRim {
|
|
|
1401
1618
|
readonly rimWidth: number;
|
|
1402
1619
|
readonly rimAlpha: number;
|
|
1403
1620
|
}
|
|
1621
|
+
/**
|
|
1622
|
+
* The outer shadow (W8) — the material's own occlusion of the backdrop *outside*
|
|
1623
|
+
* its contour, and the largest single facet the project has measured.
|
|
1624
|
+
*
|
|
1625
|
+
* Not the same quantity as `MaterialOptics.shadowDepth`/`shadowAlpha`, which are
|
|
1626
|
+
* the *inner* shadow: that one darkens the material's own body near its contour,
|
|
1627
|
+
* this one darkens what is behind and beside the surface. Profile-level rather
|
|
1628
|
+
* than per-variant, because the bed measures it per profile and never varied the
|
|
1629
|
+
* variant.
|
|
1630
|
+
*
|
|
1631
|
+
* ## The mechanism, as measured
|
|
1632
|
+
*
|
|
1633
|
+
* The reference's shadow is the component's OWN rounded silhouette, outset by
|
|
1634
|
+
* `spreadPx`, translated down by `offsetPx`, blurred by a Gaussian of standard
|
|
1635
|
+
* deviation `sigmaPx`, and applied MULTIPLICATIVELY: the backdrop keeps
|
|
1636
|
+
* `1 − occlusion·falloff` of its own light. Fitted in two dimensions against the
|
|
1637
|
+
* active bed, that model reproduces the reference to an RMS of 0.0021 in
|
|
1638
|
+
* occlusion over 142,550 pixels on the finest cell, and the same three lengths
|
|
1639
|
+
* describe every profile, backdrop, span and scale in the bed.
|
|
1640
|
+
*
|
|
1641
|
+
* **Multiplicative, and not additively.** Mirrored pixel pairs either side of a
|
|
1642
|
+
* capsule over the `photo` backdrop see the same shadow over different backdrop
|
|
1643
|
+
* luminances: the darkening's ratio tracks the backdrop's ratio to 4.5% while a
|
|
1644
|
+
* constant-subtraction model misses by 79% of the signal. So the shadow is
|
|
1645
|
+
* analytically INVISIBLE over black — `dark-solid` cells are byte-identical to
|
|
1646
|
+
* their background — and that property is what both tiers reproduce exactly,
|
|
1647
|
+
* because a fully transparent black composited over anything leaves it alone and
|
|
1648
|
+
* black times anything is black.
|
|
1649
|
+
*
|
|
1650
|
+
* ## Lengths, in points
|
|
1651
|
+
*
|
|
1652
|
+
* Every length below is in CSS px and the 2× bed proves it: `sigmaPx` measures
|
|
1653
|
+
* 15.5 at 1× and 31.0 at 2× device px, `offsetPx` 7.9 and 15.8. A shadow
|
|
1654
|
+
* specified in points is what doubles that way.
|
|
1655
|
+
*
|
|
1656
|
+
* They are also SPAN-INVARIANT, which is a positive measurement rather than an
|
|
1657
|
+
* absence: across spans of 32, 44, 96 and 160 px the fitted σ stays within
|
|
1658
|
+
* 15.4…15.9 and the offset within 6.9…8.1. The size law reaches the amplitude
|
|
1659
|
+
* (`sizeGain`) and nothing else.
|
|
1660
|
+
*/
|
|
1661
|
+
interface MaterialOuterShadow {
|
|
1662
|
+
/** Downward translation of the shadow's silhouette, CSS px. */
|
|
1663
|
+
readonly offsetPx: number;
|
|
1664
|
+
/** Gaussian σ the silhouette is blurred by, CSS px. A `box-shadow` blur is 2σ. */
|
|
1665
|
+
readonly sigmaPx: number;
|
|
1666
|
+
/** Outward spread of the silhouette before the blur, CSS px. */
|
|
1667
|
+
readonly spreadPx: number;
|
|
1668
|
+
/**
|
|
1669
|
+
* Peak occlusion: the fraction of the backdrop's own LINEAR light removed deep
|
|
1670
|
+
* inside the shadow. Zero stands the whole facet down, pad and all.
|
|
1671
|
+
*/
|
|
1672
|
+
readonly occlusion: number;
|
|
1673
|
+
/**
|
|
1674
|
+
* What reduced transparency does to `occlusion` — MEASURED, not assumed, which
|
|
1675
|
+
* is what the charter asked for before the fold was written.
|
|
1676
|
+
*
|
|
1677
|
+
* The reference's shadow under `reduce transparency` is the same shadow at
|
|
1678
|
+
* 0.566 of the amplitude: 0.1830/0.3259, 0.1884/0.3309 and 0.1882/0.3314 on the
|
|
1679
|
+
* three structured backdrops at a 44 px span, with σ, offset and spread
|
|
1680
|
+
* unmoved. It does not vanish and it does not intensify.
|
|
1681
|
+
*
|
|
1682
|
+
* The `increased contrast` reference reproduces the reduced-transparency
|
|
1683
|
+
* amplitude to four decimals (0.1830, 0.1884, 0.1882 — the same numbers), which
|
|
1684
|
+
* is Decision Log 8's finding again: macOS force-couples the two toggles, so the
|
|
1685
|
+
* contrast reference IS the reduced-transparency state and the bed cannot
|
|
1686
|
+
* separate them. The fold therefore keys on `frost`, the axis reduced
|
|
1687
|
+
* transparency alone sets, rather than on the contrast axes it would be
|
|
1688
|
+
* indistinguishable on here.
|
|
1689
|
+
*/
|
|
1690
|
+
readonly reducedTransparencyOcclusion: number;
|
|
1691
|
+
/**
|
|
1692
|
+
* The size law's grip on the amplitude: the fraction of the REMAINING
|
|
1693
|
+
* transparency a full-thickness surface's shadow closes, on
|
|
1694
|
+
* `sizeOcclusionGain`'s relative form.
|
|
1695
|
+
*
|
|
1696
|
+
* Ships at 0 — the identity — and the reason is a measurement rather than an
|
|
1697
|
+
* absence of one. Fitted per scene at a frozen geometry, the amplitude's span
|
|
1698
|
+
* dependence points in OPPOSITE directions in the two colour schemes: light
|
|
1699
|
+
* standard falls from 0.326 to 0.196 between a 44 px and a 96 px span over
|
|
1700
|
+
* `photo` (and 0.331 → 0.285 over `checkerboard`, 0.331 → 0.245 over
|
|
1701
|
+
* `hc-text`), while dark standard RISES from 0.060 to 0.177 to 0.274 across 44,
|
|
1702
|
+
* 96 and 160 px. Under reduced transparency it is flat (0.183, 0.192, 0.165).
|
|
1703
|
+
* One monotone gain on one thickness curve cannot be all three, and any
|
|
1704
|
+
* non-zero value fitted to one scheme is wrong in the other — the same shape of
|
|
1705
|
+
* finding Decision Log 13 recorded for W7's curve ("surface size is its own
|
|
1706
|
+
* axis"). The seam ships so the cascade can fit it if a two-axis rework lands;
|
|
1707
|
+
* the value stays at the identity until something can identify it.
|
|
1708
|
+
*/
|
|
1709
|
+
readonly sizeGain: number;
|
|
1710
|
+
}
|
|
1404
1711
|
/**
|
|
1405
1712
|
* Every number the material runs on, in one place.
|
|
1406
1713
|
*
|
|
@@ -1432,24 +1739,138 @@ interface MaterialProfile {
|
|
|
1432
1739
|
*/
|
|
1433
1740
|
readonly refractionScale: Readonly<Record<RefractionQuality, number>>;
|
|
1434
1741
|
/**
|
|
1435
|
-
* The size
|
|
1742
|
+
* **The size law's one curve** — the span band over which the material stops
|
|
1743
|
+
* reading as a thin sheet and starts reading as a thick slab (W2).
|
|
1436
1744
|
*
|
|
1437
|
-
*
|
|
1438
|
-
*
|
|
1439
|
-
*
|
|
1440
|
-
*
|
|
1441
|
-
*
|
|
1745
|
+
* Apple states one mechanism and lists its consequences: as glass "morphs to
|
|
1746
|
+
* larger sizes… its material characteristics change to simulate a thicker, more
|
|
1747
|
+
* substantial material. It casts deeper, richer shadows, has more pronounced
|
|
1748
|
+
* lensing and refraction effects, and a softer scattering of light" (S219). One
|
|
1749
|
+
* mechanism means one curve: `sizeThickness(span)` is a smoothstep from
|
|
1750
|
+
* `sizeSpanMin` to `sizeSpanMax`, and the thickness-derived facets are gains
|
|
1751
|
+
* on it — the lens (`lensSizeGainMax`), the occlusion (`sizeOcclusionGain`)
|
|
1752
|
+
* and the inner shadow (`sizeShadowGainMax`). The scattering was one of them
|
|
1753
|
+
* until W11c measured its curve to be a different one (a floor at small
|
|
1754
|
+
* spans, a band top past 96 — see `sizeScatterFloor`); it now rides its own,
|
|
1755
|
+
* from the same `sizeSpanMin`, and this band is untouched by it.
|
|
1442
1756
|
*
|
|
1443
1757
|
* A smoothstep rather than a straight ratio, so two surfaces of nearly the same
|
|
1444
|
-
* size never read as differently thick, and so
|
|
1445
|
-
* growing without bound on a full-width platter.
|
|
1758
|
+
* size never read as differently thick, and so every gain saturates instead of
|
|
1759
|
+
* growing without bound on a full-width platter. Below `sizeSpanMin` the whole
|
|
1760
|
+
* law is **exactly inert**: a small control renders as it did before the law
|
|
1761
|
+
* existed, which is what makes the law additive rather than a global retune.
|
|
1762
|
+
*
|
|
1763
|
+
* MEASURED (W2, on the settled bed): the band is where the reference's own
|
|
1764
|
+
* size-dependence happens. Over a fixed checkerboard backdrop the light-standard
|
|
1765
|
+
* reference passes 0.244 of the backdrop's contrast at a 32 px span, 0.230 at
|
|
1766
|
+
* 44 px and 0.144 at 96 px, and its backdrop correlation falls 0.634 → 0.606 →
|
|
1767
|
+
* 0.475 across the same three — so the movement is essentially complete by 96 px
|
|
1768
|
+
* and has barely started at 32. See the claims doc's size-law section.
|
|
1769
|
+
*/
|
|
1770
|
+
readonly sizeSpanMin: number;
|
|
1771
|
+
readonly sizeSpanMax: number;
|
|
1772
|
+
/**
|
|
1773
|
+
* The lens's gain on the size curve — "more pronounced lensing and refraction".
|
|
1774
|
+
*
|
|
1775
|
+
* `lensDepthPx` is `thickness × lensSizeGain(span)`, clamped to the shorter
|
|
1776
|
+
* *half* extent. The clamp is what keeps a small control from being all lens: a
|
|
1777
|
+
* 24 px-tall button cannot bend more than 12 px of backdrop however thick it is
|
|
1778
|
+
* authored.
|
|
1446
1779
|
*/
|
|
1447
|
-
readonly lensSpanMin: number;
|
|
1448
|
-
readonly lensSpanMax: number;
|
|
1449
1780
|
readonly lensSizeGainMax: number;
|
|
1450
|
-
/**
|
|
1451
|
-
|
|
1452
|
-
|
|
1781
|
+
/**
|
|
1782
|
+
* The scattering gain — "a softer scattering of light". How many times wider
|
|
1783
|
+
* the material's body blur runs at full size.
|
|
1784
|
+
*
|
|
1785
|
+
* **The facet the settled bed identifies most directly.** Two backdrops
|
|
1786
|
+
* disagree in exactly the way a widening kernel predicts and an opacity change
|
|
1787
|
+
* does not. Over the checkerboard — all of whose structure sits at one 16 px
|
|
1788
|
+
* period, and whose surroundings carry the same mean as its interior — the
|
|
1789
|
+
* reference's retained contrast falls 41% from a 32 px span to a 96 px one while
|
|
1790
|
+
* its interior *level* stays put (0.607 → 0.641). Over the synthetic photo —
|
|
1791
|
+
* broadband, and with surroundings whose mean differs from the mask's — the
|
|
1792
|
+
* retained contrast barely moves between 44 px and 96 px (0.546 → 0.544) while
|
|
1793
|
+
* the level converges toward the neighbourhood (0.585 → 0.628). A larger alpha
|
|
1794
|
+
* would have moved both backdrops' contrast together and pulled both levels
|
|
1795
|
+
* toward the tint; a wider kernel moves exactly what moved.
|
|
1796
|
+
*
|
|
1797
|
+
* Both tiers carry it, from one function (`sizeScatterSigma`): the CSS tier
|
|
1798
|
+
* multiplies its `blur()` σ, and the GPU tier lerps its body sample toward the
|
|
1799
|
+
* chain level whose blur is that σ.
|
|
1800
|
+
*
|
|
1801
|
+
* MEASURED (W11c G1, claims §5.41), and no longer a gain on `sizeThickness`
|
|
1802
|
+
* alone — see `sizeScatterFloor` and `sizeScatterSpanMax` below for the curve
|
|
1803
|
+
* it rides. 8: the heavy component of the reference's interior sits near σ 10
|
|
1804
|
+
* CSS px against a body σ of 1.25, and the gain sweep has a clear minimum at
|
|
1805
|
+
* 8 (RMS 0.0164 against 0.0180 at 6 and 0.0191 at 10 on the probe bed).
|
|
1806
|
+
*/
|
|
1807
|
+
readonly sizeScatterGainMax: number;
|
|
1808
|
+
/**
|
|
1809
|
+
* **The scattering facet's own curve** (W11c G1, claims §5.41).
|
|
1810
|
+
*
|
|
1811
|
+
* The reference's interior over structured content is two components, read
|
|
1812
|
+
* off the W9 probe bed across four checkerboard pitches and five spans: a
|
|
1813
|
+
* sharp one near σ 1.25 CSS px and a heavy one near σ 10, mixed by a share
|
|
1814
|
+
* that is already ≈ 0.4 at spans of 32–44 and still rising at 160 (0.52 at
|
|
1815
|
+
* 96, 0.64 at 128, 0.76 at 160). `sizeThickness` — zero at `sizeSpanMin` and
|
|
1816
|
+
* saturated at `sizeSpanMax` = 96 — can express neither the floor nor a band
|
|
1817
|
+
* top past 96, and moving `sizeSpanMax` would move the lens, the occlusion,
|
|
1818
|
+
* the inner shadow and W9's thin/thick response rows with it. So the scatter
|
|
1819
|
+
* mix rides its own curve:
|
|
1820
|
+
*
|
|
1821
|
+
* ```
|
|
1822
|
+
* kScatter = floor + (1 − floor) · smoothstep(sizeSpanMin, sizeScatterSpanMax, span) · fold
|
|
1823
|
+
* ```
|
|
1824
|
+
*
|
|
1825
|
+
* The floor is the material's own frost and is **not** folded under an
|
|
1826
|
+
* accessibility preference; the span-dependent rise is a depth effect and
|
|
1827
|
+
* folds like every other facet (`scatterThickness`). Fitted with `rrect-lg`
|
|
1828
|
+
* held out: floor 0.40 (0.0175 at 0.3, 0.0174 at 0.45), band top 256 (0.0182
|
|
1829
|
+
* at 224, 0.0174 at 320); the held-out cell's residual 0.0366 → 0.0174.
|
|
1830
|
+
*/
|
|
1831
|
+
readonly sizeScatterFloor: number;
|
|
1832
|
+
readonly sizeScatterSpanMax: number;
|
|
1833
|
+
/**
|
|
1834
|
+
* The occlusion gain — "a larger size is more opaque. A smaller size is
|
|
1835
|
+
* clearer" (S284). The fraction of the *remaining* transparency the size law
|
|
1836
|
+
* closes at full size.
|
|
1837
|
+
*
|
|
1838
|
+
* Relative rather than absolute, for `increasedOcclusionLift`'s reason: a floor
|
|
1839
|
+
* dies silently the moment nominal passes it, and a fraction of the headroom
|
|
1840
|
+
* cannot. It also composes correctly with the accessibility lift — under reduced
|
|
1841
|
+
* transparency nominal is already near 1, so the size law has almost no headroom
|
|
1842
|
+
* left to close, which is exactly what the reference does there (its transmission
|
|
1843
|
+
* reads 0.011 at a 44 px span and 0.014 at 96 px — no size dependence, because
|
|
1844
|
+
* there is none left to have).
|
|
1845
|
+
*/
|
|
1846
|
+
readonly sizeOcclusionGain: number;
|
|
1847
|
+
/**
|
|
1848
|
+
* The inner shadow's gain — "casts deeper, richer shadows". A multiplier on
|
|
1849
|
+
* `shadowDepth` at full size.
|
|
1850
|
+
*
|
|
1851
|
+
* **Coupled by construction, not fitted, and the difference is stated rather
|
|
1852
|
+
* than hidden.** The fixtures cannot identify it: the reference's peak darkening
|
|
1853
|
+
* outside its contour measures 0.0000–0.0001 on almost every calibration scene
|
|
1854
|
+
* and vitrea's measures the same order (C9a, `shadowFalloff`), so there is no
|
|
1855
|
+
* measured gap for a sweep to close, and what this renderer's `shadowDepth`
|
|
1856
|
+
* scales is an *inner* shadow whose contribution to the interior level is
|
|
1857
|
+
* degenerate with the tint's — two constants, one observable. So the direction
|
|
1858
|
+
* comes from Apple's sentence and the magnitude is held to what the objective is
|
|
1859
|
+
* flat over, with that flatness recorded. GPU tier only: the CSS tier's shadow is
|
|
1860
|
+
* an outer `box-shadow` the reference does not cast at all (Decision Log #32(c)).
|
|
1861
|
+
*/
|
|
1862
|
+
readonly sizeShadowGainMax: number;
|
|
1863
|
+
/**
|
|
1864
|
+
* The lens's magnitude: the contour displacement in lens depths (W11c G2).
|
|
1865
|
+
*
|
|
1866
|
+
* The shader reads the body from `lensDepth × lensRefractionGain × (1 − depth)²`
|
|
1867
|
+
* further inside, so the band is the plate folded back from that far in. The
|
|
1868
|
+
* two rim-LOD constants that used to sit here (`lensBodyLodPerPx`,
|
|
1869
|
+
* `lensRimLodBias`) are retired: the reference's band is not sharper than its
|
|
1870
|
+
* interior — W11c G2 measured σ 6 → 4 → 3 → the deep value across the band —
|
|
1871
|
+
* and the "sharper rim" was the fold, not a finer sample.
|
|
1872
|
+
*/
|
|
1873
|
+
readonly lensRefractionGain: number;
|
|
1453
1874
|
/**
|
|
1454
1875
|
* What each accessibility regime does to the numbers above. The multipliers
|
|
1455
1876
|
* match `platform-web`'s CSS tier so the two renderers degrade the same way
|
|
@@ -1471,12 +1892,137 @@ interface MaterialProfile {
|
|
|
1471
1892
|
* (0.62 − 0.28) / (1 − 0.28) = 0.4722, which reproduces the old floor exactly at
|
|
1472
1893
|
* the old nominal. At today's nominal it reads 0.62 → 0.799.
|
|
1473
1894
|
*
|
|
1474
|
-
* Mirrored by `@vitrea
|
|
1895
|
+
* Mirrored by `@vitreajs/vitrea-web`'s `INCREASED_OCCLUSION_LIFT`, and pinned in
|
|
1475
1896
|
* both directions by `packages/calibration/test/tier-coherence.test.ts`.
|
|
1476
1897
|
*/
|
|
1477
1898
|
readonly increasedOcclusionLift: number;
|
|
1478
1899
|
readonly strongBorderRim: MaterialRim;
|
|
1479
1900
|
readonly reducedTintAdaptation: number;
|
|
1901
|
+
/**
|
|
1902
|
+
* The author tint's shade law (W10) — Apple's "range of tones **mapped to
|
|
1903
|
+
* content brightness underneath**" (S219), measured per pixel on the frozen
|
|
1904
|
+
* bed and the W9 probe (claims §5.36).
|
|
1905
|
+
*
|
|
1906
|
+
* The tinted material is an OPAQUE, hue-preserving shade of the seed: the seed
|
|
1907
|
+
* times a scalar, and the scalar is linear in the luminance the untinted
|
|
1908
|
+
* material shows at the same pixel — `mix(tintShadeDark, tintShadeLight, u)`,
|
|
1909
|
+
* clamped so a shade is never brighter than the seed. Over black content the
|
|
1910
|
+
* reference shows about half the seed's light; over white it shows the seed
|
|
1911
|
+
* itself; over a checkerboard it shows both, cell by cell, with the seed's
|
|
1912
|
+
* chromaticity intact to three decimals at every pitch measured. That layer
|
|
1913
|
+
* composites over the material at the AUTHOR's opacity (the colour's alpha) in
|
|
1914
|
+
* the encoded space — the half-strength cell is the 0.501 encoded-space mix
|
|
1915
|
+
* of its untinted and full-tinted twins, per channel — so the material's own
|
|
1916
|
+
* alpha is not what a tinted surface shows.
|
|
1917
|
+
*
|
|
1918
|
+
* `tintShadeStrength` is the law's provenance gate: 1 where the constants were
|
|
1919
|
+
* measured (the light scheme), 0 where they were not — the dark scheme
|
|
1920
|
+
* renders the pure seed over every backdrop it was measured on, which is
|
|
1921
|
+
* consistent with "a shade relative to the material's own body level" but is
|
|
1922
|
+
* not yet separable from "no shading in the dark scheme". The collapse (W7)
|
|
1923
|
+
* folds the shade out the same way, because a collapsed material IS a dark
|
|
1924
|
+
* body and the reference renders the pure seed there too.
|
|
1925
|
+
*
|
|
1926
|
+
* MEASURED, both scales, twelve light-standard cells across three pitches:
|
|
1927
|
+
* fitted on the five probe cells only (17 700 px, RMS 0.0035) and refereed by
|
|
1928
|
+
* every canonical tinted row. Mirrored by `@vitreajs/vitrea-web`'s
|
|
1929
|
+
* `TINT_SHADE`, pinned in both directions by
|
|
1930
|
+
* `packages/calibration/test/tier-coherence.test.ts`.
|
|
1931
|
+
*/
|
|
1932
|
+
readonly tintShadeDark: number;
|
|
1933
|
+
readonly tintShadeLight: number;
|
|
1934
|
+
readonly tintShadeStrength: number;
|
|
1935
|
+
/**
|
|
1936
|
+
* **Backdrop tone adaptation (W7)** — the axis Apple's material has and this
|
|
1937
|
+
* one did not: over a dark enough backdrop the material stops being a lighter
|
|
1938
|
+
* thing in front of it and takes the backdrop's own tone.
|
|
1939
|
+
*
|
|
1940
|
+
* The mechanism is one mix, and it is deliberately the *tint colour* rather
|
|
1941
|
+
* than the tint alpha: `backdropToneMax` at full strength makes the tint equal
|
|
1942
|
+
* the sampled backdrop, so `mix(backdrop, tint, tintAlpha)` collapses to the
|
|
1943
|
+
* backdrop exactly and the surface is left with its rim, its inner shadow and
|
|
1944
|
+
* its lensing and nothing else. That is what the settled reference does —
|
|
1945
|
+
* `dark-solid__capsule-button__rest` is byte-identical to its own background
|
|
1946
|
+
* in every standard profile, at both scales, in both colour schemes.
|
|
1947
|
+
*
|
|
1948
|
+
* `backdropToneLow`/`backdropToneHigh` are the backdrop luminances (linear)
|
|
1949
|
+
* the two ends are reached at, crossed with a smoothstep for the same reason
|
|
1950
|
+
* `tintToneLow`/`High` are.
|
|
1951
|
+
*
|
|
1952
|
+
* `backdropToneSizeBias` is the size gate, and it is not decoration: the same
|
|
1953
|
+
* backdrop moves a small surface and a large one by very different amounts.
|
|
1954
|
+
* Over `dark-solid` the reference's 44 px capsule adapts completely while its
|
|
1955
|
+
* 96 px rrect keeps three quarters of its own appearance, measured on both
|
|
1956
|
+
* scales independently and agreeing to three decimals. The bias enters the
|
|
1957
|
+
* curve's *argument* rather than its amplitude — a thicker surface behaves as
|
|
1958
|
+
* though its backdrop were brighter, which is what more material between the
|
|
1959
|
+
* viewer and the backdrop means — because an amplitude gate cannot reproduce
|
|
1960
|
+
* the second dark backdrop (`impulse`) and this does.
|
|
1961
|
+
*
|
|
1962
|
+
* The axis is WITHIN a colour scheme. The scheme picks the neutral; this moves
|
|
1963
|
+
* the material away from that neutral toward what is actually behind it. So the
|
|
1964
|
+
* dark profile runs the same law with the same constants and does not
|
|
1965
|
+
* double-adapt: over `dark-solid` its capsule collapses onto the backdrop too,
|
|
1966
|
+
* and the light and dark references become the same pixels there.
|
|
1967
|
+
*/
|
|
1968
|
+
readonly backdropToneMax: number;
|
|
1969
|
+
readonly backdropToneLow: number;
|
|
1970
|
+
readonly backdropToneHigh: number;
|
|
1971
|
+
readonly backdropToneSizeBias: number;
|
|
1972
|
+
/**
|
|
1973
|
+
* **The backdrop tone response (W9)** — the law that owns the interior MEAN,
|
|
1974
|
+
* where the four constants above own texture collapse and nothing else.
|
|
1975
|
+
*
|
|
1976
|
+
* The W9 probe falsified the mix-toward-backdrop form outright (claims
|
|
1977
|
+
* §5.33): six cells need mix strengths outside [0, 1], because the
|
|
1978
|
+
* reference adapts toward the material's own light/dark appearance, which
|
|
1979
|
+
* coincides with the backdrop's tone only over `dark-solid` — the one
|
|
1980
|
+
* background the mix was fitted on. What the probe measured instead is a
|
|
1981
|
+
* LAW: at equal encoded-space backdrop mean the reference's settled
|
|
1982
|
+
* interior is the same number regardless of the backdrop's structure
|
|
1983
|
+
* (checker vs text rows, 0.81 both at input 0.69), so the interior level is
|
|
1984
|
+
* a function `R(encodedMean, thickness)` and these constants are that
|
|
1985
|
+
* function's anchors.
|
|
1986
|
+
*
|
|
1987
|
+
* `backdropToneAnchorX` is the three solid anchors' encoded-space means —
|
|
1988
|
+
* measured backdrop luminances, not tuned. `backdropToneResponseThin` and
|
|
1989
|
+
* `...Thick` are the reference's settled interior levels at those anchors
|
|
1990
|
+
* for a thin surface (`sizeThickness` 0, the 32 px rrect) and a thick one
|
|
1991
|
+
* (saturated, the 96 px+ rrects pooled — their residual spread ±0.012 is
|
|
1992
|
+
* the accepted cost of `sizeSpanMax` saturation, claims §5.33). Between
|
|
1993
|
+
* the rows: smoothstep in thickness; between the anchors: monotone
|
|
1994
|
+
* (Fritsch–Carlson) interpolation in the ENCODED input, the space the
|
|
1995
|
+
* probe validated to RMS 0.034 with zero fitting.
|
|
1996
|
+
*
|
|
1997
|
+
* Below the dark anchor the surface has no data (the probe's grid floor
|
|
1998
|
+
* is `dark-solid`), and the one validation cell down there —
|
|
1999
|
+
* `impulse__rrect-md`, backdrop 0.0039, reference 0.4358 — reads DARKER
|
|
2000
|
+
* than the dark anchor's thick row, so clamping would regress it. The
|
|
2001
|
+
* solve's authority fades to zero from the dark anchor downward
|
|
2002
|
+
* (smoothstep over the anchor's own lower half, no new constant); the
|
|
2003
|
+
* extreme-dark region stays with the collapse constants that were fitted
|
|
2004
|
+
* on it.
|
|
2005
|
+
*/
|
|
2006
|
+
readonly backdropToneAnchorX: readonly [number, number, number];
|
|
2007
|
+
readonly backdropToneResponseThin: readonly [number, number, number];
|
|
2008
|
+
readonly backdropToneResponseThick: readonly [number, number, number];
|
|
2009
|
+
/**
|
|
2010
|
+
* How much authority the response law has in THIS profile, 0…1 (W9).
|
|
2011
|
+
*
|
|
2012
|
+
* The anchors above are measurements of the LIGHT reference's settled
|
|
2013
|
+
* appearance. The dark scheme's material settles at its own levels over the
|
|
2014
|
+
* same backdrops (0.809 light against 0.055 dark over one checkerboard,
|
|
2015
|
+
* §5.8), so a dark profile running the light response surface brightens the
|
|
2016
|
+
* dark material toward the wrong scheme's appearance — measured on the
|
|
2017
|
+
* canonical dark bed as ΔE p95 0.08 → 0.58 before this constant existed.
|
|
2018
|
+
* The dark profiles set it to 0: the collapse (whose target is the
|
|
2019
|
+
* backdrop, not a scheme's appearance) still runs there, and a dark
|
|
2020
|
+
* response surface is follow-up work that needs the dark reference probed,
|
|
2021
|
+
* not an assumption.
|
|
2022
|
+
*/
|
|
2023
|
+
readonly backdropToneResponseStrength: number;
|
|
2024
|
+
/** The outer shadow (W8) — see `MaterialOuterShadow`. */
|
|
2025
|
+
readonly outerShadow: MaterialOuterShadow;
|
|
1480
2026
|
/**
|
|
1481
2027
|
* Advisory light direction, in viewport coordinates with y pointing down: a
|
|
1482
2028
|
* little left of straight overhead, which is where Apple's material reads its
|
|
@@ -1503,15 +2049,31 @@ interface MaterialProfilePatch {
|
|
|
1503
2049
|
readonly adaptiveLuminanceLow?: number;
|
|
1504
2050
|
readonly adaptiveLuminanceHigh?: number;
|
|
1505
2051
|
readonly refractionScale?: Readonly<Partial<Record<RefractionQuality, number>>>;
|
|
1506
|
-
readonly
|
|
1507
|
-
readonly
|
|
2052
|
+
readonly sizeSpanMin?: number;
|
|
2053
|
+
readonly sizeSpanMax?: number;
|
|
1508
2054
|
readonly lensSizeGainMax?: number;
|
|
1509
|
-
readonly
|
|
1510
|
-
readonly
|
|
2055
|
+
readonly sizeScatterGainMax?: number;
|
|
2056
|
+
readonly sizeScatterFloor?: number;
|
|
2057
|
+
readonly sizeScatterSpanMax?: number;
|
|
2058
|
+
readonly sizeOcclusionGain?: number;
|
|
2059
|
+
readonly sizeShadowGainMax?: number;
|
|
2060
|
+
readonly lensRefractionGain?: number;
|
|
1511
2061
|
readonly reducedTransparencyFrost?: number;
|
|
1512
2062
|
readonly increasedOcclusionLift?: number;
|
|
1513
2063
|
readonly strongBorderRim?: Readonly<Partial<MaterialRim>>;
|
|
1514
2064
|
readonly reducedTintAdaptation?: number;
|
|
2065
|
+
readonly tintShadeDark?: number;
|
|
2066
|
+
readonly tintShadeLight?: number;
|
|
2067
|
+
readonly tintShadeStrength?: number;
|
|
2068
|
+
readonly backdropToneMax?: number;
|
|
2069
|
+
readonly backdropToneLow?: number;
|
|
2070
|
+
readonly backdropToneHigh?: number;
|
|
2071
|
+
readonly backdropToneSizeBias?: number;
|
|
2072
|
+
readonly backdropToneAnchorX?: readonly [number, number, number];
|
|
2073
|
+
readonly backdropToneResponseThin?: readonly [number, number, number];
|
|
2074
|
+
readonly backdropToneResponseThick?: readonly [number, number, number];
|
|
2075
|
+
readonly backdropToneResponseStrength?: number;
|
|
2076
|
+
readonly outerShadow?: Readonly<Partial<MaterialOuterShadow>>;
|
|
1515
2077
|
readonly lightDirection?: readonly [number, number];
|
|
1516
2078
|
readonly sweepBandRadians?: number;
|
|
1517
2079
|
readonly glowRadiusCss?: number;
|
|
@@ -1734,137 +2296,6 @@ interface VideoProviderOptions {
|
|
|
1734
2296
|
readonly generation?: number;
|
|
1735
2297
|
}
|
|
1736
2298
|
|
|
1737
|
-
/**
|
|
1738
|
-
* Device ownership, loss teardown, and rebuild (§GPU device ownership).
|
|
1739
|
-
*
|
|
1740
|
-
* `platform-web` owns the *browser* half of the story — is there an adapter, get
|
|
1741
|
-
* a device, notice when it goes away. This module owns the *resource* half: what
|
|
1742
|
-
* has to be thrown away when a device dies, when it is safe to build again, and
|
|
1743
|
-
* what core's capability inputs should read while that is in flight.
|
|
1744
|
-
*
|
|
1745
|
-
* ## The two ownership modes, and why they are not symmetric
|
|
1746
|
-
*
|
|
1747
|
-
* - **vitrea-owned** — this module can re-request a device by itself, so loss is
|
|
1748
|
-
* a transient it recovers from: tear down, re-request, re-attach, rebuild.
|
|
1749
|
-
* Every backdrop source is re-imported on the next frame because loss marks
|
|
1750
|
-
* them all dirty, which routes recovery through the same
|
|
1751
|
-
* one-rebuild-per-dirty-source-per-frame path a content change takes rather
|
|
1752
|
-
* than through a special case.
|
|
1753
|
-
* - **app-owned** — the app owns the resources that would have to be
|
|
1754
|
-
* re-registered, so this module reports the loss, raises
|
|
1755
|
-
* `replacementPending`, and **waits**. Groups stay demoted until
|
|
1756
|
-
* `replaceDevice` arrives and the re-registration handshake completes. Inventing
|
|
1757
|
-
* a device the app did not give us would break the one guarantee app-ownership
|
|
1758
|
-
* exists for: that every texture the renderer samples came from the app's own
|
|
1759
|
-
* device, because WebGPU has no cross-device sharing.
|
|
1760
|
-
*
|
|
1761
|
-
* `info.reason === "destroyed"` is our own teardown and is not recovered from —
|
|
1762
|
-
* re-requesting there would resurrect a renderer the host just destroyed.
|
|
1763
|
-
*
|
|
1764
|
-
* ## Generations
|
|
1765
|
-
*
|
|
1766
|
-
* Every attach bumps a generation counter, and every GPU object this package
|
|
1767
|
-
* holds is tagged with the generation it was made under. A resource from a lost
|
|
1768
|
-
* device is unusable forever, and the failure mode is silent — bindings simply
|
|
1769
|
-
* produce nothing — so "is this from the current device" has to be a cheap
|
|
1770
|
-
* integer comparison somewhere. It is here.
|
|
1771
|
-
*/
|
|
1772
|
-
/**
|
|
1773
|
-
* Structurally identical to `vitrea`'s `WebGPUAvailability` (X2's K1
|
|
1774
|
-
* amendment, Decision Log #21c). Declared here rather than imported because this
|
|
1775
|
-
* package sits *below* core in the dependency graph — core reaches the renderer
|
|
1776
|
-
* through a dynamic import, so an import back would close a cycle. A test pins
|
|
1777
|
-
* the two unions to the same members.
|
|
1778
|
-
*/
|
|
1779
|
-
type WebGPUAvailability = "not-requested" | "unavailable" | "available";
|
|
1780
|
-
type DeviceOwnership = "vitrea" | "app";
|
|
1781
|
-
interface RendererDeviceStatus {
|
|
1782
|
-
/** Feeds core's `PlatformProbe.webgpu` unchanged. */
|
|
1783
|
-
readonly webgpu: WebGPUAvailability;
|
|
1784
|
-
readonly deviceHealth: "ok" | "lost";
|
|
1785
|
-
readonly ownership: DeviceOwnership;
|
|
1786
|
-
readonly device: GPUDevice | undefined;
|
|
1787
|
-
/** Bumped on every attach. Tags every resource built under it. */
|
|
1788
|
-
readonly generation: number;
|
|
1789
|
-
/** True while an app-owned device is lost and no replacement has arrived. */
|
|
1790
|
-
readonly replacementPending: boolean;
|
|
1791
|
-
/** Why there is no device, when there is a reason worth reporting. */
|
|
1792
|
-
readonly unavailableReason?: "no-adapter" | "device-request-failed" | "lost";
|
|
1793
|
-
}
|
|
1794
|
-
/** The capability facts a host folds into core's `PlatformProbe`. */
|
|
1795
|
-
interface DeviceCapabilityInput {
|
|
1796
|
-
readonly webgpu: WebGPUAvailability;
|
|
1797
|
-
readonly deviceHealth: "ok" | "lost";
|
|
1798
|
-
}
|
|
1799
|
-
|
|
1800
|
-
/**
|
|
1801
|
-
* The governor's knobs.
|
|
1802
|
-
*
|
|
1803
|
-
* §Performance envelope: "The governor degrades **within** a tier first
|
|
1804
|
-
* (refraction resolution, adaptation cadence, edge analysis) and switches tiers
|
|
1805
|
-
* only with long hysteresis and cooldown." Decision Log #19 adds that intra-tier
|
|
1806
|
-
* degradation is **not a state change** — a group under `degrade-in-tier`
|
|
1807
|
-
* pressure keeps `activeRenderer: "webgpu"` and its whole resolved state.
|
|
1808
|
-
*
|
|
1809
|
-
* So the split is: **the policy lives in core, the knobs live here.** This module
|
|
1810
|
-
* exposes what can be turned and publishes a suggested ladder as *data*; it never
|
|
1811
|
-
* decides to turn anything, never reads a clock, and never applies hysteresis.
|
|
1812
|
-
* A governor that lived in the renderer would be a governor that could not see
|
|
1813
|
-
* the scene it is governing.
|
|
1814
|
-
*
|
|
1815
|
-
* ## The three knobs, weakest cost first
|
|
1816
|
-
*
|
|
1817
|
-
* 1. **`fieldFamily`** — `rsupn` → `rsup`. S2 priced this at 29% of the field's
|
|
1818
|
-
* cost for a bound that degrades from 0.170 px / 2.91° to 0.574 px / 4.26°.
|
|
1819
|
-
* It is the *first* step because it is one uniform and one pipeline: no
|
|
1820
|
-
* resolution change, so nothing resamples and nothing shimmers as it engages.
|
|
1821
|
-
* **Conditional on the f32 cross-check** (Decision Log #20) — and the check
|
|
1822
|
-
* has now been run, so the condition is met. See `FAMILY_C_CROSS_CHECK`.
|
|
1823
|
-
* 2. **`refractionResolutionScale`** — the group's **field** targets are
|
|
1824
|
-
* rasterised at a fraction of device resolution, and the optics and highlight
|
|
1825
|
-
* passes filter them instead of indexing them (`passes.ts`, and the
|
|
1826
|
-
* `fieldUpsampled` flag both shaders branch on). Quadratic saving on the pass
|
|
1827
|
-
* that evaluates the pseudo-SDF union per pixel per member, and the most
|
|
1828
|
-
* visible step, so it comes second.
|
|
1829
|
-
*
|
|
1830
|
-
* What it does **not** yet do is shrink the optics and highlight passes
|
|
1831
|
-
* themselves: those still render at full device resolution into the plane
|
|
1832
|
-
* canvases, because rendering them smaller means an offscreen target and a
|
|
1833
|
-
* resolve pass rather than a change of extent. So rungs 2 and 3 deliver the
|
|
1834
|
-
* field's quadratic saving and the cadence saving, not the full quadratic
|
|
1835
|
-
* saving on both heavy passes. Recorded here rather than implied, because a
|
|
1836
|
-
* ladder whose rungs are priced for savings they do not deliver is a ladder
|
|
1837
|
-
* core's policy will walk too far down.
|
|
1838
|
-
* 3. **`adaptationCadenceHz`** — how often analysis is reduced and read back.
|
|
1839
|
-
* Cheapest of the three in visual terms because the values it feeds are
|
|
1840
|
-
* already low-passed over hundreds of milliseconds; dropping the cadence
|
|
1841
|
-
* mostly changes how quickly a scroll's new backdrop is noticed.
|
|
1842
|
-
*/
|
|
1843
|
-
type FieldFamily = "rsupn" | "rsup";
|
|
1844
|
-
interface GovernorKnobs {
|
|
1845
|
-
/** Which pseudo-SDF family the field pass compiles. */
|
|
1846
|
-
readonly fieldFamily: FieldFamily;
|
|
1847
|
-
/**
|
|
1848
|
-
* Device-resolution fraction the group's field targets are rasterised at,
|
|
1849
|
-
* 0 < s <= 1. The optics and highlight passes upsample what they read. See the
|
|
1850
|
-
* module note for what this does and does not save.
|
|
1851
|
-
*/
|
|
1852
|
-
readonly refractionResolutionScale: number;
|
|
1853
|
-
/** Analysis reduction + readback rate. 0 disables adaptation entirely. */
|
|
1854
|
-
readonly adaptationCadenceHz: number;
|
|
1855
|
-
}
|
|
1856
|
-
interface Governor {
|
|
1857
|
-
readonly knobs: GovernorKnobs;
|
|
1858
|
-
/** True when `fieldFamily: "rsup"` is permitted to engage. */
|
|
1859
|
-
readonly familyCVerified: boolean;
|
|
1860
|
-
set(patch: Partial<GovernorKnobs>): GovernorKnobs;
|
|
1861
|
-
/** Move to a rung of the suggested ladder. Out-of-range clamps to the ends. */
|
|
1862
|
-
setLevel(level: number): GovernorKnobs;
|
|
1863
|
-
reset(): GovernorKnobs;
|
|
1864
|
-
/** Record that the cross-check passed, unlocking family C. */
|
|
1865
|
-
recordFamilyCVerified(): void;
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
2299
|
/**
|
|
1869
2300
|
* What the renderer consumes each frame, and why it is declared here rather than
|
|
1870
2301
|
* imported from `vitrea`.
|
|
@@ -1896,6 +2327,13 @@ interface Governor {
|
|
|
1896
2327
|
* none in core.
|
|
1897
2328
|
*/
|
|
1898
2329
|
|
|
2330
|
+
/** Viewport-space rectangle in CSS px. Matches core's `Rect`. */
|
|
2331
|
+
interface Rect {
|
|
2332
|
+
readonly x: number;
|
|
2333
|
+
readonly y: number;
|
|
2334
|
+
readonly width: number;
|
|
2335
|
+
readonly height: number;
|
|
2336
|
+
}
|
|
1899
2337
|
/** Motion-driver outputs for one surface. Every one is a value, never a time. */
|
|
1900
2338
|
interface SurfaceChannels {
|
|
1901
2339
|
/** `pressCompression`, 0..1. Scaled by motion's `pressCompressionScale`. */
|
|
@@ -1909,6 +2347,11 @@ interface SurfaceChannels {
|
|
|
1909
2347
|
/** Press point in viewport CSS px. Defaults to the surface's centre. */
|
|
1910
2348
|
readonly pressPoint?: readonly [number, number];
|
|
1911
2349
|
}
|
|
2350
|
+
/** An author tint as this package takes it: a seed in linear light, and a strength. */
|
|
2351
|
+
interface MaterialTintInput {
|
|
2352
|
+
readonly color: readonly [number, number, number];
|
|
2353
|
+
readonly strength: number;
|
|
2354
|
+
}
|
|
1912
2355
|
interface SurfaceInput {
|
|
1913
2356
|
readonly nodeId: string;
|
|
1914
2357
|
readonly family: ShapeFamily;
|
|
@@ -1917,6 +2360,17 @@ interface SurfaceInput {
|
|
|
1917
2360
|
/** Defaults to `"apple-continuous"` — see the module note. */
|
|
1918
2361
|
readonly reference?: CornerReference;
|
|
1919
2362
|
readonly variant?: MaterialVariant;
|
|
2363
|
+
/**
|
|
2364
|
+
* The author's tint (core's `ResolvedMaterial.tint`), in **linear** light —
|
|
2365
|
+
* the host converts, because this package's whole optical model is linear and
|
|
2366
|
+
* the seed is about to be mixed into it.
|
|
2367
|
+
*
|
|
2368
|
+
* The strength travels per surface and reaches the fragment stage per pixel;
|
|
2369
|
+
* the seed colour is resolved once per group, because a group is one optics
|
|
2370
|
+
* pass. Core warns when a group's members ask for different seeds
|
|
2371
|
+
* (`tint-mixing`), and the first tinted member's colour is the one drawn.
|
|
2372
|
+
*/
|
|
2373
|
+
readonly tint?: MaterialTintInput;
|
|
1920
2374
|
readonly channels?: Partial<SurfaceChannels>;
|
|
1921
2375
|
/**
|
|
1922
2376
|
* X8 rider 2. When present this surface renders as `parentField + inset`, and
|
|
@@ -1951,6 +2405,63 @@ interface GroupRenderInput {
|
|
|
1951
2405
|
readonly refraction: RefractionQuality;
|
|
1952
2406
|
/** True where X2 resolved `analysis: "exact"`; gates adaptive tint. */
|
|
1953
2407
|
readonly analysisExact: boolean;
|
|
2408
|
+
/**
|
|
2409
|
+
* The backdrop source's own average colour, linear light — what backdrop tone
|
|
2410
|
+
* adaptation (W7) adapts toward, and the luminance it decides from.
|
|
2411
|
+
*
|
|
2412
|
+
* A **per-source scalar rather than a per-pixel sample**, and that is why it
|
|
2413
|
+
* arrives from outside rather than being read off the pyramid. The host measures
|
|
2414
|
+
* it once from the pixels it already supplied and both tiers then read the
|
|
2415
|
+
* identical number: the CSS tier cannot sample per pixel at all, and a per-pixel
|
|
2416
|
+
* GPU adaptation beside a per-surface CSS one puts the two tiers on different
|
|
2417
|
+
* pictures wherever the backdrop has structure — measured on the impulse cell at
|
|
2418
|
+
* an interior level ratio of 79 against a gated band of 0.80…1.25. It is also
|
|
2419
|
+
* what the reference does: its capsule over a sparse bright grid is a *flat*
|
|
2420
|
+
* body, not a window onto the grid.
|
|
2421
|
+
*
|
|
2422
|
+
* Absent means the adaptation stands down for this group, rather than falling
|
|
2423
|
+
* back to a level nobody measured.
|
|
2424
|
+
*/
|
|
2425
|
+
readonly backdropTone?: Rgb;
|
|
2426
|
+
/**
|
|
2427
|
+
* The backdrop's ENCODED-space tone level (W9, claims §5.31–§5.34): the mean
|
|
2428
|
+
* taken in sRGB-encoded space, decoded once — the input the reference's tone
|
|
2429
|
+
* response tracks, feeding the collapse band's argument and the response
|
|
2430
|
+
* curve. Distinct from `backdropTone` on any structured backdrop: the
|
|
2431
|
+
* COLOUR is the physical linear mean (what the collapse converges onto —
|
|
2432
|
+
* on the impulse grid the two differ 2.6×, and converging onto the encoded
|
|
2433
|
+
* reading was a measured ΔE p95 0.03 → 0.12 regression), while the LEVEL is
|
|
2434
|
+
* the encoded reading. Absent falls back to `backdropTone`'s own luminance.
|
|
2435
|
+
*/
|
|
2436
|
+
readonly backdropToneLevel?: number;
|
|
2437
|
+
/**
|
|
2438
|
+
* The backdrop's LINEAR-space mean luminance, beside `backdropToneLevel`'s
|
|
2439
|
+
* encoded-space reading (W9, claims §5.31). The per-pixel tint-tone input
|
|
2440
|
+
* samples a chain that averages linearly, so the optics pass multiplies it by
|
|
2441
|
+
* `backdropToneLevel / backdropToneLinearLuminance` — locality is
|
|
2442
|
+
* preserved and the input's spatial mean matches the model exactly. Absent
|
|
2443
|
+
* (or equal to the tone's level) collapses the ratio to 1.
|
|
2444
|
+
*/
|
|
2445
|
+
readonly backdropToneLinearLuminance?: number;
|
|
2446
|
+
/**
|
|
2447
|
+
* The material's tint and alpha for a group that samples NOTHING (W11a) — a
|
|
2448
|
+
* `css-backdrop` group whose blurred backdrop is a DOM proxy beneath the
|
|
2449
|
+
* canvas, or a `none` group over the page itself. Such a group's body is
|
|
2450
|
+
* not composited in the shader: the optics pass writes the material as a
|
|
2451
|
+
* premultiplied layer and the browser composites it over the DOM, in
|
|
2452
|
+
* encoded sRGB. A linear-light alpha written into that composite lands the
|
|
2453
|
+
* surface darker than the same material sampled on the GPU — the gap
|
|
2454
|
+
* `cssTintAlpha` closes for the CSS tier, at a declared reference level —
|
|
2455
|
+
* so the host, which owns that mapping, resolves the pair once and hands
|
|
2456
|
+
* the same numbers to both tiers. Linear light; the renderer folds the
|
|
2457
|
+
* accessibility policy over it exactly as over the profile's own. Ignored
|
|
2458
|
+
* wherever the group samples a backdrop; absent, the profile's pair is
|
|
2459
|
+
* written as it is (the golden harness, which has no host).
|
|
2460
|
+
*/
|
|
2461
|
+
readonly unsampledMaterial?: {
|
|
2462
|
+
readonly tint: Rgb;
|
|
2463
|
+
readonly tintAlpha: number;
|
|
2464
|
+
};
|
|
1954
2465
|
readonly variant?: MaterialVariant;
|
|
1955
2466
|
/** Overrides the calibration-delegated union defaults. */
|
|
1956
2467
|
readonly union?: GroupUnionParams;
|
|
@@ -1999,6 +2510,173 @@ interface FrameParticipantView {
|
|
|
1999
2510
|
readonly render?: (context: FrameContextView) => void;
|
|
2000
2511
|
}
|
|
2001
2512
|
|
|
2513
|
+
/**
|
|
2514
|
+
* Where a backdrop texture sits on the plane, and what that makes of a CSS px.
|
|
2515
|
+
*
|
|
2516
|
+
* The optics pass samples the backdrop through one uv transform on
|
|
2517
|
+
* viewport-normalised coordinates — `uv = viewport01 · scale + offset` — and
|
|
2518
|
+
* the pyramid converts the material's CSS-px σ into source texels once, at build.
|
|
2519
|
+
* Both numbers are functions of the same thing: the rectangle of the viewport the
|
|
2520
|
+
* texture's pixels actually occupy. This module is the one place that rectangle
|
|
2521
|
+
* turns into either.
|
|
2522
|
+
*
|
|
2523
|
+
* ## Placed
|
|
2524
|
+
*
|
|
2525
|
+
* A texture handed over from a DOM element — an `<img>`, a `<canvas>`, a
|
|
2526
|
+
* `<video>` — has a box the host measures every read phase, in CSS px relative
|
|
2527
|
+
* to the viewport, and that box IS the placement: a 320 px raster in the corner
|
|
2528
|
+
* of a 1440 px page maps the 320 px, not the page. The source's own extent is
|
|
2529
|
+
* still what the pyramid is built from; the placement only says where on the
|
|
2530
|
+
* plane its texels land, so one texel is `placement.width / sourceWidth` CSS px.
|
|
2531
|
+
*
|
|
2532
|
+
* Outside the placement the sampler clamps to the edge. A surface hanging past
|
|
2533
|
+
* the texture's box reads the nearest edge texel rather than nothing; the
|
|
2534
|
+
* unsampled layer (W11a) is not applied to partial overlap in this cut.
|
|
2535
|
+
*
|
|
2536
|
+
* ## Cover
|
|
2537
|
+
*
|
|
2538
|
+
* A source with no placement — an `ImageBitmap`, an `OffscreenCanvas`, an
|
|
2539
|
+
* element not in the document, or a renderer driven without a host at all —
|
|
2540
|
+
* keeps the original rule: the backdrop fills the viewport and the overflow is
|
|
2541
|
+
* cropped symmetrically. Every golden and every calibration capture was taken
|
|
2542
|
+
* with the texture the size of the stage, where the two rules coincide exactly;
|
|
2543
|
+
* the demo's reference panel is where they came apart (claims §5.47).
|
|
2544
|
+
*/
|
|
2545
|
+
|
|
2546
|
+
/** A backdrop source's box on the plane, in CSS px relative to the viewport. */
|
|
2547
|
+
type BackdropPlacement = Rect;
|
|
2548
|
+
|
|
2549
|
+
/**
|
|
2550
|
+
* Device ownership, loss teardown, and rebuild (§GPU device ownership).
|
|
2551
|
+
*
|
|
2552
|
+
* `platform-web` owns the *browser* half of the story — is there an adapter, get
|
|
2553
|
+
* a device, notice when it goes away. This module owns the *resource* half: what
|
|
2554
|
+
* has to be thrown away when a device dies, when it is safe to build again, and
|
|
2555
|
+
* what core's capability inputs should read while that is in flight.
|
|
2556
|
+
*
|
|
2557
|
+
* ## The two ownership modes, and why they are not symmetric
|
|
2558
|
+
*
|
|
2559
|
+
* - **vitrea-owned** — this module can re-request a device by itself, so loss is
|
|
2560
|
+
* a transient it recovers from: tear down, re-request, re-attach, rebuild.
|
|
2561
|
+
* Every backdrop source is re-imported on the next frame because loss marks
|
|
2562
|
+
* them all dirty, which routes recovery through the same
|
|
2563
|
+
* one-rebuild-per-dirty-source-per-frame path a content change takes rather
|
|
2564
|
+
* than through a special case.
|
|
2565
|
+
* - **app-owned** — the app owns the resources that would have to be
|
|
2566
|
+
* re-registered, so this module reports the loss, raises
|
|
2567
|
+
* `replacementPending`, and **waits**. Groups stay demoted until
|
|
2568
|
+
* `replaceDevice` arrives and the re-registration handshake completes. Inventing
|
|
2569
|
+
* a device the app did not give us would break the one guarantee app-ownership
|
|
2570
|
+
* exists for: that every texture the renderer samples came from the app's own
|
|
2571
|
+
* device, because WebGPU has no cross-device sharing.
|
|
2572
|
+
*
|
|
2573
|
+
* `info.reason === "destroyed"` is our own teardown and is not recovered from —
|
|
2574
|
+
* re-requesting there would resurrect a renderer the host just destroyed.
|
|
2575
|
+
*
|
|
2576
|
+
* ## Generations
|
|
2577
|
+
*
|
|
2578
|
+
* Every attach bumps a generation counter, and every GPU object this package
|
|
2579
|
+
* holds is tagged with the generation it was made under. A resource from a lost
|
|
2580
|
+
* device is unusable forever, and the failure mode is silent — bindings simply
|
|
2581
|
+
* produce nothing — so "is this from the current device" has to be a cheap
|
|
2582
|
+
* integer comparison somewhere. It is here.
|
|
2583
|
+
*/
|
|
2584
|
+
/**
|
|
2585
|
+
* Structurally identical to `vitrea`'s `WebGPUAvailability` (X2's K1
|
|
2586
|
+
* amendment, Decision Log #21c). Declared here rather than imported because this
|
|
2587
|
+
* package sits *below* core in the dependency graph — core reaches the renderer
|
|
2588
|
+
* through a dynamic import, so an import back would close a cycle. A test pins
|
|
2589
|
+
* the two unions to the same members.
|
|
2590
|
+
*/
|
|
2591
|
+
type WebGPUAvailability = "not-requested" | "unavailable" | "available";
|
|
2592
|
+
type DeviceOwnership = "vitrea" | "app";
|
|
2593
|
+
interface RendererDeviceStatus {
|
|
2594
|
+
/** Feeds core's `PlatformProbe.webgpu` unchanged. */
|
|
2595
|
+
readonly webgpu: WebGPUAvailability;
|
|
2596
|
+
readonly deviceHealth: "ok" | "lost";
|
|
2597
|
+
readonly ownership: DeviceOwnership;
|
|
2598
|
+
readonly device: GPUDevice | undefined;
|
|
2599
|
+
/** Bumped on every attach. Tags every resource built under it. */
|
|
2600
|
+
readonly generation: number;
|
|
2601
|
+
/** True while an app-owned device is lost and no replacement has arrived. */
|
|
2602
|
+
readonly replacementPending: boolean;
|
|
2603
|
+
/** Why there is no device, when there is a reason worth reporting. */
|
|
2604
|
+
readonly unavailableReason?: "no-adapter" | "device-request-failed" | "lost";
|
|
2605
|
+
}
|
|
2606
|
+
/** The capability facts a host folds into core's `PlatformProbe`. */
|
|
2607
|
+
interface DeviceCapabilityInput {
|
|
2608
|
+
readonly webgpu: WebGPUAvailability;
|
|
2609
|
+
readonly deviceHealth: "ok" | "lost";
|
|
2610
|
+
}
|
|
2611
|
+
|
|
2612
|
+
/**
|
|
2613
|
+
* The governor's knobs.
|
|
2614
|
+
*
|
|
2615
|
+
* §Performance envelope: "The governor degrades **within** a tier first
|
|
2616
|
+
* (refraction resolution, adaptation cadence, edge analysis) and switches tiers
|
|
2617
|
+
* only with long hysteresis and cooldown." Decision Log #19 adds that intra-tier
|
|
2618
|
+
* degradation is **not a state change** — a group under `degrade-in-tier`
|
|
2619
|
+
* pressure keeps `activeRenderer: "webgpu"` and its whole resolved state.
|
|
2620
|
+
*
|
|
2621
|
+
* So the split is: **the policy lives in core, the knobs live here.** This module
|
|
2622
|
+
* exposes what can be turned and publishes a suggested ladder as *data*; it never
|
|
2623
|
+
* decides to turn anything, never reads a clock, and never applies hysteresis.
|
|
2624
|
+
* A governor that lived in the renderer would be a governor that could not see
|
|
2625
|
+
* the scene it is governing.
|
|
2626
|
+
*
|
|
2627
|
+
* ## The three knobs, weakest cost first
|
|
2628
|
+
*
|
|
2629
|
+
* 1. **`fieldFamily`** — `rsupn` → `rsup`. S2 priced this at 29% of the field's
|
|
2630
|
+
* cost for a bound that degrades from 0.170 px / 2.91° to 0.574 px / 4.26°.
|
|
2631
|
+
* It is the *first* step because it is one uniform and one pipeline: no
|
|
2632
|
+
* resolution change, so nothing resamples and nothing shimmers as it engages.
|
|
2633
|
+
* **Conditional on the f32 cross-check** (Decision Log #20) — and the check
|
|
2634
|
+
* has now been run, so the condition is met. See `FAMILY_C_CROSS_CHECK`.
|
|
2635
|
+
* 2. **`refractionResolutionScale`** — the group's **field** targets are
|
|
2636
|
+
* rasterised at a fraction of device resolution, and the optics and highlight
|
|
2637
|
+
* passes filter them instead of indexing them (`passes.ts`, and the
|
|
2638
|
+
* `fieldUpsampled` flag both shaders branch on). Quadratic saving on the pass
|
|
2639
|
+
* that evaluates the pseudo-SDF union per pixel per member, and the most
|
|
2640
|
+
* visible step, so it comes second.
|
|
2641
|
+
*
|
|
2642
|
+
* What it does **not** yet do is shrink the optics and highlight passes
|
|
2643
|
+
* themselves: those still render at full device resolution into the plane
|
|
2644
|
+
* canvases, because rendering them smaller means an offscreen target and a
|
|
2645
|
+
* resolve pass rather than a change of extent. So rungs 2 and 3 deliver the
|
|
2646
|
+
* field's quadratic saving and the cadence saving, not the full quadratic
|
|
2647
|
+
* saving on both heavy passes. Recorded here rather than implied, because a
|
|
2648
|
+
* ladder whose rungs are priced for savings they do not deliver is a ladder
|
|
2649
|
+
* core's policy will walk too far down.
|
|
2650
|
+
* 3. **`adaptationCadenceHz`** — how often analysis is reduced and read back.
|
|
2651
|
+
* Cheapest of the three in visual terms because the values it feeds are
|
|
2652
|
+
* already low-passed over hundreds of milliseconds; dropping the cadence
|
|
2653
|
+
* mostly changes how quickly a scroll's new backdrop is noticed.
|
|
2654
|
+
*/
|
|
2655
|
+
type FieldFamily = "rsupn" | "rsup";
|
|
2656
|
+
interface GovernorKnobs {
|
|
2657
|
+
/** Which pseudo-SDF family the field pass compiles. */
|
|
2658
|
+
readonly fieldFamily: FieldFamily;
|
|
2659
|
+
/**
|
|
2660
|
+
* Device-resolution fraction the group's field targets are rasterised at,
|
|
2661
|
+
* 0 < s <= 1. The optics and highlight passes upsample what they read. See the
|
|
2662
|
+
* module note for what this does and does not save.
|
|
2663
|
+
*/
|
|
2664
|
+
readonly refractionResolutionScale: number;
|
|
2665
|
+
/** Analysis reduction + readback rate. 0 disables adaptation entirely. */
|
|
2666
|
+
readonly adaptationCadenceHz: number;
|
|
2667
|
+
}
|
|
2668
|
+
interface Governor {
|
|
2669
|
+
readonly knobs: GovernorKnobs;
|
|
2670
|
+
/** True when `fieldFamily: "rsup"` is permitted to engage. */
|
|
2671
|
+
readonly familyCVerified: boolean;
|
|
2672
|
+
set(patch: Partial<GovernorKnobs>): GovernorKnobs;
|
|
2673
|
+
/** Move to a rung of the suggested ladder. Out-of-range clamps to the ends. */
|
|
2674
|
+
setLevel(level: number): GovernorKnobs;
|
|
2675
|
+
reset(): GovernorKnobs;
|
|
2676
|
+
/** Record that the cross-check passed, unlocking family C. */
|
|
2677
|
+
recordFamilyCVerified(): void;
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2002
2680
|
/**
|
|
2003
2681
|
* Pass-by-pass timing, for the benchmark §Performance envelope pins the ~2 ms
|
|
2004
2682
|
* hypothesis to.
|
|
@@ -2154,6 +2832,28 @@ interface PyramidResources {
|
|
|
2154
2832
|
readonly sizeEpoch: number;
|
|
2155
2833
|
/** The dirty epoch the last successful rebuild satisfied. */
|
|
2156
2834
|
readonly builtEpoch: number;
|
|
2835
|
+
/**
|
|
2836
|
+
* The body blur's σ in **level-0 texels** — the CSS-px σ the material asked
|
|
2837
|
+
* for, through the same cover fit and plan downscale the build applied.
|
|
2838
|
+
*
|
|
2839
|
+
* Published because the conversion is only knowable here: it needs the frame's
|
|
2840
|
+
* real extent, which is exactly why `bodySigmaCss` arrives in CSS px. The size
|
|
2841
|
+
* law's scattering facet consumes it (W2) — the optics pass widens the body blur
|
|
2842
|
+
* per surface by sampling the chain, and it cannot find the level to measure
|
|
2843
|
+
* from without knowing where the body already sits.
|
|
2844
|
+
*/
|
|
2845
|
+
readonly bodySigmaTexels: number;
|
|
2846
|
+
/**
|
|
2847
|
+
* Source texels per CSS px the build converted `bodySigmaCss` with — the placed
|
|
2848
|
+
* density where the source had a placement, the cover ratio where it did not
|
|
2849
|
+
* (`backdrop-fit.ts`) — and the source extent it was computed from. Recorded so
|
|
2850
|
+
* a later request can tell whether the body it would produce differs from the
|
|
2851
|
+
* one on the chain: a static image never re-dirties, so a placement whose SIZE
|
|
2852
|
+
* moved is the only signal that the σ in texels has gone stale.
|
|
2853
|
+
*/
|
|
2854
|
+
readonly texelsPerCss: number;
|
|
2855
|
+
readonly sourceWidth: number;
|
|
2856
|
+
readonly sourceHeight: number;
|
|
2157
2857
|
}
|
|
2158
2858
|
interface PyramidInstrumentation {
|
|
2159
2859
|
/** Successful rebuilds since the store was created. */
|
|
@@ -2184,6 +2884,11 @@ interface PyramidBuildRequest {
|
|
|
2184
2884
|
*/
|
|
2185
2885
|
readonly bodySigmaCss: number;
|
|
2186
2886
|
readonly viewportCss: readonly [number, number];
|
|
2887
|
+
/**
|
|
2888
|
+
* Where the source sits on the plane, in CSS px relative to the viewport, if
|
|
2889
|
+
* the host measured one. Absent, the source is cover-fit to the viewport.
|
|
2890
|
+
*/
|
|
2891
|
+
readonly placement?: BackdropPlacement;
|
|
2187
2892
|
}
|
|
2188
2893
|
type PyramidBuildOutcome = {
|
|
2189
2894
|
readonly status: "built";
|
|
@@ -2368,6 +3073,16 @@ interface GlassRenderer {
|
|
|
2368
3073
|
registerBackdrop(provider: BackdropProvider): void;
|
|
2369
3074
|
unregisterBackdrop(sourceId: string): void;
|
|
2370
3075
|
backdrop(sourceId: string): BackdropProvider | undefined;
|
|
3076
|
+
/**
|
|
3077
|
+
* Where a source's pixels sit on the plane, in CSS px relative to the viewport
|
|
3078
|
+
* (`backdrop-fit.ts`). Set every read phase by a host that measured the source
|
|
3079
|
+
* element's box; `undefined` (or never set) is the cover fit, the rule every
|
|
3080
|
+
* golden and calibration capture was taken under. Accepted before the provider
|
|
3081
|
+
* is registered and kept across device generations; cleared by
|
|
3082
|
+
* `unregisterBackdrop`.
|
|
3083
|
+
*/
|
|
3084
|
+
setBackdropPlacement(sourceId: string, placement: BackdropPlacement | undefined): void;
|
|
3085
|
+
backdropPlacement(sourceId: string): BackdropPlacement | undefined;
|
|
2371
3086
|
setViewport(viewport: ViewportState): void;
|
|
2372
3087
|
readonly viewport: ViewportState;
|
|
2373
3088
|
setGroup(input: GroupRenderInput): void;
|
|
@@ -2433,7 +3148,7 @@ declare function loadWebGPURenderer(): Promise<GlassRenderer>;
|
|
|
2433
3148
|
*
|
|
2434
3149
|
* Pure and passive: no DOM, no Node built-ins (X4), no timers and no clocks.
|
|
2435
3150
|
* Every probe result, media-query answer and layout rect arrives as plain data;
|
|
2436
|
-
* @vitrea
|
|
3151
|
+
* @vitreajs/vitrea-web owns the browser and drives the frames.
|
|
2437
3152
|
*
|
|
2438
3153
|
* The modules, roughly in dependency order:
|
|
2439
3154
|
*
|
|
@@ -2463,4 +3178,4 @@ declare const VITREA_CONTRACTS: {
|
|
|
2463
3178
|
declare const RENDERER_TIERS: readonly ["webgpu", "css"];
|
|
2464
3179
|
type RendererTier = (typeof RENDERER_TIERS)[number];
|
|
2465
3180
|
|
|
2466
|
-
export { ACCESSIBILITY_BEHAVIOR_TABLE, ACCESSIBILITY_FLAGS, ACCESSIBILITY_PRECEDENCE, type AccessibilityConsequences, type AccessibilityFlag, type AccessibilityOverride, type AccessibilityOverrides, type ActiveRenderer, type AnalysisQuality, type BackdropEstimatorProvider, type BackdropHint, type BackdropHintRequest, type BackdropProvider, type BackdropRebuildRequest, type BackdropResolutionPolicy, type BackdropSourceDescriptor, type BackdropSourceRecord, type BackdropTone, type CapabilityInputs, type ConfiguredSource, type CopyProviderOptions, type CornerProfile, type CornerRadii, DEFAULT_BACKDROP_RESOLUTION, DEFAULT_CLEAR_DIMMING, DEFAULT_GROUP_SAMPLING, DEMOTION_REASONS, DEMOTION_RECOVERY, DIAGNOSTIC_CODES, type DemotionReason, type DescriptorPatch, type Diagnostic, type DiagnosticCode, type DiagnosticSeverity, type DiagnosticSink, type DiagnosticsChannel, type DiagnosticsChannelOptions, type DimmingPolicy, type DomBackdropSource, FOREGROUND_MODES, FRAME_PHASES, type ForegroundAdaptation, type ForegroundMode, type ForegroundResolutionOptions, type FrameContext, type FrameInfo, type FrameParticipant, type FramePhase, type FrameReport, type FrameScheduler, type FrameSchedulerOptions, GLASS_PLANES, GOVERNOR_PRESSURES, type GlassGroupDescriptor, type GlassGroupRecord, type GlassGroupState, type GlassNodeDescriptor, type GlassNodeRecord, type GlassPlane, type GlassRenderer, type GlassScene, GlassSceneError, type GlassSceneErrorCode, type GlassSceneOptions, type GovernorPressure, type GroupHealth, type GroupSamplingGeometry, type GroupStateChange, HINT_AVAILABILITIES, type HintAvailability, type InteractionState, MATERIAL_VARIANTS$1 as MATERIAL_VARIANTS, type MaterialProfile$1 as MaterialProfile, type MaterialRequest, type MaterialVariant$1 as MaterialVariant, type MotionChannel, type MotionDriverKind, NOMINAL_ACCESSIBILITY_POLICY, OVERRIDABLE_ACCESSIBILITY_FLAGS, type OverridableAccessibilityFlag, type PlaneOverlap, type PlatformProbe, type ProxyOverlap, RENDERER_TIERS, type RecoveryContract, type RecoveryTrigger, type Rect
|
|
3181
|
+
export { ACCESSIBILITY_BEHAVIOR_TABLE, ACCESSIBILITY_FLAGS, ACCESSIBILITY_PRECEDENCE, type AccessibilityConsequences, type AccessibilityFlag, type AccessibilityOverride, type AccessibilityOverrides, type ActiveRenderer, type AnalysisQuality, type BackdropEstimatorProvider, type BackdropHint, type BackdropHintRequest, type BackdropProvider, type BackdropRebuildRequest, type BackdropResolutionPolicy, type BackdropSourceDescriptor, type BackdropSourceRecord, type BackdropTone, type CapabilityInputs, type ConcentricParent, type ConfiguredSource, type CopyProviderOptions, type CornerProfile, type CornerRadii, type CornerReference, DEFAULT_BACKDROP_RESOLUTION, DEFAULT_CLEAR_DIMMING, DEFAULT_GROUP_SAMPLING, DEMOTION_REASONS, DEMOTION_RECOVERY, DIAGNOSTIC_CODES, type DemotionReason, type DescriptorPatch, type Diagnostic, type DiagnosticCode, type DiagnosticSeverity, type DiagnosticSink, type DiagnosticsChannel, type DiagnosticsChannelOptions, type DimmingPolicy, type DomBackdropSource, FOREGROUND_MODES, FRAME_PHASES, type ForegroundAdaptation, type ForegroundMode, type ForegroundResolutionOptions, type FrameContext, type FrameInfo, type FrameParticipant, type FramePhase, type FrameReport, type FrameScheduler, type FrameSchedulerOptions, GLASS_PLANES, GOVERNOR_PRESSURES, type GlassGroupDescriptor, type GlassGroupRecord, type GlassGroupState, type GlassNodeDescriptor, type GlassNodeRecord, type GlassPlane, type GlassRenderer, type GlassScene, GlassSceneError, type GlassSceneErrorCode, type GlassSceneOptions, type GlassTint, type GovernorPressure, type GroupHealth, type GroupSamplingGeometry, type GroupStateChange, HINT_AVAILABILITIES, type HintAvailability, type InteractionState, MATERIAL_VARIANTS$1 as MATERIAL_VARIANTS, type MaterialProfile$1 as MaterialProfile, type MaterialRequest, type MaterialVariant$1 as MaterialVariant, type MotionChannel, type MotionDriverKind, NOMINAL_ACCESSIBILITY_POLICY, OVERRIDABLE_ACCESSIBILITY_FLAGS, type OverridableAccessibilityFlag, type PlaneOverlap, type PlatformProbe, type ProxyOverlap, RENDERER_TIERS, type RecoveryContract, type RecoveryTrigger, type Rect$1 as Rect, type RefractionQuality, type RendererTier, type ResolvedAccessibilityPolicy, type ResolvedBackdropHint, type ResolvedForegroundAdaptation, type ResolvedGroup, type ResolvedMaterial, type ResolvedMaterialPolicy, type ResolvedMotionPolicy, type ResolvedNode, SAMPLED_ASYNC_DEFAULTS, SAMPLED_ASYNC_RATE_LIMITS, type SamplingBackend, type SceneResolution, type ShapeChannels, type ShapeFamily, type SourceProbe, type StateChange, type SystemAccessibilityPreferences, type TextureBackdropSource, type TintColor, type TintMixingCheck, VITREA_CONTRACTS, type VariantMixingCheck, type Vec2, type VideoProviderOptions, WEBGPU_AVAILABILITIES, type WebGPUAvailability$1 as WebGPUAvailability, type WebGPURendererModule, type ZSlot, checkTintMixing, checkVariantMixing, classifyStateChange, clipRect, compareZSlot, createDiagnosticsChannel, createFrameScheduler, createGlassScene, defaultForegroundAdaptation, glassTint, inflateRect, isHealthy, loadWebGPURenderer, loadWebGPURendererModule, rectsOverlap, resolveAccessibilityPolicy, resolveBackdropHint, resolveForegroundAdaptation, resolveGlassGroupState, resolveMaterial, unionRect };
|