# Terrain editor performance.

This topic is 3034 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Ahoy. After realising that creating each individual tile on the map would take me a few centuries, I added a generator to populate the map with a starting grid of x*y tiles. This is when I discovered that the performance is erm... not very good. At 50x50, performance is acceptable (with the rag-tag frame rate calculator showing about 23 FPS) but still, 23 FPS on just a textureless map with no other objects in the world will never do. 50x50 is also WAY too small; the player could run from one end to the other in 10-20 seconds. Bumping it up to 100x100, FPS drops to 9. 100x100 is also still too small. At the ideal 300x300, FPS is 0-1 and moving the camera takes a few seconds to update. So I'm wondering what my options are here. Being able to only draw 2500 quads at 23 FPS is a bit extreme. It could just be my amazing 64Mb onboard graphics card, but I can play a lot of games (e.g. WoW) perfectly fine and I'm sure they use more than 2500/5000 triangles. I also struggle to believe that a PS2 with its 32Mb RAM and 4Mb graphics card is capable of drawing larger terrain than my PC with over 10x the resources. The only other thing I can think of is code optimization, but the only thing I can do there is play with the loops. Each tile is one iteration due to the per-tile structure so at best, I could change it so that one "terrain node" holds data for 4 tiles and then have the loop draw all 4 in one iteration. Any other suggestions would be appreciated. (Note: Using a display list for the map made no difference. In fact, this holds true for every occasion I've used display lists so far. Maybe I'm doing it wrong.)  To give you some idea of scale: a tree modeled to be 3x the height and approx the same girth of a human takes up 4 tiles.

##### Share on other sites
How are you rendering the map?
I hope you're not rendering each tile separately, because if you are, then theres is your problem. In my experience, to get the best performance of terrain rendering you should design the terrain system in a way that allows you to draw the whole visible terrain in very few calls.
Use something like a quadtree to subdivide the terrain into sections.
I assume since you're using tiles, each tile can have a different material, if so, you should bake all materials/textures into one, so you wont need extra calls per each material.

##### Share on other sites
There are no textures yet.

I have to keep the tiles segregated for editing purposes, but as suggested at the end of the OP, I'm now working on making it draw 4 tiles at a time instead of one per iteration. I'm skeptical that reducing the nodes and in turn the loop iterations from 90k to 25k will make the difference needed to get back to 60-ish FPS, but let's hope.

As for dividing the terrain into visible sections... the problem with that is that the vast majority of the tiles are visible at any given time, even when using 300x300.

##### Share on other sites
Well the good news is that 50x50 has gone from 23 FPS to 80 FPS after switching to the 4-per-node method. The bad news is that 300x300 has only gone up to 2 FPS. :p

I suppose that I can sacrifice a bit of completeness and divide it into 50x50 blocks, showing only the block I'm editing at the time. I still have concerns about how it's gonna work in-game, though. 'Tis probably time to do some reading.

##### Share on other sites
It appears you're concerned about 2 relatively unrelated aspects of your terrain. a) editing or creating the map, and b) rendering the final map.

For instance, if you have an untextured grid of tiles, the editor may be slow but, in your game, you will render that grid as just one buffer of geometry with a single material.

Your map without materials and textures isn't what you're going to be rendering in your game. Editors can be expected to be much slower. But, because editors spend most of their time waiting for user input, that's generally not a problem. Don't compare your editor's performance with the final application's performance.

After the map has been edited, you can optimize performance in the game several different ways, as Relfos suggests. That will include sorting materials and textures and rendering a buffer of geometry for a large groups of tiles which have the same material. If you haven't seen an improvement in performance using display lists (OGL?), then you're probably right that you're not applying them efficiently.

To get rendering speed up in the editor, you may well store and render information entirely differently than you would in the game, perhaps rendering only a portion of the entire map.

##### Share on other sites
How are you sending the data to the graphics card? If all the quads are defined in world space and you have not segmented your world using a quadtree or other data structure for culling purposes, then you should be able to send all that data to the card with one draw call. I suspect your problem is that you are making too many draw calls per frame and that is killing your performance.

##### Share on other sites
as others have said, I believe youre doing something like drawing one quad/tri at a time

typically u devide a terrain mesh up into patches
eg 32x32 or 64x64 (tris==*2) + draw each patch in a single go

##### Share on other sites
'lo, all.

I understand that the "in-game" rendering will be different to the editor rendering. My concern is that a) at 300x300, the editor is basically unusable and b) it only took 2500 quads to drag my frame rate down to 20 FPS.

I've played around with it further and managed to get the 50x50 up to 110 FPS, with the 300x300 going up to 9 FPS so there's definite improvement.

The way I'm drawing the tiles is by looping over the linked list and drawing the 8 tiles of the two nodes between one glBegin/End pair. Or:

Move to new node
Call glBegin
Draw 4 tiles
Move to next node
Draw 4 tiles
Call glEnd

The only way I could open it up further and draw ALL tiles between one glBegin/End would be if every single tile on the map was going to be using a section of a single texture, but with different texture coordinates. The problem with this is that I doubt I'll be able to fit all of the tile textures into one 1024x1024 image - and I believe that binding is not allowed between glBegin and End. I suppose a compromise would be to have 2+ 1024x1024 images and break the glBegin/End up so that there's one per texture.

As for display lists... there's literally no difference in the framerate when I use them. I'm guessing vertex buffer(s) (which I'm planning to use for the in-game map) will be much better?

##### Share on other sites
First off, if your looping through all your tiles do not do this:

While( tiles to draw )
{
glVertex()
glVertex()
glVertex()
glVertex()
glEnd()
}

It would be better to do this...

While( tiles to draw )
{
glVertex()
glVertex()
glVertex()
glVertex()
}
glEnd()

It would be a lot better to use vertex buffers and eliminate all those draw calls. Right now your just spending too much cpu time calling all those functions.

##### Share on other sites
', Darius.

That's basically what I'm doing with the quad drawing (see last post).

I'm currently not using arrays or display lists for the map as it needs to be editable. Maybe later on, I'll make it possible to regen the vertex buffer after changes have been made. That is, assuming the data in the vertex buffer has to remain unmodified (which I'm sure it is, but could be wrong).

##### Share on other sites
You can not modify display lists but you can definitely modify a vertex buffer. All a vertex buffer does is tell your graphics card where your data is stored in memory. There is no restriction on modifying the data stored in that memory.

##### Share on other sites
Thanks for the tip. I'll look into it.

##### Share on other sites
Quote:
 I'm currently not using arrays or display lists for the map as it needs to be editable

Not sure why you think display lists and editing are mutually exclusive.

Granted, if the drawing sequence is just a few functions per tile and you're drawing 1000s of sequences, there'll be little benefit.

However, you're probably going to display tiles 1000s of times between modifications (depending on your frame rate). You're going to draw the buffer so why not generate a display list using the draw calls you're going to use anyway?
void Render(GLuint bufferNum) {   if( !buffer_is_dirty[bufferNum] ) glCallList( bufferNum );   else { // buffer changed. regen the display list      glNewList( bufferNum, GL_COMPILE_AND_EXECUTE);      // ... your buffer drawing calls      glEndList();      buffer_is_dirty[bufferNum] = false;   }}

Initialize a bool array buffer_is_dirty[all buffer nums] to true.
Call render() and the lists get generated.
...
Whenever you modify a buffer, set buffer_is_dirty[bufferNum] = true and gen the list automatically on the next render.

##### Share on other sites
Quote:
 Original post by GuinnieThe only way I could open it up further and draw ALL tiles between one glBegin/End would be if every single tile on the map was going to be using a section of a single texture, but with different texture coordinates. The problem with this is that I doubt I'll be able to fit all of the tile textures into one 1024x1024 image - and I believe that binding is not allowed between glBegin and End. I suppose a compromise would be to have 2+ 1024x1024 images and break the glBegin/End up so that there's one per texture.

Use vertex arrays or VBOs.
Have one element array per texture.

Conceptually, each draw call will draw tile map with holes in it, but after all calls, map will be full.

Update element arrays as the map is edited, adding/removing quads as needed if they happen to require different texture. Even if you update all elements on each pass, it should be faster (by an order of magnitude) than calling display lists.

For reference, when rendering 50k+ quads, going from display lists to VBO reduced my rendering times from 120ms to 0.2ms. Granted, this is a high end card, but there should be quite some benefit on simpler ones.