Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Thousands of Ellipses: FPS Slowdown?

em2em2
in Questions Posts: 174

I have tables of classes many items long, and each class has a draw function which dynamically creates figures. The FPS drops below 30 when there are around 1000 items. The objects interact with each other but that doesn't seem to be the issue because the FPS returns to the 50-60 range when I comment out the "draw" lines.
Is there a better way to draw many objects on screen (possibly with mesh)? I dug up some unresolved discussions and couldn't find a solution for my situation. I'll post some sample code in a bit.

Comments

  • dave1707dave1707 Mod
    Posts: 6,392

    @em2 You say the objects interact with each other which means they have to be drawn one at a time. I assume they’re defined as physics objects. You’re drawing ellipses which are probably already meshes drawn by Codea. You don’t say how big the ellipses are or what you’re trying to do.

  • dave1707dave1707 Mod
    Posts: 6,392

    @em2 Here’s a comparison of different size ellipses, different number drawn, and the frames/second that it takes on my iPad Air. This is just to draw the ellipses, nothing else going on.

    Size  10  Nbr  100  FPS  59.44
    Size  10  Nbr  200  FPS  58.69
    Size  10  Nbr  400  FPS  57.71
    Size  10  Nbr  800  FPS  43.90
    Size  10  Nbr 1600  FPS  24.89
    
    Size  20  Nbr  100  FPS  59.47
    Size  20  Nbr  200  FPS  57.41
    Size  20  Nbr  400  FPS  57.41
    Size  20  Nbr  800  FPS  46.17
    Size  20  Nbr 1600  FPS  24.83
    
    Size  40  Nbr  100  FPS  59.60
    Size  40  Nbr  200  FPS  57.34
    Size  40  Nbr  400  FPS  58.25
    Size  40  Nbr  800  FPS  40.16
    Size  40  Nbr 1600  FPS  24.95
    
    Size  80  Nbr  100  FPS  59.22
    Size  80  Nbr  200  FPS  57.31
    Size  80  Nbr  400  FPS  59.60
    Size  80  Nbr  800  FPS  39.62
    Size  80  Nbr 1600  FPS  23.97
    
    Size 160  Nbr  100  FPS  59.05
    Size 160  Nbr  200  FPS  55.53
    Size 160  Nbr  400  FPS  29.42
    Size 160  Nbr  800  FPS  13.46
    Size 160  Nbr 1600  FPS   6.70
    
    Size 320  Nbr  100  FPS  34.76
    Size 320  Nbr  200  FPS  16.96
    Size 320  Nbr  400  FPS   8.04
    Size 320  Nbr  800  FPS   3.88
    Size 320  Nbr 1600  FPS   1.95
    
  • dave1707dave1707 Mod
    Posts: 6,392

    @em2 One other thing that I noticed with physics objects, they don’t slow down FPS unless they interact with each other. If you have a lot of large objects in a small area, there’s going to be a lot of interaction between them which will cause the FPS to decrease. If there’s a lot of small objects in a large area, they won’t interact that often, so FPS won’t be affected that much. So the size of physics objects and the area they’re in have a varying affect on FPS. From what I show above, the size of an ellipse and the number of ellipses have a direct affect on FPS.

  • em2em2
    Posts: 174

    @dave1707 sorry for the lack of explanation. I rushed writing the post. I don't use physics, and the ellipses are 100 px wide (along with many other shapes BTW).
    It's probably not my custom interaction engine, because I've tested it and it works fine, with the FPS around 50-60 without drawing anything.

  • dave1707dave1707 Mod
    Posts: 6,392

    @em2 From the table above, you can see that drawing a lot of objects eats up the FPS. If you have any objects that don’t move or interact with other objects, you can draw all of them on a single image and then sprite the image. That would save FPS.

  • Posts: 2,011

    By far the fastest way to draw 2d objects is using setRect on a single mesh or a handful of meshes. You can have 10s of thousands of objects without slow down.

    Note that one mesh has only one texture. If you want to have rects that have different textures, you either need to combine the textures into a single image (sometimes called a sprite atlas or a texture map), or have a separate mesh for each variety of object.

    If you do a forum search for setRect you'll find a lot of example code

  • Posts: 310

    ... but if they're all ellipses, you could have a single texture and then separate colours per rect.

  • dave1707dave1707 Mod
    Posts: 6,392

    @yojimbo2000 In his first post, he said there were around 1000 items and they interact with each other. If they interact with each other, they need to be drawn individually. I tried doing 1000 meshes at different sizes and they didn’t seem any faster than the ellipses at different sizes.

  • em2em2
    Posts: 174

    @yojimbo2000 It seems possible, but as I mentioned before, the objects are dynamic (and not limited to just ellipses).

  • em2em2
    Posts: 174

    @dave1707 I wouldn't create a separate mesh for each ellipse, that's for sure.

  • dave1707dave1707 Mod
    Posts: 6,392

    @em2 What are your objects and how are they created. Do you use ellipses, rects, sprites, lines, etc. Just trying to get an idea of what/how you’re trying to draw. That would have a large effect on the speed. You might just have to limit the number of your objects.

  • em2em2
    Posts: 174

    I use all of the above mentioned except for sprites.

    You might just have to limit the number of your objects.

    Yes, that seems to be the only conceivable solution currently.

  • Posts: 2,011

    What do you mean by "the objects are dynamic"?

    Getting fast performance is really just a matter of getting the number of draw() calls down. That's really all there is to it.

    You have a small number of meshes, pack the various textures you need into 1 sprite atlas per mesh, and then move the objects around by calling setRect (you don't translate/ rotate the mesh).

  • dave1707dave1707 Mod
    edited November 26 Posts: 6,392

    @yojimbo2000 I totally forgot about setRect, thanks for the reminder. @em2 Here’s an example of 1000 sprites moving around the screen at 59 or 60 FPS. This uses 1 mesh and the addRect and setRect functions.

    displayMode(FULLSCREEN)
    
    function setup()
        tab={}
        m=mesh()
        m.texture=readImage("Planet Cute:Character Horn Girl")
        for z=1,1000 do
            x=math.random(20,WIDTH-20)
            y=math.random(30,HEIGHT-30)
            xv=math.random(-5,5)
            if xv==0 then
                xv=1
            end
            yv=math.random(-5,5)
            if yv==0 then
                yv=-1
            end
            table.insert(tab,vec4(x,y,xv,yv))
            m:addRect(x,y,30,60)
        end
    end
    
    function draw()
        background(40, 40, 50)
        for a,b in pairs(tab) do
            b.x=b.x+b.z
            if b.x<20 or b.x>WIDTH-20 then
                b.z=-b.z
            end
            b.y=b.y+b.w  
            if b.y<30 or b.y>HEIGHT-30 then
                b.w=-b.w
            end
            m:setRect(a,b.x,b.y,30,60)
        end
        m:draw()
        fill(255, 0, 0, 255)
        fps=1/DeltaTime//1
        text(fps,WIDTH/2,HEIGHT-20)
    end
    
  • em2em2
    Posts: 174

    @dave1707 you are the king of conciseness! Thanks a lot.

  • em2em2
    Posts: 174

    @yojimbo2000 I have already devised a way to cut the number of objects being drawn. Thanks for the tip.

  • dave1707dave1707 Mod
    Posts: 6,392

    @em2 I increased the number of sprites in my above code from 1000 to 3000 and the FPS was still at 59 fps. At 4000 it dropped to 52 fps and at 5000 it dropped to 41 fps. At 8000 it was 24 fps and at 10,000 it was 17 fps. So using 1 mesh with addRect and setRect allows you to really increase the number of objects with not too much of a decrease in fps. Not sure what someone would use 10,000 objects for.

Sign In or Register to comment.