@genome-spy/core 0.39.0 → 0.41.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.
Files changed (49) hide show
  1. package/dist/bundle/index.es.js +3619 -3459
  2. package/dist/bundle/index.js +73 -80
  3. package/dist/schema.json +215 -44
  4. package/dist/src/encoder/accessor.js +4 -2
  5. package/dist/src/genomeSpy.d.ts +2 -0
  6. package/dist/src/genomeSpy.d.ts.map +1 -1
  7. package/dist/src/genomeSpy.js +5 -0
  8. package/dist/src/gl/includes/scales.glsl.js +1 -1
  9. package/dist/src/gl/link.fragment.glsl.js +1 -1
  10. package/dist/src/gl/link.vertex.glsl.js +1 -1
  11. package/dist/src/gl/point.common.glsl.js +2 -0
  12. package/dist/src/gl/point.fragment.glsl.js +1 -1
  13. package/dist/src/gl/point.vertex.glsl.js +1 -1
  14. package/dist/src/gl/rect.vertex.glsl.js +1 -1
  15. package/dist/src/gl/rule.common.glsl.js +2 -0
  16. package/dist/src/gl/rule.fragment.glsl.js +1 -1
  17. package/dist/src/gl/rule.vertex.glsl.js +1 -1
  18. package/dist/src/gl/text.common.glsl.js +2 -0
  19. package/dist/src/gl/text.fragment.glsl.js +1 -1
  20. package/dist/src/gl/text.vertex.glsl.js +1 -1
  21. package/dist/src/marks/link.d.ts.map +1 -1
  22. package/dist/src/marks/link.js +30 -12
  23. package/dist/src/marks/mark.d.ts +35 -4
  24. package/dist/src/marks/mark.d.ts.map +1 -1
  25. package/dist/src/marks/mark.js +84 -1
  26. package/dist/src/marks/pointMark.d.ts.map +1 -1
  27. package/dist/src/marks/pointMark.js +21 -9
  28. package/dist/src/marks/rectMark.d.ts +1 -2
  29. package/dist/src/marks/rectMark.d.ts.map +1 -1
  30. package/dist/src/marks/rectMark.js +28 -17
  31. package/dist/src/marks/rule.d.ts.map +1 -1
  32. package/dist/src/marks/rule.js +17 -6
  33. package/dist/src/marks/text.d.ts.map +1 -1
  34. package/dist/src/marks/text.js +22 -7
  35. package/dist/src/paramBroker.d.ts +30 -0
  36. package/dist/src/paramBroker.d.ts.map +1 -0
  37. package/dist/src/paramBroker.js +102 -0
  38. package/dist/src/spec/mark.d.ts +46 -16
  39. package/dist/src/spec/view.d.ts +2 -1
  40. package/dist/src/types/viewContext.d.ts +2 -0
  41. package/dist/src/utils/expression.d.ts +12 -2
  42. package/dist/src/utils/expression.d.ts.map +1 -1
  43. package/dist/src/utils/expression.js +68 -9
  44. package/dist/src/utils/linearstep.d.ts +7 -0
  45. package/dist/src/utils/linearstep.d.ts.map +1 -0
  46. package/dist/src/utils/linearstep.js +10 -0
  47. package/dist/src/view/view.d.ts.map +1 -1
  48. package/dist/src/view/view.js +6 -0
  49. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { drawBufferInfo, setBuffersAndAttributes, setUniforms } from "twgl.js";
1
+ import { drawBufferInfo, setBuffersAndAttributes } from "twgl.js";
2
2
  import VERTEX_SHADER from "../gl/link.vertex.glsl.js";
3
3
  import FRAGMENT_SHADER from "../gl/link.fragment.glsl.js";
4
4
  import { LinkVertexBuilder } from "../gl/dataToVertices.js";
@@ -32,6 +32,8 @@ export default class LinkMark extends Mark {
32
32
  minArcHeight: 1.5,
33
33
  minPickingSize: 3.0,
34
34
  clampApex: false,
35
+ maxChordLength: 50000,
36
+ arcFadingDistance: false,
35
37
 
36
38
  linkShape: "arc",
37
39
  orient: "vertical",
@@ -95,15 +97,22 @@ export default class LinkMark extends Mark {
95
97
 
96
98
  const props = this.properties;
97
99
 
98
- // TODO: Use uniform block.
99
- setUniforms(this.programInfo, {
100
- uArcHeightFactor: props.arcHeightFactor,
101
- uMinArcHeight: props.minArcHeight,
102
- uMinPickingSize: props.minPickingSize,
103
- uShape: LINK_SHAPES.indexOf(props.linkShape),
104
- uOrient: ORIENTS.indexOf(props.orient),
105
- uClampApex: !!props.clampApex,
106
- });
100
+ this.registerMarkUniform(
101
+ "uArcFadingDistance",
102
+ props.arcFadingDistance,
103
+ (x) => x || /** @type {[number, number]} */ ([0, 0])
104
+ );
105
+ this.registerMarkUniform("uArcHeightFactor", props.arcHeightFactor);
106
+ this.registerMarkUniform("uMinArcHeight", props.minArcHeight);
107
+ this.registerMarkUniform("uMinPickingSize", props.minPickingSize);
108
+ this.registerMarkUniform("uShape", props.linkShape, (linkShape) =>
109
+ LINK_SHAPES.indexOf(linkShape)
110
+ );
111
+ this.registerMarkUniform("uOrient", props.orient, (orient) =>
112
+ ORIENTS.indexOf(orient)
113
+ );
114
+ this.registerMarkUniform("uClampApex", props.clampApex, (x) => !!x);
115
+ this.registerMarkUniform("uMaxChordLength", props.maxChordLength);
107
116
  }
108
117
 
109
118
  updateGraphicsData() {
@@ -137,14 +146,23 @@ export default class LinkMark extends Mark {
137
146
  this.updateBufferInfo(vertexData);
138
147
  }
139
148
 
149
+ /**
150
+ * @param {import("../types/rendering.js").GlobalRenderingOptions} options
151
+ */
152
+ prepareRender(options) {
153
+ const ops = super.prepareRender(options);
154
+
155
+ ops.push(() => this.bindOrSetMarkUniformBlock());
156
+
157
+ return ops;
158
+ }
159
+
140
160
  /**
141
161
  * @param {import("./mark.js").MarkRenderingOptions} options
142
162
  */
143
163
  render(options) {
144
164
  const gl = this.gl;
145
165
 
146
- // TODO: Vertical clipping in faceted view
147
-
148
166
  return this.createRenderCallback((offset, count) => {
149
167
  // We are using instanced drawing here.
150
168
  // However, WebGL does not provide glDrawArraysInstancedBaseInstance and thus,
@@ -1,4 +1,9 @@
1
1
  /// <reference types="external-typings/internmap.js" />
2
+ /**
3
+ * @param {any} x
4
+ * @returns {x is import("../spec/mark.js").ExprRef}
5
+ */
6
+ export function isExprRef(x: any): x is import("../spec/mark.js").ExprRef;
2
7
  export const SAMPLE_FACET_UNIFORM: "SAMPLE_FACET_UNIFORM";
3
8
  export const SAMPLE_FACET_TEXTURE: "SAMPLE_FACET_TEXTURE";
4
9
  /**
@@ -20,6 +25,7 @@ export default class Mark {
20
25
  * @typedef {import("../spec/channel.js").Channel} Channel
21
26
  * @typedef {import("../spec/channel.js").Encoding} Encoding
22
27
  * @typedef {import("../spec/channel.js").ValueDef} ValueDef
28
+ * @typedef {import("../spec/mark.js").ExprRef} ExprRef
23
29
  */
24
30
  /**
25
31
  * @param {import("../view/unitView.js").default} unitView
@@ -40,6 +46,18 @@ export default class Mark {
40
46
  domainUniformInfo: import("twgl.js").UniformBlockInfo;
41
47
  /** @type {import("twgl.js").UniformBlockInfo} WebGL buffers */
42
48
  viewUniformInfo: import("twgl.js").UniformBlockInfo;
49
+ /**
50
+ * Uniforms related to the specific mark type.
51
+ * @type {import("twgl.js").UniformBlockInfo}
52
+ */
53
+ markUniformInfo: import("twgl.js").UniformBlockInfo;
54
+ /**
55
+ * Indicates whether the mark's uniforms have been altered since the last rendering.
56
+ * If set to true, the uniforms will be sent to the GPU before rendering the next frame.
57
+
58
+ * @protected
59
+ */
60
+ protected markUniformsAltered: boolean;
43
61
  /** @type {RangeMap<any>} keep track of facet locations within the vertex array */
44
62
  rangeMap: RangeMap<any>;
45
63
  /** @type {MarkConfig} */
@@ -115,10 +133,7 @@ export default class Mark {
115
133
  program: WebGLProgram;
116
134
  getProgramErrors: () => {
117
135
  message: string;
118
- detail: string; /**
119
- *
120
- * @param {any} vertexData TODO: Extract type from VertexBuilder
121
- */
136
+ detail: string;
122
137
  };
123
138
  };
124
139
  /**
@@ -126,6 +141,18 @@ export default class Mark {
126
141
  * initialization.
127
142
  */
128
143
  finalizeGraphicsInitialization(): void;
144
+ /**
145
+ * Set a uniform based on a mark property. If the property is an expression,
146
+ * register a listener to update the uniform when the params referenced by the
147
+ * expression change.
148
+ *
149
+ * @protected
150
+ * @template T
151
+ * @param {string} uniformName
152
+ * @param {T} propValue
153
+ * @param {(x: Exclude<T, ExprRef>) => any} adjuster
154
+ */
155
+ protected registerMarkUniform<T>(uniformName: string, propValue: T, adjuster?: (x: Exclude<T, import("../spec/mark.js").ExprRef>) => any): void;
129
156
  _setDatums(): void;
130
157
  /**
131
158
  * Delete WebGL buffers etc.
@@ -150,6 +177,10 @@ export default class Mark {
150
177
  * TODO: Check if selection (when it's implemented) is enabled
151
178
  */
152
179
  isPickingParticipant(): boolean;
180
+ /**
181
+ * @protected
182
+ */
183
+ protected bindOrSetMarkUniformBlock(): void;
153
184
  /**
154
185
  * Configures the WebGL state for rendering the mark instances.
155
186
  * A separate preparation stage allows for efficient rendering of faceted
@@ -1 +1 @@
1
- {"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":";AAwCA,0DAA2D;AAC3D,0DAA2D;AAE3D;;;;;;;;;;;;GAYG;AACH;IACI;;;;;OAKG;IAEH;;OAEG;IACH,sBAFW,OAAO,qBAAqB,EAAE,OAAO,EAoE/C;IAjEG,gDAAwB;IAExB,oEAAoE;IACpE,UADW,OAAO,MAAM,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CACvC;IAIzB,0FAA0F;IAC1F,YADW,OAAO,SAAS,EAAE,UAAU,GAAG;QAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,CAC7C;IAE3B,0DAA0D;IAC1D,aADW,OAAO,SAAS,EAAE,WAAW,CACZ;IAE5B,8DAA8D;IAC9D,iBADW,OAAO,SAAS,EAAE,eAAe,CACZ;IAEhC,+DAA+D;IAC/D,mBADW,OAAO,SAAS,EAAE,gBAAgB,CACX;IAElC,+DAA+D;IAC/D,iBADW,OAAO,SAAS,EAAE,gBAAgB,CACb;IAEhC,kFAAkF;IAClF,UADW,SAAS,GAAG,CAAC,CACM;IAG9B,yBAAyB;IACzB,wDAqBC;IAED;;;;;;;;OAQG;IACH,mEAKC;IAGL,sBAEC;IAED;;;;;;;OAOG;IACH,iBAFa,MAAM,EAAE,CAKpB;IAED;;OAEG;IACH,+DAWC;IAED;;OAEG;IACH,oEAcC;IAED;;;;;OAKG;IACH,oHAEC;IAED;;;;OAIG;IACH,8DAyCC;IAED,wDAEC;IAED,8CAEC;IAED,uBAEC;IAED;;;OAGG;IACH,2BAEC;IAED;;OAEG;IACH,oCAEC;IAED;;OAEG;IACH,2BAEC;IAED,sEAeC;IAED;;;;;OAKG;IACH,mCAJW,MAAM,kBACN,MAAM,iBACN,MAAM,EAAE,QA+FlB;IAtFG,uBAAuB;IACvB,gBADW,MAAM,EAAE,CACK;IAgFxB;;;;4BAgGJ;;;eAGG;;MA/FE;IAGL;;;OAGG;IACH,uCA2CC;IAED,mBAgBC;IAED;;OAEG;IACH,2BAiBC;IAED;;;OAGG;IACH,6BAFW,GAAG,QAoCb;IAED,yBAAyB;IACzB,uDAEC;IAED,yBAAyB;IACzB,iCAEC;IAED,gCAEC;IAED,+BAEC;IAED,yCAEC;IAED;;;;;OAKG;IACH,gCAcC;IAED;;;;;;;;OAQG;IAEH,uBAJW,OAAO,uBAAuB,EAAE,sBAAsB,GACpD,CAAC,MAAM,IAAI,CAAC,EAAE,CA+H1B;IAED;;;;;;OAMG;IACH,qCAJW,oBAAoB,GAClB,OAAO,CAqCnB;IAED;;;;;;;OAOG;IACH,gBAJW,oBAAoB,SACP,IAAI,CAM3B;IAED;;;OAGG;IACH,2BAHW,YAAY,WACZ,OAAO,WAAW,EAAE,oBAAoB,cAiElD;IAED;;;;;;OAMG;IACH,oBAJW,OAAO,6BAA6B,EAAE,OAAO,aAC7C,OAAO,6BAA6B,EAAE,OAAO,GAC3C,OAAO,CAuHnB;IAED;;;;;;;;;OASG;IACH,qBAJW,MAAM,KACN,OAAO,oBAAoB,EAAE,MAAM,GACjC,GAAG,CAIf;CACJ;+BA75BY,OAAO,uBAAuB,EAAE,gBAAgB;;;;;;wBAEnD,OAAO;;mCAEJ,gBAAgB,GAAG,qBAAqB;oCAG1C,MAAM,SACN,MAAM;AAu5BjB;;;GAGG;AACH;IACI,cAEC;IAkBD;;;OAGG;IACH,2BAFW,IAAI,CAAC,EAAE,OAAO,yBAAyB,EAAE,UAAU,CAAC,QAM9D;CACJ;0BA18ByB,WAAW"}
1
+ {"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":";AA2jCA;;;GAGG;AACH,6BAHW,GAAG,0CAKb;AAvhCD,0DAA2D;AAC3D,0DAA2D;AAE3D;;;;;;;;;;;;GAYG;AACH;IACI;;;;;;OAMG;IAEH;;OAEG;IACH,sBAFW,OAAO,qBAAqB,EAAE,OAAO,EAkF/C;IA/EG,gDAAwB;IAExB,oEAAoE;IACpE,UADW,OAAO,MAAM,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CACvC;IAIzB,0FAA0F;IAC1F,YADW,OAAO,SAAS,EAAE,UAAU,GAAG;QAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,CAC7C;IAE3B,0DAA0D;IAC1D,aADW,OAAO,SAAS,EAAE,WAAW,CACZ;IAE5B,8DAA8D;IAC9D,iBADW,OAAO,SAAS,EAAE,eAAe,CACZ;IAEhC,+DAA+D;IAC/D,mBADW,OAAO,SAAS,EAAE,gBAAgB,CACX;IAElC,+DAA+D;IAC/D,iBADW,OAAO,SAAS,EAAE,gBAAgB,CACb;IAEhC;;;OAGG;IACH,iBAFU,OAAO,SAAS,EAAE,gBAAgB,CAEZ;IAEhC;;;;;OAKG;IACH,uCAA+B;IAE/B,kFAAkF;IAClF,UADW,SAAS,GAAG,CAAC,CACM;IAG9B,yBAAyB;IACzB,wDAqBC;IAED;;;;;;;;OAQG;IACH,mEAKC;IAGL,sBAEC;IAED;;;;;;;OAOG;IACH,iBAFa,MAAM,EAAE,CAKpB;IAED;;OAEG;IACH,+DAWC;IAED;;OAEG;IACH,oEAcC;IAED;;;;;OAKG;IACH,oHAEC;IAED;;;;OAIG;IACH,8DAyCC;IAED,wDAEC;IAED,8CAEC;IAED,uBAEC;IAED;;;OAGG;IACH,2BAEC;IAED;;OAEG;IACH,oCAEC;IAED;;OAEG;IACH,2BAEC;IAED,sEAeC;IAED;;;;;OAKG;IACH,mCAJW,MAAM,kBACN,MAAM,iBACN,MAAM,EAAE,QAiGlB;IAxFG,uBAAuB;IACvB,gBADW,MAAM,EAAE,CACK;IAkFxB;;;;;;MAIC;IAGL;;;OAGG;IACH,uCAkDC;IAED;;;;;;;;;;OAUG;IACH,8CAJW,MAAM,iFAEsB,GAAG,QAyBzC;IAED,mBAgBC;IAED;;OAEG;IACH,2BAiBC;IAED;;;OAGG;IACH,6BAFW,GAAG,QAoCb;IAED,yBAAyB;IACzB,uDAEC;IAED,yBAAyB;IACzB,iCAEC;IAED,gCAEC;IAED,+BAEC;IAED,yCAEC;IAED;;;;;OAKG;IACH,gCAcC;IAED;;OAEG;IACH,4CAOC;IAED;;;;;;;;OAQG;IAEH,uBAJW,OAAO,uBAAuB,EAAE,sBAAsB,GACpD,CAAC,MAAM,IAAI,CAAC,EAAE,CA+H1B;IAED;;;;;;OAMG;IACH,qCAJW,oBAAoB,GAClB,OAAO,CAqCnB;IAED;;;;;;;OAOG;IACH,gBAJW,oBAAoB,SACP,IAAI,CAM3B;IAED;;;OAGG;IACH,2BAHW,YAAY,WACZ,OAAO,WAAW,EAAE,oBAAoB,cAiElD;IAED;;;;;;OAMG;IACH,oBAJW,OAAO,6BAA6B,EAAE,OAAO,aAC7C,OAAO,6BAA6B,EAAE,OAAO,GAC3C,OAAO,CAuHnB;IAED;;;;;;;;;OASG;IACH,qBAJW,MAAM,KACN,OAAO,oBAAoB,EAAE,MAAM,GACjC,GAAG,CAIf;CACJ;+BAr+BY,OAAO,uBAAuB,EAAE,gBAAgB;;;;;;wBAEnD,OAAO;;mCAEJ,gBAAgB,GAAG,qBAAqB;oCAG1C,MAAM,SACN,MAAM;AA+9BjB;;;GAGG;AACH;IACI,cAEC;IAkBD;;;OAGG;IACH,2BAFW,IAAI,CAAC,EAAE,OAAO,yBAAyB,EAAE,UAAU,CAAC,QAM9D;CACJ;0BAnhCyB,WAAW"}
@@ -1,4 +1,5 @@
1
1
  import {
2
+ bindUniformBlock,
2
3
  createBufferInfoFromArrays,
3
4
  createProgramInfoFromProgram,
4
5
  createUniformBlockInfo,
@@ -37,6 +38,7 @@ import { isScalar } from "../utils/variableTools.js";
37
38
  import { InternMap } from "internmap";
38
39
  import scaleNull from "../utils/scaleNull.js";
39
40
  import ViewError from "../view/viewError.js";
41
+ import { isString } from "vega-util";
40
42
 
41
43
  export const SAMPLE_FACET_UNIFORM = "SAMPLE_FACET_UNIFORM";
42
44
  export const SAMPLE_FACET_TEXTURE = "SAMPLE_FACET_TEXTURE";
@@ -60,6 +62,7 @@ export default class Mark {
60
62
  * @typedef {import("../spec/channel.js").Channel} Channel
61
63
  * @typedef {import("../spec/channel.js").Encoding} Encoding
62
64
  * @typedef {import("../spec/channel.js").ValueDef} ValueDef
65
+ * @typedef {import("../spec/mark.js").ExprRef} ExprRef
63
66
  */
64
67
 
65
68
  /**
@@ -88,6 +91,20 @@ export default class Mark {
88
91
  /** @type {import("twgl.js").UniformBlockInfo} WebGL buffers */
89
92
  this.viewUniformInfo = undefined;
90
93
 
94
+ /**
95
+ * Uniforms related to the specific mark type.
96
+ * @type {import("twgl.js").UniformBlockInfo}
97
+ */
98
+ this.markUniformInfo = undefined;
99
+
100
+ /**
101
+ * Indicates whether the mark's uniforms have been altered since the last rendering.
102
+ * If set to true, the uniforms will be sent to the GPU before rendering the next frame.
103
+
104
+ * @protected
105
+ */
106
+ this.markUniformsAltered = true;
107
+
91
108
  /** @type {RangeMap<any>} keep track of facet locations within the vertex array */
92
109
  this.rangeMap = new RangeMap();
93
110
 
@@ -304,7 +321,7 @@ export default class Mark {
304
321
  const attributes = this.getAttributes();
305
322
 
306
323
  // For debugging
307
- extraHeaders.push("// view: " + this.unitView.getPathString());
324
+ const debugHeader = "// view: " + this.unitView.getPathString();
308
325
 
309
326
  // TODO: This is a temporary variable, don't store it in the mark object
310
327
  /** @type {string[]} */
@@ -366,6 +383,7 @@ export default class Mark {
366
383
 
367
384
  const vertexParts = [
368
385
  vertexPrecision,
386
+ debugHeader,
369
387
  ...extraHeaders,
370
388
  GLSL_COMMON,
371
389
  GLSL_SCALES,
@@ -377,6 +395,7 @@ export default class Mark {
377
395
  ];
378
396
 
379
397
  const fragmentParts = [
398
+ debugHeader,
380
399
  ...extraHeaders,
381
400
  GLSL_COMMON,
382
401
  GLSL_PICKING_FRAGMENT,
@@ -433,6 +452,12 @@ export default class Mark {
433
452
  "View"
434
453
  );
435
454
 
455
+ this.markUniformInfo = createUniformBlockInfo(
456
+ this.gl,
457
+ this.programInfo,
458
+ "Mark"
459
+ );
460
+
436
461
  this.gl.useProgram(this.programInfo.program);
437
462
 
438
463
  this._setDatums();
@@ -441,9 +466,46 @@ export default class Mark {
441
466
  // left pos, left height, right pos, right height
442
467
  uSampleFacet: [0, 1, 0, 1],
443
468
  uTransitionOffset: 0.0,
469
+ uZero: 0.0,
444
470
  });
445
471
  }
446
472
 
473
+ /**
474
+ * Set a uniform based on a mark property. If the property is an expression,
475
+ * register a listener to update the uniform when the params referenced by the
476
+ * expression change.
477
+ *
478
+ * @protected
479
+ * @template T
480
+ * @param {string} uniformName
481
+ * @param {T} propValue
482
+ * @param {(x: Exclude<T, ExprRef>) => any} adjuster
483
+ */
484
+ registerMarkUniform(uniformName, propValue, adjuster = (x) => x) {
485
+ const uniformSetter = this.markUniformInfo.setters[uniformName];
486
+
487
+ if (isExprRef(propValue)) {
488
+ const fn = this.unitView.context.paramBroker.createExpression(
489
+ propValue.expr
490
+ );
491
+
492
+ const set = () => {
493
+ uniformSetter(adjuster(fn(null)));
494
+ this.markUniformsAltered = true;
495
+ };
496
+
497
+ // Register a listener ...
498
+ fn.addListener(set);
499
+ // ... and set the initial value
500
+ set();
501
+ } else {
502
+ uniformSetter(
503
+ adjuster(/** @type {Exclude<T, ExprRef>} */ (propValue))
504
+ );
505
+ this.markUniformsAltered = true;
506
+ }
507
+ }
508
+
447
509
  _setDatums() {
448
510
  for (const [channel, channelDef] of Object.entries(this.encoding)) {
449
511
  if (isDatumDef(channelDef)) {
@@ -568,6 +630,18 @@ export default class Mark {
568
630
  return true;
569
631
  }
570
632
 
633
+ /**
634
+ * @protected
635
+ */
636
+ bindOrSetMarkUniformBlock() {
637
+ if (this.markUniformsAltered) {
638
+ setUniformBlock(this.gl, this.programInfo, this.markUniformInfo);
639
+ this.markUniformsAltered = false;
640
+ } else {
641
+ bindUniformBlock(this.gl, this.programInfo, this.markUniformInfo);
642
+ }
643
+ }
644
+
571
645
  /**
572
646
  * Configures the WebGL state for rendering the mark instances.
573
647
  * A separate preparation stage allows for efficient rendering of faceted
@@ -1005,3 +1079,12 @@ class RangeMap extends InternMap {
1005
1079
  }
1006
1080
  }
1007
1081
  }
1082
+
1083
+ // TODO: Find a better place for this function
1084
+ /**
1085
+ * @param {any} x
1086
+ * @returns {x is import("../spec/mark.js").ExprRef}
1087
+ */
1088
+ export function isExprRef(x) {
1089
+ return typeof x === "object" && "expr" in x && isString(x.expr);
1090
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"pointMark.d.ts","sourceRoot":"","sources":["../../../src/marks/pointMark.js"],"names":[],"mappings":"AAaA;IAsGY,oCAMC;IAwCT,mCAQC;IAED;;OAEG;IACH,wDASC;IAED,+BAoBC;CA6CJ;iBApPgB,WAAW"}
1
+ {"version":3,"file":"pointMark.d.ts","sourceRoot":"","sources":["../../../src/marks/pointMark.js"],"names":[],"mappings":"AAkBA;IAsGY,oCAMC;IA2CT,mCAQC;IAED;;OAEG;IACH,wDASC;IAED,+BAoBC;CAiDJ;iBA3PgB,WAAW"}
@@ -1,8 +1,13 @@
1
- import { drawBufferInfo, setBuffersAndAttributes, setUniforms } from "twgl.js";
1
+ import {
2
+ drawBufferInfo,
3
+ setBlockUniforms,
4
+ setBuffersAndAttributes,
5
+ } from "twgl.js";
2
6
  import { quantileSorted } from "d3-array";
3
7
  import { PointVertexBuilder } from "../gl/dataToVertices.js";
4
8
  import VERTEX_SHADER from "../gl/point.vertex.glsl.js";
5
9
  import FRAGMENT_SHADER from "../gl/point.fragment.glsl.js";
10
+ import COMMON_SHADER from "../gl/point.common.glsl.js";
6
11
 
7
12
  import Mark from "./mark.js";
8
13
  import { sampleIterable } from "../data/transforms/sample.js";
@@ -126,7 +131,9 @@ export default class PointMark extends Mark {
126
131
 
127
132
  async initializeGraphics() {
128
133
  await super.initializeGraphics();
129
- this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER);
134
+ this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER, [
135
+ COMMON_SHADER,
136
+ ]);
130
137
  }
131
138
 
132
139
  finalizeGraphicsInitialization() {
@@ -135,9 +142,10 @@ export default class PointMark extends Mark {
135
142
  this.gl.useProgram(this.programInfo.program);
136
143
 
137
144
  const props = this.properties;
138
- setUniforms(this.programInfo, {
139
- uInwardStroke: props.inwardStroke,
140
- uGradientStrength: props.fillGradientStrength,
145
+
146
+ setBlockUniforms(this.markUniformInfo, {
147
+ uInwardStroke: !!props.inwardStroke,
148
+ uGradientStrength: +props.fillGradientStrength,
141
149
  uMaxRelativePointDiameter: 1 - 2 * props.sampleFacetPadding,
142
150
  });
143
151
  }
@@ -211,13 +219,17 @@ export default class PointMark extends Mark {
211
219
  prepareRender(options) {
212
220
  const ops = super.prepareRender(options);
213
221
 
214
- ops.push(() =>
215
- setUniforms(this.programInfo, {
222
+ ops.push(() => {
223
+ // TODO: Use bindUniformBlock if none of the uniform has changed
224
+ setBlockUniforms(this.markUniformInfo, {
216
225
  uMaxPointSize: this._getMaxPointSize(),
217
226
  uScaleFactor: this._getGeometricScaleFactor(),
218
227
  uSemanticThreshold: this.getSemanticThreshold(),
219
- })
220
- );
228
+ });
229
+ this.markUniformsAltered = true;
230
+ });
231
+
232
+ ops.push(() => this.bindOrSetMarkUniformBlock());
221
233
 
222
234
  ops.push(() =>
223
235
  setBuffersAndAttributes(
@@ -1,6 +1,4 @@
1
1
  export default class RectMark extends Mark {
2
- _isRoundedCorners(): number;
3
- _isStroked(): boolean;
4
2
  /**
5
3
  * Finds a datum that overlaps the given value on the x domain.
6
4
  * The result is unspecified if multiple data are found.
@@ -13,6 +11,7 @@ export default class RectMark extends Mark {
13
11
  * @override
14
12
  */
15
13
  override findDatumAt(facetId: any, x: import("../spec/channel.js").Scalar): any;
14
+ #private;
16
15
  }
17
16
  import Mark from "./mark.js";
18
17
  //# sourceMappingURL=rectMark.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rectMark.d.ts","sourceRoot":"","sources":["../../../src/marks/rectMark.js"],"names":[],"mappings":"AAYA;IAsGI,4BASC;IAED,sBAGC;IA4FD;;;;;;;;;;OAUG;IACH,8BALW,GAAG,KACH,OAAO,oBAAoB,EAAE,MAAM,GACjC,GAAG,CAyBf;CACJ;iBAzPgB,WAAW"}
1
+ {"version":3,"file":"rectMark.d.ts","sourceRoot":"","sources":["../../../src/marks/rectMark.js"],"names":[],"mappings":"AAYA;IA2NI;;;;;;;;;;OAUG;IACH,8BALW,GAAG,KACH,OAAO,oBAAoB,EAAE,MAAM,GACjC,GAAG,CAyBf;;CACJ;iBApQgB,WAAW"}
@@ -1,4 +1,4 @@
1
- import { drawBufferInfo, setBuffersAndAttributes, setUniforms } from "twgl.js";
1
+ import { drawBufferInfo, setBuffersAndAttributes } from "twgl.js";
2
2
  import VERTEX_SHADER from "../gl/rect.vertex.glsl.js";
3
3
  import FRAGMENT_SHADER from "../gl/rect.fragment.glsl.js";
4
4
  import { RectVertexBuilder } from "../gl/dataToVertices.js";
@@ -76,8 +76,8 @@ export default class RectMark extends Mark {
76
76
  this,
77
77
  "opaque",
78
78
  () =>
79
- !this._isRoundedCorners() &&
80
- !this._isStroked() &&
79
+ !this.#isRoundedCorners() &&
80
+ !this.#isStroked() &&
81
81
  isValueDef(this.encoding.fillOpacity) &&
82
82
  this.encoding.fillOpacity.value == 1.0 &&
83
83
  this.properties.minOpacity == 1.0
@@ -112,7 +112,7 @@ export default class RectMark extends Mark {
112
112
  // TODO: Pop the previous buffers
113
113
  }
114
114
 
115
- _isRoundedCorners() {
115
+ #isRoundedCorners() {
116
116
  const p = this.properties;
117
117
  return (
118
118
  p.cornerRadius ||
@@ -123,7 +123,7 @@ export default class RectMark extends Mark {
123
123
  );
124
124
  }
125
125
 
126
- _isStroked() {
126
+ #isStroked() {
127
127
  const sw = this.encoding.strokeWidth;
128
128
  return !(isValueDef(sw) && !sw.value);
129
129
  }
@@ -133,10 +133,10 @@ export default class RectMark extends Mark {
133
133
 
134
134
  /** @type {string[]} */
135
135
  const defines = [];
136
- if (this._isRoundedCorners()) {
136
+ if (this.#isRoundedCorners()) {
137
137
  defines.push("ROUNDED_CORNERS");
138
138
  }
139
- if (this._isStroked()) {
139
+ if (this.#isStroked()) {
140
140
  defines.push("STROKED");
141
141
  }
142
142
 
@@ -154,16 +154,25 @@ export default class RectMark extends Mark {
154
154
 
155
155
  const props = this.properties;
156
156
 
157
- setUniforms(this.programInfo, {
158
- uMinSize: [props.minWidth, props.minHeight], // in pixels
159
- uMinOpacity: props.minOpacity,
160
- uCornerRadii: [
161
- props.cornerRadiusTopRight ?? props.cornerRadius,
162
- props.cornerRadiusBottomRight ?? props.cornerRadius,
163
- props.cornerRadiusTopLeft ?? props.cornerRadius,
164
- props.cornerRadiusBottomLeft ?? props.cornerRadius,
165
- ],
166
- });
157
+ this.registerMarkUniform("uMinWidth", props.minWidth);
158
+ this.registerMarkUniform("uMinHeight", props.minHeight);
159
+ this.registerMarkUniform("uMinOpacity", props.minOpacity);
160
+ this.registerMarkUniform(
161
+ "uCornerRadiusTopRight",
162
+ props.cornerRadiusTopRight ?? props.cornerRadius ?? 0
163
+ );
164
+ this.registerMarkUniform(
165
+ "uCornerRadiusBottomRight",
166
+ props.cornerRadiusBottomRight ?? props.cornerRadius ?? 0
167
+ );
168
+ this.registerMarkUniform(
169
+ "uCornerRadiusTopLeft",
170
+ props.cornerRadiusTopLeft ?? props.cornerRadius ?? 0
171
+ );
172
+ this.registerMarkUniform(
173
+ "uCornerRadiusBottomLeft",
174
+ props.cornerRadiusBottomLeft ?? props.cornerRadius ?? 0
175
+ );
167
176
  }
168
177
 
169
178
  updateGraphicsData() {
@@ -190,6 +199,8 @@ export default class RectMark extends Mark {
190
199
  prepareRender(options) {
191
200
  const ops = super.prepareRender(options);
192
201
 
202
+ ops.push(() => this.bindOrSetMarkUniformBlock());
203
+
193
204
  ops.push(() =>
194
205
  setBuffersAndAttributes(
195
206
  this.gl,
@@ -1 +1 @@
1
- {"version":3,"file":"rule.d.ts","sourceRoot":"","sources":["../../../src/marks/rule.js"],"names":[],"mappings":"AAYA;IAOQ,wBAAwB;IA4GpB,0BAOE;CAmFb;iBAzNgB,WAAW"}
1
+ {"version":3,"file":"rule.d.ts","sourceRoot":"","sources":["../../../src/marks/rule.js"],"names":[],"mappings":"AAcA;IAOQ,wBAAwB;IA4GpB,0BAOE;CA4Fb;iBApOgB,WAAW"}
@@ -2,11 +2,13 @@ import Mark from "./mark.js";
2
2
  import {
3
3
  createTexture,
4
4
  drawBufferInfo,
5
+ setBlockUniforms,
5
6
  setBuffersAndAttributes,
6
7
  setUniforms,
7
8
  } from "twgl.js";
8
9
  import VERTEX_SHADER from "../gl/rule.vertex.glsl.js";
9
10
  import FRAGMENT_SHADER from "../gl/rule.fragment.glsl.js";
11
+ import COMMON_SHADER from "../gl/rule.common.glsl.js";
10
12
  import { RuleVertexBuilder } from "../gl/dataToVertices.js";
11
13
  import { isChannelDefWithScale } from "../encoder/encoder.js";
12
14
 
@@ -136,7 +138,9 @@ export default class RuleMark extends Mark {
136
138
  this.dashTextureSize = textureData.length; // Not needed with WebGL2
137
139
  }
138
140
 
139
- this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER);
141
+ this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER, [
142
+ COMMON_SHADER,
143
+ ]);
140
144
  }
141
145
 
142
146
  finalizeGraphicsInitialization() {
@@ -146,11 +150,17 @@ export default class RuleMark extends Mark {
146
150
 
147
151
  const props = this.properties;
148
152
 
149
- setUniforms(this.programInfo, {
150
- uMinLength: props.minLength,
151
- uDashTextureSize: this.dashTextureSize,
152
- uStrokeCap: ["butt", "square", "round"].indexOf(props.strokeCap),
153
+ this.registerMarkUniform("uMinLength", props.minLength);
154
+ this.registerMarkUniform(
155
+ "uStrokeCap",
156
+ props.strokeCap ?? "butt",
157
+ (cap) => ["butt", "square", "round"].indexOf(cap)
158
+ );
159
+
160
+ setBlockUniforms(this.markUniformInfo, {
161
+ uDashTextureSize: +this.dashTextureSize,
153
162
  });
163
+ this.markUniformsAltered = true;
154
164
  }
155
165
 
156
166
  updateGraphicsData() {
@@ -177,11 +187,12 @@ export default class RuleMark extends Mark {
177
187
  prepareRender(options) {
178
188
  const ops = super.prepareRender(options);
179
189
 
190
+ ops.push(() => this.bindOrSetMarkUniformBlock());
191
+
180
192
  if (this.dashTexture) {
181
193
  ops.push(() =>
182
194
  setUniforms(this.programInfo, {
183
195
  uDashTexture: this.dashTexture,
184
- uStrokeDashOffset: this.properties.strokeDashOffset,
185
196
  })
186
197
  );
187
198
  }
@@ -1 +1 @@
1
- {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/marks/text.js"],"names":[],"mappings":"AA0BA;;;;;;;GAOG;AACH;IAsDQ,oDAMmD;CAwL1D;iBA/QgB,WAAW"}
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/marks/text.js"],"names":[],"mappings":"AAgCA;;;;;;;GAOG;AACH;IAsDQ,oDAMmD;CAiM1D;iBAxRgB,WAAW"}
@@ -1,8 +1,14 @@
1
1
  import { isString } from "vega-util";
2
2
  import { format } from "d3-format";
3
- import { drawBufferInfo, setBuffersAndAttributes, setUniforms } from "twgl.js";
3
+ import {
4
+ drawBufferInfo,
5
+ setBlockUniforms,
6
+ setBuffersAndAttributes,
7
+ setUniforms,
8
+ } from "twgl.js";
4
9
  import VERTEX_SHADER from "../gl/text.vertex.glsl.js";
5
10
  import FRAGMENT_SHADER from "../gl/text.fragment.glsl.js";
11
+ import COMMON_SHADER from "../gl/text.common.glsl.js";
6
12
  import { TextVertexBuilder } from "../gl/dataToVertices.js";
7
13
 
8
14
  import Mark from "./mark.js";
@@ -142,7 +148,9 @@ export default class TextMark extends Mark {
142
148
 
143
149
  async initializeGraphics() {
144
150
  await super.initializeGraphics();
145
- this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER);
151
+ this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER, [
152
+ COMMON_SHADER,
153
+ ]);
146
154
  }
147
155
 
148
156
  finalizeGraphicsInitialization() {
@@ -153,7 +161,7 @@ export default class TextMark extends Mark {
153
161
  const props = this.properties;
154
162
 
155
163
  // TODO: Use uniform block.
156
- setUniforms(this.programInfo, {
164
+ setBlockUniforms(this.markUniformInfo, {
157
165
  uPaddingX: props.paddingX,
158
166
  uPaddingY: props.paddingY,
159
167
  uFlushX: !!props.flushX,
@@ -240,12 +248,19 @@ export default class TextMark extends Mark {
240
248
  this.font.metrics.common.base /
241
249
  (this.unitView.context.devicePixelRatio / q);
242
250
 
243
- ops.push(() =>
251
+ ops.push(() => {
252
+ // TODO: only set if dpr changed
253
+ setBlockUniforms(this.markUniformInfo, {
254
+ uSdfNumerator,
255
+ });
256
+ this.markUniformsAltered = true;
257
+
244
258
  setUniforms(this.programInfo, {
245
259
  uTexture: this.font.texture,
246
- uSdfNumerator,
247
- })
248
- );
260
+ });
261
+ });
262
+
263
+ ops.push(() => this.bindOrSetMarkUniformBlock());
249
264
 
250
265
  ops.push(() =>
251
266
  setBuffersAndAttributes(
@@ -0,0 +1,30 @@
1
+ /**
2
+ * A class that manages parameters and expressions. Still a work in progress.
3
+ *
4
+ * TODO: Write tests for this class.
5
+ *
6
+ * This should eventually handle the following:
7
+ * - Parameter registration
8
+ * - Dependency tracking
9
+ * - Calling observers when a parameter changes
10
+ * - Somehow saving parameter "state" (in bookmarks)
11
+ * - Maybe something else
12
+ */
13
+ export default class ParamBroker {
14
+ /**
15
+ *
16
+ * @param {string} paramName
17
+ * @returns {(value: any) => void}
18
+ */
19
+ allocateSetter(paramName: string): (value: any) => void;
20
+ /**
21
+ * Parse expr and return a function that returns the value of the parameter.
22
+ *
23
+ * @param {string} expr
24
+ */
25
+ createExpression(expr: string): ((x: object) => any) & import("./utils/expression.js").ExpressionProps & {
26
+ addListener: (listener: () => void) => void;
27
+ };
28
+ #private;
29
+ }
30
+ //# sourceMappingURL=paramBroker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paramBroker.d.ts","sourceRoot":"","sources":["../../src/paramBroker.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH;IAyBI;;;;OAIG;IACH,0BAHW,MAAM,WACI,GAAG,KAAK,IAAI,CAqBhC;IAID;;;;OAIG;IACH,uBAFW,MAAM;gCAG6E,MAAM,IAAI,KAAK,IAAI;MA0BhH;;CACJ"}