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

Performance optimisation guidance for app that uses a lot of vector primatives (circles) #736

Closed
inflex opened this issue Jul 15, 2016 · 3 comments

Comments

@inflex
Copy link

inflex commented Jul 15, 2016

I'm working on a cross-platform project that will generate up to thousands of small circles to be rendered and for some lower powered systems there's a bit of a stuttering/lag issue (runs fine on Pentium G3420 and built in intel gfx).

We were previously using textures to draw the circles but I moved over to AddCircle() and AddCircleFilled() to eliminate the need for custom textures and of course provide infinite quality when zoomed in.

Using;
draw->AddCircleFilled( ImVec2(pos.x, pos.y), psz, color, segments);
draw->AddCircle( ImVec2(pos.x, pos.y), psz, color, segments);

Already am varying the number of segments drawn based on the radius, since obviously for very small circles (on screen) we don't really need that many segments (varying between 8~32).

Digging through the ImGui code I can see that essentially everything seems to get broken up in to segments (to be rendered), which I suppose ultimately means that there's no chance to provide an optimised (if slightly less than perfect) perfect-circle draw/fill algorithm.

TL;DR; Is there a faster way of handling circles and filled circles ?

obv

@ocornut
Copy link
Owner

ocornut commented Jul 15, 2016

Those circles are quite costly indeed because of the anti-aliasing + there's no code to automatically decide on number of segment (we have add for the Bezier curves, configured with io.CurveTessellationTol). But basically and mostly the AA is quite costly.

A)
You can disable AA with:

io.AntiAliasedLines = false;
io.AntiAliasedShapes = false;

B)
We could improve AddCircle/AddCircleFilled to automatically decide on segment count when the value is 0, based on radius. That would be enough of a work-around to provide nice looking big circles. Obviously you can always experiment with choosing the segment_count on the user's side. That tesselation could probably be parametrized (the same way curves are parametrized with io.CurveTessellationTol + be custom tweaked for small values. I haven't looking into this but I assume it is a fairly simple problem to solve.

C)
If you are going to draw tens of thousands of small circles it may be worth it just using textures as you did. One of the upcoming task to better support skinning is to pre-rasterize quarter-circles of different sizes into the main atlas texture, so rounded frames and circles can be drawn with less CPU/GPU overhead. So we would likely include say, all circles from 1 to 20 pixels, outline and filled in the texture atlas and automatically use those when radius is under that limit.
There's already code in RenderCustomTexData that add custom pixels into the font atlas, to fit in the cursor. In this code we'll need to include rasterized quarter-circles in the atlas.

@inflex
Copy link
Author

inflex commented Jul 15, 2016

Thanks for the fast feedback.

I had hoped maybe I could push the circle primitive all the way down to the final rendering (display) stage such that when it came to putting actual pixels to the frame buffer a specific circle-drawing function could be called on. Obviously that's somewhat more of a serious project, requiring a lot more work.

I'll try the disabling of the AA as well. Choosing the segment count works well currently ( which is probably why it doesn't kill my G3420 yet ).

Many thanks once more for your time.

@ocornut
Copy link
Owner

ocornut commented Jul 15, 2016

I had hoped maybe I could push the circle primitive all the way down to the final rendering (display) stage such that when it came to putting actual pixels to the frame buffer a specific circle-drawing function could be called on. Obviously that's somewhat more of a serious project, requiring a lot more work.

There's no need to do that, we're doing it as we go as the frame buffer size is already known. Either way ImGui always assume that 1.0 in his coordinate space means 1 pixel.

Disabling the AA will boost everything by a huge amount for that sort of worse case situation you have, but obviously things won't look nearly as nice.

(C) is something that needs to be done either way and will solve your issues, and the main reason why rounded buttons aren't the default right now. As 1.50 wants to provide default themes (#707) it is likely I will work on that soonish.

@inflex inflex closed this as completed Jul 15, 2016
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

2 participants