@perspective-dev/viewer-charts 4.3.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.
- package/LICENSE.md +193 -0
- package/dist/cdn/perspective-viewer-charts.js +3 -0
- package/dist/cdn/perspective-viewer-charts.js.map +7 -0
- package/dist/esm/axis/axis-primitives.d.ts +24 -0
- package/dist/esm/axis/bar-axis.d.ts +51 -0
- package/dist/esm/axis/canvas.d.ts +24 -0
- package/dist/esm/axis/categorical-axis-core.d.ts +42 -0
- package/dist/esm/axis/categorical-axis.d.ts +27 -0
- package/dist/esm/axis/facet-chrome.d.ts +13 -0
- package/dist/esm/axis/label-geometry.d.ts +41 -0
- package/dist/esm/axis/legend.d.ts +44 -0
- package/dist/esm/axis/numeric-axis.d.ts +20 -0
- package/dist/esm/charts/candlestick/candlestick-build.d.ts +129 -0
- package/dist/esm/charts/candlestick/candlestick-interact.d.ts +10 -0
- package/dist/esm/charts/candlestick/candlestick-render.d.ts +24 -0
- package/dist/esm/charts/candlestick/candlestick.d.ts +144 -0
- package/dist/esm/charts/candlestick/glyphs/draw-candlesticks.d.ts +36 -0
- package/dist/esm/charts/candlestick/glyphs/draw-ohlc.d.ts +33 -0
- package/dist/esm/charts/canvas-types.d.ts +15 -0
- package/dist/esm/charts/cartesian/cartesian-build.d.ts +14 -0
- package/dist/esm/charts/cartesian/cartesian-interact.d.ts +20 -0
- package/dist/esm/charts/cartesian/cartesian-render.d.ts +26 -0
- package/dist/esm/charts/cartesian/cartesian.d.ts +239 -0
- package/dist/esm/charts/cartesian/glyph.d.ts +53 -0
- package/dist/esm/charts/cartesian/glyphs/density.d.ts +142 -0
- package/dist/esm/charts/cartesian/glyphs/lines.d.ts +23 -0
- package/dist/esm/charts/cartesian/glyphs/points.d.ts +24 -0
- package/dist/esm/charts/cartesian/label-interner.d.ts +21 -0
- package/dist/esm/charts/cartesian/tooltip-lines.d.ts +11 -0
- package/dist/esm/charts/chart-base.d.ts +402 -0
- package/dist/esm/charts/chart.d.ts +338 -0
- package/dist/esm/charts/common/band-layout.d.ts +32 -0
- package/dist/esm/charts/common/categorical-y-chart.d.ts +53 -0
- package/dist/esm/charts/common/category-axis-resolver.d.ts +90 -0
- package/dist/esm/charts/common/chrome-cache.d.ts +18 -0
- package/dist/esm/charts/common/draw-tooltip-box.d.ts +9 -0
- package/dist/esm/charts/common/leaf-color.d.ts +33 -0
- package/dist/esm/charts/common/node-store.d.ts +81 -0
- package/dist/esm/charts/common/tree-chart.d.ts +48 -0
- package/dist/esm/charts/common/tree-chrome.d.ts +31 -0
- package/dist/esm/charts/common/tree-data.d.ts +54 -0
- package/dist/esm/charts/common/visible-extent.d.ts +51 -0
- package/dist/esm/charts/heatmap/heatmap-build.d.ts +86 -0
- package/dist/esm/charts/heatmap/heatmap-interact.d.ts +19 -0
- package/dist/esm/charts/heatmap/heatmap-render.d.ts +19 -0
- package/dist/esm/charts/heatmap/heatmap-y-axis.d.ts +46 -0
- package/dist/esm/charts/heatmap/heatmap.d.ts +117 -0
- package/dist/esm/charts/map/map.d.ts +67 -0
- package/dist/esm/charts/registry.d.ts +14 -0
- package/dist/esm/charts/series/glyphs/draw-areas.d.ts +30 -0
- package/dist/esm/charts/series/glyphs/draw-bars.d.ts +15 -0
- package/dist/esm/charts/series/glyphs/draw-lines.d.ts +34 -0
- package/dist/esm/charts/series/glyphs/draw-scatter.d.ts +33 -0
- package/dist/esm/charts/series/series-build.d.ts +228 -0
- package/dist/esm/charts/series/series-interact.d.ts +35 -0
- package/dist/esm/charts/series/series-render.d.ts +41 -0
- package/dist/esm/charts/series/series-type.d.ts +49 -0
- package/dist/esm/charts/series/series.d.ts +317 -0
- package/dist/esm/charts/sunburst/sunburst-interact.d.ts +7 -0
- package/dist/esm/charts/sunburst/sunburst-layout.d.ts +33 -0
- package/dist/esm/charts/sunburst/sunburst-render.d.ts +22 -0
- package/dist/esm/charts/sunburst/sunburst.d.ts +85 -0
- package/dist/esm/charts/treemap/treemap-interact.d.ts +12 -0
- package/dist/esm/charts/treemap/treemap-layout.d.ts +28 -0
- package/dist/esm/charts/treemap/treemap-render.d.ts +18 -0
- package/dist/esm/charts/treemap/treemap.d.ts +74 -0
- package/dist/esm/config.d.ts +27 -0
- package/dist/esm/data/lazy-row.d.ts +32 -0
- package/dist/esm/data/split-groups.d.ts +20 -0
- package/dist/esm/data/view-reader.d.ts +35 -0
- package/dist/esm/event-detail.d.ts +28 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/interaction/hit-test.d.ts +30 -0
- package/dist/esm/interaction/host-sink-dom.d.ts +19 -0
- package/dist/esm/interaction/host-sink-message.d.ts +46 -0
- package/dist/esm/interaction/lazy-tooltip.d.ts +61 -0
- package/dist/esm/interaction/raw-event-forwarder.d.ts +27 -0
- package/dist/esm/interaction/spatial-grid.d.ts +15 -0
- package/dist/esm/interaction/tooltip-controller.d.ts +193 -0
- package/dist/esm/interaction/zoom-controller.d.ts +106 -0
- package/dist/esm/interaction/zoom-router.d.ts +48 -0
- package/dist/esm/layout/facet-grid.d.ts +126 -0
- package/dist/esm/layout/plot-layout.d.ts +104 -0
- package/dist/esm/layout/ticks.d.ts +17 -0
- package/dist/esm/map/mercator.d.ts +102 -0
- package/dist/esm/map/tile-cache.d.ts +38 -0
- package/dist/esm/map/tile-layer.d.ts +66 -0
- package/dist/esm/map/tile-loader.d.ts +52 -0
- package/dist/esm/map/tile-source.d.ts +66 -0
- package/dist/esm/perspective-viewer-charts.js +3 -0
- package/dist/esm/perspective-viewer-charts.js.map +7 -0
- package/dist/esm/plugin/charts.d.ts +40 -0
- package/dist/esm/plugin/plugin.d.ts +95 -0
- package/dist/esm/render/scheduler.d.ts +41 -0
- package/dist/esm/theme/gradient.d.ts +48 -0
- package/dist/esm/theme/palette.d.ts +13 -0
- package/dist/esm/theme/theme-snapshot.d.ts +7 -0
- package/dist/esm/theme/theme.d.ts +53 -0
- package/dist/esm/transport/protocol.d.ts +430 -0
- package/dist/esm/transport/renderer-transport.d.ts +201 -0
- package/dist/esm/utils/css.d.ts +1 -0
- package/dist/esm/utils/font-snapshot.d.ts +50 -0
- package/dist/esm/webgl/buffer-pool.d.ts +62 -0
- package/dist/esm/webgl/context-manager.d.ts +184 -0
- package/dist/esm/webgl/gradient-texture.d.ts +17 -0
- package/dist/esm/webgl/instanced-attrs.d.ts +44 -0
- package/dist/esm/webgl/plot-frame.d.ts +39 -0
- package/dist/esm/webgl/program-cache.d.ts +13 -0
- package/dist/esm/webgl/shader-manifest.d.ts +53 -0
- package/dist/esm/webgl/shader-registry.d.ts +22 -0
- package/dist/esm/worker/boot.d.ts +0 -0
- package/dist/esm/worker/dispatch.d.ts +9 -0
- package/dist/esm/worker/font-loader.d.ts +2 -0
- package/dist/esm/worker/renderer.worker.d.ts +115 -0
- package/dist/esm/worker/session-host.d.ts +26 -0
- package/package.json +47 -0
- package/src/css/perspective-viewer-charts.css +95 -0
- package/src/ts/axis/axis-primitives.ts +125 -0
- package/src/ts/axis/bar-axis.ts +345 -0
- package/src/ts/axis/canvas.ts +64 -0
- package/src/ts/axis/categorical-axis-core.ts +125 -0
- package/src/ts/axis/categorical-axis.ts +716 -0
- package/src/ts/axis/facet-chrome.ts +42 -0
- package/src/ts/axis/label-geometry.ts +188 -0
- package/src/ts/axis/legend.ts +218 -0
- package/src/ts/axis/numeric-axis.ts +353 -0
- package/src/ts/charts/candlestick/candlestick-build.ts +516 -0
- package/src/ts/charts/candlestick/candlestick-interact.ts +256 -0
- package/src/ts/charts/candlestick/candlestick-render.ts +387 -0
- package/src/ts/charts/candlestick/candlestick.ts +367 -0
- package/src/ts/charts/candlestick/glyphs/draw-candlesticks.ts +432 -0
- package/src/ts/charts/candlestick/glyphs/draw-ohlc.ts +317 -0
- package/src/ts/charts/canvas-types.ts +30 -0
- package/src/ts/charts/cartesian/cartesian-build.ts +616 -0
- package/src/ts/charts/cartesian/cartesian-interact.ts +355 -0
- package/src/ts/charts/cartesian/cartesian-render.ts +948 -0
- package/src/ts/charts/cartesian/cartesian.ts +469 -0
- package/src/ts/charts/cartesian/glyph.ts +81 -0
- package/src/ts/charts/cartesian/glyphs/density.ts +1263 -0
- package/src/ts/charts/cartesian/glyphs/lines.ts +320 -0
- package/src/ts/charts/cartesian/glyphs/points.ts +239 -0
- package/src/ts/charts/cartesian/label-interner.ts +56 -0
- package/src/ts/charts/cartesian/tooltip-lines.ts +80 -0
- package/src/ts/charts/chart-base.ts +840 -0
- package/src/ts/charts/chart.ts +427 -0
- package/src/ts/charts/common/band-layout.ts +63 -0
- package/src/ts/charts/common/categorical-y-chart.ts +81 -0
- package/src/ts/charts/common/category-axis-resolver.ts +314 -0
- package/src/ts/charts/common/chrome-cache.ts +79 -0
- package/src/ts/charts/common/draw-tooltip-box.ts +84 -0
- package/src/ts/charts/common/leaf-color.ts +92 -0
- package/src/ts/charts/common/node-store.ts +235 -0
- package/src/ts/charts/common/tree-chart.ts +76 -0
- package/src/ts/charts/common/tree-chrome.ts +123 -0
- package/src/ts/charts/common/tree-data.ts +623 -0
- package/src/ts/charts/common/visible-extent.ts +112 -0
- package/src/ts/charts/heatmap/heatmap-build.ts +426 -0
- package/src/ts/charts/heatmap/heatmap-interact.ts +274 -0
- package/src/ts/charts/heatmap/heatmap-render.ts +815 -0
- package/src/ts/charts/heatmap/heatmap-y-axis.ts +351 -0
- package/src/ts/charts/heatmap/heatmap.ts +368 -0
- package/src/ts/charts/map/map.ts +201 -0
- package/src/ts/charts/registry.ts +65 -0
- package/src/ts/charts/series/glyphs/draw-areas.ts +331 -0
- package/src/ts/charts/series/glyphs/draw-bars.ts +113 -0
- package/src/ts/charts/series/glyphs/draw-lines.ts +320 -0
- package/src/ts/charts/series/glyphs/draw-scatter.ts +328 -0
- package/src/ts/charts/series/series-build.ts +848 -0
- package/src/ts/charts/series/series-interact.ts +604 -0
- package/src/ts/charts/series/series-render.ts +1109 -0
- package/src/ts/charts/series/series-type.ts +99 -0
- package/src/ts/charts/series/series.ts +794 -0
- package/src/ts/charts/sunburst/sunburst-interact.ts +460 -0
- package/src/ts/charts/sunburst/sunburst-layout.ts +238 -0
- package/src/ts/charts/sunburst/sunburst-render.ts +887 -0
- package/src/ts/charts/sunburst/sunburst.ts +248 -0
- package/src/ts/charts/treemap/treemap-interact.ts +445 -0
- package/src/ts/charts/treemap/treemap-layout.ts +328 -0
- package/src/ts/charts/treemap/treemap-render.ts +886 -0
- package/src/ts/charts/treemap/treemap.ts +247 -0
- package/src/ts/config.ts +41 -0
- package/src/ts/data/lazy-row.ts +140 -0
- package/src/ts/data/split-groups.ts +97 -0
- package/src/ts/data/view-reader.ts +107 -0
- package/src/ts/event-detail.ts +44 -0
- package/src/ts/index.ts +53 -0
- package/src/ts/interaction/hit-test.ts +106 -0
- package/src/ts/interaction/host-sink-dom.ts +85 -0
- package/src/ts/interaction/host-sink-message.ts +75 -0
- package/src/ts/interaction/lazy-tooltip.ts +102 -0
- package/src/ts/interaction/raw-event-forwarder.ts +175 -0
- package/src/ts/interaction/spatial-grid.ts +100 -0
- package/src/ts/interaction/tooltip-controller.ts +407 -0
- package/src/ts/interaction/zoom-controller.ts +468 -0
- package/src/ts/interaction/zoom-router.ts +230 -0
- package/src/ts/layout/facet-grid.ts +346 -0
- package/src/ts/layout/plot-layout.ts +277 -0
- package/src/ts/layout/ticks.ts +168 -0
- package/src/ts/map/mercator.ts +204 -0
- package/src/ts/map/tile-cache.ts +96 -0
- package/src/ts/map/tile-layer.ts +382 -0
- package/src/ts/map/tile-loader.ts +143 -0
- package/src/ts/map/tile-source.ts +156 -0
- package/src/ts/plugin/charts.ts +286 -0
- package/src/ts/plugin/plugin.ts +668 -0
- package/src/ts/render/scheduler.ts +339 -0
- package/src/ts/shaders/area.frag.glsl +20 -0
- package/src/ts/shaders/area.vert.glsl +19 -0
- package/src/ts/shaders/bar.frag.glsl +25 -0
- package/src/ts/shaders/bar.vert.glsl +60 -0
- package/src/ts/shaders/candlestick-body.frag.glsl +19 -0
- package/src/ts/shaders/candlestick-body.vert.glsl +34 -0
- package/src/ts/shaders/density-extreme.frag.glsl +30 -0
- package/src/ts/shaders/density-mrt.frag.glsl +44 -0
- package/src/ts/shaders/density-mrt.vert.glsl +48 -0
- package/src/ts/shaders/density-resolve.frag.glsl +89 -0
- package/src/ts/shaders/density-resolve.vert.glsl +23 -0
- package/src/ts/shaders/density-splat.frag.glsl +34 -0
- package/src/ts/shaders/density-splat.vert.glsl +52 -0
- package/src/ts/shaders/gridline.frag.glsl +18 -0
- package/src/ts/shaders/gridline.vert.glsl +18 -0
- package/src/ts/shaders/heatmap.frag.glsl +23 -0
- package/src/ts/shaders/heatmap.vert.glsl +42 -0
- package/src/ts/shaders/line-uniform.frag.glsl +26 -0
- package/src/ts/shaders/line-uniform.vert.glsl +54 -0
- package/src/ts/shaders/line.frag.glsl +28 -0
- package/src/ts/shaders/line.vert.glsl +87 -0
- package/src/ts/shaders/scatter.frag.glsl +39 -0
- package/src/ts/shaders/scatter.vert.glsl +67 -0
- package/src/ts/shaders/sunburst-arc.frag.glsl +19 -0
- package/src/ts/shaders/sunburst-arc.vert.glsl +79 -0
- package/src/ts/shaders/tile.frag.glsl +27 -0
- package/src/ts/shaders/tile.vert.glsl +35 -0
- package/src/ts/shaders/treemap.frag.glsl +19 -0
- package/src/ts/shaders/treemap.vert.glsl +25 -0
- package/src/ts/shaders/y-scatter.frag.glsl +30 -0
- package/src/ts/shaders/y-scatter.vert.glsl +31 -0
- package/src/ts/theme/gradient.ts +312 -0
- package/src/ts/theme/palette.ts +64 -0
- package/src/ts/theme/theme-snapshot.ts +66 -0
- package/src/ts/theme/theme.ts +166 -0
- package/src/ts/transport/protocol.ts +497 -0
- package/src/ts/transport/renderer-transport.ts +788 -0
- package/src/ts/utils/css.ts +36 -0
- package/src/ts/utils/font-snapshot.ts +159 -0
- package/src/ts/webgl/buffer-pool.ts +163 -0
- package/src/ts/webgl/context-manager.ts +414 -0
- package/src/ts/webgl/gradient-texture.ts +84 -0
- package/src/ts/webgl/instanced-attrs.ts +139 -0
- package/src/ts/webgl/plot-frame.ts +91 -0
- package/src/ts/webgl/program-cache.ts +46 -0
- package/src/ts/webgl/shader-manifest.ts +148 -0
- package/src/ts/webgl/shader-registry.ts +97 -0
- package/src/ts/worker/boot.ts +22 -0
- package/src/ts/worker/dispatch.ts +99 -0
- package/src/ts/worker/font-loader.ts +89 -0
- package/src/ts/worker/renderer.worker.ts +734 -0
- package/src/ts/worker/session-host.ts +118 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
import type { WebGLContextManager } from "../../../webgl/context-manager";
|
|
14
|
+
import type { SeriesChart } from "../series";
|
|
15
|
+
import {
|
|
16
|
+
createLineCornerBuffer,
|
|
17
|
+
getInstancing,
|
|
18
|
+
} from "../../../webgl/instanced-attrs";
|
|
19
|
+
import { compileProgram } from "../../../webgl/program-cache";
|
|
20
|
+
import lineVert from "../../../shaders/line-uniform.vert.glsl";
|
|
21
|
+
import lineFrag from "../../../shaders/line-uniform.frag.glsl";
|
|
22
|
+
|
|
23
|
+
type GL = WebGL2RenderingContext | WebGLRenderingContext;
|
|
24
|
+
|
|
25
|
+
interface LineProgramCache {
|
|
26
|
+
program: WebGLProgram;
|
|
27
|
+
cornerBuffer: WebGLBuffer;
|
|
28
|
+
u_projection: WebGLUniformLocation | null;
|
|
29
|
+
u_color: WebGLUniformLocation | null;
|
|
30
|
+
u_resolution: WebGLUniformLocation | null;
|
|
31
|
+
u_line_width: WebGLUniformLocation | null;
|
|
32
|
+
a_start: number;
|
|
33
|
+
a_end: number;
|
|
34
|
+
a_corner: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface LineRun {
|
|
38
|
+
/**
|
|
39
|
+
* Byte offset into the per-series GPU buffer at the start of this run.
|
|
40
|
+
*/
|
|
41
|
+
offsetBytes: number;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Number of points in this run; the run draws `count - 1` segments.
|
|
45
|
+
*/
|
|
46
|
+
count: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface LineSeriesEntry {
|
|
50
|
+
seriesId: number;
|
|
51
|
+
axis: 0 | 1;
|
|
52
|
+
color: [number, number, number];
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* GPU buffer holding `[x0,y0,x1,y1,...]` for every run in the series.
|
|
56
|
+
*/
|
|
57
|
+
gpuBuffer: WebGLBuffer;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Run offsets into `gpuBuffer`. Empty when the series has no segments.
|
|
61
|
+
*/
|
|
62
|
+
runs: LineRun[];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Persistent line glyph state. Built in `rebuildBuffers` (called from
|
|
67
|
+
* `uploadAndRender`) and reused across pan/zoom frames. Legacy code
|
|
68
|
+
* rebuilt the JS-side polylines + GPU buffers on every frame, which
|
|
69
|
+
* dominated the per-frame budget at high N.
|
|
70
|
+
*/
|
|
71
|
+
interface LineBuffers {
|
|
72
|
+
/**
|
|
73
|
+
* One entry per line series (hidden series included; draw skips them).
|
|
74
|
+
*/
|
|
75
|
+
series: LineSeriesEntry[];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Reusable Float32 scratch for assembling polyline points before GPU
|
|
80
|
+
* upload. Sized lazily and grown on demand. Replaces the legacy
|
|
81
|
+
* `scratch: number[]` (boxed) → `Float32Array.from(scratch)` (copy)
|
|
82
|
+
* pattern.
|
|
83
|
+
*/
|
|
84
|
+
let _lineScratch: Float32Array = new Float32Array(0);
|
|
85
|
+
|
|
86
|
+
function ensureLineScratch(n: number): Float32Array {
|
|
87
|
+
if (_lineScratch.length >= n) {
|
|
88
|
+
return _lineScratch;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
_lineScratch = new Float32Array(Math.max(n, _lineScratch.length * 2));
|
|
92
|
+
return _lineScratch;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Line glyph for {@link SeriesChart}. Owns its program + per-series
|
|
97
|
+
* GPU buffers privately; chart routes lifecycle through
|
|
98
|
+
* `_glyphs.lines`.
|
|
99
|
+
*/
|
|
100
|
+
export class LineGlyph {
|
|
101
|
+
private _program: LineProgramCache | null = null;
|
|
102
|
+
private _buffers: LineBuffers | null = null;
|
|
103
|
+
|
|
104
|
+
private ensureProgram(glManager: WebGLContextManager): LineProgramCache {
|
|
105
|
+
if (this._program) {
|
|
106
|
+
return this._program;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const cornerBuffer = createLineCornerBuffer(glManager.gl);
|
|
110
|
+
const partial = compileProgram<Omit<LineProgramCache, "cornerBuffer">>(
|
|
111
|
+
glManager,
|
|
112
|
+
"bar-line",
|
|
113
|
+
lineVert,
|
|
114
|
+
lineFrag,
|
|
115
|
+
["u_projection", "u_color", "u_resolution", "u_line_width"],
|
|
116
|
+
["a_start", "a_end", "a_corner"],
|
|
117
|
+
);
|
|
118
|
+
this._program = { ...partial, cornerBuffer };
|
|
119
|
+
return this._program;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Drop persistent line buffers. Subsequent draws will no-op until
|
|
124
|
+
* the next `rebuildBuffers` call.
|
|
125
|
+
*/
|
|
126
|
+
invalidateBuffers(chart: SeriesChart): void {
|
|
127
|
+
const buf = this._buffers;
|
|
128
|
+
if (!buf || !chart._glManager) {
|
|
129
|
+
this._buffers = null;
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const gl = chart._glManager.gl;
|
|
134
|
+
for (const s of buf.series) {
|
|
135
|
+
gl.deleteBuffer(s.gpuBuffer);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
this._buffers = null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Rebuild the per-series GPU buffers for line glyphs. Called once
|
|
143
|
+
* per data load (and once after `restyle()` because palette colors
|
|
144
|
+
* are captured on the {@link LineSeriesEntry}). The buffer contents
|
|
145
|
+
* encode `[x,y]` points in run-major order; one `bufferData` per
|
|
146
|
+
* series. After this, every `draw` call rebinds + dispatches with
|
|
147
|
+
* no further uploads until the next data load.
|
|
148
|
+
*/
|
|
149
|
+
rebuildBuffers(chart: SeriesChart, glManager: WebGLContextManager): void {
|
|
150
|
+
const lineSeries = chart._lineSeries;
|
|
151
|
+
if (lineSeries.length === 0) {
|
|
152
|
+
this._buffers = null;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const N = chart._numCategories;
|
|
157
|
+
if (N === 0) {
|
|
158
|
+
this._buffers = null;
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
this.ensureProgram(glManager);
|
|
163
|
+
const gl = glManager.gl;
|
|
164
|
+
const samples = chart._samples;
|
|
165
|
+
const valid = chart._sampleValid;
|
|
166
|
+
const xOrigin = chart._categoryOrigin;
|
|
167
|
+
const positions = chart._categoryPositions;
|
|
168
|
+
const S = chart._series.length;
|
|
169
|
+
|
|
170
|
+
const entries: LineSeriesEntry[] = [];
|
|
171
|
+
for (const s of lineSeries) {
|
|
172
|
+
// Walk the per-category sample grid for this series, breaking
|
|
173
|
+
// into contiguous valid runs. Write directly into a pre-sized
|
|
174
|
+
// Float32 scratch — no boxed JS arrays, no `Float32Array.from`.
|
|
175
|
+
const scratch = ensureLineScratch(N * 2);
|
|
176
|
+
const runs: LineRun[] = [];
|
|
177
|
+
let write = 0;
|
|
178
|
+
let runStart = 0;
|
|
179
|
+
for (let c = 0; c < N; c++) {
|
|
180
|
+
const idx = c * S + s.seriesId;
|
|
181
|
+
const ok = (valid[idx >> 3] >> (idx & 7)) & 1;
|
|
182
|
+
if (ok) {
|
|
183
|
+
const x = positions ? positions[c] - xOrigin : c;
|
|
184
|
+
scratch[write++] = x;
|
|
185
|
+
scratch[write++] = samples[idx];
|
|
186
|
+
} else if (write > runStart) {
|
|
187
|
+
const count = (write - runStart) / 2;
|
|
188
|
+
if (count >= 2) {
|
|
189
|
+
runs.push({ offsetBytes: runStart * 4, count });
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
runStart = write;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (write > runStart) {
|
|
197
|
+
const count = (write - runStart) / 2;
|
|
198
|
+
if (count >= 2) {
|
|
199
|
+
runs.push({ offsetBytes: runStart * 4, count });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (runs.length === 0) {
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const buf = gl.createBuffer()!;
|
|
208
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
209
|
+
gl.bufferData(
|
|
210
|
+
gl.ARRAY_BUFFER,
|
|
211
|
+
scratch.subarray(0, write),
|
|
212
|
+
gl.STATIC_DRAW,
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
entries.push({
|
|
216
|
+
seriesId: s.seriesId,
|
|
217
|
+
axis: s.axis,
|
|
218
|
+
color: [s.color[0], s.color[1], s.color[2]],
|
|
219
|
+
gpuBuffer: buf,
|
|
220
|
+
runs,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
this._buffers = { series: entries };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Bind the persistent vertex buffers and dispatch one instanced draw
|
|
229
|
+
* per (series, run). Skips hidden series via `_hiddenSeries`.
|
|
230
|
+
*/
|
|
231
|
+
draw(
|
|
232
|
+
chart: SeriesChart,
|
|
233
|
+
gl: GL,
|
|
234
|
+
glManager: WebGLContextManager,
|
|
235
|
+
projLeft: Float32Array,
|
|
236
|
+
projRight: Float32Array,
|
|
237
|
+
): void {
|
|
238
|
+
const buf = this._buffers;
|
|
239
|
+
const cache = this._program;
|
|
240
|
+
if (!buf || !cache || buf.series.length === 0) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const dpr = glManager.dpr;
|
|
245
|
+
gl.useProgram(cache.program);
|
|
246
|
+
gl.uniform2f(cache.u_resolution, gl.canvas.width, gl.canvas.height);
|
|
247
|
+
gl.uniform1f(
|
|
248
|
+
cache.u_line_width,
|
|
249
|
+
chart._pluginConfig.line_width_px * dpr,
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
const instancing = getInstancing(glManager);
|
|
253
|
+
const { setDivisor, drawArraysInstanced } = instancing;
|
|
254
|
+
|
|
255
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, cache.cornerBuffer);
|
|
256
|
+
gl.enableVertexAttribArray(cache.a_corner);
|
|
257
|
+
gl.vertexAttribPointer(cache.a_corner, 1, gl.FLOAT, false, 0, 0);
|
|
258
|
+
setDivisor(cache.a_corner, 0);
|
|
259
|
+
|
|
260
|
+
const stride = 2 * Float32Array.BYTES_PER_ELEMENT;
|
|
261
|
+
const hidden = chart._hiddenSeries;
|
|
262
|
+
for (const s of buf.series) {
|
|
263
|
+
if (hidden.has(s.seriesId)) {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, s.gpuBuffer);
|
|
268
|
+
gl.uniformMatrix4fv(
|
|
269
|
+
cache.u_projection,
|
|
270
|
+
false,
|
|
271
|
+
s.axis === 1 ? projRight : projLeft,
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
const color = chart._series[s.seriesId].color;
|
|
275
|
+
gl.uniform4f(cache.u_color, color[0], color[1], color[2], 1.0);
|
|
276
|
+
|
|
277
|
+
gl.enableVertexAttribArray(cache.a_start);
|
|
278
|
+
setDivisor(cache.a_start, 1);
|
|
279
|
+
gl.enableVertexAttribArray(cache.a_end);
|
|
280
|
+
setDivisor(cache.a_end, 1);
|
|
281
|
+
|
|
282
|
+
for (const run of s.runs) {
|
|
283
|
+
gl.vertexAttribPointer(
|
|
284
|
+
cache.a_start,
|
|
285
|
+
2,
|
|
286
|
+
gl.FLOAT,
|
|
287
|
+
false,
|
|
288
|
+
stride,
|
|
289
|
+
run.offsetBytes,
|
|
290
|
+
);
|
|
291
|
+
gl.vertexAttribPointer(
|
|
292
|
+
cache.a_end,
|
|
293
|
+
2,
|
|
294
|
+
gl.FLOAT,
|
|
295
|
+
false,
|
|
296
|
+
stride,
|
|
297
|
+
run.offsetBytes + stride,
|
|
298
|
+
);
|
|
299
|
+
drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, run.count - 1);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
setDivisor(cache.a_start, 0);
|
|
304
|
+
setDivisor(cache.a_end, 0);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
destroy(chart: SeriesChart): void {
|
|
308
|
+
const gl = chart._glManager?.gl;
|
|
309
|
+
if (gl) {
|
|
310
|
+
this.invalidateBuffers(chart);
|
|
311
|
+
const cache = this._program;
|
|
312
|
+
if (cache) {
|
|
313
|
+
gl.deleteBuffer(cache.cornerBuffer);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
this._program = null;
|
|
318
|
+
this._buffers = null;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
import type { WebGLContextManager } from "../../../webgl/context-manager";
|
|
14
|
+
import type { SeriesChart } from "../series";
|
|
15
|
+
import { compileProgram } from "../../../webgl/program-cache";
|
|
16
|
+
import scatterVert from "../../../shaders/y-scatter.vert.glsl";
|
|
17
|
+
import scatterFrag from "../../../shaders/y-scatter.frag.glsl";
|
|
18
|
+
|
|
19
|
+
type GL = WebGL2RenderingContext | WebGLRenderingContext;
|
|
20
|
+
|
|
21
|
+
interface ScatterProgramCache {
|
|
22
|
+
program: WebGLProgram;
|
|
23
|
+
posLeftBuffer: WebGLBuffer;
|
|
24
|
+
posRightBuffer: WebGLBuffer;
|
|
25
|
+
colorLeftBuffer: WebGLBuffer;
|
|
26
|
+
colorRightBuffer: WebGLBuffer;
|
|
27
|
+
u_projection: WebGLUniformLocation | null;
|
|
28
|
+
u_point_size: WebGLUniformLocation | null;
|
|
29
|
+
a_position: number;
|
|
30
|
+
a_color: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Persistent scatter glyph state — left/right axis position + color
|
|
35
|
+
* buffers built once at data load. Pan/zoom redraws rebind without
|
|
36
|
+
* uploading.
|
|
37
|
+
*/
|
|
38
|
+
interface ScatterBuffers {
|
|
39
|
+
leftCount: number;
|
|
40
|
+
rightCount: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Reusable Float32 scratch for point assembly. Two buckets (positions
|
|
45
|
+
* and colors) packed into one buffer; sized lazily.
|
|
46
|
+
*/
|
|
47
|
+
let _posScratch: Float32Array = new Float32Array(0);
|
|
48
|
+
let _colScratch: Float32Array = new Float32Array(0);
|
|
49
|
+
|
|
50
|
+
function ensureScratch(n: number): void {
|
|
51
|
+
if (_posScratch.length < n * 2) {
|
|
52
|
+
_posScratch = new Float32Array(Math.max(n * 2, _posScratch.length * 2));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (_colScratch.length < n * 3) {
|
|
56
|
+
_colScratch = new Float32Array(Math.max(n * 3, _colScratch.length * 2));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Scatter glyph for {@link SeriesChart}. Owns the program + per-axis
|
|
62
|
+
* (position, color) GPU buffers. Single program/buffer set; left and
|
|
63
|
+
* right axes are merged into shared buffers with sub-ranges.
|
|
64
|
+
*/
|
|
65
|
+
export class ScatterGlyph {
|
|
66
|
+
private _program: ScatterProgramCache | null = null;
|
|
67
|
+
private _buffers: ScatterBuffers | null = null;
|
|
68
|
+
|
|
69
|
+
private ensureProgram(glManager: WebGLContextManager): ScatterProgramCache {
|
|
70
|
+
if (this._program) {
|
|
71
|
+
return this._program;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const gl = glManager.gl;
|
|
75
|
+
const partial = compileProgram<
|
|
76
|
+
Omit<
|
|
77
|
+
ScatterProgramCache,
|
|
78
|
+
| "posLeftBuffer"
|
|
79
|
+
| "posRightBuffer"
|
|
80
|
+
| "colorLeftBuffer"
|
|
81
|
+
| "colorRightBuffer"
|
|
82
|
+
>
|
|
83
|
+
>(
|
|
84
|
+
glManager,
|
|
85
|
+
"bar-scatter",
|
|
86
|
+
scatterVert,
|
|
87
|
+
scatterFrag,
|
|
88
|
+
["u_projection", "u_point_size"],
|
|
89
|
+
["a_position", "a_color"],
|
|
90
|
+
);
|
|
91
|
+
this._program = {
|
|
92
|
+
...partial,
|
|
93
|
+
posLeftBuffer: gl.createBuffer()!,
|
|
94
|
+
posRightBuffer: gl.createBuffer()!,
|
|
95
|
+
colorLeftBuffer: gl.createBuffer()!,
|
|
96
|
+
colorRightBuffer: gl.createBuffer()!,
|
|
97
|
+
};
|
|
98
|
+
return this._program;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Drop persistent scatter buffer state. The underlying GL buffer
|
|
103
|
+
* objects on `_program` are reused (owned by the program cache,
|
|
104
|
+
* not the per-build buffer view).
|
|
105
|
+
*/
|
|
106
|
+
invalidateBuffers(_chart: SeriesChart): void {
|
|
107
|
+
this._buffers = null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Build merged per-axis (position, color) buffers for every visible
|
|
112
|
+
* scatter series and upload them. Hidden series are excluded — call
|
|
113
|
+
* this from data-load and from the legend-toggle path so the GPU
|
|
114
|
+
* buffers always reflect the current visible mask.
|
|
115
|
+
*/
|
|
116
|
+
rebuildBuffers(chart: SeriesChart, glManager: WebGLContextManager): void {
|
|
117
|
+
const scatterSeries = chart._scatterSeries;
|
|
118
|
+
if (scatterSeries.length === 0) {
|
|
119
|
+
this._buffers = null;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const N = chart._numCategories;
|
|
124
|
+
const S = chart._series.length;
|
|
125
|
+
if (N === 0 || S === 0) {
|
|
126
|
+
this._buffers = null;
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const cache = this.ensureProgram(glManager);
|
|
131
|
+
const gl = glManager.gl;
|
|
132
|
+
|
|
133
|
+
const samples = chart._samples;
|
|
134
|
+
const valid = chart._sampleValid;
|
|
135
|
+
const positions = chart._categoryPositions;
|
|
136
|
+
const xOrigin = chart._categoryOrigin;
|
|
137
|
+
const hidden = chart._hiddenSeries;
|
|
138
|
+
|
|
139
|
+
// Two-pass: first count to size scratch, then fill. Avoids a
|
|
140
|
+
// number[] growth path while still accommodating both axes in a
|
|
141
|
+
// single pair of buffers.
|
|
142
|
+
let leftCount = 0;
|
|
143
|
+
let rightCount = 0;
|
|
144
|
+
for (const s of scatterSeries) {
|
|
145
|
+
if (hidden.has(s.seriesId)) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
for (let c = 0; c < N; c++) {
|
|
150
|
+
const idx = c * S + s.seriesId;
|
|
151
|
+
if (!((valid[idx >> 3] >> (idx & 7)) & 1)) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (s.axis === 1) {
|
|
156
|
+
rightCount++;
|
|
157
|
+
} else {
|
|
158
|
+
leftCount++;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const total = leftCount + rightCount;
|
|
164
|
+
if (total === 0) {
|
|
165
|
+
this._buffers = null;
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
ensureScratch(total);
|
|
170
|
+
|
|
171
|
+
// Fill left bucket from `[0, leftCount)`, right bucket from
|
|
172
|
+
// `[leftCount, total)` — single typed-array allocation each.
|
|
173
|
+
let leftWrite = 0;
|
|
174
|
+
let rightWrite = leftCount;
|
|
175
|
+
for (const s of scatterSeries) {
|
|
176
|
+
if (hidden.has(s.seriesId)) {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const r = s.color[0];
|
|
181
|
+
const g = s.color[1];
|
|
182
|
+
const b = s.color[2];
|
|
183
|
+
for (let c = 0; c < N; c++) {
|
|
184
|
+
const idx = c * S + s.seriesId;
|
|
185
|
+
if (!((valid[idx >> 3] >> (idx & 7)) & 1)) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const x = positions ? positions[c] - xOrigin : c;
|
|
190
|
+
const v = samples[idx];
|
|
191
|
+
if (s.axis === 1) {
|
|
192
|
+
_posScratch[rightWrite * 2] = x;
|
|
193
|
+
_posScratch[rightWrite * 2 + 1] = v;
|
|
194
|
+
_colScratch[rightWrite * 3] = r;
|
|
195
|
+
_colScratch[rightWrite * 3 + 1] = g;
|
|
196
|
+
_colScratch[rightWrite * 3 + 2] = b;
|
|
197
|
+
rightWrite++;
|
|
198
|
+
} else {
|
|
199
|
+
_posScratch[leftWrite * 2] = x;
|
|
200
|
+
_posScratch[leftWrite * 2 + 1] = v;
|
|
201
|
+
_colScratch[leftWrite * 3] = r;
|
|
202
|
+
_colScratch[leftWrite * 3 + 1] = g;
|
|
203
|
+
_colScratch[leftWrite * 3 + 2] = b;
|
|
204
|
+
leftWrite++;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (leftCount > 0) {
|
|
210
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, cache.posLeftBuffer);
|
|
211
|
+
gl.bufferData(
|
|
212
|
+
gl.ARRAY_BUFFER,
|
|
213
|
+
_posScratch.subarray(0, leftCount * 2),
|
|
214
|
+
gl.STATIC_DRAW,
|
|
215
|
+
);
|
|
216
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, cache.colorLeftBuffer);
|
|
217
|
+
gl.bufferData(
|
|
218
|
+
gl.ARRAY_BUFFER,
|
|
219
|
+
_colScratch.subarray(0, leftCount * 3),
|
|
220
|
+
gl.STATIC_DRAW,
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (rightCount > 0) {
|
|
225
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, cache.posRightBuffer);
|
|
226
|
+
gl.bufferData(
|
|
227
|
+
gl.ARRAY_BUFFER,
|
|
228
|
+
_posScratch.subarray(leftCount * 2, total * 2),
|
|
229
|
+
gl.STATIC_DRAW,
|
|
230
|
+
);
|
|
231
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, cache.colorRightBuffer);
|
|
232
|
+
gl.bufferData(
|
|
233
|
+
gl.ARRAY_BUFFER,
|
|
234
|
+
_colScratch.subarray(leftCount * 3, total * 3),
|
|
235
|
+
gl.STATIC_DRAW,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
this._buffers = { leftCount, rightCount };
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Bind the persistent left/right buffers and issue up to two draw
|
|
244
|
+
* calls. No per-frame allocations or buffer uploads.
|
|
245
|
+
*/
|
|
246
|
+
draw(
|
|
247
|
+
chart: SeriesChart,
|
|
248
|
+
gl: GL,
|
|
249
|
+
glManager: WebGLContextManager,
|
|
250
|
+
projLeft: Float32Array,
|
|
251
|
+
projRight: Float32Array,
|
|
252
|
+
): void {
|
|
253
|
+
const buf = this._buffers;
|
|
254
|
+
const cache = this._program;
|
|
255
|
+
if (!buf || !cache) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (buf.leftCount === 0 && buf.rightCount === 0) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const dpr = glManager.dpr;
|
|
264
|
+
gl.useProgram(cache.program);
|
|
265
|
+
gl.uniform1f(
|
|
266
|
+
cache.u_point_size,
|
|
267
|
+
chart._pluginConfig.point_size_px * dpr,
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
drawBucket(
|
|
271
|
+
gl,
|
|
272
|
+
cache,
|
|
273
|
+
cache.posLeftBuffer,
|
|
274
|
+
cache.colorLeftBuffer,
|
|
275
|
+
buf.leftCount,
|
|
276
|
+
projLeft,
|
|
277
|
+
);
|
|
278
|
+
drawBucket(
|
|
279
|
+
gl,
|
|
280
|
+
cache,
|
|
281
|
+
cache.posRightBuffer,
|
|
282
|
+
cache.colorRightBuffer,
|
|
283
|
+
buf.rightCount,
|
|
284
|
+
projRight,
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
destroy(chart: SeriesChart): void {
|
|
289
|
+
const gl = chart._glManager?.gl;
|
|
290
|
+
if (gl) {
|
|
291
|
+
const cache = this._program;
|
|
292
|
+
if (cache) {
|
|
293
|
+
gl.deleteBuffer(cache.posLeftBuffer);
|
|
294
|
+
gl.deleteBuffer(cache.posRightBuffer);
|
|
295
|
+
gl.deleteBuffer(cache.colorLeftBuffer);
|
|
296
|
+
gl.deleteBuffer(cache.colorRightBuffer);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
this._program = null;
|
|
301
|
+
this._buffers = null;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function drawBucket(
|
|
306
|
+
gl: GL,
|
|
307
|
+
cache: ScatterProgramCache,
|
|
308
|
+
posBuf: WebGLBuffer,
|
|
309
|
+
colBuf: WebGLBuffer,
|
|
310
|
+
count: number,
|
|
311
|
+
proj: Float32Array,
|
|
312
|
+
): void {
|
|
313
|
+
if (count === 0) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
gl.uniformMatrix4fv(cache.u_projection, false, proj);
|
|
318
|
+
|
|
319
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, posBuf);
|
|
320
|
+
gl.enableVertexAttribArray(cache.a_position);
|
|
321
|
+
gl.vertexAttribPointer(cache.a_position, 2, gl.FLOAT, false, 0, 0);
|
|
322
|
+
|
|
323
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, colBuf);
|
|
324
|
+
gl.enableVertexAttribArray(cache.a_color);
|
|
325
|
+
gl.vertexAttribPointer(cache.a_color, 3, gl.FLOAT, false, 0, 0);
|
|
326
|
+
|
|
327
|
+
gl.drawArrays(gl.POINTS, 0, count);
|
|
328
|
+
}
|