@multiplekex/shallot 0.2.2 → 0.2.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplekex/shallot",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -28,7 +28,7 @@ import { Transform } from "../../standard/transforms";
28
28
  const MAX_GLYPHS = 50000;
29
29
  const GLYPH_FLOATS = 16;
30
30
  const SDF_SIZE = 96;
31
- const SDF_EXPONENT = 6;
31
+ const SDF_EXPONENT = 9;
32
32
  const fontUrls: string[] = [];
33
33
  const loadedFonts: (Font | null)[] = [];
34
34
 
@@ -498,20 +498,40 @@ struct FragmentOutput {
498
498
  @location(1) mask: f32,
499
499
  }
500
500
 
501
+ const SDF_EXPONENT: f32 = 9.0;
502
+
503
+ fn sdfToSignedDistance(sdfValue: f32, maxDimension: f32) -> f32 {
504
+ let alpha = select(sdfValue, 1.0 - sdfValue, sdfValue > 0.5);
505
+ let absDist = (1.0 - pow(2.0 * alpha, 1.0 / SDF_EXPONENT)) * maxDimension;
506
+ return absDist * select(1.0, -1.0, sdfValue > 0.5);
507
+ }
508
+
501
509
  @fragment
502
510
  fn fs(input: VertexOutput) -> FragmentOutput {
503
511
  let sdfValue = textureSample(atlasTexture, atlasSampler, input.uv).r;
504
512
 
505
- let aaWidth = fwidth(sdfValue) * 0.707;
506
- let alpha = smoothstep(0.5 - aaWidth, 0.5 + aaWidth, sdfValue);
513
+ // Decode SDF to signed distance (negative = inside, positive = outside)
514
+ let maxDimension = max(input.glyphDimensions.x, input.glyphDimensions.y);
515
+ let signedDist = sdfToSignedDistance(sdfValue, maxDimension);
516
+
517
+ // Screen-space AA distance from UV derivatives
518
+ let aaDist = length(fwidth(input.localUV * input.glyphDimensions)) * 0.5;
519
+
520
+ // Smoothstep with adaptive band
521
+ let alpha = smoothstep(aaDist, -aaDist, signedDist);
522
+
523
+ // Dilate mask by FXAA span (8 pixels) to prevent edge bleeding
524
+ let fxaaSpan = aaDist * 8.0;
525
+ let inMaskRegion = signedDist < fxaaSpan;
507
526
 
508
- if alpha < 0.01 {
527
+ // Only discard if outside both visible region and mask region
528
+ if alpha < 0.01 && !inMaskRegion {
509
529
  discard;
510
530
  }
511
531
 
512
532
  var out: FragmentOutput;
513
533
  out.color = vec4(input.color.rgb, input.color.a * alpha);
514
- out.mask = select(0.0, 1.0, alpha > 0.01);
534
+ out.mask = select(0.0, 1.0, inMaskRegion);
515
535
  return out;
516
536
  }
517
537
  `;