Creating a set of buffers for tiles I am currently converting a 2D game to 3D, never having worked with 3D before I am trying to learn as I go. I am wondering what the best way to use vertex/index buffers is.

I am currently looping through a grid and creating a set of buffers for each tile type, which are are then used in the draw method. I'm presuming I shouldn't use multiple sets of vertex buffers, but I don't know of another way to do this, as each tile is a different texture.

Grid loop

for (int i = Convert.ToInt32(xPos / 2) - 30; i &lt; Convert.ToInt32(xPos / 2) + 30; i++)
{
    for (int a = Convert.ToInt32(yPos / 2); a &lt; Convert.ToInt32(yPos / 2) + 50; a++)
    {
        if (mapXtile &gt; 0 &amp;&amp; mapYtile &gt; 0 &amp;&amp; mapXtile &lt; Globals.mapsizex &amp;&amp; mapYtile &lt; Globals.mapsizey)
        {
            int currentTile = Globals.levelArray[level, mapXtile, mapYtile].TyleType;

            if (currentTile == tyleType.grass)
            {
                createCubeVertices(i * 2, a * 2, 1, 0f, count, grassVertices);
                SetUpBufferIndices(count, grassIndices);
                count++;
            }

            if (currentTile == tyleType.water)
            {
                createCubeVertices(i * 2, a * 2, 1, 0f, count, waterVertices);
                SetUpBufferIndices(count, waterIndices);
                waterCount++;
            }
        }
        mapYtile = mapYtile + 1;
        //mapYtile++;
    }
    mapXtile = mapXtile + 1;
    mapYtile = Convert.ToInt32(yPos / 2);
}

CopyToBuffers(grassVertices, grassIndices);
CopyToWaterBuffers(waterVertices, waterIndices);


Draw code

foreach (EffectPass pass in grassEffect.CurrentTechnique.Passes)
{
    pass.Apply();

    device.Indices = myIndexBuffer;
    device.SetVertexBuffer(myVertexBuffer);
    device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, grassVertices.Length, 0, grassIndices.Length/3);  
}

foreach (EffectPass pass in mouseEffect.CurrentTechnique.Passes)
{
    pass.Apply();

    device.Indices = myWaterIndexBuffer;
    device.SetVertexBuffer(myWaterVertexBuffer);
    device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 10000, 0, 10000);
}
You could batch by tiletype, so that the number of buffers submitted is only n (where n is the number of tile types).

e.g.

Dictionary&lt;TileType,List&lt;Tuple&lt;int,int&gt;&gt;&gt; tiles = new Dictionary&lt;TileType,List&lt;Tuple&lt;int,int&gt;&gt;&gt;();

for (int x = Convert.ToInt32(xPos / 2) - 30; x &lt; Convert.ToInt32(xPos / 2) + 30; x++)
{
    for (int y = Convert.ToInt32(yPos / 2); y &lt; Convert.ToInt32(yPos / 2) + 50; y++)
    {
        if (mapXtile &gt; 0 &amp;&amp; mapYtile &gt; 0 &amp;&amp; mapXtile &lt; Globals.mapsizex &amp;&amp; mapYtile &lt; Globals.mapsizey)
        {
            int currentTile = Globals.levelArray[level, mapXtile, mapYtile].TyleType;

            if(!tiles.ContainsKey((TileType)currentTile))
            {
                tiles.Add((TileType)currentTile, new List&lt;Tuple&lt;int,int&gt;&gt;());
            }
            tiles[(TileType)currentTile].Add(new Tuple&lt;int,int&gt;(x*2,y*2));
        }
        mapYtile = mapYtile + 1;
        //mapYtile++;
    }
    mapXtile = mapXtile + 1;
    mapYtile = Convert.ToInt32(yPos / 2);
}

foreach(var tileCoords in tiles[TyleType.grass])
{
    //You would have to modify this to append to the buffer
    createCubeVertices(tileCoords.Item1, tileCoords.Item2, 1, 0f, count, grassVertices);
    SetUpBufferIndices(count, grassIndices);
    count++;
}

foreach(var tileCoords in tiles[TyleType.water])
{
    //You would have to modify this to append to the buffer
    createCubeVertices(tileCoords.Item1, tileCoords.Item2, 1, 0f, count, waterVertices);
    SetUpBufferIndices(count, waterIndices);
    count++;
}

CopyToBuffers(grassVertices, grassIndices);
CopyToWaterBuffers(waterVertices, waterIndices);


While this does involve additional looping, the extra looping will be considerably faster than clearing / sending buffers redundantly.

On the other hand since you seem to be rendering the same couple of meshes multiple times. have you considered Instanced Rendering? That will be a significant speed up, even over batching, and should result in some cleaner code too.