@perspective-dev/viewer-charts 4.3.0 → 4.5.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.
Files changed (72) hide show
  1. package/dist/cdn/perspective-viewer-charts.js +2 -2
  2. package/dist/cdn/perspective-viewer-charts.js.map +3 -3
  3. package/dist/esm/axis/bar-axis.d.ts +9 -1
  4. package/dist/esm/axis/categorical-axis.d.ts +0 -2
  5. package/dist/esm/charts/cartesian/cartesian.d.ts +26 -0
  6. package/dist/esm/charts/common/category-axis-resolver.d.ts +43 -1
  7. package/dist/esm/charts/common/expand-domain.d.ts +20 -0
  8. package/dist/esm/charts/common/tree-chart.d.ts +7 -0
  9. package/dist/esm/charts/common/tree-chrome.d.ts +23 -1
  10. package/dist/esm/charts/common/tree-interact.d.ts +46 -0
  11. package/dist/esm/charts/series/glyphs/draw-lines.d.ts +11 -4
  12. package/dist/esm/charts/series/series-build.d.ts +38 -2
  13. package/dist/esm/charts/series/series-render.d.ts +1 -4
  14. package/dist/esm/charts/series/series-type.d.ts +19 -17
  15. package/dist/esm/charts/series/series.d.ts +16 -0
  16. package/dist/esm/charts/sunburst/sunburst-interact.d.ts +1 -1
  17. package/dist/esm/charts/treemap/treemap-interact.d.ts +1 -6
  18. package/dist/esm/interaction/host-sink-message.d.ts +10 -28
  19. package/dist/esm/interaction/raw-event-forwarder.d.ts +6 -7
  20. package/dist/esm/interaction/zoom-controller.d.ts +31 -20
  21. package/dist/esm/interaction/zoom-router.d.ts +3 -26
  22. package/dist/esm/perspective-viewer-charts.js +2 -2
  23. package/dist/esm/perspective-viewer-charts.js.map +3 -3
  24. package/dist/esm/plugin/plugin.d.ts +0 -1
  25. package/dist/esm/theme/palette.d.ts +0 -5
  26. package/dist/esm/transport/protocol.d.ts +2 -7
  27. package/dist/esm/worker/renderer.worker.d.ts +2 -4
  28. package/package.json +1 -1
  29. package/src/ts/axis/bar-axis.ts +74 -45
  30. package/src/ts/axis/categorical-axis.ts +0 -2
  31. package/src/ts/charts/candlestick/candlestick-render.ts +10 -7
  32. package/src/ts/charts/candlestick/candlestick.ts +10 -29
  33. package/src/ts/charts/candlestick/glyphs/draw-candlesticks.ts +36 -2
  34. package/src/ts/charts/candlestick/glyphs/draw-ohlc.ts +36 -2
  35. package/src/ts/charts/cartesian/cartesian-build.ts +143 -9
  36. package/src/ts/charts/cartesian/cartesian-render.ts +205 -30
  37. package/src/ts/charts/cartesian/cartesian.ts +43 -4
  38. package/src/ts/charts/cartesian/glyphs/density.ts +36 -41
  39. package/src/ts/charts/cartesian/glyphs/lines.ts +13 -15
  40. package/src/ts/charts/cartesian/glyphs/points.ts +12 -17
  41. package/src/ts/charts/chart-base.ts +20 -6
  42. package/src/ts/charts/chart.ts +1 -1
  43. package/src/ts/charts/common/category-axis-resolver.ts +135 -1
  44. package/src/ts/charts/common/expand-domain.ts +40 -0
  45. package/src/ts/charts/common/tree-chart.ts +16 -0
  46. package/src/ts/charts/common/tree-chrome.ts +86 -1
  47. package/src/ts/charts/common/tree-interact.ts +209 -0
  48. package/src/ts/charts/heatmap/heatmap-render.ts +9 -11
  49. package/src/ts/charts/series/glyphs/draw-areas.ts +30 -1
  50. package/src/ts/charts/series/glyphs/draw-lines.ts +151 -76
  51. package/src/ts/charts/series/series-build.ts +394 -21
  52. package/src/ts/charts/series/series-render.ts +159 -38
  53. package/src/ts/charts/series/series-type.ts +37 -17
  54. package/src/ts/charts/series/series.ts +63 -68
  55. package/src/ts/charts/sunburst/sunburst-interact.ts +18 -162
  56. package/src/ts/charts/sunburst/sunburst-render.ts +24 -89
  57. package/src/ts/charts/sunburst/sunburst.ts +1 -15
  58. package/src/ts/charts/treemap/treemap-interact.ts +22 -189
  59. package/src/ts/charts/treemap/treemap-render.ts +19 -46
  60. package/src/ts/charts/treemap/treemap.ts +1 -16
  61. package/src/ts/interaction/host-sink-message.ts +33 -22
  62. package/src/ts/interaction/raw-event-forwarder.ts +10 -12
  63. package/src/ts/interaction/zoom-controller.ts +120 -83
  64. package/src/ts/interaction/zoom-router.ts +3 -126
  65. package/src/ts/map/tile-layer.ts +13 -13
  66. package/src/ts/plugin/plugin.ts +100 -184
  67. package/src/ts/shaders/line-uniform.frag.glsl +2 -1
  68. package/src/ts/shaders/line-uniform.vert.glsl +19 -0
  69. package/src/ts/theme/palette.ts +1 -4
  70. package/src/ts/transport/protocol.ts +3 -8
  71. package/src/ts/worker/dispatch.ts +0 -1
  72. package/src/ts/worker/renderer.worker.ts +10 -46
@@ -88,7 +88,6 @@ export declare class HTMLPerspectiveViewerWebGLPluginElement extends HTMLElement
88
88
  clear(): Promise<void>;
89
89
  resize(): Promise<void>;
90
90
  restyle(): number;
91
- save(): any;
92
91
  render(view: View): Promise<Blob>;
93
92
  restore(config: any, columns_config?: Record<string, any>): void;
94
93
  delete(): void;
@@ -1,10 +1,5 @@
1
1
  import { type GradientStop } from "./gradient";
2
2
  export type Vec3 = [number, number, number];
3
- /**
4
- * Build a series palette of length `count` by sampling the theme gradient
5
- * at evenly-spaced offsets. For count == 1 returns the 50% stop.
6
- */
7
- export declare function interpolatePalette(stops: GradientStop[], count: number): Vec3[];
8
3
  /**
9
4
  * Resolve a series palette: use the discrete `--psp-charts--series-N--color`
10
5
  * palette when available, otherwise fall back to evenly-spaced samples of
@@ -1,6 +1,8 @@
1
1
  import type { FacetConfig, PluginConfig } from "../charts/chart";
2
2
  import type { PerspectiveClickDetail } from "../event-detail";
3
+ import type { ThemeSnapshot } from "../theme/theme";
3
4
  import type { ViewConfig } from "@perspective-dev/client";
5
+ export type { ThemeSnapshot };
4
6
  /**
5
7
  * Worker-mode control-channel messages. Distinct from the perspective
6
8
  * `ProxySession` channel that the worker's `Client` uses to talk to the
@@ -160,13 +162,6 @@ export interface FontFaceDescriptor {
160
162
  featureSettings?: string;
161
163
  display?: string;
162
164
  }
163
- /**
164
- * Theme values resolved on the host via `getComputedStyle` and shipped
165
- * to the renderer scope, which has no DOM. Decoded by the chart via
166
- * `theme/theme.ts::resolveThemeFromVars`. Plain map for
167
- * structured-clone.
168
- */
169
- export type ThemeSnapshot = Record<string, string>;
170
165
  export interface SetViewByNameMsg {
171
166
  kind: "setViewByName";
172
167
  name: string;
@@ -81,10 +81,8 @@ export declare class WorkerRenderer {
81
81
  resetExpandedDomain(): void;
82
82
  /**
83
83
  * Hit-test the cursor against the chart's facet grid (in faceted
84
- * mode) or its current layout (single-plot). Mirrors the resolver
85
- * `_setupZoomRouter` builds on the host for in-process mode — the
86
- * worker owns the facet grid and controllers, so the resolution
87
- * runs here.
84
+ * mode) or its current layout (single-plot). The worker owns the
85
+ * facet grid and controllers, so the resolution runs here.
88
86
  */
89
87
  private _resolveTarget;
90
88
  onInteraction(event: InteractionEvent): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perspective-dev/viewer-charts",
3
- "version": "4.3.0",
3
+ "version": "4.5.1",
4
4
  "description": "Perspective.js WebGL Plugin",
5
5
  "unpkg": "./dist/cdn/perspective-viewer-charts.js",
6
6
  "jsdelivr": "./dist/cdn/perspective-viewer-charts.js",
@@ -142,6 +142,10 @@ export type BarCategoryAxis =
142
142
  | { mode: "category"; domain: CategoricalDomain }
143
143
  | { mode: "numeric"; domain: AxisDomain; ticks: number[] };
144
144
 
145
+ export type BarValueAxis =
146
+ | { mode: "category"; domain: CategoricalDomain }
147
+ | { mode: "numeric"; domain: AxisDomain; ticks: number[] };
148
+
145
149
  /**
146
150
  * Render a numeric date-aware axis along the bottom of the plot. Aliases
147
151
  * the bar-axis bottom variant so heatmap can share the implementation.
@@ -190,13 +194,11 @@ export interface BarAxesFormatters {
190
194
  export function renderBarAxesChrome(
191
195
  canvas: Canvas2D,
192
196
  catAxis: BarCategoryAxis,
193
- valueDomain: AxisDomain,
194
- valueTicks: number[],
197
+ valueAxis: BarValueAxis,
195
198
  layout: PlotLayout,
196
199
  theme: Theme,
197
200
  dpr: number,
198
- altDomain?: AxisDomain,
199
- altTicks?: number[],
201
+ altAxis: BarValueAxis | undefined,
200
202
  isHorizontal = false,
201
203
  formatters: BarAxesFormatters = {},
202
204
  ): void {
@@ -212,7 +214,7 @@ export function renderBarAxesChrome(
212
214
  ctx.moveTo(plot.x, plot.y);
213
215
  ctx.lineTo(plot.x, plot.y + plot.height);
214
216
  ctx.lineTo(plot.x + plot.width, plot.y + plot.height);
215
- if (altDomain) {
217
+ if (altAxis) {
216
218
  if (isHorizontal) {
217
219
  ctx.moveTo(plot.x, plot.y);
218
220
  ctx.lineTo(plot.x + plot.width, plot.y);
@@ -238,31 +240,49 @@ export function renderBarAxesChrome(
238
240
  );
239
241
  }
240
242
 
241
- drawNumericXAxis(
242
- ctx,
243
- layout,
244
- valueDomain,
245
- valueTicks,
246
- "bottom",
247
- theme,
248
- formatters.value,
249
- );
250
- if (altDomain && altTicks) {
251
- const origMin = layout.paddedXMin;
252
- const origMax = layout.paddedXMax;
253
- layout.paddedXMin = altDomain.min;
254
- layout.paddedXMax = altDomain.max;
243
+ if (valueAxis.mode === "category") {
244
+ // Categorical value axis on the bottom: reuse the X
245
+ // categorical painter. Slot indices on the layout's X
246
+ // domain already place each category at its slot pixel.
247
+ renderCategoricalXTicks(ctx, layout, valueAxis.domain, theme);
248
+ } else {
255
249
  drawNumericXAxis(
256
250
  ctx,
257
251
  layout,
258
- altDomain,
259
- altTicks,
260
- "top",
252
+ valueAxis.domain,
253
+ valueAxis.ticks,
254
+ "bottom",
261
255
  theme,
262
- formatters.alt,
256
+ formatters.value,
263
257
  );
264
- layout.paddedXMin = origMin;
265
- layout.paddedXMax = origMax;
258
+ }
259
+
260
+ if (altAxis) {
261
+ // Alt-axis painter expects the layout's X domain to match
262
+ // the alt domain — temporarily swap in `altDomain.min/max`
263
+ // for the duration of the call. Categorical alt has no
264
+ // top-side painter; render with the bottom-side painter
265
+ // (visual overlap with the primary side — documented
266
+ // limitation; user-pinned categorical alt is rare).
267
+ if (altAxis.mode === "category") {
268
+ renderCategoricalXTicks(ctx, layout, altAxis.domain, theme);
269
+ } else {
270
+ const origMin = layout.paddedXMin;
271
+ const origMax = layout.paddedXMax;
272
+ layout.paddedXMin = altAxis.domain.min;
273
+ layout.paddedXMax = altAxis.domain.max;
274
+ drawNumericXAxis(
275
+ ctx,
276
+ layout,
277
+ altAxis.domain,
278
+ altAxis.ticks,
279
+ "top",
280
+ theme,
281
+ formatters.alt,
282
+ );
283
+ layout.paddedXMin = origMin;
284
+ layout.paddedXMax = origMax;
285
+ }
266
286
  }
267
287
  } else {
268
288
  if (catAxis.mode === "category") {
@@ -278,31 +298,40 @@ export function renderBarAxesChrome(
278
298
  );
279
299
  }
280
300
 
281
- drawYAxis(
282
- ctx,
283
- layout,
284
- valueDomain,
285
- valueTicks,
286
- "left",
287
- theme,
288
- formatters.value,
289
- );
290
- if (altDomain && altTicks) {
291
- const origMin = layout.paddedYMin;
292
- const origMax = layout.paddedYMax;
293
- layout.paddedYMin = altDomain.min;
294
- layout.paddedYMax = altDomain.max;
301
+ if (valueAxis.mode === "category") {
302
+ renderCategoricalYTicks(ctx, layout, valueAxis.domain, theme);
303
+ } else {
295
304
  drawYAxis(
296
305
  ctx,
297
306
  layout,
298
- altDomain,
299
- altTicks,
300
- "right",
307
+ valueAxis.domain,
308
+ valueAxis.ticks,
309
+ "left",
301
310
  theme,
302
- formatters.alt,
311
+ formatters.value,
303
312
  );
304
- layout.paddedYMin = origMin;
305
- layout.paddedYMax = origMax;
313
+ }
314
+
315
+ if (altAxis) {
316
+ if (altAxis.mode === "category") {
317
+ renderCategoricalYTicks(ctx, layout, altAxis.domain, theme);
318
+ } else {
319
+ const origMin = layout.paddedYMin;
320
+ const origMax = layout.paddedYMax;
321
+ layout.paddedYMin = altAxis.domain.min;
322
+ layout.paddedYMax = altAxis.domain.max;
323
+ drawYAxis(
324
+ ctx,
325
+ layout,
326
+ altAxis.domain,
327
+ altAxis.ticks,
328
+ "right",
329
+ theme,
330
+ formatters.alt,
331
+ );
332
+ layout.paddedYMin = origMin;
333
+ layout.paddedYMax = origMax;
334
+ }
306
335
  }
307
336
  }
308
337
  }
@@ -56,8 +56,6 @@ function categoryIndexToPixelY(layout: PlotLayout, index: number): number {
56
56
  return layout.dataToPixel(0, index).py;
57
57
  }
58
58
 
59
- export const categoryIndexToPixel = categoryIndexToPixelX;
60
-
61
59
  function leafLevelLayout(
62
60
  numRows: number,
63
61
  longestCharCount: number,
@@ -125,13 +125,14 @@ export function renderCandlestickFrame(
125
125
  yMax: chart._yDomain.max,
126
126
  };
127
127
 
128
- // Auto-fit the price axis to the visible X window. Skipped at
129
- // default zoom (the refit equals `_yDomain` there and would only
130
- // churn baselines).
128
+ // Auto-fit the price axis to the visible X window. Skipped when X
129
+ // is at default zoom (the refit equals `_yDomain` there and would
130
+ // only churn baselines) — Y-axis pan/zoom alone shouldn't trigger
131
+ // an X-window refit.
131
132
  if (
132
133
  chart._autoFitValue &&
133
134
  chart._zoomController &&
134
- !chart._zoomController.isDefault()
135
+ !chart._zoomController.isXDefault()
135
136
  ) {
136
137
  const fit = computeVisibleCandleExtent(chart, vis.xMin, vis.xMax);
137
138
  if (fit.hasFit) {
@@ -271,13 +272,15 @@ export function renderCandlestickChromeOverlay(chart: CandlestickChart): void {
271
272
  renderBarAxesChrome(
272
273
  chart._chromeCanvas,
273
274
  catAxis,
274
- chart._lastYDomain,
275
- chart._lastYTicks,
275
+ {
276
+ mode: "numeric",
277
+ domain: chart._lastYDomain,
278
+ ticks: chart._lastYTicks,
279
+ },
276
280
  chart._lastLayout,
277
281
  theme,
278
282
  chart._glManager?.dpr ?? 1,
279
283
  undefined,
280
- undefined,
281
284
  false,
282
285
  {
283
286
  value: chart.getColumnFormatter(valueColumn, "tick"),
@@ -33,6 +33,7 @@ import {
33
33
  } from "./candlestick-interact";
34
34
  import { BodyWickGlyph } from "./glyphs/draw-candlesticks";
35
35
  import { OHLCGlyph } from "./glyphs/draw-ohlc";
36
+ import { expandDomainInPlace } from "../common/expand-domain";
36
37
 
37
38
  /**
38
39
  * Per-frame memo of the auto-fit Y extent for a {@link CandlestickChart},
@@ -266,38 +267,18 @@ export class CandlestickChart extends CategoricalYChart {
266
267
  scratchCandles: this._candles,
267
268
  });
268
269
  // `domain_mode: "expand"` post-build union — mirrors the series
269
- // pipeline. Mutate the pipeline result in place so the
270
+ // pipeline. `expandDomainInPlace` mutates `result.*` so the
270
271
  // assignments below pick up the grown extent automatically.
271
272
  if (this._pluginConfig.domain_mode === "expand") {
272
- if (this._expandedYDomain) {
273
- result.yDomain.min = Math.min(
274
- this._expandedYDomain.min,
275
- result.yDomain.min,
276
- );
277
- result.yDomain.max = Math.max(
278
- this._expandedYDomain.max,
279
- result.yDomain.max,
280
- );
281
- }
282
-
283
- this._expandedYDomain = { ...result.yDomain };
284
-
273
+ this._expandedYDomain = expandDomainInPlace(
274
+ this._expandedYDomain,
275
+ result.yDomain,
276
+ );
285
277
  if (result.numericCategoryDomain) {
286
- if (this._expandedCategoryDomain) {
287
- result.numericCategoryDomain.min = Math.min(
288
- this._expandedCategoryDomain.min,
289
- result.numericCategoryDomain.min,
290
- );
291
- result.numericCategoryDomain.max = Math.max(
292
- this._expandedCategoryDomain.max,
293
- result.numericCategoryDomain.max,
294
- );
295
- }
296
-
297
- this._expandedCategoryDomain = {
298
- min: result.numericCategoryDomain.min,
299
- max: result.numericCategoryDomain.max,
300
- };
278
+ this._expandedCategoryDomain = expandDomainInPlace(
279
+ this._expandedCategoryDomain,
280
+ result.numericCategoryDomain,
281
+ );
301
282
  }
302
283
  } else {
303
284
  this._expandedYDomain = null;
@@ -46,9 +46,23 @@ interface WickCache {
46
46
  u_color: WebGLUniformLocation | null;
47
47
  u_resolution: WebGLUniformLocation | null;
48
48
  u_line_width: WebGLUniformLocation | null;
49
+
50
+ /**
51
+ * `line-uniform` was extended to support the Y-Line `interpolate`
52
+ * feature with a per-segment alpha multiplier driven by
53
+ * `a_real_start * a_real_end` and `u_interp_alpha`. Wicks are
54
+ * always "real" data — every segment renders fully — so we hold
55
+ * these locations to neutralize them at draw time (uniform = 1.0,
56
+ * constant attribute values = 1.0). Without that, an unset uniform
57
+ * defaults to 0 and the fragment alpha collapses to 0, rendering
58
+ * the wicks invisible.
59
+ */
60
+ u_interp_alpha: WebGLUniformLocation | null;
49
61
  a_corner: number;
50
62
  a_start: number;
51
63
  a_end: number;
64
+ a_real_start: number;
65
+ a_real_end: number;
52
66
  }
53
67
 
54
68
  interface ProgramCache {
@@ -124,8 +138,14 @@ export class BodyWickGlyph {
124
138
  "line-uniform",
125
139
  lineVert,
126
140
  lineFrag,
127
- ["u_projection", "u_color", "u_resolution", "u_line_width"],
128
- ["a_corner", "a_start", "a_end"],
141
+ [
142
+ "u_projection",
143
+ "u_color",
144
+ "u_resolution",
145
+ "u_line_width",
146
+ "u_interp_alpha",
147
+ ],
148
+ ["a_corner", "a_start", "a_end", "a_real_start", "a_real_end"],
129
149
  );
130
150
  const wick: WickCache = {
131
151
  ...wickPartial,
@@ -375,6 +395,20 @@ function drawWicks(
375
395
  gl.uniform2f(cache.u_resolution, gl.canvas.width, gl.canvas.height);
376
396
  gl.uniform1f(cache.u_line_width, chart._pluginConfig.wick_width_px * dpr);
377
397
 
398
+ // `line-uniform` was extended for the Y-Line interpolate feature
399
+ // with a per-segment alpha multiplier; neutralize it here.
400
+ // Constant attribute values (used when the array is disabled) and
401
+ // uniform are stable for every draw, so set once after
402
+ // `useProgram`. Disabling the arrays first guards against a prior
403
+ // Y-Line draw that left them enabled at the same attribute index
404
+ // (locations are shared because both programs link from the same
405
+ // source).
406
+ gl.disableVertexAttribArray(cache.a_real_start);
407
+ gl.disableVertexAttribArray(cache.a_real_end);
408
+ gl.vertexAttrib1f(cache.a_real_start, 1.0);
409
+ gl.vertexAttrib1f(cache.a_real_end, 1.0);
410
+ gl.uniform1f(cache.u_interp_alpha, 1.0);
411
+
378
412
  const instancing = getInstancing(glManager);
379
413
  const { setDivisor } = instancing;
380
414
 
@@ -30,9 +30,23 @@ interface OHLCCache {
30
30
  u_color: WebGLUniformLocation | null;
31
31
  u_resolution: WebGLUniformLocation | null;
32
32
  u_line_width: WebGLUniformLocation | null;
33
+
34
+ /**
35
+ * `line-uniform` was extended to support the Y-Line `interpolate`
36
+ * feature with a per-segment alpha multiplier driven by
37
+ * `a_real_start * a_real_end` and `u_interp_alpha`. The OHLC glyph
38
+ * doesn't need that — every segment is "real" — so we hold these
39
+ * locations to neutralize them at draw time (uniform = 1.0,
40
+ * constant attribute values = 1.0). Without that, an unset uniform
41
+ * defaults to 0 and the fragment alpha collapses to 0, rendering
42
+ * the entire OHLC glyph invisible.
43
+ */
44
+ u_interp_alpha: WebGLUniformLocation | null;
33
45
  a_corner: number;
34
46
  a_start: number;
35
47
  a_end: number;
48
+ a_real_start: number;
49
+ a_real_end: number;
36
50
  }
37
51
 
38
52
  /**
@@ -76,8 +90,14 @@ export class OHLCGlyph {
76
90
  "line-uniform",
77
91
  lineVert,
78
92
  lineFrag,
79
- ["u_projection", "u_color", "u_resolution", "u_line_width"],
80
- ["a_corner", "a_start", "a_end"],
93
+ [
94
+ "u_projection",
95
+ "u_color",
96
+ "u_resolution",
97
+ "u_line_width",
98
+ "u_interp_alpha",
99
+ ],
100
+ ["a_corner", "a_start", "a_end", "a_real_start", "a_real_end"],
81
101
  );
82
102
  this._program = {
83
103
  ...partial,
@@ -229,6 +249,20 @@ export class OHLCGlyph {
229
249
  chart._pluginConfig.ohlc_line_width_px * dpr,
230
250
  );
231
251
 
252
+ // `line-uniform` was extended for the Y-Line interpolate
253
+ // feature with a per-segment alpha multiplier; neutralize it
254
+ // here. Constant attribute values (used when the array is
255
+ // disabled) and uniform are stable for every draw, so set
256
+ // once after `useProgram`. Disabling the arrays first guards
257
+ // against a prior Y-Line draw that left them enabled at the
258
+ // same attribute index (locations are shared because both
259
+ // programs link from the same source).
260
+ gl.disableVertexAttribArray(cache.a_real_start);
261
+ gl.disableVertexAttribArray(cache.a_real_end);
262
+ gl.vertexAttrib1f(cache.a_real_start, 1.0);
263
+ gl.vertexAttrib1f(cache.a_real_end, 1.0);
264
+ gl.uniform1f(cache.u_interp_alpha, 1.0);
265
+
232
266
  const instancing = getInstancing(glManager);
233
267
  const { setDivisor } = instancing;
234
268