mozilla / shumway

Shumway is a Flash VM and runtime written in JavaScript
Apache License 2.0
3.68k stars 395 forks source link

WebGL renderer draws blurred shapes #1336

Open tschneidereit opened 10 years ago

tschneidereit commented 10 years ago

With shape rendering landed, it becomes clear that the WebGL-based renderer has a problem with drawing elements without blur.

Test case: stroked-boxes.swf in the dropbox. All lines are sharp in the Canvas2D renderer, while some are blurred in the WebGL renderer. Note that the first and second pair of boxes are exactly the same, shape-wise, respectively; they're just drawn at different positions.

mbebenita commented 10 years ago

On Retina:

screen shot 2014-05-31 at 5 05 45 pm

No Retina:

screen shot 2014-05-31 at 5 06 23 pm

I think this boils down to antialiasing issues. Our textured quads are the same size as cached images which probably causes ugly aliasing artifacts. It may help if we make our quads 1 pixel larger so that texture filtering does its thing. Also, we probably need to render at twice the size and scale down.

mbebenita commented 10 years ago

And canvas for reference:

screen shot 2014-05-31 at 5 12 01 pm

mbebenita commented 10 years ago

Here is another experiment: The top row of boxes are all drawn at hole pixel coordinates, the bottom are drawn at 0.1 incremental offsets, so the 7th box is drawn at 0.7 offset from the top one. Here is what the flash player does. (I'd recommend using Pixie in OSX after installing the graphics tools).

Low Quality:

image

(.5 rounds down, 0.6 rounds up)

Medium Quality:

image

High Quality:

image

(.8 rounds down, .9 rounds up)

8x8:

image

16z16:

image

Shumway Canvas: (no retina)

image

Shumway WebGL:

image

Looks like there is a bug in the WebGL backend that probably excludes the last pixel.

mbebenita commented 10 years ago

K, digging a bit further. The width of drawRect here is 10, however if I count the number of pixels drawn in Flash it's actually 11x11, see below;

image

Same thing actually happens in the canvas renderer:

image

The problem is that I allocate GPU textures based on the width of the bounds, which is 10, so i'm missing the right column and the bottom row of pixels.

tschneidereit commented 10 years ago

Here is another experiment: The top row of boxes are all drawn at hole pixel coordinates, the bottom are drawn at 0.1 incremental offsets, so the 7th box is drawn at 0.7 offset from the top one. Here is what the flash player does. (I'd recommend using Pixie in OSX after installing the graphics tools).

Right, as the comment in the Shape rendering method explains, our behavior doesn't fully match Flash's here, but it covers the important case of (with the Canvas2D backend) rendering crisp lines for 1px and 3px lines where the object is drawn at full-pixel coordinates.

The problem is that I allocate GPU textures based on the width of the bounds, which is 10, so i'm missing the right column and the bottom row of pixels.

The bounds should be correct in all cases except the first. (Well, they're correct in absolutely all cases in that they match Flash's bounds.) I updated the test case to trace the bounding boxes, with the result being the following in both Flash and Shumway:

(x=50, y=50, w=50, h=50)
(x=114.5, y=49.5, w=51, h=51)
(x=179, y=49, w=52, h=52)
(x=244, y=49, w=52, h=52)
(x=307.5, y=47.5, w=55, h=55)
(x=372.5, y=47.5, w=55, h=55)
(x=435, y=45, w=60, h=60)

The first case has effective lineBounds that are larger than the fillBounds (because it has a stroke width of 0, but is drawn with a 1px stroke), but that is not reflected in the lineBounds object. For the others, are you maybe just coercing them to int instead of rounding? I think the correct behavior is to round down x and y, and round up width and height.