Skip to content

Commit

Permalink
feat: add renderPointsAsSquares and disableAlphaBlending (#210)
Browse files Browse the repository at this point in the history
  • Loading branch information
flekschas authored Jan 13, 2025
1 parent 1420cf5 commit 3b3f28e
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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: prevent drawing points if all are filtered out ([#201](https://github.com/flekschas/regl-scatterplot/issues/201))
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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` |

<a name="property-notes" href="#property-notes">#</a> <b>Notes:</b>

Expand Down Expand Up @@ -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.

<a name="property-by" href="#property-by">#</a> <b>colorBy, opacityBy, sizeBy:</b>

Expand Down
25 changes: 20 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -3611,6 +3618,14 @@ const createScatterplot = (
return performanceMode;
}

if (property === 'renderPointsAsSquares') {
return renderPointsAsSquares;
}

if (property === 'disableAlphaBlending') {
return disableAlphaBlending;
}

if (property === 'gamma') {
return renderer.gamma;
}
Expand Down
2 changes: 2 additions & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ export type Properties = {
lassoLongPressIndicatorParentElement: HTMLElement;
camera: Camera2D;
performanceMode: boolean;
renderPointsAsSquares: boolean;
disableAlphaBlending: boolean;
opacityByDensityDebounceTime: number;
spatialIndex: ArrayBuffer;
spatialIndexUseWorker: undefined | boolean;
Expand Down
55 changes: 54 additions & 1 deletion tests/get-set.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,6 @@ test('get("isDrawing")', async () => {
scatterplot.destroy();
});


test('set() after destroy', async () => {
const scatterplot = createScatterplot({ canvas: createCanvas() });

Expand All @@ -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();
});

0 comments on commit 3b3f28e

Please sign in to comment.