XNA Creators Club Online
Page 1 of 1 (22 items)
Sort Posts: Previous Next

Lots of models performance issue

Last post 09-03-2008 4:23 PM by Shawn Hargreaves. 21 replies.
  • 08-29-2008 8:08 AM

    Lots of models performance issue

    As anyone who read my posts can see, I`m still a begginer in game development.

    I have a question that`s been tormenting me for some time now.
    I`m trying to create a simple RTS game, and I want to display a map with lots of units on it.
    I have a unit model that has about 1200 vertices, and i want to display 1000 of them, or more.
    To display the model i`ve created a class UnitClass, which is derived from DrawableGameComponent.

    The way I`m doing the display is like this:
    - i create a list of 1000 instances of the UnitClass, each with its on start position on the map;
    - in the load content function of the main game i load the content for the entire list (using a for loop);
    - in the update function i call the update for the entire list (using a for loop);
    - in the draw function, i call the draw method for all the elements in the list (using a for loop);
    - in the draw methods of the UnitClass i`m calculating the new positions of the unit, and then i draw the mesh again.

    From what I can tell, this approach is very performance taxing. Is there another way to populate a map with lots of models, and still perserve some performance?




  • 08-29-2008 8:30 AM In reply to

    Re: Lots of models performance issue

    Hi Cosmin,

    Whilst I too am a beginner, I think there are a few things that you could do to improve performance.

    It sounds like you are rendering the entire list, whether the units are on the screen or not.  For this you could probably implement a Quadtree, which basically filters through a bunch of 'nodes', checking all the while if this particular node is visible by the camera.  This starts at a parent (largest) node and goes down into progressivly smaller (child) nodes.  When the last node is reached (leaf node) AND if it is visible, you render all units attached to the node.  This should save alot of draw calls.  There are loads of references on the net, so just google it.

     

    The code for moving the units should be within the Update() method, as the position will most likely always be changing, even though you won't always be rendering the unit.  Also, I'm not sure what you mean by 

     

    cosmin:
    and then i draw the mesh again.

     

    as you should only draw a unit once per frame, all the changes to the unit (class) should be done in update.

     

    I think there is also a better way than loading the models and textures for each unit individually, by implementing a texture/model manager.  Although I'm not too sure about this because I think the content manager sort of helps with this (I think it only loads resources once, even if the code attemps to load the same resource again?)

     

    If you need any more help, or a better explanation of a quadtree, then just ask.

     

    Hope this helps,

     -Lintford Pickle

     


  • 08-29-2008 9:15 AM In reply to

    Re: Lots of models performance issue


    Lintford Pickle:
    Hi Cosmin,

    Whilst I too am a beginner, I think there are a few things that you could do to improve performance.

    It sounds like you are rendering the entire list, whether the units are on the screen or not.  For this you could probably implement a Quadtree, which basically filters through a bunch of 'nodes', checking all the while if this particular node is visible by the camera.  This starts at a parent (largest) node and goes down into progressivly smaller (child) nodes.  When the last node is reached (leaf node) AND if it is visible, you render all units attached to the node.  This should save alot of draw calls.  There are loads of references on the net, so just google it.

     

     I already know about quadtree.
    I`m assuming that all the unit are in the visible range.
    All the changes to the unit position are done in the update of the unit class.
    The draw event is called every frame i think.

  • 08-29-2008 9:31 AM In reply to

    Re: Lots of models performance issue

    Hello again,
    cosmin:
     I already know about quadtree.
    Ihttp://www.ziggyware.com/news.php?readmore=336`m assuming that all the unit are in the visible range.
    All the changes to the unit position are done in the update of the unit class.
    The draw event is called every frame i think.

     

    Then perhaps, as another suggestion, you could try to implement Hardware Instancing.  This is not something I have tried before, but I think the idea is to send two streams to the graphic device.  One with the original vertex information (i.e. the model), and the other with all the instancing data (all the positions, rotations etc.).  this way, the rendering can be done with 1 draw call (per unit type) and almost entirly on the GPU, as you only send the textures/models once.

    I think there is an article on Ziggyware, as well as a few samples.

    http://www.ziggyware.com/weblinks.php?cat_id=13&weblink_item=3999

    http://www.ziggyware.com/news.php?readmore=336

     

    Again, I'm no expert, but maybe this would help?

    -Lintford

     

     

  • 08-29-2008 10:54 AM In reply to

    Re: Lots of models performance issue

    I`ll try this Hardware instancing approach.. Perhaps is something there..:)

    Thanks.


  • 08-29-2008 11:25 AM In reply to

    Re: Lots of models performance issue

    If your view can be of part of the map, rather than the whole map - for instance if you can zoom in or rotate the camera - then you may find it helpful to avoid drawing models which are not in view. Depending on your setup this can be a small saving or a large one. An easy way do this is is to create a BoundingFrustum from your view and projection matrixes in your Draw() method. Then before drawing each model, test whether it intersects with the frustum. If it doesn't, don't draw it.

    The code would go something like this (from memory, so I can't guarantee this is error free):

    BoundingFrustum viewFrustum = new BoundingFrustum(ViewMatrix * ProjectionMatrix); 
     
    foreach (Model model in myModelList) 
        Vector3 position = GetModelPosition(model); // get the position from wherever you store it 
        foreach (ModelMesh mesh in model.Meshes) 
        { 
            BoundingSphere sphere = new BoundingSphere(mesh.BoundingSphere.Center + position, mesh.BoundingSphere.Radius); 
            if (!viewFrustum.Intersects(sphere)) 
                continue// don't draw this mesh, it's not in view 
     
            // (drawing code here) 
            ... 
        } 
     

    If/when the whole map is in view, I imagine a good number of your objects are quite tiny onscreen. You may want to consider having two or more levels of detail for your objects. An easy way to do this is to simply have two or more Models representing the same object. One of them is normal, to be used when the model you're drawing is close to the camera. The other(s) have progressively less and less detail (less vertexes, possibly lower resolution textures, etc.). Then at draw time you compare the object's position to the camera position to work out the distance from the camera. If the model is far from the camera, you select an appropriately low detail model. Assuming your game is also for the PC, you could also allow the user to choose the maximum level of detail in the game options, so that slow PCs can run the game quicker.

    Having said all that, with a thousand objects onscreen, some form of instancing is quite likely the way to go, if it's necessary for your game to be able to see all these objects simultaneously.

    --formerly Genstein
  • 08-29-2008 3:11 PM In reply to

    Re: Lots of models performance issue

    1200 verts per model and 1000 models at once? My guess is to get 1000 on the screen at once, they will need to be pretty small, which means 1200 verts might be overkill. However, if you ever zoom in on them you may need 1200 verts to have nice looking models up close. Sounds like a good case for LOD for your models. At a distance maybe they're 100 verts, and up close they're 1200 verts.
    XNA QuickStart Engine | My site
    "I'll be whatever I want to do!", Philip J. Fry
  • 08-29-2008 4:04 PM In reply to

    Re: Lots of models performance issue

    To draw 1000 models at once, you definitely want to be using some kind of instancing technique. Check out the Instancing sample on this site for details.
    XNA Framework Developer - blog - homepage
  • 08-29-2008 5:55 PM In reply to

    Re: Lots of models performance issue

    If your screen is 1280x720 in size, each screen is 921,600 pixels.

    If you display 1,000 units, that means each unit gets an average of 921 pixels -- assuming there's no space for terrain, GUI, etc.

    Do you really need 1200 verts for a 900 pixel unit? That's more than one vertex per pixel. In general, you want to have about 10 pixels per triangle, which turns into about 5 pixels per vertex. It seems like you need to work on some level of detail meshes for your units.

    Also, if there are 1,000 of them on the screen, how will the user actually interact with them?

    Jon Watte, Direct3D MVP kW X-port 3ds Max .X exporter kW Animation source code
  • 08-29-2008 8:24 PM In reply to

    Re: Lots of models performance issue


    jwatte:

    Also, if there are 1,000 of them on the screen, how will the user actually interact with them?

    I intend to make a RTS game, and so 1000 units wont be that much.. :). The interaction will be at unit level and/or groups..
    Thanks all of you for your reply. Very useful.
    For the moment, as I see the situation, i have 2 options: either use a LOD for the meshes, or use some kind of instancing..

  • 08-29-2008 10:12 PM In reply to

    Re: Lots of models performance issue

    cosmin:

    For the moment, as I see the situation, i have 2 options: either use a LOD for the meshes, or use some kind of instancing..

    I suspect you will need both.

    With instancing alone, you would end up with efficient CPU code (just one draw call for all your units) but you would be sending 1000 * detailed model to the graphics card, which is going to take it a long time to draw.

    With mesh LOD alone, you will be sending less triangles to the graphics card, but you will be issuing thousands of separate draw calls, which will grind your CPU to a halt.

    To get great performance, you want both a small number of draw calls and a small number of triangles.

    XNA Framework Developer - blog - homepage
  • 08-29-2008 11:51 PM In reply to

    Re: Lots of models performance issue

    I intend to make a RTS game, and so 1000 units wont be that much.. :)

    You do realize that in Warcraft III, the user had less than 100 units to a side, right? 1,000 units really is a whole darned lot.

    Unless you're calling a phalanx of 36 archers one "unit" but draw each individual archer. However, in that case, 1200 polys per archer is way overkill.