4
\$\begingroup\$

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);
}
\$\endgroup\$
1
\$\begingroup\$

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))
            {
                tiles.Add((TileType)currentTile, new List<Tuple<int,int>>());
            }
            tiles[(TileType)currentTile].Add(new Tuple<int,int>(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.

\$\endgroup\$

Your Answer

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