Limiting area drawn a bit

Started by
12 comments, last by Erik Rufelt 15 years, 1 month ago
Quote:Original post by Erik Rufelt
The corner-coordinates are in world OpenGL coordinates. You never want to cull tiles, just sectors right?


Umm sector is collection of tiles(in my case 32x32 though that's adjustable in settings). World is collection of sectors(currently 6x6 though again adjustable in settings). I wouldn't want to draw every single tile as techicly there's no reason why sector couldn't be 10000x10000 tiles(though obviously that would be getting pretty silly). I specifically would wish to limit number of tiles to not draw any more tiles than absolutly neccessary.

Though I suppose I CAN draw it but that will be lots o' wasted effort drawing stuff that's outside the camera.

Would determining number of tiles in X/Z axis(and starting point) be slower than drawing spare tiles? If I draw complete sectors then in worst case scenario I would be in my example be drawing total of 4096 tiles when only 484 tiles is actually needed(and even that includes tiles off the camera but getting non-rectangle area limited is probably inefficient). Almost 10x as many tiles as is needed! And we aren't even talking about objects yet which would cause similar wasted effort if I would draw full sectors.

And if we assume average vertex count for terrain tile is 8(ATM tile #1 has 6, tile #2 has 12. Polygonwise one of them has 18 and other 2(but then again the 2 is just flat ground)) that's 32000 vertexes to be drawn. Ugh. When 3200 or thereabout would be enough.

Doable and I suppose it wouldn't be issue in my limited needs but sure would hate to do so inefficient engine here.

Edit: Crap. I think I know where the issue might lie. I wonder if the sector co-ordinates are essentially from top-left to bottom right. Ie 0,0 tile is at top-left of sector. This would play havoc of drawing routine...Have to check this.
Advertisement
Depends on your target hardware, on most modern hardware you could draw 320,000 vertices without any problems. However I get what you are saying, you want to cull tiles then. It should work the same way.
First you calculate the corner points, and divide by tile-width instead of sector-width, which gives you a rect in global tile-indexes, starting at tile 0,0 in sector 0,0. Then you also calculate sector-indexes by dividing tile-indexes by 32. Then you draw the visible sectors, and within them subtract sector-index*32 from the tile-index, which gives you the relative tile-index within the sector. Then draw only those tiles within the sector.

What I have written so far in all my posts deals with finding the index numbers of the visible tiles and/or sectors. This may or may not be what you need, if you treat the player sector as 0,0. Then you might instead need to simply keep the rectangle world-coordinates directly from the corner points, and compare these to each sector you try to draw. If they fall within the sector, then proceed by calculating the tile-indexes from there.

I'm not sure how you handle everything in your engine, so I can't say the best method to cull geometry. The main method of getting the area of the ground intersected by the camera view-frustum should give correct numbers, as long as the ground is reasonably flat (if not simply use the lowest point on the ground). From there it should not be too hard to calculate which geometry is currently within that area, but how to do it depends on details in how you draw everything.

Usually the camera is set up like the following:
glLoadIdentity();glRotatef(x, 1.0f, 0.0f, 0.0f);glRotatef(y, 0.0f, 1.0f, 0.0f);glTranslatef(-x, -y, -z);

If you do it like that, then find the corner points, then they will be relative 0,0,0 in OpenGL coordinates. If you at a later time do other changes to the matrix, then the coordinates you give OpenGL will of course no longer match the corner point coordinate space, so you have to compensate by subtracting the current coordinate space offset from the old one.
Thanks. I'll try to get it working.

BTW the black area issue I got fixed. I forgot to carry the x and z offsets into recursive calls so in the end that sector simply got drawn top of already drawn sector. Damn I felt stupid :D

And yeah the camera is set just like that in my game(well except for some reason I have third angle added as well though I don't think I really need it...Leftover from my first 3d-attempts for space flight simulator I suppose :D

Edit: And reason to limit drawing area to tile: Already FPS is ~200 when I draw rectangle whose size I have created by trial and error(problem is that it's not particulary flexible. Change screen resolution and it goes haywire. Change zoom level and it goes haywire. Change block size and it goes haywire). This with vertex arrays and arrays in graphic cards memory. This with pretty darned fast computer.

Actually I'm starting to wonder wether I'm doing something seriously wrong. Afterall there's just simple terrain and one model neither which is particulary detailed and 200FPS? There's not even that much non-drawing stuff done!

Albeit I can divide FPS by 5 and still have it good but sure is dropping scarily fast...

[Edited by - tneva82 on April 14, 2009 1:47:32 PM]
I guess you are drawing one tile at a time?
This is why you might only want to cull sectors. If you have 32x32 tiles in a sector, that is 1024 draw() calls when drawing them one at a time. Now say you have two partly visible sectors, and need to draw about 500 tiles, it is very possible that drawing 500 tiles one at a time is slower than drawing 2048 (or even much more) tiles in one call. Especially if the vertex array is in video memory, where the only real overhead is the draw call.

It's insanely fast when you batch geometry up like that, already in video memory. I have an old application where I draw a terrain in one draw call, of size 1024x1024, giving more than two million triangles, and it runs at more than 200 FPS (Nvidia 8800GT). Of course you want to support lower end cards also, but I doubt anything below 100,000 triangles will be a problem.

If you have the memory, I would try building a large vertex array for the whole sector, and draw it in as few draw() calls as possible. You have indicated you already use a technique that allows for dynamic loading of sectors, in which case you don't need to keep very many sectors in video memory at a time.
To limit the number of draw calls, sort the triangles by texture, or better yet make a large texture in which you combine all the textures needed for that sector (put them side by side in a larger image), and just modify the texture coords to match the new texture.

If you do not want to do that then I would continue with the method you use now, and get an exact rectangle enclosing visible tiles, you can't really get much better than that.

This topic is closed to new replies.

Advertisement