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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add graphics with antialiasing: SmoothRectangle, SmoothEllipse, SmoothRoundedRectangle, SmoothQuad and SmoothTriangle #8309

Merged
merged 16 commits into from Oct 28, 2023

Conversation

DexerBR
Copy link
Contributor

@DexerBR DexerBR commented Jul 2, 2023

This PR adds a new graphics section with antialiasing. In addition, some classes have been adjusted to expose the points used in their build (necessary for the antialiasing approach).

Similar to what we have with SmoothLine, the new introduced graphics will be:

  • SmoothRectangle
  • SmoothRoundedRectangle
  • SmoothEllipse
  • SmoothQuad
  • SmoothTriangle

Although there was a desire to integrate antialiasing directly into the current graphics, it seemed better to maintain support for figures without antialiasing and add the new instructions as Smooth___.

馃煛 All support for antialiasing is maintained regardless of the opacity of the context in which the graphic is drawn.
馃煛 There is still no support for texture antialiasing.


Antialiasing is achieved through a combination of a graphic without antialiasing and AntiAliasingLine (a new instruction used internally only for the purpose of antialiasing).

AntiAliasingLine was created and designed to fit around a graphic without antialiasing, providing a smoothing effect to its edges. Although a similar effect could be achieved with SmoothLine, AntiAliasingLine has some advantages over SmoothLine, such as:

  • Keeps the antialiasing implementation isolated, avoiding breaking changes when depending on SmoothLine.
  • It is significantly more stable as it uses miter joints and has a point filter to ensure consistent behavior. Its point filter also discards irrelevant points, which can improve performance in some cases.
  • Some properties, such as width and premultiplied texture, were specifically defined through extensive experimentation for the purpose of antialiasing.
  • It has the ability to perform stencil operations based on the target graphic to avoid alpha channel overlap at the intersection between the target graphic and AntiAliasingLine.

馃煛 It is worth noting that a customized version of stencil instructions is used here. The reason for this is that the function glClear(GL_STENCIL_BUFFER_BIT) is somewhat expensive when it comes to constant updates, which can significantly increase GPU usage. However, by limiting the call to clear stencil functions only when an update is actually needed, performance increases significantly; otherwise, GPU consumption would be close to the maximum limit (when there are tens of thousands of instructions). During the tests, no side effects were observed.

  • Perhaps this is an improvement that could be implemented in stencil_instructions.pyx, and although it requires more testing, the performance improvement would be significant!

Depends on:

Here are some basic comparison data from a test performed with canvas_stress.py, using 64000 RoundedRectangle/SmoothRoundedRectangle:

Using RoundedRectangle:

  • CPU ~20%
  • GPU ~32%
  • MEMORY ~1100MB

Using SmoothRoundedRectangle:

  • CPU ~20%
  • GPU ~38%
  • MEMORY ~1800MB

The data was obtained by observing the resource monitor while resizing the window or dragging touch across the window using the multitouch simulator (red dot created by the right mouse button).

In almost all cases, the difference between using an instruction with antialiasing and one without would be very small (or insignificant) in terms of resource consumption.


Some comparisons between graphics with and without antialiasing:

aa1

aa2

aa3

aa4

aa5

aa6

aa7

Test code:

from kivy.app import App
from kivy.lang import Builder

KV = """
FloatLayout:
    # on_touch_down:
    #     self.export_to_png("img.png")
    canvas:
        Color:
            rgba: 0, 0, 0, 1
        Rectangle:
            size: self.size
            pos: self.pos

        Color:
            rgba: 0, 0, 1, 1
        Rectangle:
            size: self.width, 150
            pos: 0, 250

        Color:
            rgba: 1, 1, 1, 0.5

        SmoothQuad:
            points: [50, 350, 200, 375, 175, 500, 150, 500]
        
        SmoothTriangle:
            points: [250, 350, 345, 400, 325, 500]

        SmoothEllipse:
            pos: 400, 350
            size: 150, 150
            angle_start: 0
            angle_end: 300

        SmoothRoundedRectangle:
            pos: 500, 350
            size: 150, 150
            segments: 30
            radius: [(200, 200), (100, 50), (100, 50),(100, 250),]
        
        PushMatrix
        Rotate:
            angle: 30
            origin: 900, 450
        SmoothRectangle:
            pos: 800, 400
            size: 100, 100
        PopMatrix

        
                
        Quad:
            points: [50, 150, 200, 175, 175, 300, 150, 300]
        
        Triangle:
            points: [250, 150, 345, 200, 325, 300]

        Ellipse:
            pos: 400, 150
            size: 150, 150
            angle_start: 0
            angle_end: 300

        RoundedRectangle:
            pos: 500, 150
            size: 150, 150
            segments: 30
            radius: [(200, 200), (100, 50), (100, 50),(100, 250),]
        
        PushMatrix
        Rotate:
            angle: 30
            origin: 900, 250
        Rectangle:
            pos: 800, 200
            size: 100, 100
        PopMatrix

"""


class Example(App):
    def build(self):
        return Builder.load_string(KV)

Example().run()

Maintainer merge checklist

  • Title is descriptive/clear for inclusion in release notes.
  • Applied a Component: xxx label.
  • Applied the api-deprecation or api-break label.
  • Applied the release-highlight label to be highlighted in release notes.
  • Added to the milestone version it was merged into.
  • Unittests are included in PR.
  • Properly documented, including versionadded, versionchanged as needed.

@misl6 misl6 added this to the 2.3.0 milestone Jul 2, 2023
@misl6 misl6 added the Component: graphics kivy/graphics label Jul 2, 2023
@misl6
Copy link
Member

misl6 commented Jul 22, 2023

Hi @DexerBR !

Did you managed to find out why the tests are failing?

@DexerBR
Copy link
Contributor Author

DexerBR commented Jul 22, 2023

Hi @DexerBR !

Did you managed to find out why the tests are failing?

@misl6 I noticed that the tests fail right after attempting to disable the antialiasing line (by setting "kivy/tests/test_button.png" to the source attribute of the target graphic instruction).

I wonder why the test doesn't fail on other platforms. Maybe it's a race condition on that specific platform?

@DexerBR
Copy link
Contributor Author

DexerBR commented Jul 22, 2023

I found that the problem is on the platform in identifying the file path ("kivy/tests/test_button.png"). So, it seems to be an issue not related to this PR.

@misl6
Copy link
Member

misl6 commented Oct 12, 2023

Now all tests pass.
Unless you have new uncommitted changes to add, I will start a review tomorrow.

@DexerBR
Copy link
Contributor Author

DexerBR commented Oct 13, 2023

Now all tests pass. Unless you have new uncommitted changes to add, I will start a review tomorrow.

Hi! So far, I have no changes to add.

@misl6 misl6 mentioned this pull request Oct 13, 2023
7 tasks
Copy link
Member

@misl6 misl6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @DexerBR !

I've left some minor comments.

Unfortunately, with Cython we do not have a clean way to reduce the duplicated code, but if you have an idea to reduce (at least partially) the duplicated code between the figures, feel free to share.

kivy/graphics/vertex_instructions.pyx Outdated Show resolved Hide resolved
kivy/graphics/vertex_instructions.pyx Outdated Show resolved Hide resolved
kivy/graphics/vertex_instructions.pyx Outdated Show resolved Hide resolved
kivy/graphics/vertex_instructions.pyx Outdated Show resolved Hide resolved
@DexerBR
Copy link
Contributor Author

DexerBR commented Oct 15, 2023

Hi @DexerBR !

I've left some minor comments.

Unfortunately, with Cython we do not have a clean way to reduce the duplicated code, but if you have an idea to reduce (at least partially) the duplicated code between the figures, feel free to share.

Hi @misl6! I totally agree with you about Cython!

I did a small refactoring, moving all the code that could be defined centrally out of the "snooth instructions".

@DexerBR DexerBR requested a review from misl6 October 15, 2023 17:20
@misl6
Copy link
Member

misl6 commented Oct 28, 2023

Hi @DexerBR !
I've left some minor comments.
Unfortunately, with Cython we do not have a clean way to reduce the duplicated code, but if you have an idea to reduce (at least partially) the duplicated code between the figures, feel free to share.

Hi @misl6! I totally agree with you about Cython!

I did a small refactoring, moving all the code that could be defined centrally out of the "snooth instructions".

Love it!

Copy link
Member

@misl6 misl6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thank you!

@misl6 misl6 added the Notes: Release-highlight Highlight this PR in the release notes. label Oct 28, 2023
@misl6 misl6 merged commit bc5904f into kivy:master Oct 28, 2023
34 checks passed
@DexerBR DexerBR deleted the smooth_graphics branch October 28, 2023 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: graphics kivy/graphics Notes: Release-highlight Highlight this PR in the release notes.
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet

2 participants