Rich's picture

OpenTK instead of Tao

Hello there!

I'm currently using Tao & Mono for my Project to rebuild a 10 year old 2D game.
I came to your side once in a while and I think that OpenTK is much more serious than Tao.

My question is now:

Is OpenTK a good choice for that? Are there more advantages than less cryptic code (which is a present from heaven for me)?

thx rich


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Yes, display lists should be faster in this case. The best ways to improve performance are to:

  1. Draw more stuff with less calls. Modern hardware performs best when you draw at least (IIRC) 4096 vertices per draw call - anything less and it starts to stall.
  2. Minimize state changes. Sorting everything by shader / texture will be much faster than binding a different shader / texture every time you issue a draw call.

Display lists help in both regards: you draw more stuff in one call and they driver may be able to minimize state changes.

However, before you go in and make any large changes, make sure you are benchmarking a release build (this includes OpenTK) ran outside of the IDE. It is a good idea to try a profiler, too - you wouldn't want to optimize something that isn't a bottleneck!

Rich's picture

@the Fiddler: what you mean with your seconde statement (2.)? how can i sort everything by shader / texture? can you give me a tutorial, because i do not really understand what you mean with it!

ok thx for your advice... I'll give those display lists a try, and i hope that i'll get a huge performance boost :).
I also think i put the mushrooms and stuff into the lists because they will never change or vanish during game play.

But first i will run everything outside the IDE...

thx rich

the Fiddler's picture

If you keep a different texture per tile, you can improve performance a lot by drawing all grass tiles first, all water tiles next, etc.

Instead of this (pseudo-code):

for (int y = 0; y < map.Height; y++)
{
    for (int x = 0; x < map.Width; x++)
    {
        // Bind texture
        // Draw tile map[x, y]
    }
}

you can do this:

// When you load your map, sort the tiles by texture:
Dictionary<Texture, List<Point>> sorted_tiles = new Dictionary<Texture, List<Point>>();
for (int y = 0; y < map.Height; y++)
{
    for (int x = 0; x < map.Width; x++)
    {
        if (!sorted_tiles.Contains(map[x, y].Texture))
            sorted_tiles.Add(map[x, y].Texture, new List<Point>());
 
       sorted_tiles[map[x, y].Texture].Add(new Point(x, y));
    }
}
 
// In your draw function
foreach (var texture in sorted_tiles.Keys)
{
    // Bind texture, then
    foreach (var point in sorted_tiles[texture])
    {
        // Draw tile map[point.X, point.Y]
    }
}

This way you reduce the number of times you need to call GL.BindTexture, which can give a nice performance boost. How nice? Try commenting out your BindTexture calls and see if your fps improve.

Rich's picture

Hello there,

after a long break, i sorted the BindTexture calls and reduced them to a minimum. It turns out that the map now needs 0 milliseconds which is a huge improvement!
But still an annoying problem: the frame flickers black. With the old implementation the frame is constantly drawn without any flickering. Any suggestions? (I cannot remove the clear - colorbit call because my game does not cover the hole frame)

thx

the Fiddler's picture

This shouldn't happen. Are you, by any chance, drawing to the front buffer? (This is no longer supported in OpenGL).

As long as you don't call GL.DrawBuffer(DrawBufferMode.Front) and call SwapBuffers at the end of the RenderFrame event, there shouldn't be any flickering at all.

Rich's picture

This is my code: (I use VBOs)

//1 ms + no flickering
/*for (int i=0;i<600;i++)
{
	Textures.BindTexture(todraw[i]);
	GL.DrawArrays(BeginMode.Quads,i*4,4);
}*/
 
//0 ms + flickering
for (int i=0;i < 600;i++)
{
	if (todraw[i] != -1)
	{
		Textures.BindTexture(todraw[i]);
		int bound = todraw[i];
		for (int j=0;j < 600;j++)
		{
			if (bound == todraw[j])
			{	
				GL.DrawArrays(BeginMode.Quads,j*4,4);
				todraw[j] = -1;
			}
		}
	}
}
the Fiddler's picture

What does the flickering look like? Does the whole screen flash between black and color? Only the tiles? Can you capture it in a screenshot?

Rich's picture

Like this:

AttachmentSize
Bildschirmfoto.png238.47 KB
Rich's picture

Finally i found the error:

I do not update the mapdata every frame. So if i set the todraw[i] = -1; -> the nextframe do not do anything and just clears the map...

This works fine:

List<int> list = new List<int>();
foreach (int i in todraw)
{
	if (!list.Contains(i))
	list.Add(i);
}
 
foreach (int i in list)
{
	Textures.BindTexture(i);
	for (int j=0;j < 600;j++)
	{
		if (i == todraw[j])
		{	
			GL.DrawArrays(BeginMode.Quads,j*4,4);
		}
	}
}