# 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 < Convert.ToInt32(xPos / 2) + 30; i++)
{
for (int a = Convert.ToInt32(yPos / 2); a < Convert.ToInt32(yPos / 2) + 50; a++)
{
if (mapXtile > 0 && mapYtile > 0 && mapXtile < Globals.mapsizex && mapYtile < 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<TileType,List<Tuple<int,int>>> tiles = new Dictionary<TileType,List<Tuple<int,int>>>();

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

if(!tiles.ContainsKey((TileType)currentTile))
{
}
}
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.