Terrain Editor pt2
Hello all, i've got a terrain editor render at the moment using dynamic vertex buffers and index buffers.
This works great for not so many vertices, but if i want to render a terrain of 2048 x 2048 vertices, my application runs at about 2-5 FPS. This method worked fine, when i generated the terrain and use a non dynamic VB however seems very slow with dynamic Vertex Buffers, i suspect the problem might be that i am copying the entire terrain into the VB every frame, although i think this is the approach i should take since, using an editor the terrain could be altered at any time, maybe the problem is due to the fact that i haven't implemented my View frustum culling again 'yet'.
When i add vertices to the Vertex Cache i use the Chunk size to define the Vertex Cache, odviously the more chunks i have the more this will affect performance, but it seemed to be the most sensible size for the cache, is there an optimal size for Dynamic Vertex Buffers on modern Hardware?
One last question, is that i've had my terrain, land and water rendering with a quadtree before, but it was a big mess, DirectX code and vertices / indices buffers inside the Quadtree class, how would you combine a quadtree with other level data, such as the land, water and trees etc.
My initial idea was to have the quadtree do the view frustum test and return an array of size numberOfNodes, this array specified which node is viewed and which nodes aren't. Then pass this info to the individual classes, terrain, water, models etc, and have the classes determine what was rendered or what wasnt. Does this method sound ok? How else could it be done?
[Edited by - LordFallout on February 17, 2008 5:12:08 PM]
Quote:i suspect the problem might be that i am copying the entire terrain into the VB every frame, although i think this is the approach i should take since, using an editor the terrain could be altered at any time
If your terrain is divided into chunks (as it should be for frustum culling, LOD, etc.), then every time the terrain is edited, you check which chunk is affected and only modify it's VB.
BTW, are you using the dynamic VBs properly (proper locking flags (nooverwrite/discard), proper creation flags (writeonly))? There's info in the SDK on this. Also, you might want to enable the debug runtime to see if you get any performance warnings.
And of course, add frustum culling (but you knew that :).
Thanks for the reply, yeah i've always used static VB's so i read alot on the topic before i implemented them, i think what i'm going to do is have a big VB for the terrain, but use a cache so that the vertices and indices are appended, this way i can for each chunk check if it should be rendered, if it is, add it's vertices and indices to the cache. then flush.
At the moment though my VB is created with D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY and is locked with D3DLOCK_DISCARD however the problem with low FPS will not be helped with Frustum Culling if the editor can see the whole terrain, which might be the case since we have an artist working on the terrain.
At the moment my terrain class has a array of terrain chunks and each chunk has its own Vertex Cache, and i have a seperate Quadtree / Frustum class, im not 100% sure how im going to get the quadtree class to tell the terrain and then each chunk what does or does not need to be rendered?
At the moment though my VB is created with D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY and is locked with D3DLOCK_DISCARD however the problem with low FPS will not be helped with Frustum Culling if the editor can see the whole terrain, which might be the case since we have an artist working on the terrain.
At the moment my terrain class has a array of terrain chunks and each chunk has its own Vertex Cache, and i have a seperate Quadtree / Frustum class, im not 100% sure how im going to get the quadtree class to tell the terrain and then each chunk what does or does not need to be rendered?
Quote:i think what i'm going to do is have a big VB for the terrain
This might not be a good idea. First, there's a limit to a VB's size. Second, if the VB is too big, the GPU might be forced to keep it in system memory, while with smaller VB's it can move them into and out of video memory as needed (or some other place that is better than system memory).
Quote:i can for each chunk check if it should be rendered, if it is, add it's vertices and indices to the cache. then flush.
Like I said, if a chunk is not edited than there is no need to refill it's VB. I think this one optimization will give a huge performance increase, but I'm not sure.
Quote:the problem with low FPS will not be helped with Frustum Culling if the editor can see the whole terrain, which might be the case since we have an artist working on the terrain.
In that case, you might need to implement some sort of LOD method.
Quote:
This might not be a good idea. First, there's a limit to a VB's size. Second, if the VB is too big, the GPU might be forced to keep it in system memory, while with smaller VB's it can move them into and out of video memory as needed (or some other place that is better than system memory).
If i use one Vertex Cache i can give it a maximum size, and flush it when its full, i may not be storing all terrain data in on VB but i could store a fixed amount, this should give performance increase however i dont know the optimum number of vertices to be drawn in one call.
Quote:
Like I said, if a chunk is not edited than there is no need to refill it's VB. I think this one optimization will give a huge performance increase, but I'm not sure.
Everything will not be edited straight away but i would like the artist to have the chance to edit or shape the terrain any way they see fit, i think it would probably be more of a waste to use static VB's in this case and have to change the contents when the terrain was re shaped, im not sure on this though.
Quote:
In that case, you might need to implement some sort of LOD method.
At the moment i can use geomipmapping, i have it in the renderer but havn't implemented it, i was thinking instead of using a overall distance to the camera method i could use a difference in height and edit the whole terrain accordingly, this may stop the editor from displaying some High detail some low detail areas, if i did this though i would have to decrement the basic LOD by 1 or 2.
When the terrain has been shaped and is either exported or saved, if the artist loads it into a game i will use static VB's there since there will be no terrain editing.
Quote:Everything will not be edited straight away but i would like the artist to have the chance to edit or shape the terrain any way they see fit, i think it would probably be more of a waste to use static VB's in this case and have to change the contents when the terrain was re shaped, im not sure on this though.
I think you misunderstood me. I'm not saying that you should use static VBs. For an editor, dynamic VBs are definitely the way to go, but that doesn't mean that you have to refill them with vertex data each frame.
For each terrain chunk, you can have a bool that states if the chunk's geometry was edited. If it was, you copy the vertices to the VB. If it wasn't, you just render the chunk as it is. This approach doesn't limit you or your artists in any way, and is vastly more efficient than copying the entire terrain geometry to the VB each frame.
Consider also, that using the above approach, when the terrain is not being edited (for example, when you are placing objects in the world or editing objects properties), there is no copying at all. With your approach, you incur the performance penalty for copying every frame, which can make other editing operations needlessly slow.
Quote:Original post by Gage64Quote:Everything will not be edited straight away but i would like the artist to have the chance to edit or shape the terrain any way they see fit, i think it would probably be more of a waste to use static VB's in this case and have to change the contents when the terrain was re shaped, im not sure on this though.
I think you misunderstood me. I'm not saying that you should use static VBs. For an editor, dynamic VBs are definitely the way to go, but that doesn't mean that you have to refill them with vertex data each frame.
For each terrain chunk, you can have a bool that states if the chunk's geometry was edited. If it was, you copy the vertices to the VB. If it wasn't, you just render the chunk as it is. This approach doesn't limit you or your artists in any way, and is vastly more efficient than copying the entire terrain geometry to the VB each frame.
Consider also, that using the above approach, when the terrain is not being edited (for example, when you are placing objects in the world or editing objects properties), there is no copying at all. With your approach, you incur the performance penalty for copying every frame, which can make other editing operations needlessly slow.
Oh my God :S you're absolutely right :) wow, i am probably wasting so much time just now, the main reason is how my vertex cache is designed, by default you have to flush it and fill it every frame, im going to have to change that to the method you described :) the only problem then is that when the user creates a steep hill, he is going to probably edit more than on chunk at a time, supose he edits all the chunks at once its going to cause this slowdown again, but i guess it will be running smoothly the rest of the time. Cheers for the advice :)
Whats the prefered method for having your Quadtree and other class 'talk' to each other, i could bung all the terrain into the quadtree but i then get the problem that the quadtree will have to hold everything else, water verts, grass verts, tree verts. Which is going to make it very messy.
Quote:he only problem then is that when the user creates a steep hill, he is going to probably edit more than on chunk at a time, supose he edits all the chunks at once its going to cause this slowdown again
I think this will be very uncommon. Usually you just edit a small area, so most of the time you will only be refilling one chunk. There will be times when you are editing the corner of the chunk and that might affect the 3 neighboring chunks, so you will end up changing 4 chunks, but that's still better than changing the entire terrain.
Quote:Whats the prefered method for having your Quadtree and other class 'talk' to each other, i could bung all the terrain into the quadtree but i then get the problem that the quadtree will have to hold everything else, water verts, grass verts, tree verts. Which is going to make it very messy.
I don't have a lot of experience with this sort of thing, but you could create a base class like Renderable and derive specific classes from that. Then your quadtree will only hold pointers to Renderables and won't know anything about terrain, grass, etc.
You might also want to search the forums here. There are many interesting threads on how to create a rendering architecture that deals with things like the above.
Quote:Original post by Gage64Quote:he only problem then is that when the user creates a steep hill, he is going to probably edit more than on chunk at a time, supose he edits all the chunks at once its going to cause this slowdown again
I think this will be very uncommon. Usually you just edit a small area, so most of the time you will only be refilling one chunk. There will be times when you are editing the corner of the chunk and that might affect the 3 neighboring chunks, so you will end up changing 4 chunks, but that's still better than changing the entire terrain.Quote:Whats the prefered method for having your Quadtree and other class 'talk' to each other, i could bung all the terrain into the quadtree but i then get the problem that the quadtree will have to hold everything else, water verts, grass verts, tree verts. Which is going to make it very messy.
I don't have a lot of experience with this sort of thing, but you could create a base class like Renderable and derive specific classes from that. Then your quadtree will only hold pointers to Renderables and won't know anything about terrain, grass, etc.
You might also want to search the forums here. There are many interesting threads on how to create a rendering architecture that deals with things like the above.
i had a search and couldn't find anything largely useful but i'll go again, my idea at the moment was to always pass a class pointer which has its own vertex Cache, and is split into chunks so i should be able to do something like
if(chunk is visible)
terrain[chunkid]->render;
objects[chunkid]->render;
i think this might work im going to implement it anyway, just to learn how not to do it :)
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement