[Public WebGL] How to unambiguously set canvas pixel size to be pixel-perfect?

Florian Bösch [email protected]
Fri Mar 27 01:14:22 PDT 2015

This problem seems as yet unresolved, and a good candidate to solve for the
WebGL 2 specification.

An additional datapoint for consideration, for 398'000 pageviews from
Wednesday the 25th of March 2015, I captured these DPRs in the wild:

 count | value
    75 | 0.50000
    82 | 0.70000
    86 | 2.00494
    98 | 1.33000
   125 | 1.42177
   127 | 1.35000
   128 | 1.75000
   138 | 0.66600
   175 | 2.50000
   183 | 1.30000
   188 | 1.09091
   215 | 0.80000
   247 | 0.89552
   247 | 1.34422
   378 | 0.85000
   436 | 1.20000
   438 | 1.15000
   625 | 4.00000
   698 | 0.95000
   796 | 1.33125
   855 | 1.05000
   909 | 0.75000
  1960 | 0.90000
  2510 | 1.10000
  5534 | 1.25000
  7393 | 3.00000
  8913 | 1.50000
 27176 | 2.00000
327576 | 1.00000

We have everything here, insane ratios (3 and beyond), ratios below 1
(seriously, does that even make sense?), fractional ratios (you like your
pixels blurred irregularly do you?), periodic fractions (who could be
bothered by even divisibility), irrational numbers (how do you even come up
with that given that your screen has an integer number of pixels..., did
you just fiddle with the ratio by hand?), you name it.

Regardless of all other concerns (CSS sizes, what have you). The first task
is to make sure a WebGL application can render a viewport in the actual
device resolution. There is no point in rendering
incidentially/accidentially larger/smaller than the physical pixels on the
device. There is very much a point to be able to precisely render at a
desired super/sub resolution (which is only possible once you can
accurately render at device resolution).

This problem is somewhat complicated by zooming. If things are reduced in
size, this isn't a big problem because the underlying buffer can equally be
reduced in size and things will work out fine. However if zooming enlarges
the viewport, it's easily possible that just enlarging the underlying
buffer by that ratio will lead to performance issues and/or exceeding the
drawing buffer size limits.

Unfortunately the zoom-in case cannot be handled automatically (such as
viewport curtailment) because post-processing algorithms on the presented
result might do things with pixels that are off screen (like say a high
horizontal spread anamorphic lens simulating bloom blur).

But viewport curtailment is still a practical device to have, and so it
should be considered as an opt-in semantic for those wishing to regard it.

I propose the following simple API to take care of this problem:

   1. canvas.getDevicePixelSize() -> this returns width/height of the
   canvas in terms of real device pixels. Whatever DPR/zoom/CSS transform is
   applied to the content, it will return an integer width/height that is
   closest (ideally perfect) to the real screen coverage. It is primarily
   intended to adjust the canvas.width/canvas.height to this dimension.
   2. canvas.getVisibleRect() -> this returns a left/top width/height
   structure that specifies which part of the canvas needs to be rendered in
   terms of the DevicePixelSize in order to fill a rendering on screen. It is
   intended to be used in the gl.viewport setting.

I'm not sure this is sufficient/correct, as it leaves out how to handle the
affine transform correctly, and doesn't handle the drawing buffer exceeding
size limits case. I hope it's a starting point.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://khronos.org/pipermail/public_webgl_khronos.org/attachments/20150327/a035c0e6/attachment.html>

More information about the public_webgl mailing list