@mui/x-charts-premium 9.1.0 → 9.2.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/BarChartPremium/BarChartPremium.d.mts +4 -1
- package/BarChartPremium/BarChartPremium.d.ts +4 -1
- package/BarChartPremium/BarChartPremium.js +21 -8
- package/BarChartPremium/BarChartPremium.mjs +22 -9
- package/BarChartPremium/BarPlotPremium.d.mts +37 -0
- package/BarChartPremium/BarPlotPremium.d.ts +37 -0
- package/BarChartPremium/BarPlotPremium.js +78 -0
- package/BarChartPremium/BarPlotPremium.mjs +72 -0
- package/BarChartPremium/RangeBar/useUtilityClasses.d.mts +1 -1
- package/BarChartPremium/RangeBar/useUtilityClasses.d.ts +1 -1
- package/BarChartPremium/index.d.mts +1 -0
- package/BarChartPremium/index.d.ts +1 -0
- package/BarChartPremium/index.js +12 -0
- package/BarChartPremium/index.mjs +1 -0
- package/BarChartPremium/useBarChartPremiumProps.d.mts +2 -1
- package/BarChartPremium/useBarChartPremiumProps.d.ts +2 -1
- package/BarChartPremium/useBarChartPremiumProps.js +39 -5
- package/BarChartPremium/useBarChartPremiumProps.mjs +39 -5
- package/BarChartPremium/webgl/BarWebGLPlot.d.mts +10 -0
- package/BarChartPremium/webgl/BarWebGLPlot.d.ts +10 -0
- package/BarChartPremium/webgl/BarWebGLPlot.js +81 -0
- package/BarChartPremium/webgl/BarWebGLPlot.mjs +75 -0
- package/BarChartPremium/webgl/BarWebGLProgram.d.mts +19 -0
- package/BarChartPremium/webgl/BarWebGLProgram.d.ts +19 -0
- package/BarChartPremium/webgl/BarWebGLProgram.js +107 -0
- package/BarChartPremium/webgl/BarWebGLProgram.mjs +100 -0
- package/BarChartPremium/webgl/shaders.d.mts +2 -0
- package/BarChartPremium/webgl/shaders.d.ts +2 -0
- package/BarChartPremium/webgl/shaders.js +69 -0
- package/BarChartPremium/webgl/shaders.mjs +63 -0
- package/BarChartPremium/webgl/useBarWebGLPlotData.d.mts +10 -0
- package/BarChartPremium/webgl/useBarWebGLPlotData.d.ts +10 -0
- package/BarChartPremium/webgl/useBarWebGLPlotData.js +160 -0
- package/BarChartPremium/webgl/useBarWebGLPlotData.mjs +154 -0
- package/CHANGELOG.md +103 -0
- package/ChartsDataProviderPremium/ChartsDataProviderPremium.js +2 -2
- package/ChartsDataProviderPremium/ChartsDataProviderPremium.mjs +2 -2
- package/ChartsRadialDataProviderPremium/ChartsRadialDataProviderPremium.js +9 -3
- package/ChartsRadialDataProviderPremium/ChartsRadialDataProviderPremium.mjs +9 -3
- package/RadialBarChart/RadialBarChart.d.mts +7 -0
- package/RadialBarChart/RadialBarChart.d.ts +7 -0
- package/RadialBarChart/RadialBarChart.js +15 -2
- package/RadialBarChart/RadialBarChart.mjs +15 -2
- package/RadialBarChart/RadialBarElement.js +15 -1
- package/RadialBarChart/RadialBarElement.mjs +15 -1
- package/RadialBarChart/radialBarClasses.d.mts +1 -1
- package/RadialBarChart/radialBarClasses.d.ts +1 -1
- package/RadialBarChart/seriesConfig/axisTooltipGetter.js +5 -2
- package/RadialBarChart/seriesConfig/axisTooltipGetter.mjs +5 -2
- package/RadialBarChart/seriesConfig/getItemAtPosition.d.mts +6 -0
- package/RadialBarChart/seriesConfig/getItemAtPosition.d.ts +6 -0
- package/RadialBarChart/seriesConfig/getItemAtPosition.js +69 -0
- package/RadialBarChart/seriesConfig/getItemAtPosition.mjs +63 -0
- package/RadialBarChart/seriesConfig/index.js +2 -1
- package/RadialBarChart/seriesConfig/index.mjs +2 -1
- package/RadialBarChart/useRadialBarChartProps.d.mts +2 -0
- package/RadialBarChart/useRadialBarChartProps.d.ts +2 -0
- package/RadialBarChart/useRadialBarChartProps.js +10 -2
- package/RadialBarChart/useRadialBarChartProps.mjs +10 -2
- package/RadialLineChart/RadialLineChart.js +4 -2
- package/RadialLineChart/RadialLineChart.mjs +4 -2
- package/RadialLineChart/RadialLineChart.plugins.d.mts +1 -1
- package/RadialLineChart/RadialLineChart.plugins.d.ts +1 -1
- package/RadialLineChart/RadialLineChart.plugins.js +1 -1
- package/RadialLineChart/RadialLineChart.plugins.mjs +1 -1
- package/RadialLineChart/seriesConfig/getItemAtPosition.js +3 -3
- package/RadialLineChart/seriesConfig/getItemAtPosition.mjs +4 -4
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +125 -125
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface BarWebGLPlotProps {
|
|
3
|
+
borderRadius?: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* @ignore - Internal component used for rendering the bar plot using WebGL. Not exported from the package.
|
|
7
|
+
*/
|
|
8
|
+
export declare function BarWebGLPlot({
|
|
9
|
+
borderRadius
|
|
10
|
+
}: BarWebGLPlotProps): React.JSX.Element | null;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface BarWebGLPlotProps {
|
|
3
|
+
borderRadius?: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* @ignore - Internal component used for rendering the bar plot using WebGL. Not exported from the package.
|
|
7
|
+
*/
|
|
8
|
+
export declare function BarWebGLPlot({
|
|
9
|
+
borderRadius
|
|
10
|
+
}: BarWebGLPlotProps): React.JSX.Element | null;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
|
|
4
|
+
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.BarWebGLPlot = BarWebGLPlot;
|
|
9
|
+
var React = _interopRequireWildcard(require("react"));
|
|
10
|
+
var _hooks = require("@mui/x-charts/hooks");
|
|
11
|
+
var _internals = require("@mui/x-charts/internals");
|
|
12
|
+
var _ChartsWebGLContext = require("../../ChartsWebGLLayer/ChartsWebGLContext");
|
|
13
|
+
var _BarWebGLProgram = require("./BarWebGLProgram");
|
|
14
|
+
var _useBarWebGLPlotData = require("./useBarWebGLPlotData");
|
|
15
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
16
|
+
/**
|
|
17
|
+
* @ignore - Internal component used for rendering the bar plot using WebGL. Not exported from the package.
|
|
18
|
+
*/
|
|
19
|
+
function BarWebGLPlot({
|
|
20
|
+
borderRadius = 0
|
|
21
|
+
}) {
|
|
22
|
+
const layer = (0, _ChartsWebGLContext.useWebGLLayer)();
|
|
23
|
+
const drawingArea = (0, _hooks.useDrawingArea)();
|
|
24
|
+
const {
|
|
25
|
+
xAxis: xAxes
|
|
26
|
+
} = (0, _hooks.useXAxes)();
|
|
27
|
+
const {
|
|
28
|
+
yAxis: yAxes
|
|
29
|
+
} = (0, _hooks.useYAxes)();
|
|
30
|
+
const {
|
|
31
|
+
completedData
|
|
32
|
+
} = (0, _internals.useBarPlotData)(drawingArea, xAxes, yAxes);
|
|
33
|
+
if (!layer) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(BarWebGLPlotImpl, {
|
|
37
|
+
gl: layer.gl,
|
|
38
|
+
registerDraw: layer.registerDraw,
|
|
39
|
+
requestRender: layer.requestRender,
|
|
40
|
+
borderRadius: borderRadius,
|
|
41
|
+
completedData: completedData
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function BarWebGLPlotImpl(props) {
|
|
45
|
+
const {
|
|
46
|
+
gl,
|
|
47
|
+
registerDraw,
|
|
48
|
+
requestRender,
|
|
49
|
+
borderRadius,
|
|
50
|
+
completedData
|
|
51
|
+
} = props;
|
|
52
|
+
const drawingArea = (0, _hooks.useDrawingArea)();
|
|
53
|
+
const plotData = (0, _useBarWebGLPlotData.useBarWebGLPlotData)(drawingArea, completedData, borderRadius);
|
|
54
|
+
const [program, setProgram] = React.useState(null);
|
|
55
|
+
const drawRef = React.useRef(null);
|
|
56
|
+
React.useEffect(() => {
|
|
57
|
+
const prog = new _BarWebGLProgram.BarWebGLProgram(gl);
|
|
58
|
+
setProgram(prog);
|
|
59
|
+
return () => {
|
|
60
|
+
prog.dispose();
|
|
61
|
+
};
|
|
62
|
+
}, [gl]);
|
|
63
|
+
React.useEffect(() => {
|
|
64
|
+
drawRef.current = () => {
|
|
65
|
+
program?.render(plotData.count);
|
|
66
|
+
};
|
|
67
|
+
}, [program, plotData.count]);
|
|
68
|
+
React.useEffect(() => {
|
|
69
|
+
const unregister = registerDraw(drawRef);
|
|
70
|
+
return unregister;
|
|
71
|
+
}, [registerDraw]);
|
|
72
|
+
React.useEffect(() => {
|
|
73
|
+
program?.setResolution(drawingArea.width, drawingArea.height);
|
|
74
|
+
requestRender();
|
|
75
|
+
}, [drawingArea.width, drawingArea.height, program, requestRender]);
|
|
76
|
+
React.useEffect(() => {
|
|
77
|
+
program?.plot(plotData);
|
|
78
|
+
requestRender();
|
|
79
|
+
}, [program, plotData, requestRender]);
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { useDrawingArea, useXAxes, useYAxes } from '@mui/x-charts/hooks';
|
|
5
|
+
import { useBarPlotData } from '@mui/x-charts/internals';
|
|
6
|
+
import { useWebGLLayer } from "../../ChartsWebGLLayer/ChartsWebGLContext.mjs";
|
|
7
|
+
import { BarWebGLProgram } from "./BarWebGLProgram.mjs";
|
|
8
|
+
import { useBarWebGLPlotData } from "./useBarWebGLPlotData.mjs";
|
|
9
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
|
+
/**
|
|
11
|
+
* @ignore - Internal component used for rendering the bar plot using WebGL. Not exported from the package.
|
|
12
|
+
*/
|
|
13
|
+
export function BarWebGLPlot({
|
|
14
|
+
borderRadius = 0
|
|
15
|
+
}) {
|
|
16
|
+
const layer = useWebGLLayer();
|
|
17
|
+
const drawingArea = useDrawingArea();
|
|
18
|
+
const {
|
|
19
|
+
xAxis: xAxes
|
|
20
|
+
} = useXAxes();
|
|
21
|
+
const {
|
|
22
|
+
yAxis: yAxes
|
|
23
|
+
} = useYAxes();
|
|
24
|
+
const {
|
|
25
|
+
completedData
|
|
26
|
+
} = useBarPlotData(drawingArea, xAxes, yAxes);
|
|
27
|
+
if (!layer) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return /*#__PURE__*/_jsx(BarWebGLPlotImpl, {
|
|
31
|
+
gl: layer.gl,
|
|
32
|
+
registerDraw: layer.registerDraw,
|
|
33
|
+
requestRender: layer.requestRender,
|
|
34
|
+
borderRadius: borderRadius,
|
|
35
|
+
completedData: completedData
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function BarWebGLPlotImpl(props) {
|
|
39
|
+
const {
|
|
40
|
+
gl,
|
|
41
|
+
registerDraw,
|
|
42
|
+
requestRender,
|
|
43
|
+
borderRadius,
|
|
44
|
+
completedData
|
|
45
|
+
} = props;
|
|
46
|
+
const drawingArea = useDrawingArea();
|
|
47
|
+
const plotData = useBarWebGLPlotData(drawingArea, completedData, borderRadius);
|
|
48
|
+
const [program, setProgram] = React.useState(null);
|
|
49
|
+
const drawRef = React.useRef(null);
|
|
50
|
+
React.useEffect(() => {
|
|
51
|
+
const prog = new BarWebGLProgram(gl);
|
|
52
|
+
setProgram(prog);
|
|
53
|
+
return () => {
|
|
54
|
+
prog.dispose();
|
|
55
|
+
};
|
|
56
|
+
}, [gl]);
|
|
57
|
+
React.useEffect(() => {
|
|
58
|
+
drawRef.current = () => {
|
|
59
|
+
program?.render(plotData.count);
|
|
60
|
+
};
|
|
61
|
+
}, [program, plotData.count]);
|
|
62
|
+
React.useEffect(() => {
|
|
63
|
+
const unregister = registerDraw(drawRef);
|
|
64
|
+
return unregister;
|
|
65
|
+
}, [registerDraw]);
|
|
66
|
+
React.useEffect(() => {
|
|
67
|
+
program?.setResolution(drawingArea.width, drawingArea.height);
|
|
68
|
+
requestRender();
|
|
69
|
+
}, [drawingArea.width, drawingArea.height, program, requestRender]);
|
|
70
|
+
React.useEffect(() => {
|
|
71
|
+
program?.plot(plotData);
|
|
72
|
+
requestRender();
|
|
73
|
+
}, [program, plotData, requestRender]);
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type BarWebGLPlotData } from "./useBarWebGLPlotData.mjs";
|
|
2
|
+
export declare class BarWebGLProgram {
|
|
3
|
+
private gl;
|
|
4
|
+
private readonly shaders;
|
|
5
|
+
private readonly program;
|
|
6
|
+
private readonly vao;
|
|
7
|
+
private readonly quadBuffer;
|
|
8
|
+
private readonly aPositionLocation;
|
|
9
|
+
private readonly centersBuffer;
|
|
10
|
+
private readonly halfSizesBuffer;
|
|
11
|
+
private readonly colorsBuffer;
|
|
12
|
+
private readonly cornerRadiiBuffer;
|
|
13
|
+
private readonly uResolution;
|
|
14
|
+
constructor(gl: WebGL2RenderingContext);
|
|
15
|
+
setResolution(width: number, height: number): void;
|
|
16
|
+
plot(plotData: BarWebGLPlotData): void;
|
|
17
|
+
render(count: number): void;
|
|
18
|
+
dispose(): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type BarWebGLPlotData } from "./useBarWebGLPlotData.js";
|
|
2
|
+
export declare class BarWebGLProgram {
|
|
3
|
+
private gl;
|
|
4
|
+
private readonly shaders;
|
|
5
|
+
private readonly program;
|
|
6
|
+
private readonly vao;
|
|
7
|
+
private readonly quadBuffer;
|
|
8
|
+
private readonly aPositionLocation;
|
|
9
|
+
private readonly centersBuffer;
|
|
10
|
+
private readonly halfSizesBuffer;
|
|
11
|
+
private readonly colorsBuffer;
|
|
12
|
+
private readonly cornerRadiiBuffer;
|
|
13
|
+
private readonly uResolution;
|
|
14
|
+
constructor(gl: WebGL2RenderingContext);
|
|
15
|
+
setResolution(width: number, height: number): void;
|
|
16
|
+
plot(plotData: BarWebGLPlotData): void;
|
|
17
|
+
render(count: number): void;
|
|
18
|
+
dispose(): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.BarWebGLProgram = void 0;
|
|
7
|
+
var _utils = require("../../utils/webgl/utils");
|
|
8
|
+
var _shaders = require("./shaders");
|
|
9
|
+
class BarWebGLProgram {
|
|
10
|
+
shaders = [];
|
|
11
|
+
constructor(gl) {
|
|
12
|
+
this.gl = gl;
|
|
13
|
+
gl.enable(gl.BLEND);
|
|
14
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
15
|
+
this.program = gl.createProgram();
|
|
16
|
+
const vertexShader = (0, _utils.compileShader)(gl, _shaders.barVertexShaderSource, gl.VERTEX_SHADER);
|
|
17
|
+
const fragmentShader = (0, _utils.compileShader)(gl, _shaders.barFragmentShaderSource, gl.FRAGMENT_SHADER);
|
|
18
|
+
gl.attachShader(this.program, vertexShader);
|
|
19
|
+
gl.attachShader(this.program, fragmentShader);
|
|
20
|
+
gl.linkProgram(this.program);
|
|
21
|
+
this.shaders.push(vertexShader, fragmentShader);
|
|
22
|
+
if (process.env.NODE_ENV !== 'production' && !gl.getProgramParameter(this.program, gl.LINK_STATUS)) {
|
|
23
|
+
console.error(`Program linking failed: ${gl.getProgramInfoLog(this.program)}`);
|
|
24
|
+
console.error(`Vertex info-log: ${gl.getShaderInfoLog(vertexShader)}`);
|
|
25
|
+
console.error(`Fragment info-log: ${gl.getShaderInfoLog(fragmentShader)}`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Cache locations once.
|
|
29
|
+
this.uResolution = gl.getUniformLocation(this.program, 'u_resolution');
|
|
30
|
+
this.aPositionLocation = gl.getAttribLocation(this.program, 'a_position');
|
|
31
|
+
this.quadBuffer = (0, _utils.uploadQuadBuffer)(gl);
|
|
32
|
+
this.vao = gl.createVertexArray();
|
|
33
|
+
this.centersBuffer = createInstancedBuffer(gl, this.program, 'a_center', 2, gl.FLOAT, false);
|
|
34
|
+
this.halfSizesBuffer = createInstancedBuffer(gl, this.program, 'a_halfSize', 2, gl.FLOAT, false);
|
|
35
|
+
// Colors come in as Uint8 [0, 255]; normalized=true makes the GPU read them back as vec4 in [0, 1].
|
|
36
|
+
this.colorsBuffer = createInstancedBuffer(gl, this.program, 'a_color', 4, gl.UNSIGNED_BYTE, true);
|
|
37
|
+
this.cornerRadiiBuffer = createInstancedBuffer(gl, this.program, 'a_cornerRadii', 4, gl.FLOAT, false);
|
|
38
|
+
}
|
|
39
|
+
setResolution(width, height) {
|
|
40
|
+
this.gl.useProgram(this.program);
|
|
41
|
+
this.gl.uniform2f(this.uResolution, width, height);
|
|
42
|
+
}
|
|
43
|
+
plot(plotData) {
|
|
44
|
+
const gl = this.gl;
|
|
45
|
+
gl.useProgram(this.program);
|
|
46
|
+
gl.bindVertexArray(this.vao);
|
|
47
|
+
|
|
48
|
+
// Bind quad buffer + a_position (per-vertex).
|
|
49
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);
|
|
50
|
+
gl.enableVertexAttribArray(this.aPositionLocation);
|
|
51
|
+
gl.vertexAttribPointer(this.aPositionLocation, 2, gl.FLOAT, false, 0, 0);
|
|
52
|
+
uploadAndBindInstanced(gl, this.centersBuffer, plotData.centers);
|
|
53
|
+
uploadAndBindInstanced(gl, this.halfSizesBuffer, plotData.halfSizes);
|
|
54
|
+
uploadAndBindInstanced(gl, this.colorsBuffer, plotData.colors);
|
|
55
|
+
uploadAndBindInstanced(gl, this.cornerRadiiBuffer, plotData.cornerRadii);
|
|
56
|
+
gl.bindVertexArray(null);
|
|
57
|
+
(0, _utils.logWebGLErrors)(gl);
|
|
58
|
+
}
|
|
59
|
+
render(count) {
|
|
60
|
+
if (count === 0) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const gl = this.gl;
|
|
64
|
+
gl.useProgram(this.program);
|
|
65
|
+
gl.bindVertexArray(this.vao);
|
|
66
|
+
gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, count);
|
|
67
|
+
gl.bindVertexArray(null);
|
|
68
|
+
}
|
|
69
|
+
dispose() {
|
|
70
|
+
const gl = this.gl;
|
|
71
|
+
gl.deleteProgram(this.program);
|
|
72
|
+
gl.deleteVertexArray(this.vao);
|
|
73
|
+
gl.deleteBuffer(this.quadBuffer);
|
|
74
|
+
gl.deleteBuffer(this.centersBuffer.buffer);
|
|
75
|
+
gl.deleteBuffer(this.halfSizesBuffer.buffer);
|
|
76
|
+
gl.deleteBuffer(this.colorsBuffer.buffer);
|
|
77
|
+
gl.deleteBuffer(this.cornerRadiiBuffer.buffer);
|
|
78
|
+
this.shaders.forEach(shader => gl.deleteShader(shader));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.BarWebGLProgram = BarWebGLProgram;
|
|
82
|
+
function createInstancedBuffer(gl, program, name, size, glType, normalized) {
|
|
83
|
+
return {
|
|
84
|
+
buffer: gl.createBuffer(),
|
|
85
|
+
capacityBytes: 0,
|
|
86
|
+
lastUploaded: null,
|
|
87
|
+
location: gl.getAttribLocation(program, name),
|
|
88
|
+
size,
|
|
89
|
+
glType,
|
|
90
|
+
normalized
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function uploadAndBindInstanced(gl, target, data) {
|
|
94
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, target.buffer);
|
|
95
|
+
if (target.lastUploaded !== data) {
|
|
96
|
+
if (data.byteLength <= target.capacityBytes) {
|
|
97
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, 0, data);
|
|
98
|
+
} else {
|
|
99
|
+
gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
|
|
100
|
+
target.capacityBytes = data.byteLength;
|
|
101
|
+
}
|
|
102
|
+
target.lastUploaded = data;
|
|
103
|
+
}
|
|
104
|
+
gl.enableVertexAttribArray(target.location);
|
|
105
|
+
gl.vertexAttribPointer(target.location, target.size, target.glType, target.normalized, 0, 0);
|
|
106
|
+
gl.vertexAttribDivisor(target.location, 1);
|
|
107
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { compileShader, logWebGLErrors, uploadQuadBuffer } from "../../utils/webgl/utils.mjs";
|
|
2
|
+
import { barFragmentShaderSource, barVertexShaderSource } from "./shaders.mjs";
|
|
3
|
+
export class BarWebGLProgram {
|
|
4
|
+
shaders = [];
|
|
5
|
+
constructor(gl) {
|
|
6
|
+
this.gl = gl;
|
|
7
|
+
gl.enable(gl.BLEND);
|
|
8
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
9
|
+
this.program = gl.createProgram();
|
|
10
|
+
const vertexShader = compileShader(gl, barVertexShaderSource, gl.VERTEX_SHADER);
|
|
11
|
+
const fragmentShader = compileShader(gl, barFragmentShaderSource, gl.FRAGMENT_SHADER);
|
|
12
|
+
gl.attachShader(this.program, vertexShader);
|
|
13
|
+
gl.attachShader(this.program, fragmentShader);
|
|
14
|
+
gl.linkProgram(this.program);
|
|
15
|
+
this.shaders.push(vertexShader, fragmentShader);
|
|
16
|
+
if (process.env.NODE_ENV !== 'production' && !gl.getProgramParameter(this.program, gl.LINK_STATUS)) {
|
|
17
|
+
console.error(`Program linking failed: ${gl.getProgramInfoLog(this.program)}`);
|
|
18
|
+
console.error(`Vertex info-log: ${gl.getShaderInfoLog(vertexShader)}`);
|
|
19
|
+
console.error(`Fragment info-log: ${gl.getShaderInfoLog(fragmentShader)}`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Cache locations once.
|
|
23
|
+
this.uResolution = gl.getUniformLocation(this.program, 'u_resolution');
|
|
24
|
+
this.aPositionLocation = gl.getAttribLocation(this.program, 'a_position');
|
|
25
|
+
this.quadBuffer = uploadQuadBuffer(gl);
|
|
26
|
+
this.vao = gl.createVertexArray();
|
|
27
|
+
this.centersBuffer = createInstancedBuffer(gl, this.program, 'a_center', 2, gl.FLOAT, false);
|
|
28
|
+
this.halfSizesBuffer = createInstancedBuffer(gl, this.program, 'a_halfSize', 2, gl.FLOAT, false);
|
|
29
|
+
// Colors come in as Uint8 [0, 255]; normalized=true makes the GPU read them back as vec4 in [0, 1].
|
|
30
|
+
this.colorsBuffer = createInstancedBuffer(gl, this.program, 'a_color', 4, gl.UNSIGNED_BYTE, true);
|
|
31
|
+
this.cornerRadiiBuffer = createInstancedBuffer(gl, this.program, 'a_cornerRadii', 4, gl.FLOAT, false);
|
|
32
|
+
}
|
|
33
|
+
setResolution(width, height) {
|
|
34
|
+
this.gl.useProgram(this.program);
|
|
35
|
+
this.gl.uniform2f(this.uResolution, width, height);
|
|
36
|
+
}
|
|
37
|
+
plot(plotData) {
|
|
38
|
+
const gl = this.gl;
|
|
39
|
+
gl.useProgram(this.program);
|
|
40
|
+
gl.bindVertexArray(this.vao);
|
|
41
|
+
|
|
42
|
+
// Bind quad buffer + a_position (per-vertex).
|
|
43
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);
|
|
44
|
+
gl.enableVertexAttribArray(this.aPositionLocation);
|
|
45
|
+
gl.vertexAttribPointer(this.aPositionLocation, 2, gl.FLOAT, false, 0, 0);
|
|
46
|
+
uploadAndBindInstanced(gl, this.centersBuffer, plotData.centers);
|
|
47
|
+
uploadAndBindInstanced(gl, this.halfSizesBuffer, plotData.halfSizes);
|
|
48
|
+
uploadAndBindInstanced(gl, this.colorsBuffer, plotData.colors);
|
|
49
|
+
uploadAndBindInstanced(gl, this.cornerRadiiBuffer, plotData.cornerRadii);
|
|
50
|
+
gl.bindVertexArray(null);
|
|
51
|
+
logWebGLErrors(gl);
|
|
52
|
+
}
|
|
53
|
+
render(count) {
|
|
54
|
+
if (count === 0) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const gl = this.gl;
|
|
58
|
+
gl.useProgram(this.program);
|
|
59
|
+
gl.bindVertexArray(this.vao);
|
|
60
|
+
gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, count);
|
|
61
|
+
gl.bindVertexArray(null);
|
|
62
|
+
}
|
|
63
|
+
dispose() {
|
|
64
|
+
const gl = this.gl;
|
|
65
|
+
gl.deleteProgram(this.program);
|
|
66
|
+
gl.deleteVertexArray(this.vao);
|
|
67
|
+
gl.deleteBuffer(this.quadBuffer);
|
|
68
|
+
gl.deleteBuffer(this.centersBuffer.buffer);
|
|
69
|
+
gl.deleteBuffer(this.halfSizesBuffer.buffer);
|
|
70
|
+
gl.deleteBuffer(this.colorsBuffer.buffer);
|
|
71
|
+
gl.deleteBuffer(this.cornerRadiiBuffer.buffer);
|
|
72
|
+
this.shaders.forEach(shader => gl.deleteShader(shader));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function createInstancedBuffer(gl, program, name, size, glType, normalized) {
|
|
76
|
+
return {
|
|
77
|
+
buffer: gl.createBuffer(),
|
|
78
|
+
capacityBytes: 0,
|
|
79
|
+
lastUploaded: null,
|
|
80
|
+
location: gl.getAttribLocation(program, name),
|
|
81
|
+
size,
|
|
82
|
+
glType,
|
|
83
|
+
normalized
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function uploadAndBindInstanced(gl, target, data) {
|
|
87
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, target.buffer);
|
|
88
|
+
if (target.lastUploaded !== data) {
|
|
89
|
+
if (data.byteLength <= target.capacityBytes) {
|
|
90
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, 0, data);
|
|
91
|
+
} else {
|
|
92
|
+
gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
|
|
93
|
+
target.capacityBytes = data.byteLength;
|
|
94
|
+
}
|
|
95
|
+
target.lastUploaded = data;
|
|
96
|
+
}
|
|
97
|
+
gl.enableVertexAttribArray(target.location);
|
|
98
|
+
gl.vertexAttribPointer(target.location, target.size, target.glType, target.normalized, 0, 0);
|
|
99
|
+
gl.vertexAttribDivisor(target.location, 1);
|
|
100
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const barVertexShaderSource = "\n precision mediump float;\n\n attribute vec2 a_position;\n attribute vec2 a_center;\n attribute vec2 a_halfSize;\n attribute vec4 a_color;\n attribute vec4 a_cornerRadii;\n\n varying vec4 v_color;\n varying vec2 v_pos;\n varying vec2 v_halfSize;\n varying vec4 v_cornerRadii;\n\n uniform vec2 u_resolution;\n\n void main() {\n vec2 position = a_center + a_position * a_halfSize;\n vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0;\n gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);\n\n v_color = a_color;\n v_pos = a_position * a_halfSize;\n v_halfSize = a_halfSize;\n v_cornerRadii = a_cornerRadii;\n }\n ";
|
|
2
|
+
export declare const barFragmentShaderSource = "\n precision mediump float;\n\n varying vec4 v_color;\n varying vec2 v_pos;\n varying vec2 v_halfSize;\n varying vec4 v_cornerRadii;\n\n float roundedBoxSDF(vec2 pos, vec2 halfSize, vec4 r) {\n float radius;\n if (pos.x < 0.0) {\n radius = pos.y < 0.0 ? r.x : r.w;\n } else {\n radius = pos.y < 0.0 ? r.y : r.z;\n }\n\n vec2 q = abs(pos) - halfSize + radius;\n return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius;\n }\n\n void main() {\n float dist = roundedBoxSDF(v_pos, v_halfSize, v_cornerRadii);\n // Anti-alias only outside the SDF (dist >= 0). Starting smoothstep at 0\n // keeps interior pixels at full color instead of fading them.\n float alpha = 1.0 - smoothstep(0.0, 0.5, dist);\n\n gl_FragColor = vec4(v_color.rgb, v_color.a * alpha);\n }\n ";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const barVertexShaderSource = "\n precision mediump float;\n\n attribute vec2 a_position;\n attribute vec2 a_center;\n attribute vec2 a_halfSize;\n attribute vec4 a_color;\n attribute vec4 a_cornerRadii;\n\n varying vec4 v_color;\n varying vec2 v_pos;\n varying vec2 v_halfSize;\n varying vec4 v_cornerRadii;\n\n uniform vec2 u_resolution;\n\n void main() {\n vec2 position = a_center + a_position * a_halfSize;\n vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0;\n gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);\n\n v_color = a_color;\n v_pos = a_position * a_halfSize;\n v_halfSize = a_halfSize;\n v_cornerRadii = a_cornerRadii;\n }\n ";
|
|
2
|
+
export declare const barFragmentShaderSource = "\n precision mediump float;\n\n varying vec4 v_color;\n varying vec2 v_pos;\n varying vec2 v_halfSize;\n varying vec4 v_cornerRadii;\n\n float roundedBoxSDF(vec2 pos, vec2 halfSize, vec4 r) {\n float radius;\n if (pos.x < 0.0) {\n radius = pos.y < 0.0 ? r.x : r.w;\n } else {\n radius = pos.y < 0.0 ? r.y : r.z;\n }\n\n vec2 q = abs(pos) - halfSize + radius;\n return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius;\n }\n\n void main() {\n float dist = roundedBoxSDF(v_pos, v_halfSize, v_cornerRadii);\n // Anti-alias only outside the SDF (dist >= 0). Starting smoothstep at 0\n // keeps interior pixels at full color instead of fading them.\n float alpha = 1.0 - smoothstep(0.0, 0.5, dist);\n\n gl_FragColor = vec4(v_color.rgb, v_color.a * alpha);\n }\n ";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.barVertexShaderSource = exports.barFragmentShaderSource = void 0;
|
|
7
|
+
// language=Glsl
|
|
8
|
+
const barVertexShaderSource = exports.barVertexShaderSource = /* glsl */`
|
|
9
|
+
precision mediump float;
|
|
10
|
+
|
|
11
|
+
attribute vec2 a_position;
|
|
12
|
+
attribute vec2 a_center;
|
|
13
|
+
attribute vec2 a_halfSize;
|
|
14
|
+
attribute vec4 a_color;
|
|
15
|
+
attribute vec4 a_cornerRadii;
|
|
16
|
+
|
|
17
|
+
varying vec4 v_color;
|
|
18
|
+
varying vec2 v_pos;
|
|
19
|
+
varying vec2 v_halfSize;
|
|
20
|
+
varying vec4 v_cornerRadii;
|
|
21
|
+
|
|
22
|
+
uniform vec2 u_resolution;
|
|
23
|
+
|
|
24
|
+
void main() {
|
|
25
|
+
vec2 position = a_center + a_position * a_halfSize;
|
|
26
|
+
vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0;
|
|
27
|
+
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
|
|
28
|
+
|
|
29
|
+
v_color = a_color;
|
|
30
|
+
v_pos = a_position * a_halfSize;
|
|
31
|
+
v_halfSize = a_halfSize;
|
|
32
|
+
v_cornerRadii = a_cornerRadii;
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
// language=Glsl
|
|
37
|
+
// Per-corner radii ordering follows CSS: top-left, top-right, bottom-right, bottom-left.
|
|
38
|
+
// Screen-space conventions after the y-flip in the vertex stage:
|
|
39
|
+
// v_pos.y < 0 -> top, v_pos.y > 0 -> bottom
|
|
40
|
+
// v_pos.x < 0 -> left, v_pos.x > 0 -> right
|
|
41
|
+
const barFragmentShaderSource = exports.barFragmentShaderSource = /* glsl */`
|
|
42
|
+
precision mediump float;
|
|
43
|
+
|
|
44
|
+
varying vec4 v_color;
|
|
45
|
+
varying vec2 v_pos;
|
|
46
|
+
varying vec2 v_halfSize;
|
|
47
|
+
varying vec4 v_cornerRadii;
|
|
48
|
+
|
|
49
|
+
float roundedBoxSDF(vec2 pos, vec2 halfSize, vec4 r) {
|
|
50
|
+
float radius;
|
|
51
|
+
if (pos.x < 0.0) {
|
|
52
|
+
radius = pos.y < 0.0 ? r.x : r.w;
|
|
53
|
+
} else {
|
|
54
|
+
radius = pos.y < 0.0 ? r.y : r.z;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
vec2 q = abs(pos) - halfSize + radius;
|
|
58
|
+
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
void main() {
|
|
62
|
+
float dist = roundedBoxSDF(v_pos, v_halfSize, v_cornerRadii);
|
|
63
|
+
// Anti-alias only outside the SDF (dist >= 0). Starting smoothstep at 0
|
|
64
|
+
// keeps interior pixels at full color instead of fading them.
|
|
65
|
+
float alpha = 1.0 - smoothstep(0.0, 0.5, dist);
|
|
66
|
+
|
|
67
|
+
gl_FragColor = vec4(v_color.rgb, v_color.a * alpha);
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// language=Glsl
|
|
2
|
+
export const barVertexShaderSource = /* glsl */`
|
|
3
|
+
precision mediump float;
|
|
4
|
+
|
|
5
|
+
attribute vec2 a_position;
|
|
6
|
+
attribute vec2 a_center;
|
|
7
|
+
attribute vec2 a_halfSize;
|
|
8
|
+
attribute vec4 a_color;
|
|
9
|
+
attribute vec4 a_cornerRadii;
|
|
10
|
+
|
|
11
|
+
varying vec4 v_color;
|
|
12
|
+
varying vec2 v_pos;
|
|
13
|
+
varying vec2 v_halfSize;
|
|
14
|
+
varying vec4 v_cornerRadii;
|
|
15
|
+
|
|
16
|
+
uniform vec2 u_resolution;
|
|
17
|
+
|
|
18
|
+
void main() {
|
|
19
|
+
vec2 position = a_center + a_position * a_halfSize;
|
|
20
|
+
vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0;
|
|
21
|
+
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
|
|
22
|
+
|
|
23
|
+
v_color = a_color;
|
|
24
|
+
v_pos = a_position * a_halfSize;
|
|
25
|
+
v_halfSize = a_halfSize;
|
|
26
|
+
v_cornerRadii = a_cornerRadii;
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
// language=Glsl
|
|
31
|
+
// Per-corner radii ordering follows CSS: top-left, top-right, bottom-right, bottom-left.
|
|
32
|
+
// Screen-space conventions after the y-flip in the vertex stage:
|
|
33
|
+
// v_pos.y < 0 -> top, v_pos.y > 0 -> bottom
|
|
34
|
+
// v_pos.x < 0 -> left, v_pos.x > 0 -> right
|
|
35
|
+
export const barFragmentShaderSource = /* glsl */`
|
|
36
|
+
precision mediump float;
|
|
37
|
+
|
|
38
|
+
varying vec4 v_color;
|
|
39
|
+
varying vec2 v_pos;
|
|
40
|
+
varying vec2 v_halfSize;
|
|
41
|
+
varying vec4 v_cornerRadii;
|
|
42
|
+
|
|
43
|
+
float roundedBoxSDF(vec2 pos, vec2 halfSize, vec4 r) {
|
|
44
|
+
float radius;
|
|
45
|
+
if (pos.x < 0.0) {
|
|
46
|
+
radius = pos.y < 0.0 ? r.x : r.w;
|
|
47
|
+
} else {
|
|
48
|
+
radius = pos.y < 0.0 ? r.y : r.z;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
vec2 q = abs(pos) - halfSize + radius;
|
|
52
|
+
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
void main() {
|
|
56
|
+
float dist = roundedBoxSDF(v_pos, v_halfSize, v_cornerRadii);
|
|
57
|
+
// Anti-alias only outside the SDF (dist >= 0). Starting smoothstep at 0
|
|
58
|
+
// keeps interior pixels at full color instead of fading them.
|
|
59
|
+
float alpha = 1.0 - smoothstep(0.0, 0.5, dist);
|
|
60
|
+
|
|
61
|
+
gl_FragColor = vec4(v_color.rgb, v_color.a * alpha);
|
|
62
|
+
}
|
|
63
|
+
`;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ChartDrawingArea } from '@mui/x-charts/hooks';
|
|
2
|
+
import { type ProcessedBarSeriesData } from '@mui/x-charts/internals';
|
|
3
|
+
export interface BarWebGLPlotData {
|
|
4
|
+
centers: Float32Array;
|
|
5
|
+
halfSizes: Float32Array;
|
|
6
|
+
colors: Uint8Array;
|
|
7
|
+
cornerRadii: Float32Array;
|
|
8
|
+
count: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function useBarWebGLPlotData(drawingArea: ChartDrawingArea, completedData: ProcessedBarSeriesData[], borderRadius: number): BarWebGLPlotData;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ChartDrawingArea } from '@mui/x-charts/hooks';
|
|
2
|
+
import { type ProcessedBarSeriesData } from '@mui/x-charts/internals';
|
|
3
|
+
export interface BarWebGLPlotData {
|
|
4
|
+
centers: Float32Array;
|
|
5
|
+
halfSizes: Float32Array;
|
|
6
|
+
colors: Uint8Array;
|
|
7
|
+
cornerRadii: Float32Array;
|
|
8
|
+
count: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function useBarWebGLPlotData(drawingArea: ChartDrawingArea, completedData: ProcessedBarSeriesData[], borderRadius: number): BarWebGLPlotData;
|