PAIR-code / megaplot

Apache License 2.0
19 stars 5 forks source link

Non-zero GeometricZoom renders differently depending on devicePixelRatio #89

Closed jimbojw closed 1 year ago

jimbojw commented 1 year ago

When a Megaplot scene is rendered, it should be the same irrespective of the devicePixelRatio, other than the expected effect of pixelation.

Currently however, when GeometricZoom has a value other than zero (the default), the contribution to rendered size differs depending on the devicePixelRatio.

The offending line is in the computeSize() function in the file shader-functions.ts:

vec2 zoomScale = exp(log(viewMatrixScale.xy) * (1. - geometricZoom));

The zoomScale variable currently does not take into account the devicePixelRatio, so when it is used to project the sizeWorld into pixel space, it produces different results for different devicePixelRatio values:

vec2 projectedSizePixel = sizeWorld * zoomScale +
  sizePixel * CLIP_SPACE_RANGE * devicePixelRatio;

The answer is to incorporate the devicePixelRatio in such a way that when GeometricZoom is 0, the result is unchanged, but when GeometricZoom is 1, then the sizeWorld is effectively the same as a logical pixel:

vec2 zoomScale = exp(log(viewMatrixScale.xy) * (1. - geometricZoom))
  * pow(vec2(CLIP_SPACE_RANGE * devicePixelRatio), geometricZoom);

Make this change and add pixel-color tests to assert that the size computation is correct.