[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] Determining the number of physical pixels for a particular devicePixelRatio

On Sun, Nov 24, 2013 at 6:45 AM, Liam Wilson <cosinusoidally@yahoo.co.uk> wrote:

> On Friday, 22 November 2013, 20:17, Kenneth Russell <kbr@google.com> wrote:
>> On Thu, Nov 21, 2013 at 7:07 PM, Bill Baxter <wbaxter@google.com> wrote:
>> I think http://www.khronos.org/webgl/wiki/HandlingHighDPI should at least be
>> updated to mention that you may need to round instead of floor to get 1:1
>> rendering, and it's just implementation dependent.
> Done. Please send any feedback on the new text to the list.
> -Ken

canvas.style.width = desiredWidthInCSSPixels + "px";
canvas.style.height = desiredHeightInCSSPixels + "px";

// set the size of the drawingBuffer
var devicePixelRatio = window.devicePixelRatio || 1;
canvas.width = desiredWidthInCSSPixels * devicePixelRatio;
canvas.height = desiredHeightInCSSPixels * devicePixelRatio;

 all due respect, that approach cannot work in general. It seems to
intuitively work, and I attempted this solution, but after struggling to
 make it work for about 8 hours I came to the conclusion that it could
not work. The problem is rounding. You always end up with values that are
slightly off. For example, assume you want a canvas to be 101 CSS pixels
 wide and your devicePixelRatio is 1.5. You will need to set
canvas.width to exactly 151.5 (which cannot be done). You end up
setting canvas.width to 151 or 152 (which are slightly off). When drawn to the screen the canvas gets slightly scaled, and you get blurry rendering.

Right, well that's what this whole thread was about, and why Ken added the language saying: 
Experimentation has revealed that in order to precisely compute the number of device pixels covered by a particular element, heuristics may be necessary; whether to use Math.round() or Math.floor() may depend on such things as the current level of browser zoom. Most applications should not need to worry about these details, but applications that require a 1:1 mapping between the drawing buffer and device pixels for reasons of rendering quality may need to.

Unfortunately that's not a solution, just a statement of the current problematic situation.

If you have the freedom to choose the CSS size of your canvas, then I recommend choosing something so that canvasCssSize * devicePixelRatio comes out with a fractional component less than 0.5, since it seems that in every case browsers are either effectively doing a floor() or round(), so if you choose the size such that floor(canvasCssSize*devicePixelRatio)==round(canvasCssSize*devicePixelRatio), you should be ok.
Of course that may mean a few pixels of black bars or unused real estate around the edges of your content.
It may be that I am doing something subtly wrong, but the point is that
this should not be a difficult. This should be trivial.


In an ideal
world you would just be able to do something like set devicePixelRatio
to 1 from _javascript_.

Well, that's not so good, because then you'd lose the information devicePixelRatio is trying to tell you, which is how many physical pixels there are per CSS pixel.  Without that you just end up back in the world where everything is too tiny when you have a HighDPI screen.