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;
}
DrawModelHardwareInstancing(myModel, myTexture2D,instancedModelBones,instanceTransforms, arcadia.camera.View, arcadia.camera.Projection);
}
// ### 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.
instanceVertexBuffer.SetData(instances, 0, instances.Length, SetDataOptions.Discard);
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
Answer
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:
Good luck! Hopefully we can add your game to the list on the project page.
No comments:
Post a Comment