In an hexgrid based game, I render all terrain tiles as a separate model, reusing the same texture objects on all similar tiles. The tiles is a pretty simple model.

When the terrain is set to be at 20x20 or more (so 400 tiles), the game really slows down. The "slowdown point" is about the same on my i5 laptop or my i7 desktop. The game takes around 30megs in the memory. Here is how the render looks like :

enter image description here

The way I render each tile is the following :

foreach (ModelMesh mesh in ModelSupport.Meshes)
    foreach (BasicEffect effect in mesh.Effects)
        effect.World = transforms[mesh.ParentBone.Index] 
            * mScale * mRotationY * mPosition;
        effect.View = Camera.ViewMatrix;
        effect.Projection = Camera.ProjectionMatrix;


Any suggestion of how I could optimize the rendering of a large amount of models?


I believe you want hardware instancing.


  • \$\begingroup\$ I do believe it's exactly what I was looking for! I'll let you know once it's tested :-) \$\endgroup\$ – Tipx Jan 21 '12 at 21:26
  • \$\begingroup\$ Worked like a charm! I now get the same lag with 250x250 that I use to get with 25x25 so it's 100 times faster. I just did a proof of concept the dirty way and I know I can optimize my code to get it like... over 9000 times faster!!! \$\endgroup\$ – Tipx Jan 24 '12 at 4:53
  • \$\begingroup\$ Glad to help. There is overhead on each draw call. Both instancing and combining them into one vertex array do about the same thing as they get rid of that overhead which as you see is hefty when the models are very simple. No need to remove back facing tris though as XNA culls them by default. \$\endgroup\$ – ClassicThunder Jan 24 '12 at 5:16
  • \$\begingroup\$ It looks to me like the link above is 404'ing - I believe this is the equivalent. xbox.create.msdn.com/en-US/education/catalog/sample/… \$\endgroup\$ – Matt DeKrey Dec 21 '13 at 14:45

If you're really rendering each tile as a static hexagonal model, then you're wasting a lot of resources on the side faces that will not be visible.

Think about doing it like Minecraft, instead: generate the side faces programmatically (or create them as separate models from the top), and include each face only if its tile is higher than its neighbor in that direction, and make them no taller than necessary. Take a reasonably-sized bunch of such computed tiles and put them all in one vertex array.

  • \$\begingroup\$ It's not a bad idea. At some point, the tiles will be moving up and down so it would make the thing a bit more complicated, especially since I've never experimented with dynamically creating models (which I'll do at some point). I'll try to implement @ClassicThunder's solution this week because even if I change the way I'm rendering tiles one day, I'll need to use what he pointed me to at some point for the units and other map components. \$\endgroup\$ – Tipx Jan 22 '12 at 17:06
  • \$\begingroup\$ Doing it more than once isn't that much more complicated than doing it once :) — you just have to do the generation efficiently, and choose an appropriate chunk size (number of tiles per “model”) to trade off number of draw calls vs. time to rebuild a single model. \$\endgroup\$ – Kevin Reid Jan 23 '12 at 1:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.