pygame-ce
pygame-ce copied to clipboard
Artifacts when drawing polygons with multiple contours
I'm experimenting with drawing polygons with multiple contours, such as text and hollow shapes.
To do this I'm connecting one polygon to the next with a zero-width strip, e.g.
polys = [
[(-80, 80), (80, 80), (80, -80), (-80, -80)],
[(100, -100), (100, 100), (-100, 100), (-100, -100)]
]
closed = [[*poly, poly[0]] for poly in polys]
chained = []
for poly in closed:
if chained:
chained.extend(poly + [chained[-1]])
else:
chained.extend(poly)
pygame.draw.polygon(screen, (255, 0, 0), chained)
In OpenGL etc this would work without artifacts (but a different approach is needed to cut holes).
Using pygame.draw.polygon() I see artifacts (behind "Hello, World" and crossing the cog):
Using pygame.gfxdraw.filled_polygon() gives a very similar result:
I am able to get the expected rendering by checking x_intersect[i] != x_intersect[i+1] at https://github.com/pygame-community/pygame-ce/blob/c0f0c74788c6d9230ed3f4d5f78b731968173fe8/src_c/draw.c#L3212-L3214
and removing code at https://github.com/pygame-community/pygame-ce/blob/c0f0c74788c6d9230ed3f4d5f78b731968173fe8/src_c/draw.c#L3227-L3235
However this changes the behaviour for other polygons in a way that is not backwards-compatible. I also implemented a completely floating point version using round() that may be more accurate but pygame.draw.lines() does not match up (there are gaps) but I think maybe perceptually it's a bit better with moving/rotating polygons?
I notice there are many issues and PRs about polygon rendering: #172, #3005, #2208
What approach might make most sense for a PR for this issue? Some options:
- Change
pygame.draw.polygon()to always do this. - Add
pygame.draw.multi_contour_polygon()that also includes the chaining code above (in C) - Add a kwarg like
fine=Truetopygame.draw.polygon()and conditionally skip the sections of code I highlighted above - Pursue floating point versions of these drawing algorithms.