flekschas / regl-scatterplot

Scalable WebGL-based scatter plot library build with Regl
https://flekschas.github.io/regl-scatterplot/
MIT License
184 stars 21 forks source link

Point circles look malformed #175

Open danr opened 2 months ago

danr commented 2 months ago

I think the circles look a bit off. Take a look at these (8x zoom):

image

They are not particularily round and look a bit egg shaped. I have tinkered with the code and I have two ideas for improvement.

  1. Increase the anti-aliasing from 1px to 3px:

image

The change is in the fragment shader point.fs:

-  float alpha = linearstep(finalPointSize + 0.5, finalPointSize - 0.5, sdf);
+  float alpha = linearstep(finalPointSize + 0.5, finalPointSize - 2.5, sdf);
  1. Snap points to pixels. This makes them perfectly symmetrical, like this:

image

The change is in the vertex shader point.vs, and you have to provide the width and height in index.js.

-  gl_Position = modelViewProjection * vec4(state.x, state.y, 0.0, 1.0);
+  vec4 clipSpacePosition = modelViewProjection * vec4(state.x, state.y, 0.0, 1.0);
+  vec2 ndcPosition = clipSpacePosition.xy / clipSpacePosition.w;
+  vec2 pixelPos = 0.5 * (ndcPosition + 1.0) * vec2(drawingBufferWidth, drawingBufferHeight);
+  pixelPos = floor(pixelPos + 0.5); // Snap to nearest pixel
+  vec2 snappedPosition = (pixelPos / vec2(drawingBufferWidth, drawingBufferHeight)) * 2.0 - 1.0;
+  gl_Position = vec4(snappedPosition, 0.0, 1.0);
+       drawingBufferWidth: (context) => context.drawingBufferWidth,
+       drawingBufferHeight: (context) => context.drawingBufferHeight,

These two can be combined, of course. Then it looks like this:

image

The downside with pixel-snapped coordinates is that between two zoom levels only some of the points are affected, making it look like they jump (if you look very carefully, but looking carefully is what this issue is about). In this video you can for example focus on the two overlapping points and you see that they don't wiggle in unison:

https://github.com/flekschas/regl-scatterplot/assets/199380/f5fa8883-ad77-4aa5-bb93-cd23607ec2cc

Due to the zoom wiggling with pixel-snapping I think the most straight-forward way to improve the circles is to increase the anti-aliasing. Happy to hear your opinion on this!

flekschas commented 2 months ago

Thanks a lot for looking into this and the proposed solutions! I agree that the pixel snapping is not ideal due to the wiggling factor. It'd be cool to be able to turn this on optionally as it could be useful for pixel-perfect PNG exports but I'm not sure it's worth the maintenance effort. But I'll keep it in the back of my mind as I have some ideas for better exporting (i.e., at different resolutions)

I'm open to increasing the anti-aliasing but wonder what 1.5px, 2px, and 2.5px look like. Could you render the same point grid with those px values? I personally find 3px a tad too blurry.