WebGL plots are blurry

When I produce SVG plots with Plotly, I have no problems. When I produce WebGL plots, the plotted points aren’t nearly as sharp: they are “fuzzy” or “blurry.” I am using plotly-r 4.9.2.1.

Here is a minimal demonstration of the problem:

library(plotly)
data(iris)
mySVG <- plot_ly(
  x      = ~Petal.Length, y = ~Petal.Width,
  type   = "scatter", mode  = "markers",  
  color  = ~Species,
  data   = iris,
  marker = list(size = 10))
myWebGL <- toWebGL(mySVG)
subplot(mySVG, myWebGL, nrows = 2)  

It produces this figure. The left-hand panel, an SVG plot, is notably sharper than the right-hand panel, which is a WebGL plot. Why are Plotly’s WebGL plots so fuzzy?

The problem has been noted a few times in the Plotly.js Github repo: for example, https://github.com/plotly/plotly.js/issues/3246 and https://github.com/plotly/plotly.js/issues/2431. (The latter issue is framed as a problem with Plotly’s handling of the hsl color model, but blurry rendering arises even when we don’t use that model.)

The problem isn’t specific to retina screens. My own monitor is only 110 dpi, and the problem is acute even on that sort of monitor.

Things I’ve tried:

  • Changing the glPixelRatio option that is used when the plots are set up.
  • Manipulating the canvas element of the WebGL plots. I read that fuzziness can arise when canvas.width and canvas.clientWidth are not the same. But that isn’t a problem here. (The same is true for canvas.height and canvas.clientHeight.)
  • Using Plotly.newplot() to re-render a plot, per this comment.

None of that has worked. Is there a solution to this problem?

I posted a question about this problem on Stack Overflow more than a week ago, but there have been no responses.

1 Like

The glPixelRatio config option should help in this regard after we could merge https://github.com/plotly/plotly.js/pull/3637.

The bigger point here is that yes, there’s a real tradeoff between better looks with SVG and better performance and scale with WebGL. SVG is vector to the core, which means the browser can use all its smarts to antialias and give the best possible appearance. WebGL is pixelated at its core, so you get exactly the pixels we draw, no more no less, and we definitely don’t capture all the subtlety the browser does at edges. The only way we antialias in WebGL is via oversampling, which is what glPixelRatio is supposed to do, but as @archmoj points out this doesn’t currently work properly for scattergl. @archmoj does glPixelRatio do the right thing for 3D plots?

@alexcjohnson the answer is positive for 3-D thanks to https://github.com/plotly/plotly.js/pull/3573.

1 Like

@archmoj, @alexcjohnson, thank you. I didn’t realize that WebGL was pixelated at its core. And the pull request that @archmoj mentions seems promising.

For those looking for a solution to render their plots as SVG (high resolution), the parameter you have to call when making your plot is render_mode.

fig = px.line(df,
              x=x,   
              y=y
              render_mode="svg")