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 ?

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.
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.
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.
Most helpful comment
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:
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
RenderCustomTexDatathat 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.