Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Anti-aliased holes have 1 pixel fringe #571

Open
mattkille opened this issue Mar 13, 2020 · 5 comments
Open

Anti-aliased holes have 1 pixel fringe #571

mattkille opened this issue Mar 13, 2020 · 5 comments

Comments

@mattkille
Copy link

When a hole touches or exceeds the edge of its parent shape, there is a 1 pixel fringe drawn around it. Appears to be related to anti-aliasing, as this effect is not shown when disabled. Here is some code to demonstrate this:

   for (int pass = 0; pass < 2; pass++)
   {
      for (int i = 0; i < 8; i++)
      {
         nvgBeginPath(vg);
         nvgRect(vg, i * 18, pass * 20, 9, 9);
         nvgRect(vg, i * 18 + 3, pass * 20 + 3, 3, 3 + i);
         nvgPathWinding(vg, NVG_HOLE);
         nvgFillColor(vg, nvgRGBA(255, 255, 255, 128));
         nvgFill(vg);
      }

      // Repeat with anti-alias off.
      nvgShapeAntiAlias(vg, 0);
   }

Each step the hole is made one pixel longer. The following enlarged image shows the result. The first pass with default anti-aliasing enabled. The second pass without. The fill is 50% white, highlighting overlapped pixels.

The latter is the result I would hope for in both cases; that which matches Canvas.

aaholes

@memononen
Copy link
Owner

This is limitation of the antialiasing method used. The antialiasing is done by deflating the shape by 0.5px and rendering 1px wide "fringe" around the shape. It fails when there is a lot of geometry per pixel. If that is common in your use case, i recommend the MSAA mode instead.

@mattkille
Copy link
Author

This is limitation of the antialiasing method used. The antialiasing is done by deflating the shape by 0.5px and rendering 1px wide "fringe" around the shape.

Hmm, even if the shape in this case should be non-existent? Or are you just talking about the overlapping pixels? Take for example the fourth column examples. The 'n' shape at the bottom is a common case. The top example has an extra 1 pixel border drawn around the 3x0 sized position where the 9x9 shape and the 3x6 hole align.

@memononen
Copy link
Owner

Yes. A couple of things going on in there, really hard to explain with words.

  • The bright pixels happen because two transparent lines are drawn on top of each other, there's no whole shape accumulation of coverage
  • The too wide bottom part happens because the whole shape is deflated, once the winding is reversed outside, it's deflated instead in wrong direction
  • the extra line happens because the winding stencil is rendering using the inflated shapes, so in some cases the outer most pixels which influence the AA are rendered outside the stencil mask, which means that they do not follow the stencil rules correctly

One more limitation is small (close to sub pixel) or really sharp features, like rendering a glyph. The inflating/insetting is quite naive so it will fail and also the lack of per shape coverage accumulation makes things look ugly.

@mattkille
Copy link
Author

@memononen

I see. That's very interesting, thank you for the explanation. I'll have to see how I can work around this for my particular needs. It's this fourth column example I wanted to create. Making a hole that touches the edge without the extra line artefact would have been so much easier. I'll have to see if I can construct the shape I need as a single path. Thanks again. 👍

@daljit97
Copy link

daljit97 commented Aug 6, 2020

@memononen could this be fixed following the approach used here https://github.com/styluslabs/nanovgXC?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants