@vitreajs/vitrea 0.23.0 → 0.24.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.
@@ -1025,6 +1025,9 @@ var DEFAULT_MATERIAL_PROFILE = {
1025
1025
  backdropToneResponseThin: [0.0126, 0.4561, 0.9713],
1026
1026
  backdropToneResponseThick: [0.4953, 0.5744, 0.9358],
1027
1027
  backdropToneResponseStrength: 1,
1028
+ backdropToneBlackStrength: 0,
1029
+ backdropToneBlackThin: 0,
1030
+ backdropToneBlackThick: 0,
1028
1031
  /*
1029
1032
  * FITTED (recalibration cascade, 2026-08-31). W8's geometry SURVIVES the fit
1030
1033
  * unchanged — `sigmaPx` 15.55, `offsetPx` 7.95, `spreadPx` 3.10 — and only the
@@ -1198,6 +1201,15 @@ var MATERIAL_IDENTITY_TABLE = [
1198
1201
  law: "colour = renormaliseToLinearLuma(mix(colour, chromaticityOf(backdrop) at colour's luma, bodyChromaRetention))",
1199
1202
  inertLawCase: "TO BE COMMITTED BY W31 G3 \u2014 the leaf does not exist yet. G0 names the shape and its identity (W31 X2); the case that proves the composite is bit-identical at 0, and the `test:gpu` case that the on state draws differently from off, land with the leaf."
1200
1203
  }
1204
+ },
1205
+ {
1206
+ wave: "W36",
1207
+ gate: { backdropToneBlackStrength: 0 },
1208
+ gated: ["backdropToneBlackThin", "backdropToneBlackThick"],
1209
+ law: "Below x=0.003 blend response and authority toward the black endpoint by strength*(1-smoothstep(0,0.003,x)); elsewhere execute the old solve exactly.",
1210
+ inertLawCase: 'packages/renderer-webgpu/test/w31-gate-groups.test.ts \u2014 "gate-group 4 \u2014 black strength 0 gates both black ordinates"; drawn identity in packages/renderer-webgpu/e2e/gpu/w36-black-branch.spec.ts',
1211
+ whyGated: "The strength-0 branch never reads either ordinate, preserving the old solve.",
1212
+ claims: "c9a \xA75.179; W36 Decision Log 5"
1201
1213
  }
1202
1214
  ];
1203
1215
  function materialLeafAt(resolved, path) {
@@ -1397,6 +1409,9 @@ function withMaterialOverrides(base, patch) {
1397
1409
  backdropToneResponseThin,
1398
1410
  backdropToneResponseThick,
1399
1411
  backdropToneResponseStrength: patch.backdropToneResponseStrength ?? base.backdropToneResponseStrength,
1412
+ backdropToneBlackStrength: patch.backdropToneBlackStrength ?? base.backdropToneBlackStrength,
1413
+ backdropToneBlackThin: patch.backdropToneBlackThin ?? base.backdropToneBlackThin,
1414
+ backdropToneBlackThick: patch.backdropToneBlackThick ?? base.backdropToneBlackThick,
1400
1415
  outerShadow: { ...base.outerShadow, ...patch.outerShadow },
1401
1416
  lightDirection: patch.lightDirection ?? base.lightDirection,
1402
1417
  rimLitAxis: patch.rimLitAxis ?? base.rimLitAxis,
@@ -1578,11 +1593,24 @@ function backdropToneResponse(encodedInput, thickness, profile = DEFAULT_MATERIA
1578
1593
  s0 = slopes[seg];
1579
1594
  s1 = slopes[seg + 1];
1580
1595
  }
1581
- return y0 * (1 + 2 * t) * (1 - t) * (1 - t) + s0 * h * t * (1 - t) * (1 - t) + y1 * t * t * (3 - 2 * t) + s1 * h * t * t * (t - 1) + levelFar;
1596
+ const response = y0 * (1 + 2 * t) * (1 - t) * (1 - t) + s0 * h * t * (1 - t) * (1 - t) + y1 * t * t * (3 - 2 * t) + s1 * h * t * t * (t - 1) + levelFar;
1597
+ const black = backdropToneBlackWeight(encodedInput, profile);
1598
+ if (black === 0)
1599
+ return response;
1600
+ const level = profile.backdropToneBlackThin + (profile.backdropToneBlackThick - profile.backdropToneBlackThin) * f;
1601
+ return response + (level - response) * black;
1602
+ }
1603
+ var BACKDROP_TONE_BLACK_JOIN = 3e-3;
1604
+ function backdropToneBlackWeight(encodedInput, profile) {
1605
+ if (profile.backdropToneBlackStrength <= 0 || encodedInput >= BACKDROP_TONE_BLACK_JOIN)
1606
+ return 0;
1607
+ return Math.min(1, Math.max(0, profile.backdropToneBlackStrength)) * (1 - smoothstep(0, BACKDROP_TONE_BLACK_JOIN, encodedInput));
1582
1608
  }
1583
1609
  function backdropToneSolveWeight(encodedInput, profile = DEFAULT_MATERIAL_PROFILE) {
1584
1610
  const anchor = profile.backdropToneAnchorX[0];
1585
- return smoothstep(anchor * 0.5, anchor, encodedInput);
1611
+ const authority = smoothstep(anchor * 0.5, anchor, encodedInput);
1612
+ const black = backdropToneBlackWeight(encodedInput, profile);
1613
+ return black === 0 ? authority : authority + (1 - authority) * black;
1586
1614
  }
1587
1615
  function sizeThicknessUnderPolicy(spanPx, policy, profile = DEFAULT_MATERIAL_PROFILE) {
1588
1616
  return sizeThickness(spanPx, profile) * profile.refractionScale[accessibilityRefractionCap(policy)];
@@ -3929,6 +3957,8 @@ var WGSL_OPTICS_PASS = `struct OpticsUniforms {
3929
3957
  /// below is multiplied by zero and the composite is bit-identical to the one
3930
3958
  /// W30 left, which is why the 34 goldens do not move.
3931
3959
  bodyChroma : vec4f,
3960
+ /// W36: strength, linear thin/thick black ordinates, padding. Gate 0 is identity.
3961
+ toneBlack : vec4f,
3932
3962
  };
3933
3963
 
3934
3964
  @group(0) @binding(0) var<uniform> ou : OpticsUniforms;
@@ -4830,8 +4860,9 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
4830
4860
  *
4831
4861
  * Three stand-downs, each measured rather than defensive: the whole axis is
4832
4862
  * off where no backdrop tone was measured (same gate as the collapse); the
4833
- * solve's authority fades to zero below the dark anchor, where the only
4834
- * evidence is the impulse cell the collapse constants were fitted on; and
4863
+ * default solve's authority fades to zero below the dark anchor, where W9
4864
+ * had only its impulse evidence (W36's selected black branch restores that
4865
+ * authority within its separate support); and
4835
4866
  * at k \u2192 1 the collapse owns the pixel outright, so the solve's
4836
4867
  * extrapolation is never evaluated against a vanishing (1 \u2212 k).
4837
4868
  */
@@ -4841,10 +4872,22 @@ fn fs_optics(in : FullscreenOut) -> @location(0) vec4f {
4841
4872
  sizedAlpha > 1e-3 && toneAdapt < 0.995) {
4842
4873
  let encodedInput = srgb_encode(toneColour.w);
4843
4874
  let anchor = max(ou.toneAnchor.x, 1e-4);
4844
- let authority =
4875
+ var authority =
4845
4876
  smoothstep(anchor * 0.5, anchor, encodedInput) * clamp(ou.toneRowThin.w, 0.0, 1.0);
4877
+ var blackWeight = 0.0;
4878
+ // Compact support rejoins before the smallest packed impulse input. Keep
4879
+ // the gate-0 and above-join arithmetic exact; no Hermite slope is touched.
4880
+ if (ou.toneBlack.x > 0.0 && encodedInput < 0.003) {
4881
+ blackWeight = clamp(ou.toneBlack.x, 0.0, 1.0) *
4882
+ (1.0 - smoothstep(0.0, 0.003, encodedInput));
4883
+ authority = mix(authority, clamp(ou.toneRowThin.w, 0.0, 1.0), blackWeight);
4884
+ }
4846
4885
  if (authority > 0.0) {
4847
- let response = tone_response(encodedInput, sizeK, toneLevelFar);
4886
+ var response = tone_response(encodedInput, sizeK, toneLevelFar);
4887
+ if (blackWeight > 0.0) {
4888
+ let f = sizeK * sizeK * (3.0 - 2.0 * sizeK);
4889
+ response = mix(response, mix(ou.toneBlack.y, ou.toneBlack.z, f), blackWeight);
4890
+ }
4848
4891
  // The collapse's mean pull is toward L(toneColour.rgb) \u2014 the LINEAR
4849
4892
  // mean, which toneAnchor.w carries \u2014 not toward the encoded level.
4850
4893
  let preCollapse = (response - toneAdapt * toneLinearMean) / (1.0 - toneAdapt);
@@ -5741,7 +5784,7 @@ function createPassRunner(context) {
5741
5784
  };
5742
5785
  },
5743
5786
  opticsPass(encoder, args) {
5744
- const slot = uniformSlot(`optics:${args.resourceId}`, 136);
5787
+ const slot = uniformSlot(`optics:${args.resourceId}`, 140);
5745
5788
  const d = slot.data;
5746
5789
  d[0] = args.viewportDevice[0];
5747
5790
  d[1] = args.viewportDevice[1];
@@ -5876,6 +5919,10 @@ function createPassRunner(context) {
5876
5919
  d[133] = 0;
5877
5920
  d[134] = 0;
5878
5921
  d[135] = 0;
5922
+ d[136] = args.backdropToneBlackStrength;
5923
+ d[137] = args.backdropToneBlackThin;
5924
+ d[138] = args.backdropToneBlackThick;
5925
+ d[139] = 0;
5879
5926
  slot.write();
5880
5927
  const chain = args.backdrop?.chain ?? placeholderView;
5881
5928
  const body = args.backdrop?.body ?? placeholderView;
@@ -7502,6 +7549,9 @@ function createWebGPURenderer(options = {}) {
7502
7549
  // from `backdropToneLevel`, so the fourth slot carries the linear
7503
7550
  // mean — the one quantity the solve needs that the tone colour does
7504
7551
  // not already hold.
7552
+ backdropToneBlackStrength: material.backdropToneBlackStrength,
7553
+ backdropToneBlackThin: material.backdropToneBlackThin,
7554
+ backdropToneBlackThick: material.backdropToneBlackThick,
7505
7555
  backdropToneAnchorX: material.backdropToneAnchorX,
7506
7556
  backdropToneResponseThin: material.backdropToneResponseThin,
7507
7557
  backdropToneResponseThick: material.backdropToneResponseThick,
@@ -7872,5 +7922,5 @@ function createWebGPURenderer(options = {}) {
7872
7922
  }
7873
7923
 
7874
7924
  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_DIGEST_RULE_VERSION, MATERIAL_IDENTITY_TABLE, 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, heavySecondTapSigmaAtScale, heavyTapSigmaAtScale, highlightModule, importColorMatrix, importModule, importPassSource, isUsablePlacement, lensAmountBasePx, lensDepthPx, lensDirection, lensDisplacementPx, lensExtentPx, lensHeightBasePx, lensMagnitudePx, lensOvalizationAt, lensSizeGain, lensSizeGainFromThickness, linearGradientStops, linearToSrgb, linearToSrgbChannel, materialDigestDroppedLeaves, materialDigestInput, materialLeafAt, occlusionAlphaUnderPolicy, occlusionLiftForPolicy, opticsModule, opticsUnderPolicy, outerShadowAlpha, outerShadowFalloff, outerShadowLiftRise, outerShadowOcclusionAt, outerShadowReachPx, outerShadowSigmaPx, 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 };
7875
- //# sourceMappingURL=dist-NMQ322KB.js.map
7876
- //# sourceMappingURL=dist-NMQ322KB.js.map
7925
+ //# sourceMappingURL=dist-K743C2OC.js.map
7926
+ //# sourceMappingURL=dist-K743C2OC.js.map