diff --git a/CHANGELOG.md b/CHANGELOG.md
index e9d96c2..4f5048c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.13.0
+
+- Feat: expose `renderPointsAsSquares` and `disableAlphaBlending` to allow finer control over performance increasing settings ([#206](https://github.com/flekschas/regl-scatterplot/issues/206))
+
## 1.12.1
- Fix: destroy the encoding texture before recreating it
diff --git a/README.md b/README.md
index 73630c4..080dab4 100644
--- a/README.md
+++ b/README.md
@@ -823,6 +823,8 @@ can be read and written via [`scatterplot.get()`](#scatterplot.get) and [`scatte
| annotationHVLineLimit | number | `1000` | the extent of horizontal or vertical lines | `true` | `false` |
| antiAliasing | number | `0.5` | higher values result in more blurry points | `true` | `false` |
| pixelAligned | number | `false` | if true, points are aligned with the pixel grid | `true` | `false` |
+| renderPointsAsSquares | boolean | `false` | true of `performanceMode` is true. can only be set on init! | `true` | `false` |
+| disableAlphaBlending | boolean | `false` | true of `performanceMode` is true. can only be set on init! | `true` | `false` |
# Notes:
@@ -863,10 +865,12 @@ can be read and written via [`scatterplot.get()`](#scatterplot.get) and [`scatte
- If you need to draw more than 2 million points, you might want to set
`performanceMode` to `true` during the initialization to boost the
performance. In performance mode, points will be drawn as simple squares and
- color blending is disabled. This should allow you to draw up to 20 million
+ alpha blending is disabled. This should allow you to draw up to 20 million
points (or more depending on your hardware). Make sure to reduce the
`pointSize` as you render more and more points (e.g., `0.25` for 20 million
- works for me) to ensure good performance.
+ works for me) to ensure good performance. You can also enable squared points
+ and disable alpha blending individually via `renderPointsAsSquares` and
+ `disableAlphaBlending` respectively.
# colorBy, opacityBy, sizeBy:
diff --git a/src/index.js b/src/index.js
index b505567..5afddfb 100644
--- a/src/index.js
+++ b/src/index.js
@@ -310,6 +310,13 @@ const createScatterplot = (
spatialIndexUseWorker = DEFAULT_SPATIAL_INDEX_USE_WORKER,
} = initialProperties;
+ const renderPointsAsSquares = Boolean(
+ initialProperties.renderPointsAsSquares || performanceMode,
+ );
+ const disableAlphaBlending = Boolean(
+ initialProperties.disableAlphaBlending || performanceMode,
+ );
+
mouseMode = limit(MOUSE_MODES, MOUSE_MODE_PANZOOM)(mouseMode);
if (!renderer) {
@@ -1596,9 +1603,9 @@ const createScatterplot = (
let alpha =
((opacityByDensityFill * W * H) / (numPointsInView * p * p)) * min(1, s);
- // In performanceMode we use squares, otherwise we use circles, which only
- // take up (pi r^2) of the unit square
- alpha *= performanceMode ? 1 : 1 / (0.25 * Math.PI);
+ // Unless `renderPointsAsSquares` is true, we use circles, which only take
+ // up (pi r^2) of the unit square
+ alpha *= renderPointsAsSquares ? 1 : 1 / (0.25 * Math.PI);
// If the pixels shrink below the minimum permitted size, then we adjust the opacity instead
// and apply clamping of the point size in the vertex shader. Note that we add 0.5 since we
@@ -1641,11 +1648,11 @@ const createScatterplot = (
getPointOpacityScale = getPointOpacityScaleBase,
) =>
renderer.regl({
- frag: performanceMode ? POINT_SIMPLE_FS : POINT_FS,
+ frag: renderPointsAsSquares ? POINT_SIMPLE_FS : POINT_FS,
vert: createVertexShader(globalState),
blend: {
- enable: !performanceMode,
+ enable: !disableAlphaBlending,
func: {
// biome-ignore lint/style/useNamingConvention: Regl specific
srcRGB: 'src alpha',
@@ -3611,6 +3618,14 @@ const createScatterplot = (
return performanceMode;
}
+ if (property === 'renderPointsAsSquares') {
+ return renderPointsAsSquares;
+ }
+
+ if (property === 'disableAlphaBlending') {
+ return disableAlphaBlending;
+ }
+
if (property === 'gamma') {
return renderer.gamma;
}
diff --git a/src/types.d.ts b/src/types.d.ts
index 59b7fbf..78bf430 100644
--- a/src/types.d.ts
+++ b/src/types.d.ts
@@ -210,6 +210,8 @@ export type Properties = {
lassoLongPressIndicatorParentElement: HTMLElement;
camera: Camera2D;
performanceMode: boolean;
+ renderPointsAsSquares: boolean;
+ disableAlphaBlending: boolean;
opacityByDensityDebounceTime: number;
spatialIndex: ArrayBuffer;
spatialIndexUseWorker: undefined | boolean;
diff --git a/tests/get-set.test.js b/tests/get-set.test.js
index b5bbfc9..e80b24c 100644
--- a/tests/get-set.test.js
+++ b/tests/get-set.test.js
@@ -728,7 +728,6 @@ test('get("isDrawing")', async () => {
scatterplot.destroy();
});
-
test('set() after destroy', async () => {
const scatterplot = createScatterplot({ canvas: createCanvas() });
@@ -738,3 +737,57 @@ test('set() after destroy', async () => {
await expect(whenSet).rejects.toThrow(ERROR_INSTANCE_IS_DESTROYED);
});
+
+
+test('get() and set() performance properties', async () => {
+ const scatterplotA = createScatterplot({ canvas: createCanvas() });
+
+ expect(scatterplotA.get('performanceMode')).toBe(false);
+ expect(scatterplotA.get('renderPointsAsSquares')).toBe(false);
+ expect(scatterplotA.get('disableAlphaBlending')).toBe(false);
+
+ scatterplotA.set({
+ 'performanceMode': true,
+ 'renderPointsAsSquares': true,
+ 'disableAlphaBlending': true,
+ });
+
+ expect(scatterplotA.get('performanceMode')).toBe(false);
+ expect(scatterplotA.get('renderPointsAsSquares')).toBe(false);
+ expect(scatterplotA.get('disableAlphaBlending')).toBe(false);
+
+ scatterplotA.destroy();
+
+ const scatterplotB = createScatterplot({
+ canvas: createCanvas(),
+ performanceMode: true,
+ });
+
+ expect(scatterplotB.get('performanceMode')).toBe(true);
+ expect(scatterplotB.get('renderPointsAsSquares')).toBe(true);
+ expect(scatterplotB.get('disableAlphaBlending')).toBe(true);
+
+ scatterplotB.destroy();
+
+ const scatterplotC = createScatterplot({
+ canvas: createCanvas(),
+ renderPointsAsSquares: true,
+ });
+
+ expect(scatterplotC.get('performanceMode')).toBe(false);
+ expect(scatterplotC.get('renderPointsAsSquares')).toBe(true);
+ expect(scatterplotC.get('disableAlphaBlending')).toBe(false);
+
+ scatterplotC.destroy();
+
+ const scatterplotD = createScatterplot({
+ canvas: createCanvas(),
+ disableAlphaBlending: true,
+ });
+
+ expect(scatterplotD.get('performanceMode')).toBe(false);
+ expect(scatterplotD.get('renderPointsAsSquares')).toBe(false);
+ expect(scatterplotD.get('disableAlphaBlending')).toBe(true);
+
+ scatterplotD.destroy();
+});