@genome-spy/core 0.42.0 → 0.42.2

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.
Files changed (53) hide show
  1. package/dist/bundle/index.es.js +2575 -2567
  2. package/dist/bundle/index.js +75 -74
  3. package/dist/src/encoder/encoder.d.ts +6 -1
  4. package/dist/src/encoder/encoder.d.ts.map +1 -1
  5. package/dist/src/encoder/encoder.js +10 -0
  6. package/dist/src/gl/arrayBuilder.js +1 -1
  7. package/dist/src/gl/colorUtils.d.ts.map +1 -0
  8. package/dist/src/{scale → gl}/colorUtils.js +1 -1
  9. package/dist/src/gl/dataToVertices.d.ts +1 -9
  10. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  11. package/dist/src/gl/dataToVertices.js +33 -73
  12. package/dist/src/{scale → gl}/glslScaleGenerator.d.ts +23 -1
  13. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -0
  14. package/dist/src/{scale → gl}/glslScaleGenerator.js +61 -8
  15. package/dist/src/gl/webGLHelper.js +1 -1
  16. package/dist/src/marks/link.js +2 -2
  17. package/dist/src/marks/mark.d.ts +2 -1
  18. package/dist/src/marks/mark.d.ts.map +1 -1
  19. package/dist/src/marks/mark.js +30 -2
  20. package/dist/src/marks/{pointMark.d.ts → point.d.ts} +1 -1
  21. package/dist/src/marks/point.d.ts.map +1 -0
  22. package/dist/src/marks/{pointMark.js → point.js} +3 -3
  23. package/dist/src/marks/{rectMark.d.ts → rect.d.ts} +1 -1
  24. package/dist/src/marks/rect.d.ts.map +1 -0
  25. package/dist/src/marks/{rectMark.js → rect.js} +2 -3
  26. package/dist/src/marks/rect.vertex.glsl.js +2 -0
  27. package/dist/src/marks/rule.js +3 -3
  28. package/dist/src/marks/text.js +3 -3
  29. package/dist/src/utils/indexer.d.ts.map +1 -1
  30. package/dist/src/utils/indexer.js +10 -1
  31. package/dist/src/utils/indexer.test.js +2 -0
  32. package/dist/src/view/unitView.d.ts +1 -1
  33. package/dist/src/view/unitView.js +2 -2
  34. package/dist/src/view/view.test.js +1 -1
  35. package/package.json +2 -2
  36. package/dist/src/gl/rect.vertex.glsl.js +0 -2
  37. package/dist/src/marks/pointMark.d.ts.map +0 -1
  38. package/dist/src/marks/rectMark.d.ts.map +0 -1
  39. package/dist/src/scale/colorUtils.d.ts.map +0 -1
  40. package/dist/src/scale/glslScaleGenerator.d.ts.map +0 -1
  41. /package/dist/src/{scale → gl}/colorUtils.d.ts +0 -0
  42. /package/dist/src/{gl → marks}/link.fragment.glsl.js +0 -0
  43. /package/dist/src/{gl → marks}/link.vertex.glsl.js +0 -0
  44. /package/dist/src/{gl → marks}/point.common.glsl.js +0 -0
  45. /package/dist/src/{gl → marks}/point.fragment.glsl.js +0 -0
  46. /package/dist/src/{gl → marks}/point.vertex.glsl.js +0 -0
  47. /package/dist/src/{gl → marks}/rect.fragment.glsl.js +0 -0
  48. /package/dist/src/{gl → marks}/rule.common.glsl.js +0 -0
  49. /package/dist/src/{gl → marks}/rule.fragment.glsl.js +0 -0
  50. /package/dist/src/{gl → marks}/rule.vertex.glsl.js +0 -0
  51. /package/dist/src/{gl → marks}/text.common.glsl.js +0 -0
  52. /package/dist/src/{gl → marks}/text.fragment.glsl.js +0 -0
  53. /package/dist/src/{gl → marks}/text.vertex.glsl.js +0 -0
@@ -45,7 +45,12 @@ export function isChannelDefWithScale(channelDef: import("../spec/channel.js").C
45
45
  * @param {import("../view/unitView.js").default} view
46
46
  * @param {import("../spec/channel.js").Channel} channel
47
47
  */
48
- export function getChannelDefWithScale(view: import("../view/unitView.js").default, channel: import("../spec/channel.js").Channel): import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").PositionDatumDef | import("../spec/channel.js").MarkPropExprDef<import("../spec/channel.js").Type> | import("../spec/channel.js").MarkPropDatumDef<import("../spec/channel.js").Type> | import("../spec/channel.js").MarkPropDatumDef<import("../spec/channel.js").TypeForShape> | import("../spec/channel.js").PositionFieldDef<string> | import("../spec/channel.js").MarkPropFieldDef<string, import("../spec/channel.js").Type> | import("../spec/channel.js").MarkPropFieldDef<string, import("../spec/channel.js").TypeForShape>;
48
+ export function getChannelDefWithScale(view: import("../view/unitView.js").default, channel: import("../spec/channel.js").Channel): import("../spec/channel.js").MarkPropExprDef<import("../spec/channel.js").Type> | import("../spec/channel.js").MarkPropDatumDef<import("../spec/channel.js").Type> | import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").PositionDatumDef | import("../spec/channel.js").MarkPropDatumDef<import("../spec/channel.js").TypeForShape> | import("../spec/channel.js").MarkPropFieldDef<string, import("../spec/channel.js").Type> | import("../spec/channel.js").PositionFieldDef<string> | import("../spec/channel.js").MarkPropFieldDef<string, import("../spec/channel.js").TypeForShape>;
49
+ /**
50
+ * @param {import("../spec/channel.js").ChannelDef} channelDef
51
+ * @returns {channelDef is import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>}
52
+ */
53
+ export function isChannelDefWithType(channelDef: import("../spec/channel.js").ChannelDef): channelDef is import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>;
49
54
  /**
50
55
  * @param {import("../spec/channel.js").ChannelDef} channelDef
51
56
  * @returns {channelDef is import("../spec/channel.js").ChromPosDef}
@@ -1 +1 @@
1
- {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/encoder/encoder.js"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH,6CAJW,OAAO,kBAAkB,EAAE,OAAO,aAClC,OAAO,oBAAoB,EAAE,QAAQ,gGAsC/C;AAED;;;;;;;GAOG;AACH,0CANW,OAAO,oBAAoB,EAAE,UAAU,SACvC,GAAG,0IAyFb;AAED;;;;;GAKG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,mEAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,uDAKjD;AAED;;;GAGG;AACH,kDAHW,OAAO,oBAAoB,EAAE,UAAU,kEAWjD;AAED;;;GAGG;AACH,6CAHW,OAAO,qBAAqB,EAAE,OAAO,WACrC,OAAO,oBAAoB,EAAE,OAAO,klBAS9C;AAED;;;GAGG;AACH,0CAHW,OAAO,oBAAoB,EAAE,UAAU,0DAKjD;AAED;;;GAGG;AACH,sCAHW,OAAO,oBAAoB,EAAE,UAAU,sDAKjD;AAoBD;;;GAGG;AACH,oDAHW,OAAO,oBAAoB,EAAE,OAAO,oEAM9C;AAED;;;GAGG;AACH,6CAHW,OAAO,oBAAoB,EAAE,OAAO,6DAM9C;AAqBD;;;GAGG;AACH,4CAFW,MAAM,WAIhB;AAED;;;;GAIG;AACH,oDAFW,OAAO,oBAAoB,EAAE,OAAO,2DAS9C;AAED;;;;;GAKG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,wCAI9C;AAED;;;;GAIG;AACH,kDAFW,OAAO,oBAAoB,EAAE,OAAO,0CAM9C;AAED;;GAEG;AACH,wCAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;;GAIG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;GAGG;AACH,4CAHW,OAAO,oBAAoB,EAAE,OAAO,4DAuB9C;AAED;;;;;GAKG;AACH,0CAHW,OAAO,oBAAoB,EAAE,OAAO,GAClC,GAAG,EAAE,CAsBjB;AAED;;;GAGG;AACH,gDAHW,OAAO,oBAAoB,EAAE,OAAO,UACzB,GAAG,KAAE,MAAM,CAmBhC;AA7LD;;GAEG;AACH,wCAFU,OAAO,oBAAoB,EAAE,wBAAwB,EAAE,CAEb;AAEpD;;GAEG;AACH,0CAFU,OAAO,oBAAoB,EAAE,0BAA0B,EAAE,CAEX;AAExD;;GAEG;AACH,iCAFU,OAAO,oBAAoB,EAAE,iBAAiB,EAAE,CAKxD;AAoBF;;;;GAIG;AACH,gCAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,0BAA0B,CAAC,CAAC,CAKtH;AAEF;;;;GAIG;AACH,8BAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAInG"}
1
+ {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/encoder/encoder.js"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH,6CAJW,OAAO,kBAAkB,EAAE,OAAO,aAClC,OAAO,oBAAoB,EAAE,QAAQ,gGAsC/C;AAED;;;;;;;GAOG;AACH,0CANW,OAAO,oBAAoB,EAAE,UAAU,SACvC,GAAG,0IA2Fb;AAED;;;;;GAKG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,mEAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,uDAKjD;AAED;;;GAGG;AACH,kDAHW,OAAO,oBAAoB,EAAE,UAAU,kEAWjD;AAED;;;GAGG;AACH,6CAHW,OAAO,qBAAqB,EAAE,OAAO,WACrC,OAAO,oBAAoB,EAAE,OAAO,klBAS9C;AAED;;;GAGG;AACH,iDAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,0CAHW,OAAO,oBAAoB,EAAE,UAAU,0DAKjD;AAED;;;GAGG;AACH,sCAHW,OAAO,oBAAoB,EAAE,UAAU,sDAKjD;AAoBD;;;GAGG;AACH,oDAHW,OAAO,oBAAoB,EAAE,OAAO,oEAM9C;AAED;;;GAGG;AACH,6CAHW,OAAO,oBAAoB,EAAE,OAAO,6DAM9C;AAqBD;;;GAGG;AACH,4CAFW,MAAM,WAIhB;AAED;;;;GAIG;AACH,oDAFW,OAAO,oBAAoB,EAAE,OAAO,2DAS9C;AAED;;;;;GAKG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,wCAI9C;AAED;;;;GAIG;AACH,kDAFW,OAAO,oBAAoB,EAAE,OAAO,0CAM9C;AAED;;GAEG;AACH,wCAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;;GAIG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;GAGG;AACH,4CAHW,OAAO,oBAAoB,EAAE,OAAO,4DAuB9C;AAED;;;;;GAKG;AACH,0CAHW,OAAO,oBAAoB,EAAE,OAAO,GAClC,GAAG,EAAE,CAsBjB;AAED;;;GAGG;AACH,gDAHW,OAAO,oBAAoB,EAAE,OAAO,UACzB,GAAG,KAAE,MAAM,CAmBhC;AA7LD;;GAEG;AACH,wCAFU,OAAO,oBAAoB,EAAE,wBAAwB,EAAE,CAEb;AAEpD;;GAEG;AACH,0CAFU,OAAO,oBAAoB,EAAE,0BAA0B,EAAE,CAEX;AAExD;;GAEG;AACH,iCAFU,OAAO,oBAAoB,EAAE,iBAAiB,EAAE,CAKxD;AAoBF;;;;GAIG;AACH,gCAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,0BAA0B,CAAC,CAAC,CAKtH;AAEF;;;;GAIG;AACH,8BAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAInG"}
@@ -101,6 +101,8 @@ export function createEncoder(channelDef, scale, accessor, channel) {
101
101
  if (isDiscrete(scale.type)) {
102
102
  // TODO: pass the found values back to the scale/resolution
103
103
  const indexer = createIndexer();
104
+ // Warning: There's a chance that the domain and indexer get out of sync.
105
+ // TODO: Make this more robust
104
106
  indexer.addAll(scale.domain());
105
107
  encoder.indexer = indexer;
106
108
  }
@@ -197,6 +199,14 @@ export function getChannelDefWithScale(view, channel) {
197
199
  }
198
200
  }
199
201
 
202
+ /**
203
+ * @param {import("../spec/channel.js").ChannelDef} channelDef
204
+ * @returns {channelDef is import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>}
205
+ */
206
+ export function isChannelDefWithType(channelDef) {
207
+ return channelDef && "type" in channelDef;
208
+ }
209
+
200
210
  /**
201
211
  * @param {import("../spec/channel.js").ChannelDef} channelDef
202
212
  * @returns {channelDef is import("../spec/channel.js").ChromPosDef}
@@ -1,5 +1,5 @@
1
1
  import { isNumber } from "vega-util";
2
- import { ATTRIBUTE_PREFIX } from "../scale/glslScaleGenerator.js";
2
+ import { ATTRIBUTE_PREFIX } from "./glslScaleGenerator.js";
3
3
 
4
4
  /**
5
5
  * @typedef {Object} ConverterMetadata
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colorUtils.d.ts","sourceRoot":"","sources":["../../../src/gl/colorUtils.js"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,kDALW,MAAM,GAAG,OAAO,kBAAkB,EAAE,YAAY,MAChD,sBAAsB,UACtB,MAAM,oBACN,YAAY,gBAqCtB;AAED;;;;;GAKG;AACH,uDALW,MAAM,EAAE,qBACR,OAAO,kBAAkB,EAAE,gBAAgB,GAAG,OAAO,kBAAkB,EAAE,sBAAsB,MAC/F,sBAAsB,oBACtB,YAAY,gBA6BtB;AAED;;;;;;;;GAQG;AACH,6CALW,MAAM,EAAE,MACR,sBAAsB,UACtB,MAAM,oBACN,YAAY,gBAqBtB;AAED;;;;;;;GAOG;AACH,mDALW,MAAM,EAAE,MACR,sBAAsB,UACtB,MAAM,oBACN,YAAY,gBActB"}
@@ -3,7 +3,7 @@ import { range } from "d3-array";
3
3
  import { scheme as vegaScheme, interpolateColors } from "vega-scale";
4
4
  import { isString, isArray, isFunction } from "vega-util";
5
5
  import { peek } from "../utils/arrayUtils.js";
6
- import { createOrUpdateTexture } from "../gl/webGLHelper.js";
6
+ import { createOrUpdateTexture } from "./webGLHelper.js";
7
7
 
8
8
  /**
9
9
  * @param {string | import("../spec/scale.js").SchemeParams} schemeParams
@@ -82,21 +82,13 @@ export class RectVertexBuilder extends GeometryBuilder {
82
82
  * @param {Object} object
83
83
  * @param {Record<string, Encoder>} object.encoders
84
84
  * @param {string[]} object.attributes
85
- * @param {number} [object.tessellationThreshold]
86
- * If the rect is wider than the threshold, tessellate it into pieces
87
- * @param {number[]} [object.visibleRange]
88
85
  * @param {number} [object.numItems] Number of data items
89
86
  */
90
- constructor({ encoders, attributes, tessellationThreshold, visibleRange, numItems, }: {
87
+ constructor({ encoders, attributes, numItems }: {
91
88
  encoders: Record<string, import("../types/encoder.js").Encoder>;
92
89
  attributes: string[];
93
- tessellationThreshold?: number;
94
- visibleRange?: number[];
95
90
  numItems?: number;
96
91
  });
97
- visibleRange: number[];
98
- tessellationThreshold: number;
99
- updateFrac: (arg0: number | number[]) => any;
100
92
  }
101
93
  export class RuleVertexBuilder extends GeometryBuilder {
102
94
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"dataToVertices.d.ts","sourceRoot":"","sources":["../../../src/gl/dataToVertices.js"],"names":[],"mappings":"AAaA;;;;;GAKG;AACH;IACI;;;OAGG;IAEH;;;;;;OAMG;IACH;;qBAJW,MAAM,EAAE;sBACR,MAAM;OAqDhB;IAjDG,gEAAwB;IAGxB;;MAKC;IAED,0BAAoC;IAEpC,8BAAoD;IAiCpD,mBAAmB;IAEnB,yFAAyF;IACzF,UADW,IAAI,GAAG,EAAE,UAAU,CAAC,CACkB;IAGrD;;;;OAIG;IACH,mBAFW,GAAG,QAcb;IAED;;OAEG;IACH,oBAFW,IAAI,GAAG,EAAE,MAAM,EAAE,CAAC,QAM5B;IAED;;;OAGG;IACH,cAHW,GAAG,QACH,MAAM,EAAE,kCAYlB;IAED;;;;OAIG;IACH,sBAJW,OAAO,qBAAqB,EAAE,IAAI,OAClC,MAAM,OACN,MAAM,QAyDhB;IAED;;;;;OAKG;IACH,mBAFW,OAAO,qBAAqB,EAAE,KAAK,QAI7C;IAzDO;;;MAAyB;IA2DjC;QAEQ,uGAAuG;gBAA5F,OAAO,MAAM,EAAE;YAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC;YAAC,aAAa,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAC,CAAC;QAEnG,8BAA8B;;QAE9B,8CAA8C;;;MAIrD;CACJ;AAED;IACI;;;;;;;;;OASG;IACH;;oBANW,MAAM,EAAE;gCACR,MAAM;uBAEN,MAAM,EAAE;mBACR,MAAM;OAqBhB;IALG,uBAAgC;IAEhC,8BAA8D;IAE9D,6CAA+D;CAiFtE;AAED;IACI;;;;;;;;;OASG;IACH;;oBANW,MAAM,EAAE;gCACR,MAAM;uBAEN,MAAM,EAAE;mBACR,MAAM;OAsBhB;IANG,uBAAgC;IAEhC,8BAA8D;IAE9D,6CAA+D;IAC/D,4CAA6D;CA2CpE;AAED;IACI;;;;;;OAMG;IACH;;oBAHW,MAAM,EAAE;mBACR,MAAM;OAQhB;CACJ;AAED;IACI;;;;;OAKG;IACH;;oBAHW,MAAM,EAAE;mBACR,MAAM;OAQhB;CAYJ;AAED;IACI;;;;;;;;;OASG;IACH;;oBANW,MAAM,EAAE;qBACR,OAAO,2BAA2B,EAAE,aAAa;oBACjD,OAAO,MAAM,EAAE,GAAG,CAAC;wBACnB,MAAM;sBACN,OAAO;OA4CjB;IA7BG,4DAA2B;IAC3B,2DAA0B;IAE1B,gCAA4B;IAQ5B,qCAAqC;IACrC,sBADmB,GAAG,KAAK,MAAM,CAMf;IAElB,oDAGC;IACD,qDAGC;IAED,8CAAiE;CA8IxE;;;;;;;;YA/mBS,MAAM;;;;WACN,MAAM;YACN,OAAO,yBAAyB,EAAE,MAAM;;yBAdzB,mBAAmB"}
1
+ {"version":3,"file":"dataToVertices.d.ts","sourceRoot":"","sources":["../../../src/gl/dataToVertices.js"],"names":[],"mappings":"AAeA;;;;;GAKG;AACH;IACI;;;OAGG;IAEH;;;;;;OAMG;IACH;;qBAJW,MAAM,EAAE;sBACR,MAAM;OAyEhB;IArEG,gEAAwB;IAGxB;;MAKC;IAQD,0BAAoC;IAEpC,8BAAoD;IA+CpD,mBAAmB;IAEnB,yFAAyF;IACzF,UADW,IAAI,GAAG,EAAE,UAAU,CAAC,CACkB;IAGrD;;;;OAIG;IACH,mBAFW,GAAG,QAcb;IAED;;OAEG;IACH,oBAFW,IAAI,GAAG,EAAE,MAAM,EAAE,CAAC,QAM5B;IAED;;;OAGG;IACH,cAHW,GAAG,QACH,MAAM,EAAE,kCAYlB;IAED;;;;OAIG;IACH,sBAJW,OAAO,qBAAqB,EAAE,IAAI,OAClC,MAAM,OACN,MAAM,QAyDhB;IAED;;;;;OAKG;IACH,mBAFW,OAAO,qBAAqB,EAAE,KAAK,QAI7C;IAzDO;;;MAAyB;IA2DjC;QAEQ,uGAAuG;gBAA5F,OAAO,MAAM,EAAE;YAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC;YAAC,aAAa,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAC,CAAC;QAEnG,8BAA8B;;QAE9B,8CAA8C;;;MAIrD;CACJ;AAED;IACI;;;;;;OAMG;IACH;;oBAHW,MAAM,EAAE;mBACR,MAAM;OAQhB;CAkCJ;AAED;IACI;;;;;;;;;OASG;IACH;;oBANW,MAAM,EAAE;gCACR,MAAM;uBAEN,MAAM,EAAE;mBACR,MAAM;OAsBhB;IANG,uBAAgC;IAEhC,8BAA8D;IAE9D,6CAA+D;IAC/D,4CAA6D;CA2CpE;AAED;IACI;;;;;;OAMG;IACH;;oBAHW,MAAM,EAAE;mBACR,MAAM;OAQhB;CACJ;AAED;IACI;;;;;OAKG;IACH;;oBAHW,MAAM,EAAE;mBACR,MAAM;OAQhB;CAYJ;AAED;IACI;;;;;;;;;OASG;IACH;;oBANW,MAAM,EAAE;qBACR,OAAO,2BAA2B,EAAE,aAAa;oBACjD,OAAO,MAAM,EAAE,GAAG,CAAC;wBACnB,MAAM;sBACN,OAAO;OA4CjB;IA7BG,4DAA2B;IAC3B,2DAA0B;IAE1B,gCAA4B;IAQ5B,qCAAqC;IACrC,sBADmB,GAAG,KAAK,MAAM,CAMf;IAElB,oDAGC;IACD,qDAGC;IAED,8CAAiE;CA8IxE;;;;;;;;YArkBS,MAAM;;;;WACN,MAAM;YACN,OAAO,yBAAyB,EAAE,MAAM;;yBAhBzB,mBAAmB"}
@@ -6,9 +6,11 @@ import { SDF_PADDING } from "../fonts/bmFontMetrics.js";
6
6
  import { createBinningRangeIndexer } from "../utils/binnedIndex.js";
7
7
  import { isValueDef } from "../encoder/encoder.js";
8
8
  import {
9
+ dedupeEncodingFields,
9
10
  isHighPrecisionScale,
11
+ makeAttributeName,
10
12
  splitHighPrecision,
11
- } from "../scale/glslScaleGenerator.js";
13
+ } from "./glslScaleGenerator.js";
12
14
  import { isContinuous } from "vega-scale";
13
15
 
14
16
  /**
@@ -41,6 +43,12 @@ export class GeometryBuilder {
41
43
  )
42
44
  );
43
45
 
46
+ const dedupedEncodingFields = [
47
+ ...dedupeEncodingFields(encoders).entries(),
48
+ ]
49
+ .filter(([key, channels]) => key[1] && channels.length > 1)
50
+ .map(([_key, channels]) => channels);
51
+
44
52
  this.allocatedVertices = numVertices;
45
53
 
46
54
  this.variableBuilder = new ArrayBuilder(numVertices);
@@ -49,6 +57,16 @@ export class GeometryBuilder {
49
57
  // TODO: If more than one channels use the same field with the same data type, convert the field only once.
50
58
 
51
59
  for (const [channel, ce] of Object.entries(this.variableEncoders)) {
60
+ // Only add the first of the shared channels as all the rest are same
61
+ // For example, if both x and x2 are using the same field, only x is
62
+ // added to the array builder with the name "x_x2".
63
+ const sharedChannels = dedupedEncodingFields.find((channels) =>
64
+ channels.find((c) => c == channel)
65
+ );
66
+ if (sharedChannels && channel != sharedChannels[0]) {
67
+ continue;
68
+ }
69
+
52
70
  const accessor = ce.accessor;
53
71
 
54
72
  const doubleArray = [0, 0];
@@ -69,7 +87,11 @@ export class GeometryBuilder {
69
87
  ? (d) => splitHighPrecision(accessor(d), doubleArray)
70
88
  : accessor;
71
89
 
72
- this.variableBuilder.addConverter(channel, {
90
+ const attributeName = sharedChannels
91
+ ? makeAttributeName(sharedChannels)
92
+ : channel;
93
+
94
+ this.variableBuilder.addConverter(attributeName, {
73
95
  f,
74
96
  numComponents: hp ? 2 : 1,
75
97
  arrayReference: hp ? doubleArray : undefined,
@@ -217,30 +239,14 @@ export class RectVertexBuilder extends GeometryBuilder {
217
239
  * @param {Object} object
218
240
  * @param {Record<string, Encoder>} object.encoders
219
241
  * @param {string[]} object.attributes
220
- * @param {number} [object.tessellationThreshold]
221
- * If the rect is wider than the threshold, tessellate it into pieces
222
- * @param {number[]} [object.visibleRange]
223
242
  * @param {number} [object.numItems] Number of data items
224
243
  */
225
- constructor({
226
- encoders,
227
- attributes,
228
- tessellationThreshold = Infinity,
229
- visibleRange = [-Infinity, Infinity],
230
- numItems,
231
- }) {
244
+ constructor({ encoders, attributes, numItems }) {
232
245
  super({
233
246
  encoders,
234
247
  attributes,
235
- numVertices:
236
- tessellationThreshold == Infinity ? numItems * 6 : undefined,
248
+ numVertices: numItems * 6,
237
249
  });
238
-
239
- this.visibleRange = visibleRange;
240
-
241
- this.tessellationThreshold = tessellationThreshold || Infinity;
242
-
243
- this.updateFrac = this.variableBuilder.createUpdater("frac", 2);
244
250
  }
245
251
 
246
252
  /**
@@ -253,69 +259,23 @@ export class RectVertexBuilder extends GeometryBuilder {
253
259
  return;
254
260
  }
255
261
 
256
- const e =
257
- /** @type {Object.<string, import("../types/encoder.js").NumberEncoder>} */ (
258
- this.encoders
259
- );
260
- const [lower, upper] = this.visibleRange;
261
-
262
- /**
263
- * @param {import("../types/encoder.js").Encoder} encoder
264
- */
265
- const a = (encoder) => encoder.accessor || ((x) => 0);
266
-
267
- const xAccessor = a(e.x);
268
- const x2Accessor = a(e.x2);
269
-
270
262
  this.prepareXIndexer(data, lo, hi);
271
263
 
272
- const frac = [0, 0];
273
- this.updateFrac(frac);
274
-
275
264
  for (let i = lo; i < hi; i++) {
276
265
  const d = data[i];
277
266
 
278
- let x = xAccessor(d),
279
- x2 = x2Accessor(d);
280
-
281
- if (x > x2) {
282
- [x, x2] = [x2, x];
283
- }
284
-
285
- // Skip rects that fall outside the visible range. TODO: Optimize by using binary search / interval tree
286
- if (x2 < lower || x > upper) {
287
- continue;
288
- }
289
-
290
- // Truncate to prevent tessellation of parts that are outside the viewport
291
- if (x < lower) x = lower;
292
- if (x2 > upper) x2 = upper;
293
-
294
267
  // Start a new segment.
295
268
  this.variableBuilder.updateFromDatum(d);
296
269
 
297
- frac[0] = 0;
298
- frac[1] = 0;
299
-
300
- // Tessellate segments
301
- const tileCount = 1;
302
- // width < Infinity
303
- // ? Math.ceil(width / this.tessellationThreshold)
304
- // : 1;
305
-
306
- // Duplicate the first vertex to produce degenerate triangles
270
+ // Six vertices per rect. The vertex shader is using gl_VertexID to
271
+ // determine the vertex position within the rect.
272
+ this.variableBuilder.pushAll();
273
+ this.variableBuilder.pushAll();
307
274
  this.variableBuilder.pushAll();
308
-
309
- for (let i = 0; i <= tileCount; i++) {
310
- frac[0] = i / tileCount;
311
- frac[1] = 0;
312
- this.variableBuilder.pushAll();
313
- frac[1] = 1;
314
- this.variableBuilder.pushAll();
315
- }
316
-
317
- // Duplicate the last vertex to produce a degenerate triangle between the segments
318
275
  this.variableBuilder.pushAll();
276
+ this.variableBuilder.pushAll();
277
+ this.variableBuilder.pushAll();
278
+
319
279
  this.addToXIndex(d);
320
280
  }
321
281
 
@@ -1,3 +1,4 @@
1
+ /// <reference types="external-typings/internmap.js" />
1
2
  /**
2
3
  *
3
4
  * @param {Channel} channel
@@ -9,8 +10,10 @@ export function generateValueGlsl(channel: Channel, value: number | number[] | s
9
10
  * @param {Channel} channel
10
11
  * @param {any} scale TODO: typing
11
12
  * @param {import("../spec/channel.js").ChannelDef} channelDef
13
+ * @param {Channel[]} [sharedQuantitativeChannels] Channels that share the same quantitative field
12
14
  */
13
- export function generateScaleGlsl(channel: Channel, scale: any, channelDef: import("../spec/channel.js").ChannelDef): {
15
+ export function generateScaleGlsl(channel: Channel, scale: any, channelDef: import("../spec/channel.js").ChannelDef, sharedQuantitativeChannels?: Channel[]): {
16
+ attributeGlsl: string;
14
17
  glsl: string;
15
18
  domainUniform: string;
16
19
  };
@@ -28,6 +31,20 @@ export function splitHighPrecision(x: number, arr?: number[]): number[];
28
31
  * @param {number[]} domain
29
32
  */
30
33
  export function toHighPrecisionDomainUniform(domain: number[]): number[];
34
+ /**
35
+ * @typedef {[string, boolean]} FieldKey Tuple: [channel, isQuantitative]]
36
+ */
37
+ /**
38
+ * Finds duplicated quantitative fields in the encoding block.
39
+ * They need to be uploaded to the GPU only once.
40
+ *
41
+ * @param {Partial<Record<import("../spec/channel.js").Channel, import("../types/encoder.js").Encoder>>} encoders
42
+ */
43
+ export function dedupeEncodingFields(encoders: Partial<Record<import("../spec/channel.js").Channel, import("../types/encoder.js").Encoder>>): InternMap<FieldKey, import("../spec/channel.js").Channel[]>;
44
+ /**
45
+ * @param {import("../spec/channel.js").Channel | import("../spec/channel.js").Channel[]} channel
46
+ */
47
+ export function makeAttributeName(channel: import("../spec/channel.js").Channel | import("../spec/channel.js").Channel[]): string;
31
48
  export const ATTRIBUTE_PREFIX: "attr_";
32
49
  export const DOMAIN_PREFIX: "uDomain_";
33
50
  export const RANGE_PREFIX: "range_";
@@ -42,4 +59,9 @@ export type VectorizedValue = string & {
42
59
  type: string;
43
60
  numComponents: number;
44
61
  };
62
+ /**
63
+ * Tuple: [channel, isQuantitative]]
64
+ */
65
+ export type FieldKey = [string, boolean];
66
+ import { InternMap } from "internmap";
45
67
  //# sourceMappingURL=glslScaleGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glslScaleGenerator.d.ts","sourceRoot":"","sources":["../../../src/gl/glslScaleGenerator.js"],"names":[],"mappings":";AAmDA;;;;GAIG;AACH,2CAHW,OAAO,SACP,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,OAAO,UAsC9C;AAED;;;;;;GAMG;AAEH,2CANW,OAAO,SACP,GAAG,cACH,OAAO,oBAAoB,EAAE,UAAU,+BACvC,OAAO,EAAE;;;;EAmRnB;AA+FD;;;GAGG;AACH,2CAFW,MAAM,WAIhB;AAOD;;;GAGG;AACH,sCAHW,MAAM,QACN,MAAM,EAAE,YAYlB;AAYD;;GAEG;AACH,qDAFW,MAAM,EAAE,YAIlB;AAED;;GAEG;AAEH;;;;;GAKG;AACH,+CAFW,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CAAC,+DA4BtG;AAED;;GAEG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,GAAG,OAAO,oBAAoB,EAAE,OAAO,EAAE,UAIvF;AAzhBD,uCAAwC;AACxC,uCAAwC;AACxC,oCAAqC;AACrC,6CAA8C;AAC9C,kDAAmD;AACnD,oDAAqD;sBAMxC,OAAO,oBAAoB,EAAE,OAAO;;;;8BAsXpC,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE;;;;uBA8GhD,CAAC,MAAM,EAAE,OAAO,CAAC;0BAjfJ,WAAW"}
@@ -14,8 +14,10 @@ import {
14
14
  isDiscreteChannel,
15
15
  getPrimaryChannel,
16
16
  isValueDef,
17
+ isFieldDef,
17
18
  } from "../encoder/encoder.js";
18
- import { peek } from "../utils/arrayUtils.js";
19
+ import { asArray, peek } from "../utils/arrayUtils.js";
20
+ import { InternMap } from "internmap";
19
21
 
20
22
  export const ATTRIBUTE_PREFIX = "attr_";
21
23
  export const DOMAIN_PREFIX = "uDomain_";
@@ -95,9 +97,15 @@ ${vec.type} ${SCALED_FUNCTION_PREFIX}${channel}() {
95
97
  * @param {Channel} channel
96
98
  * @param {any} scale TODO: typing
97
99
  * @param {import("../spec/channel.js").ChannelDef} channelDef
100
+ * @param {Channel[]} [sharedQuantitativeChannels] Channels that share the same quantitative field
98
101
  */
99
102
  // eslint-disable-next-line complexity
100
- export function generateScaleGlsl(channel, scale, channelDef) {
103
+ export function generateScaleGlsl(
104
+ channel,
105
+ scale,
106
+ channelDef,
107
+ sharedQuantitativeChannels = [channel]
108
+ ) {
101
109
  if (isValueDef(channelDef)) {
102
110
  throw new Error(
103
111
  `Cannot create scale for "value": ${JSON.stringify(channelDef)}`
@@ -109,7 +117,8 @@ export function generateScaleGlsl(channel, scale, channelDef) {
109
117
  }
110
118
 
111
119
  const primary = getPrimaryChannel(channel);
112
- const attributeName = ATTRIBUTE_PREFIX + channel;
120
+ const attributeName =
121
+ ATTRIBUTE_PREFIX + makeAttributeName(sharedQuantitativeChannels);
113
122
  const domainUniformName = DOMAIN_PREFIX + primary;
114
123
  const rangeName = RANGE_PREFIX + primary;
115
124
 
@@ -270,11 +279,9 @@ export function generateScaleGlsl(channel, scale, channelDef) {
270
279
  interpolate = `getDiscreteColor(${textureUniformName}, int(transformed)).r`;
271
280
  }
272
281
 
273
- if (isDatumDef(channelDef)) {
274
- glsl.push(`uniform highp ${attributeType} ${attributeName};`);
275
- } else {
276
- glsl.push(`in highp ${attributeType} ${attributeName};`);
277
- }
282
+ const attributeGlsl = isDatumDef(channelDef)
283
+ ? `uniform highp ${attributeType} ${attributeName};`
284
+ : `in highp ${attributeType} ${attributeName};`;
278
285
 
279
286
  /** @type {string[]} Channel's scale function*/
280
287
  const scaleBody = [];
@@ -361,6 +368,7 @@ ${returnType} ${SCALED_FUNCTION_PREFIX}${channel}() {
361
368
  }
362
369
 
363
370
  return {
371
+ attributeGlsl,
364
372
  glsl: concatenated,
365
373
  domainUniform,
366
374
  };
@@ -504,3 +512,48 @@ function exactSplitHighPrecision(x) {
504
512
  export function toHighPrecisionDomainUniform(domain) {
505
513
  return [...exactSplitHighPrecision(domain[0]), domain[1] - domain[0]];
506
514
  }
515
+
516
+ /**
517
+ * @typedef {[string, boolean]} FieldKey Tuple: [channel, isQuantitative]]
518
+ */
519
+
520
+ /**
521
+ * Finds duplicated quantitative fields in the encoding block.
522
+ * They need to be uploaded to the GPU only once.
523
+ *
524
+ * @param {Partial<Record<import("../spec/channel.js").Channel, import("../types/encoder.js").Encoder>>} encoders
525
+ */
526
+ export function dedupeEncodingFields(encoders) {
527
+ /**
528
+ * Value: an array of channels
529
+ * @type {InternMap<FieldKey, import("../spec/channel.js").Channel[]>}
530
+ */
531
+ const deduped = new InternMap([], JSON.stringify);
532
+
533
+ for (const [channel, encoder] of Object.entries(encoders)) {
534
+ const channelDef = encoder.channelDef;
535
+ if (isFieldDef(channelDef)) {
536
+ const field = channelDef.field;
537
+
538
+ /** @type {[string, boolean]} */
539
+ const key = [
540
+ field,
541
+ encoder.scale
542
+ ? (isContinuous(encoder.scale.type) ||
543
+ isDiscretizing(encoder.scale.type)) ??
544
+ false
545
+ : false,
546
+ ];
547
+
548
+ deduped.set(key, [...(deduped.get(key) ?? []), channel]);
549
+ }
550
+ }
551
+ return deduped;
552
+ }
553
+
554
+ /**
555
+ * @param {import("../spec/channel.js").Channel | import("../spec/channel.js").Channel[]} channel
556
+ */
557
+ export function makeAttributeName(channel) {
558
+ return asArray(channel).join("_");
559
+ }
@@ -20,7 +20,7 @@ import {
20
20
  createDiscreteTexture,
21
21
  createInterpolatedColorTexture,
22
22
  createSchemeTexture,
23
- } from "../scale/colorUtils.js";
23
+ } from "./colorUtils.js";
24
24
  import {
25
25
  getDiscreteRangeMapper,
26
26
  isColorChannel,
@@ -1,6 +1,6 @@
1
1
  import { setBuffersAndAttributes } from "twgl.js";
2
- import VERTEX_SHADER from "../gl/link.vertex.glsl.js";
3
- import FRAGMENT_SHADER from "../gl/link.fragment.glsl.js";
2
+ import VERTEX_SHADER from "./link.vertex.glsl.js";
3
+ import FRAGMENT_SHADER from "./link.fragment.glsl.js";
4
4
  import { LinkVertexBuilder } from "../gl/dataToVertices.js";
5
5
 
6
6
  import Mark from "./mark.js";
@@ -125,8 +125,9 @@ export default class Mark {
125
125
  * @param {string} vertexShader
126
126
  * @param {string} fragmentShader
127
127
  * @param {string[]} [extraHeaders]
128
+ * @protected
128
129
  */
129
- createAndLinkShaders(vertexShader: string, fragmentShader: string, extraHeaders?: string[]): void;
130
+ protected createAndLinkShaders(vertexShader: string, fragmentShader: string, extraHeaders?: string[]): void;
130
131
  /** @type {string[]} */
131
132
  domainUniforms: string[];
132
133
  programStatus: {
@@ -1 +1 @@
1
- {"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ import createEncoders, {
14
14
  isChannelDefWithScale,
15
15
  isChannelWithScale,
16
16
  isDatumDef,
17
+ isFieldDef,
17
18
  isValueDef,
18
19
  } from "../encoder/encoder.js";
19
20
  import {
@@ -25,7 +26,8 @@ import {
25
26
  isHighPrecisionScale,
26
27
  toHighPrecisionDomainUniform,
27
28
  splitHighPrecision,
28
- } from "../scale/glslScaleGenerator.js";
29
+ dedupeEncodingFields,
30
+ } from "../gl/glslScaleGenerator.js";
29
31
  import GLSL_COMMON from "../gl/includes/common.glsl.js";
30
32
  import GLSL_SCALES from "../gl/includes/scales.glsl.js";
31
33
  import GLSL_SAMPLE_FACET from "../gl/includes/sampleFacet.glsl.js";
@@ -316,6 +318,7 @@ export default class Mark {
316
318
  * @param {string} vertexShader
317
319
  * @param {string} fragmentShader
318
320
  * @param {string[]} [extraHeaders]
321
+ * @protected
319
322
  */
320
323
  createAndLinkShaders(vertexShader, fragmentShader, extraHeaders = []) {
321
324
  const attributes = this.getAttributes();
@@ -330,6 +333,15 @@ export default class Mark {
330
333
  /** @type {string[]} */
331
334
  let scaleCode = [];
332
335
 
336
+ /**
337
+ * Attribute definitions. Using set to prevent duplicates caused by
338
+ * multiple channels using the same shared quantitative field.
339
+ * @type {Set<string>}
340
+ */
341
+ const attributeCode = new Set();
342
+
343
+ const dedupedEncodingFields = dedupeEncodingFields(this.encoders);
344
+
333
345
  const sampleFacetMode = this.getSampleFacetMode();
334
346
  if (sampleFacetMode) {
335
347
  extraHeaders.push(`#define ${sampleFacetMode}`);
@@ -364,12 +376,27 @@ export default class Mark {
364
376
  .getScale()
365
377
  : scaleNull();
366
378
 
367
- const generated = generateScaleGlsl(channel, scale, channelDef);
379
+ // Channels that share the same quantitative field
380
+ // TODO: It should be ok to share a categorical field if the channels
381
+ // share the same scale, e.g., primary and secondary positional channels
382
+ const sharedChannels = isFieldDef(channelDef)
383
+ ? dedupedEncodingFields.get([channelDef.field, true])
384
+ : [channel];
385
+
386
+ const generated = generateScaleGlsl(
387
+ channel,
388
+ scale,
389
+ channelDef,
390
+ sharedChannels
391
+ );
368
392
 
369
393
  scaleCode.push(generated.glsl);
370
394
  if (generated.domainUniform) {
371
395
  this.domainUniforms.push(generated.domainUniform);
372
396
  }
397
+ if (generated.attributeGlsl) {
398
+ attributeCode.add(generated.attributeGlsl);
399
+ }
373
400
  }
374
401
  }
375
402
 
@@ -388,6 +415,7 @@ export default class Mark {
388
415
  GLSL_COMMON,
389
416
  GLSL_SCALES,
390
417
  domainUniformBlock,
418
+ [...attributeCode].join("\n"),
391
419
  ...scaleCode,
392
420
  GLSL_SAMPLE_FACET,
393
421
  GLSL_PICKING_VERTEX,
@@ -8,4 +8,4 @@ export default class PointMark extends Mark {
8
8
  getSemanticThreshold(): number;
9
9
  }
10
10
  import Mark from "./mark.js";
11
- //# sourceMappingURL=pointMark.d.ts.map
11
+ //# sourceMappingURL=point.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../src/marks/point.js"],"names":[],"mappings":"AAkBA;IAsGY,oCAMC;IA2CT,mCAQC;IAED;;OAEG;IACH,wDASC;IAED,+BAoBC;CAiDJ;iBA3PgB,WAAW"}
@@ -5,9 +5,9 @@ import {
5
5
  } from "twgl.js";
6
6
  import { quantileSorted } from "d3-array";
7
7
  import { PointVertexBuilder } from "../gl/dataToVertices.js";
8
- import VERTEX_SHADER from "../gl/point.vertex.glsl.js";
9
- import FRAGMENT_SHADER from "../gl/point.fragment.glsl.js";
10
- import COMMON_SHADER from "../gl/point.common.glsl.js";
8
+ import VERTEX_SHADER from "./point.vertex.glsl.js";
9
+ import FRAGMENT_SHADER from "./point.fragment.glsl.js";
10
+ import COMMON_SHADER from "./point.common.glsl.js";
11
11
 
12
12
  import Mark from "./mark.js";
13
13
  import { sampleIterable } from "../data/transforms/sample.js";
@@ -14,4 +14,4 @@ export default class RectMark extends Mark {
14
14
  #private;
15
15
  }
16
16
  import Mark from "./mark.js";
17
- //# sourceMappingURL=rectMark.d.ts.map
17
+ //# sourceMappingURL=rect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rect.d.ts","sourceRoot":"","sources":["../../../src/marks/rect.js"],"names":[],"mappings":"AAYA;IA0NI;;;;;;;;;;OAUG;IACH,8BALW,GAAG,KACH,OAAO,oBAAoB,EAAE,MAAM,GACjC,GAAG,CAyBf;;CACJ;iBAnQgB,WAAW"}
@@ -1,6 +1,6 @@
1
1
  import { drawBufferInfo, setBuffersAndAttributes } from "twgl.js";
2
- import VERTEX_SHADER from "../gl/rect.vertex.glsl.js";
3
- import FRAGMENT_SHADER from "../gl/rect.fragment.glsl.js";
2
+ import VERTEX_SHADER from "./rect.vertex.glsl.js";
3
+ import FRAGMENT_SHADER from "./rect.fragment.glsl.js";
4
4
  import { RectVertexBuilder } from "../gl/dataToVertices.js";
5
5
 
6
6
  import Mark from "./mark.js";
@@ -179,7 +179,6 @@ export default class RectMark extends Mark {
179
179
  const collector = this.unitView.getCollector();
180
180
  const numItems = collector.getItemCount();
181
181
 
182
- // TODO: Disable tessellation on SimpleTrack - no need for it
183
182
  const builder = new RectVertexBuilder({
184
183
  encoders: this.encoders,
185
184
  attributes: this.getAttributes(),
@@ -0,0 +1,2 @@
1
+ const shader = "uniform Mark{uniform float uMinWidth;uniform float uMinHeight;uniform float uMinOpacity;uniform float uCornerRadiusTopRight;uniform float uCornerRadiusBottomRight;uniform float uCornerRadiusTopLeft;uniform float uCornerRadiusBottomLeft;};out lowp vec4 vFillColor;out lowp vec4 vStrokeColor;out float vHalfStrokeWidth;out vec4 vCornerRadii;\n#if defined(ROUNDED_CORNERS) || defined(STROKED)\nout vec2 vPosInPixels;\n#endif\nout vec2 vHalfSizeInPixels;/***Clamps the minimumSize and returns an opacity that reflects the amount of clamping.*/float clampMinSize(inout float pos,float frac,float size,float minSize){if(minSize>0.0&&abs(size)<minSize){pos+=(frac-0.5)*(minSize*sign(size)-size);return abs(size)/minSize;}return 1.0;}void sort(inout float a,inout float b){if(a>b){float tmp=b;b=a;a=tmp;}}/***The vertex position wrt the rectangle specified by(x,x2,y,y2).*[0,0]=[x,y],[1,1]=[x2,y2].*The x or y component may contain fractional values if the rectangle*have been tessellated.*/vec2 getVertexPos(){int index=gl_VertexID % 6;return vec2(index==0||index==1||index==3 ? 0.0 : 1.0,index==0||index==1||index==2 ? 0.0 : 1.0);}void main(void){vec2 frac=getVertexPos();vec2 normalizedMinSize=vec2(uMinWidth,uMinHeight)/uViewportSize;vec4 cornerRadii=vec4(uCornerRadiusTopRight,uCornerRadiusBottomRight,uCornerRadiusBottomLeft,uCornerRadiusTopLeft);float x=getScaled_x();float x2=getScaled_x2();float y=getScaled_y();float y2=getScaled_y2();sort(x,x2);sort(y,y2);float clampMargin=1.0;vec2 pos1=vec2(clamp(x,0.0-clampMargin,1.0+clampMargin),y);vec2 pos2=vec2(clamp(x2,0.0-clampMargin,1.0+clampMargin),y2);vec2 size=pos2-pos1;if(size.x<=0.0||size.y<=0.0){gl_Position=vec4(0.0,0.0,0.0,1.0);return;}vec2 pos=pos1+frac*size;size.y*=getSampleFacetHeight(pos);float opaFactor=uViewOpacity*max(uMinOpacity,clampMinSize(pos.x,frac.x,size.x,normalizedMinSize.x)*clampMinSize(pos.y,frac.y,size.y,normalizedMinSize.y));pos=applySampleFacet(pos);\n#if defined(ROUNDED_CORNERS) || defined(STROKED)\nfloat aaPadding=1.0/uDevicePixelRatio;float strokeWidth=getScaled_strokeWidth();float strokeOpacity=getScaled_strokeOpacity()*opaFactor;vec2 centeredFrac=frac-0.5;vec2 expand=centeredFrac*(strokeWidth+aaPadding)/uViewportSize;pos+=expand;vec2 sizeInPixels=size*uViewportSize;vPosInPixels=(centeredFrac+expand/size)*sizeInPixels;vHalfSizeInPixels=sizeInPixels/2.0;vCornerRadii=min(cornerRadii,min(vHalfSizeInPixels.x,vHalfSizeInPixels.y));vHalfStrokeWidth=strokeWidth/2.0;vStrokeColor=vec4(getScaled_stroke()*strokeOpacity,strokeOpacity);\n#endif\ngl_Position=unitToNdc(pos);float fillOpacity=getScaled_fillOpacity()*opaFactor;vFillColor=vec4(getScaled_fill()*fillOpacity,fillOpacity);setupPicking();}";
2
+ export default shader;
@@ -6,9 +6,9 @@ import {
6
6
  setBuffersAndAttributes,
7
7
  setUniforms,
8
8
  } from "twgl.js";
9
- import VERTEX_SHADER from "../gl/rule.vertex.glsl.js";
10
- import FRAGMENT_SHADER from "../gl/rule.fragment.glsl.js";
11
- import COMMON_SHADER from "../gl/rule.common.glsl.js";
9
+ import VERTEX_SHADER from "./rule.vertex.glsl.js";
10
+ import FRAGMENT_SHADER from "./rule.fragment.glsl.js";
11
+ import COMMON_SHADER from "./rule.common.glsl.js";
12
12
  import { RuleVertexBuilder } from "../gl/dataToVertices.js";
13
13
  import { isChannelDefWithScale } from "../encoder/encoder.js";
14
14