@weasel-js/renderer 1.10.0 → 1.10.1

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 CHANGED
@@ -4,7 +4,7 @@ A WebGL2 renderer that turns a list of draw commands into pixels.
4
4
 
5
5
  Part of [weasel](https://github.com/orochi235/weasel), a domain-agnostic 2D
6
6
  scene-graph canvas kit for React. See the
7
- [API reference](https://orochi235.github.io/weasel/api/).
7
+ [API reference](https://orochi235.github.io/weasel/#pkg/renderer).
8
8
 
9
9
  ```sh
10
10
  npm install @weasel-js/renderer
@@ -617,8 +617,12 @@ vec3 straightRgb(vec4 premultiplied) {
617
617
  );
618
618
 
619
619
  // src/shaders/batchFill.ts
620
- var BATCH_TEXTURE_SLOTS = 8;
620
+ var BATCH_TEXTURE_SLOTS = 16;
621
621
  var WHITE_SLOT = 0;
622
+ var RAMP_SLOT = BATCH_TEXTURE_SLOTS - 1;
623
+ var BATCH_MATRIX_SLOTS = 8;
624
+ var PAINT_MODES = 8;
625
+ var MATRIX_STRIDE = BATCH_TEXTURE_SLOTS * PAINT_MODES;
622
626
  var PAINT_MODE_PLAIN = 0;
623
627
  var PAINT_MODE_RADIAL = 3;
624
628
  var PAINT_MODE_CONIC = 4;
@@ -627,6 +631,9 @@ var INV_TAU = (1 / (2 * Math.PI)).toFixed(10);
627
631
  function packSlot(slot, mode) {
628
632
  return slot + BATCH_TEXTURE_SLOTS * mode;
629
633
  }
634
+ function withMatrix(slot, matrix) {
635
+ return slot + MATRIX_STRIDE * matrix;
636
+ }
630
637
  var BATCH_ATTRIBUTE_LOCATIONS = {
631
638
  a_position: 0,
632
639
  a_vertexColor: 1,
@@ -635,12 +642,16 @@ var BATCH_ATTRIBUTE_LOCATIONS = {
635
642
  a_texSlot: 4
636
643
  };
637
644
  var L = BATCH_ATTRIBUTE_LOCATIONS;
638
- function sampleChain(slots) {
639
- const arms = [];
640
- for (let i = 1; i < slots; i++) {
641
- arms.push(` if (slot == ${i}) return texture(u_samplers[${i}], uv);`);
642
- }
643
- return arms.join("\n");
645
+ function sampleTree(lo, hi, indent = " ") {
646
+ if (lo === hi) return `${indent}return texture(u_samplers[${lo}], uv);`;
647
+ const mid = lo + hi + 1 >> 1;
648
+ return [
649
+ `${indent}if (slot < ${mid}) {`,
650
+ sampleTree(lo, mid - 1, `${indent} `),
651
+ `${indent}} else {`,
652
+ sampleTree(mid, hi, `${indent} `),
653
+ `${indent}}`
654
+ ].join("\n");
644
655
  }
645
656
  var BATCH_VERT_SRC = (
646
657
  /* glsl */
@@ -657,6 +668,7 @@ out vec2 v_uv;
657
668
  out float v_post;
658
669
  flat out int v_texSlot;
659
670
  flat out float v_paintMode;
671
+ flat out int v_matrix;
660
672
  void main() {
661
673
  vec3 screen = u_model * vec3(a_position, 1.0);
662
674
  vec3 clip = u_proj * vec3(screen.xy, 1.0);
@@ -664,34 +676,39 @@ void main() {
664
676
  v_vertexColor = a_vertexColor;
665
677
  v_uv = a_uv;
666
678
  v_post = a_post;
667
- // slot + 8 * mode, unpacked \u2014 see the file header for why they share a float.
679
+ // slot + 16 * mode + 128 * matrix, unpacked \u2014 see the file header for why
680
+ // they share a float.
668
681
  int packed = int(a_texSlot + 0.5);
669
682
  v_texSlot = packed % ${BATCH_TEXTURE_SLOTS};
670
- v_paintMode = float(packed / ${BATCH_TEXTURE_SLOTS});
683
+ v_paintMode = float((packed / ${BATCH_TEXTURE_SLOTS}) % ${PAINT_MODES});
684
+ v_matrix = packed / ${MATRIX_STRIDE};
671
685
  }
672
686
  `
673
687
  );
674
- var BATCH_FRAG_SRC = (
675
- /* glsl */
676
- `#version 300 es
688
+ function batchFragSrc(matrices) {
689
+ const m = matrices === 1 ? "0" : "v_matrix";
690
+ return (
691
+ /* glsl */
692
+ `#version 300 es
677
693
  precision highp float;
678
694
  in vec4 v_vertexColor;
679
695
  in vec2 v_uv;
680
696
  in float v_post;
681
697
  flat in int v_texSlot;
682
698
  flat in float v_paintMode;
699
+ flat in int v_matrix;
683
700
  uniform sampler2D u_samplers[${BATCH_TEXTURE_SLOTS}];
684
701
  uniform vec4 u_color;
685
- uniform float u_alpha;
686
- uniform float u_synthBold;
702
+ uniform float u_alpha[${matrices}];
687
703
  uniform vec2 u_fieldScale[${BATCH_TEXTURE_SLOTS}];
688
- uniform mat4 u_colorMatrix;
689
- uniform vec4 u_colorBias;
704
+ uniform mat4 u_colorMatrix[${matrices}];
705
+ uniform vec4 u_colorBias[${matrices}];
690
706
  out vec4 outColor;
691
707
 
692
708
  vec4 sampleSlot(int slot, vec2 uv) {
693
- ${sampleChain(BATCH_TEXTURE_SLOTS)}
694
- return texture(u_samplers[0], uv);
709
+ ${sampleTree(0, BATCH_TEXTURE_SLOTS - 1)}
710
+ // Never reached: every slot returns above.
711
+ return vec4(0.0);
695
712
  }
696
713
  ${GLYPH_COVERAGE_GLSL}
697
714
  ${STRAIGHT_RGB_GLSL}
@@ -714,7 +731,7 @@ void main() {
714
731
  float t = v_paintMode > ${PAINT_MODE_CONIC - 0.5}
715
732
  ? fract(atan(v_uv.y, v_uv.x) * ${INV_TAU})
716
733
  : length(v_uv);
717
- texel = sampleSlot(v_texSlot, vec2(t, v_post));
734
+ texel = texture(u_samplers[${RAMP_SLOT}], vec2(t, v_post));
718
735
  } else {
719
736
  texel = sampleSlot(v_texSlot, v_uv);
720
737
  }
@@ -722,24 +739,26 @@ void main() {
722
739
  texel.rgb = mix(texel.rgb, straightRgb(texel), step(${PAINT_MODE_IMAGE - 0.5}, v_paintMode));
723
740
  float isGlyph = step(0.5, v_paintMode) * step(v_paintMode, 2.5);
724
741
  // Unconditional, and multiplied out afterwards rather than branched around:
725
- // see the file header.
726
- float coverage = glyphCoverage(texel, v_paintMode, u_synthBold, v_uv, u_fieldScale[v_texSlot]);
742
+ // see the file header. A glyph's a_post is its synthetic-bold shift.
743
+ float coverage = glyphCoverage(texel, v_paintMode, v_post * isGlyph, v_uv, u_fieldScale[v_texSlot]);
727
744
  // A glyph's texel is a distance field, so it takes no part in the color; a
728
745
  // plain vertex multiplies its texel in as it always did.
729
746
  vec4 src = mix(texel, vec4(1.0), isGlyph) * u_color * v_vertexColor;
730
- vec4 mapped = clamp(u_colorMatrix * src + u_colorBias, 0.0, 1.0);
731
- float a = mapped.a * u_alpha * mix(v_post, 1.0, isGrad) * mix(1.0, coverage, isGlyph);
747
+ vec4 mapped = clamp(u_colorMatrix[${m}] * src + u_colorBias[${m}], 0.0, 1.0);
748
+ float a = mapped.a * u_alpha[${m}] * mix(v_post, 1.0, max(isGrad, isGlyph)) * mix(1.0, coverage, isGlyph);
732
749
  outColor = vec4(mapped.rgb * a, a);
733
750
  }
734
751
  `
735
- );
752
+ );
753
+ }
754
+ var BATCH_FRAG_SRC = batchFragSrc(1);
755
+ var BATCH_MATRICES_FRAG_SRC = batchFragSrc(BATCH_MATRIX_SLOTS);
736
756
  var BATCH_FILL_UNIFORMS = [
737
757
  "u_proj",
738
758
  "u_model",
739
759
  "u_samplers",
740
760
  "u_color",
741
761
  "u_alpha",
742
- "u_synthBold",
743
762
  "u_fieldScale",
744
763
  "u_colorMatrix",
745
764
  "u_colorBias"
@@ -819,7 +838,6 @@ var INITIAL_VERTICES = 256;
819
838
  var INITIAL_INDICES = 384;
820
839
  var WHITE_U = 0.5;
821
840
  var WHITE_V = 0.5;
822
- var PLAIN_WHITE = packSlot(WHITE_SLOT, PAINT_MODE_PLAIN);
823
841
  var SOLID_RING_SIZE = 64;
824
842
  var BATCH_TIERS = [
825
843
  { vertices: 16, indices: 24 },
@@ -902,9 +920,9 @@ var DrawBatch = class {
902
920
  }
903
921
  /**
904
922
  * Append one rect's four corners through `m`, all carrying `rgba` (straight
905
- * alpha).
923
+ * alpha) and `P` in `a_texSlot`: the white texel, and the run's matrix.
906
924
  */
907
- pushRect(x, y, w, h, m, r, g, b, a) {
925
+ pushRect(x, y, w, h, m, r, g, b, a, P) {
908
926
  this.reserve(4, 6);
909
927
  let i = this.nVerts * FLOATS_PER_VERTEX;
910
928
  const ma = m[0], mb = m[1], mc = m[3], md = m[4], mtx = m[6], mty = m[7];
@@ -914,7 +932,6 @@ var DrawBatch = class {
914
932
  const bx = ma * x1 + mc * y + mtx, by = mb * x1 + md * y + mty;
915
933
  const cx = ma * x1 + mc * y1 + mtx, cy = mb * x1 + md * y1 + mty;
916
934
  const dx = ma * x + mc * y1 + mtx, dy = mb * x + md * y1 + mty;
917
- const P = PLAIN_WHITE;
918
935
  i = this.writeVertex(i, ax, ay, r, g, b, a, WHITE_U, WHITE_V, 1, P);
919
936
  i = this.writeVertex(i, bx, by, r, g, b, a, WHITE_U, WHITE_V, 1, P);
920
937
  i = this.writeVertex(i, cx, cy, r, g, b, a, WHITE_U, WHITE_V, 1, P);
@@ -926,7 +943,8 @@ var DrawBatch = class {
926
943
  * Append one image quad: the destination rect `(x, y, w, h)` mapped through
927
944
  * `m`, sampling `(u0, v0)`-`(u1, v1)`, every corner carrying `post` as the
928
945
  * after-the-color-matrix alpha factor and `rgb` as the scale on its texel.
929
- * `slot` is the texture unit the corners sample.
946
+ * `slot` is the texture unit the corners sample, and may carry the index of
947
+ * the run's matrix they are mapped by as well (`withMatrix`).
930
948
  *
931
949
  * Corners wind top-left, top-right, bottom-right, bottom-left — the same
932
950
  * winding `pushRect` uses, which is what lets a run of mixed rects and quads
@@ -956,13 +974,13 @@ var DrawBatch = class {
956
974
  * `rgba`.
957
975
  *
958
976
  * `mode` says which channels of that atlas carry the distance field, and
959
- * rides the vertices packed into the slot. The synthetic-bold threshold does
960
- * not: it is `u_synthBold`, and the caller breaks the run when it changes.
977
+ * rides the vertices packed into the slot. `synthBold` is the shift on the
978
+ * field's threshold, in `a_post`: a glyph has no use for an alpha factor there.
961
979
  *
962
980
  * A synthetic oblique is sheared here, before `m`; `tanItalic` is 0 for an
963
981
  * upright face. Corners wind as `pushQuad`'s do.
964
982
  */
965
- pushGlyph(x0, y0, x1, y1, baselineY, tanItalic, m, u0, v0, u1, v1, r, g, b, a, slot, mode) {
983
+ pushGlyph(x0, y0, x1, y1, baselineY, tanItalic, m, u0, v0, u1, v1, r, g, b, a, slot, mode, synthBold) {
966
984
  this.reserve(4, 6);
967
985
  let i = this.nVerts * FLOATS_PER_VERTEX;
968
986
  const ma = m[0], mb = m[1], mc = m[3], md = m[4], mtx = m[6], mty = m[7];
@@ -975,10 +993,10 @@ var DrawBatch = class {
975
993
  const cx = ma * bx1 + mc * y1 + mtx, cy = mb * bx1 + md * y1 + mty;
976
994
  const dx = ma * bx0 + mc * y1 + mtx, dy = mb * bx0 + md * y1 + mty;
977
995
  const P = packSlot(slot, mode);
978
- i = this.writeVertex(i, ax, ay, r, g, b, a, u0, v0, 1, P);
979
- i = this.writeVertex(i, bx, by, r, g, b, a, u1, v0, 1, P);
980
- i = this.writeVertex(i, cx, cy, r, g, b, a, u1, v1, 1, P);
981
- this.writeVertex(i, dx, dy, r, g, b, a, u0, v1, 1, P);
996
+ i = this.writeVertex(i, ax, ay, r, g, b, a, u0, v0, synthBold, P);
997
+ i = this.writeVertex(i, bx, by, r, g, b, a, u1, v0, synthBold, P);
998
+ i = this.writeVertex(i, cx, cy, r, g, b, a, u1, v1, synthBold, P);
999
+ this.writeVertex(i, dx, dy, r, g, b, a, u0, v1, synthBold, P);
982
1000
  this.pushQuadIndices();
983
1001
  return this.clip === null || this.clipQuad(this.nVerts - 4, this.nIdx - 6, this.clip);
984
1002
  }
@@ -1058,11 +1076,11 @@ var DrawBatch = class {
1058
1076
  return this.clip === null || this.clipMesh(base, this.nIdx - srcIdx.length, this.clip);
1059
1077
  }
1060
1078
  /**
1061
- * Append a tessellated mesh through `m`, all vertices carrying `rgba`. The
1062
- * mesh's own indices are rebased onto the staged vertices, which is why the
1063
- * index buffer is uploaded per flush rather than written once.
1079
+ * Append a tessellated mesh through `m`, all vertices carrying `rgba` and
1080
+ * `P`, as `pushRect`'s do. The mesh's own indices are rebased onto the staged
1081
+ * vertices, which is why the index buffer is uploaded per flush.
1064
1082
  */
1065
- pushMesh(mesh, m, r, g, b, a) {
1083
+ pushMesh(mesh, m, r, g, b, a, P) {
1066
1084
  const src = mesh.vertices;
1067
1085
  const srcIdx = mesh.indices;
1068
1086
  const n = src.length >> 1;
@@ -1083,7 +1101,7 @@ var DrawBatch = class {
1083
1101
  v[i++] = WHITE_U;
1084
1102
  v[i++] = WHITE_V;
1085
1103
  v[i++] = 1;
1086
- v[i++] = PLAIN_WHITE;
1104
+ v[i++] = P;
1087
1105
  }
1088
1106
  const base = this.nVerts;
1089
1107
  const out = this.idx;
@@ -1482,6 +1500,6 @@ function _resetImageCacheForTests() {
1482
1500
  readsAtLastPass = 0;
1483
1501
  }
1484
1502
 
1485
- export { BATCH_ATTRIBUTE_LOCATIONS, BATCH_FILL_ATTRIBUTES, BATCH_FILL_UNIFORMS, BATCH_FRAG_SRC, BATCH_TEXTURE_SLOTS, BATCH_VERT_SRC, DrawBatch, FLOATS_PER_VERTEX, GLImageCache, PAINT_MODE_CONIC, PAINT_MODE_PLAIN, PAINT_MODE_RADIAL, STRAIGHT_RGB_GLSL, __setImageLoaderForTests, _resetCacheForTests, _resetImageCacheForTests, _resetMarkerCommandCacheForTests, _resetOutlineMeshCacheForTests, _resetOutlineStrokeMeshCacheForTests, _resetPaintDrawKindsForTests, _resetPatternSpecCacheForTests, _resetProgramRegistryForTests, _resetStrokeMeshCacheForTests, axisAlignedClipRect, cachedMarkerCommands, commandFill, commandPaint, commandStroke, fillInPoseFrame, fillToBoundsFrame, getImageBitmap, getMesh, getPaintDrawKind, getProgramSource, imageStatus, intersectClipRects, isPaintKindKnown, isVectorImageSrc, outlineMesh, outlineStrokeMesh, paintDrawKindRegistry, programSourceRegistry, quantizeEmWidth, quantizeStrokeScale, registerPaintDrawKind, registerPaintDrawKindLoader, registerProgram, releaseImage, releaseImageSource, resolveFillPattern, resolvePatternSpec, retryImage, setImageCacheBudget, strokeMesh, subscribeImageReady, uploadPremultiplied, warmPaintKinds };
1486
- //# sourceMappingURL=chunk-LFD47OV2.js.map
1487
- //# sourceMappingURL=chunk-LFD47OV2.js.map
1503
+ export { BATCH_ATTRIBUTE_LOCATIONS, BATCH_FILL_ATTRIBUTES, BATCH_FILL_UNIFORMS, BATCH_FRAG_SRC, BATCH_MATRICES_FRAG_SRC, BATCH_MATRIX_SLOTS, BATCH_TEXTURE_SLOTS, BATCH_VERT_SRC, DrawBatch, FLOATS_PER_VERTEX, GLImageCache, PAINT_MODE_CONIC, PAINT_MODE_PLAIN, PAINT_MODE_RADIAL, RAMP_SLOT, STRAIGHT_RGB_GLSL, WHITE_SLOT, __setImageLoaderForTests, _resetCacheForTests, _resetImageCacheForTests, _resetMarkerCommandCacheForTests, _resetOutlineMeshCacheForTests, _resetOutlineStrokeMeshCacheForTests, _resetPaintDrawKindsForTests, _resetPatternSpecCacheForTests, _resetProgramRegistryForTests, _resetStrokeMeshCacheForTests, axisAlignedClipRect, cachedMarkerCommands, commandFill, commandPaint, commandStroke, fillInPoseFrame, fillToBoundsFrame, getImageBitmap, getMesh, getPaintDrawKind, getProgramSource, imageStatus, intersectClipRects, isPaintKindKnown, isVectorImageSrc, outlineMesh, outlineStrokeMesh, packSlot, paintDrawKindRegistry, programSourceRegistry, quantizeEmWidth, quantizeStrokeScale, registerPaintDrawKind, registerPaintDrawKindLoader, registerProgram, releaseImage, releaseImageSource, resolveFillPattern, resolvePatternSpec, retryImage, setImageCacheBudget, strokeMesh, subscribeImageReady, uploadPremultiplied, warmPaintKinds, withMatrix };
1504
+ //# sourceMappingURL=chunk-K7XCWVQH.js.map
1505
+ //# sourceMappingURL=chunk-K7XCWVQH.js.map