0

I have a method that I use to render little map using tiles, but when I finish rendering and I want to make a translation changing "transY" variable using different method nothing happens, so I must call RenderTesture() again to make it. How can I do this withot unnecessary rendering because it can slow down application when I use larger number of tiles?

void RenderTexture ()
{
    MakeCurrent ();
    GL.Clear((int)All.ColorBufferBit | (int)All.DepthBufferBit);
    GL.MatrixMode(All.Modelview);
    GL.LoadIdentity();

    GL.Translate(-transX, transY, -10);

    for (int i = 0; i < tileRows; i++) 
    {
        for (int j = 0; j < tileColumns; j++)
        {
            GL.BindTexture(All.Texture2D, textureIds [i*tileColumns + j]);
            GL.EnableClientState(All.VertexArray);
            GL.EnableClientState(All.TextureCoordArray);
            GL.PushMatrix ();
            GL.Translate(j*2, -i*2, 0);
            GL.VertexPointer(3, All.Float, 0, frontV);
            GL.TexCoordPointer(2, All.Float, 0, frontT);
            GL.DrawArrays (All.TriangleFan, 0, 4);
            GL.PopMatrix ();
        }
    }
    GL.DisableClientState(All.VertexArray);
    GL.DisableClientState(All.TextureCoordArray);

    SwapBuffers ();
}

If anybody have advice for me, I'll be very grateful!

Thanks in advance!

Bube
  • 31
  • 5

2 Answers2

0

The bottleneck lies, most likely, in the amount of state changes (GL.BindTexture) and the amount of draw calls you are making (GL.DrawArrays). In general, you should draw as much as possible in a single draw call.

The simplest approach wold be to use a "texture atlas":

  1. combine all your tile textures into a single large texture (this is the "texture atlas")
  2. combine all your tile vertices into a single vertex array
  3. call GL.BindTexture once to bind the texture atlas
  4. call GL.DrawArrays once to render all tiles

So how do you render different tile textures? Simple: you change the vertex texture coordinates to point to the correct tile inside the texture atlas.

A single 1024x1024 can hold 256 distinct 64x64 tiles. Depending on the amount of distinct tiles in your game, you might have to use multiple texture atlases. Moreover, depending on the size of your map, you might wish to split it into "regions" with separate vertex arrays for each (you don't want to render 1 million tiles every frame if your monitor can only display 1000 tiles.)

On its own, this will give a measurable performance boost. Once this is working, you can get a second large boost by storing your vertex arrays on the GPU via Vertex Buffer Objects (VBOs).

The Fiddler
  • 2,726
  • 22
  • 28
0

Thank you very much!

The "Texture atlas" strategy can be very good idea. I've implemented that last night and it looks like rendering is getting speed. I've reduce loading of NxM tiles using separate textures, by loading one big NxM tiles bitmap using single texture and I've implemented method to change vertex array (in regard to new bitmap dimensions - NxM)

    public void UpdateFrontVertex(int rowNumber, int columnsNumber)
    {
        for (int i = 0; i < 12; i++) {
            if (i % 3 == 0)
                frontVertex [i] = defaultFrontVertex[i] * rowNumber;    // x-axis
            else if (i % 3 == 1)
                frontVertex [i] = defaultFrontVertex[i] * columnsNumber;    // y-axis
            else if (i % 3 == 2)
                frontVertex [i] = defaultFrontVertex[i];    // z-axis
        }
    }

After that, I've got my map!!!

I still cannot compare performances before that implementation and now because I have to make changes for panning and zooming functionalities to work with that new rendering strategy. For example, I've used

//zoom in
transY = (transY * 2 + 1);
transX = (transX * 2 + 1);

//zoom out
transX = ((transX - 1) / 2);
transY = ((transY - 1) / 2);

for zooming calculations to figure out which tile is my central tile, and after that to load all rounding tiles.

Thank you again for great help, I'll proceed now with panning and zooming implementation.

Bube
  • 31
  • 5