# How to draw millions of cubes without idle , model instancing in XNA?

I work for a project in the style of game "Minecraft".

I started using the "Model Instancing" in order to generate a large number of cubes possessing an identical model. So far so good. My problem is that if I increase the size of my matrix to draw from [300-1-300] (90,000 cubic meters) of [500-1-500] (250,000 cubic meters) my program slows down tremendously. It goes from 60fps to 20 ...

I do not really understand why. But I use the technique correctly "Hardware Instancing". I also noticed on forums that this technique allows XNA to draw up to 7 million cubic!! Do you have any idea from where my problem ?

Thanks a lots

Here is my function that draws the model instantiated:

// Draw the 3D map (world) of game
public void drawWorld(GameTime gameTime)
{
/ * Draw all the structures that make up the world with the instancing system * /
Array.Resize(ref instanceTransforms, smallListInstance.Count);

for (int i = 0; i < ListInstance.Count; i++)
{
instanceTransforms[i] = ListInstance[i].Transform;
}

}
// ### end function drawWorld


Here is my function [DrawModelHardwareInstancing] which draws models with the method [Hardware Instancing] used in the sample from microsoft.

// Function that will draw all the models instantiated in the list
void DrawModelHardwareInstancing(Model model,Texture2D texture, Matrix[] modelBones,
Matrix[] instances, Matrix view, Matrix projection)
{
Game.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
if (instances.Length == 0)
return;

// If we have more instances than room in our vertex buffer, grow it to the neccessary size.
if ((instanceVertexBuffer == null) ||
(instances.Length > instanceVertexBuffer.VertexCount))
{
if (instanceVertexBuffer != null)
instanceVertexBuffer.Dispose();

instanceVertexBuffer = new DynamicVertexBuffer(Game.GraphicsDevice, instanceVertexDeclaration,
instances.Length, BufferUsage.WriteOnly);
}

// Transfer the latest instance transform matrices into the instanceVertexBuffer.

foreach (ModelMesh mesh in model.Meshes)
{
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
// Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer.
Game.GraphicsDevice.SetVertexBuffers(
new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
new VertexBufferBinding(instanceVertexBuffer, 0, 1)
);

Game.GraphicsDevice.Indices = meshPart.IndexBuffer;

// Set up the instance rendering effect.
Effect effect = meshPart.Effect;
//effect.CurrentTechnique = effect.Techniques["HardwareInstancing"];
effect.Parameters["World"].SetValue(modelBones[mesh.ParentBone.Index]);
effect.Parameters["View"].SetValue(view);
effect.Parameters["Projection"].SetValue(projection);
effect.Parameters["Texture"].SetValue(texture);

// Draw all the instance copies in a single call.
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();

Game.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
meshPart.NumVertices, meshPart.StartIndex,
meshPart.PrimitiveCount, instances.Length);
}
}

}
}
// ### end function DrawModelHardwareInstancing

• Generate a 3D model per chunk based upon exposed surfaces and update when things get broken or added. – ClassicThunder Mar 11 '13 at 13:49
• Yes thank you, but I realized my problem. I update every frame. So should I update only when necessity – Mehdi Bugnard Mar 11 '13 at 15:17

You shouldn't be attempting to instance individual cubes at all.

I developed Techcraft together with two close dev friends. It has all the sample code you will need to learn from, if it helps.

Feel free to download the source code and use as you wish:

http://techcraft.codeplex.com

Good luck! Hopefully we can add your game to the list on the project page.

• Waouhh. Thank you very much for the link. I will directly download this "sample". However what do you mean by "You Should not Be instance Attempting to individual cubes at all"? – Mehdi Bugnard Mar 11 '13 at 15:24
• I think he means that in terms of rendering you should be batching your cubes together and rendering each batch once per texture type. – Nic Foster Mar 11 '13 at 17:21
• Yes as Nic mentioned, its too intensive to attempt to create individual buffers for each cube. Instead, you need to work out the World View Projection matrix of your view frustum and calculate (based on the view distance you want) the cubes together. This single vertex buffer of viewable cubes is then sent to the gpu for tesselation. Again, perform a generation of the vertex buffer for all cubes, and tesselate that. The commit version techcraft.codeplex.com/SourceControl/changeset/3ba3afc07ceb is the simplest example of procedural voxel terrain in the sample code. That should help. – Jason Coombes Mar 12 '13 at 6:09
• thank you Jason Coombes and nic foster ^^ i have bette understand ! And the sample help me – Mehdi Bugnard Mar 12 '13 at 7:44