Which way is better for storing a height-mapped terrain?

Started by
9 comments, last by Krohm 17 years, 11 months ago
I have came up with 2 following ideas of storing the height map for my project. The first one is the raw image data and then I would need to draw the height map each time from that data. The second is to convert the height-mapped image to my model format, which is a list of triangles, their colors and normals. Then the model data would be used for drawing. Which way do you think is better? Or maybe you can advise me with some better way of doing this?
Advertisement
Asking which way is better without providing context is like asking which subway line gets you to where you want to go without actually knowing where you want to go.

Both ideas could work, but choosing one or the other (or some other way) depends on your needs.

For example, let's say you have lots of processing power but little storage space. Keeping only a height map is going to be more compact than a mesh, even if the latter is compressed.

On the other hand, if you have tons of storage space but want to minimize processing, then having the mesh ready to go might be a better way.

Additionally, what other needs do you have? Physics? Shadows? What else? You may find these are easier or harder depending on the model.

So ask yourself the question, "What do I need to do with the data?", then examine both ideas and how difficult it would be to satisfy each of those needs with each model. Then choose your model.
Forget about the first idea. Why on earth would you want to slow down the application by recalculating normals and creating vertex/index buffers each frame ? That would be horrible !

Just create the vertex&index buffers at startup and render from those each frame.
Also, the final memory representation depends on few other things:
1. LOD algorithm
2. Texturing - is it one unwrapped texture with some blended detail texture, or some texture splatting ?
3. Efficient Vertex Cache Usage through Vertex Compression - whatever you do, just try to round up the size of 1 vertex to multiplies of 8 Bytes (if you do some calculations inside Vertex Shader (e.g. texture coordinates), you can easily pack the Vertex data into 16 Bytes, or even just 8 bytes - though this involves bit decompression). Then, even with large terrains, the memory consumption is very small, since even with 1024x1024 heightmap, your Vertex Buffer would need just 8 MB, which is nothing these days.

VladR My 3rd person action RPG on GreenLight: http://steamcommunity.com/sharedfiles/filedetails/?id=92951596

Vlad, I don't think he means per frame, just for his map storage..
Typically you would do both (well, sort of).

You store your height map as a bitmap, and then your LOD algorithm uses that bitmap to generate meshes for the visible areas of terrain, as needed, destroying them when they go out of view.

That way you can use the heightmap for fast elevation queries, you can render from fast VBOs, and you only have to keep whatever is currently in view in the Video memory.

If you have a really good graphics card, and a fast computer, you can modify this a little, and just store the heightmap, load sections of it into the video card as textures, and then do all the rest on the GPU.

Try googling for 'real time terrain rendering', and you should get more info than you know what to do with [smile]

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

IMO storing it as model data makes more sense.

Storing as a texture will slightly increase load times, as you will have to generate the mesh first, as a seperate step after loading.

Storing as a mesh also gives you the ability to muck with textures and vertex values between the mesh generation and loading it into the game. Gives you the ability to add that extra bit of polish.

Just my opinion
The correct answer is use the best fit for the purpose of your program.

That being said, the best fit is usually a mixture of both, as swiftcoder has said.

Think about scalability, if you store a mesh, how will you implement a dynamic LOD system or even adaptive subdivion? Storing a mesh is great for squeezing the most performance out of brute force rendering as possible, but you will quickly cross the threshold where you need to start drawing fewer polygons in the distance to increase performance.

Balance performance with memory usage. Storing a 256x256 terrain in heightmap form takes 64k. Storing the exact same terrain in model format MINIMUM takes 1.536 mb (assuming 32 bit coordinates for vertex and normal). More memory usage for barely a performance gain and less flexibility, I definitely go with the former.

To reclaim the performance hit of not explicitly storing your mesh, you create a caching system. Divide your terrain into chunks of say 16x16 or 32x32 elements, and as the player moves around the world, calculate the vertex buffer for a chunk as it comes into range. Release the memory when the chunk gets sufficiently far away. Since at normal movement speeds you will only do this a few times over the course of hundreds of frames, performance will be essentially the same as brute force, but you will have a much more flexible system to work with.
OP is just starting out - that`s obvious from his question, because he didn`t specify the most basic features of his terrain (LOD,Texturing,Continuous World/Levels, minimum HW requirements).

Quote:Original post by y2kiah
Think about scalability, if you store a mesh, how will you implement a dynamic LOD system or even adaptive subdivion? Storing a mesh is great for squeezing the most performance out of brute force rendering as possible, but you will quickly cross the threshold where you need to start drawing fewer polygons in the distance to increase performance.
Obviously you haven`t heard of LOD through different Index Buffers.
Option A: You can have just single Vertex Buffer and few 32-bit Index Buffers to represent different LODs in the distance.
Option B: Or, and that`s a better alternative from memory standpoint (and comparable in performance), you can have single 16-bit Index Buffer per LOD and have multiple Vertex Buffers per chunks of terrain since you`ll be rendering in chunks anyway.

Quote:Original post by y2kiah
Storing a 256x256 terrain in heightmap form takes 64k. Storing the exact same terrain in model format MINIMUM takes 1.536 mb (assuming 32 bit coordinates for vertex and normal).
I don`t know how you calculated 1.536 Mb for sure, but it seems you assumed 24 Bytes per Vertex (256*256*24/1024 = 1536 KB). Either you forgot the Indices, or your VB is packed and decompressed in a shader ?

Quote:Original post by y2kiah
Divide your terrain into chunks of say 16x16 or 32x32 elements, and as the player moves around the world, calculate the vertex buffer for a chunk as it comes into range. Release the memory when the chunk gets sufficiently far away.
.
.
.
Since at normal movement speeds you will only do this a few times over the course of hundreds of frames, performance will be essentially the same as brute force, but you will have a much more flexible system to work with.
Average FPS over the course of 10 seconds may be very similar. But Actual FPS at the given moment shall be terrible.
Esentially, this system will punish the poor users with slow configuration. Not only the game barely runs on their system (say, 20 fps), but on top of that you`ll be slowing it down every few seconds since the renderer shall have to dynamically create the VB (and maybe even IB - depends on you).
Now, imagine some AI getting into the player`s range. So, at current frame the CPU shall be busy with initializing AI and on top of that it`ll have to create VB/IB for the terrain.
Thus the framerate will drop even lower and shall result in a horrible lag.
The fact, that other games do that is not an excuse, especially these days when games require 128 MB of VRAM.
The less reasons for a performance lag, the better.

Now, if you really want to cache the terrain around you, do it over the course of several frames so the CPU load is spread evenly.

If you desperately need to have the minimum memory requirements, put the computation load on your GPU. Each vertex shall contain:
idxVertex (2 Bytes): the 16-bit index representing the ordered number of vertex in current terrain chunk of same dimensions (256x256)
VertexHeight (2 Bytes) : Height of the vertex
Normal (4 Bytes) : Compressed normal

Since the Vertex Size is just 8 Bytes, you`ll get the Vertex Cache of GPU work for you (multiplies of 32 Bytes).
Then, in Vertex Shader, take the idxVertex (range 0-65535) and calculate the appropriate Row and Column and according to these calculate Xpos and Zpos. Take Ypos from Vertex.VertexHeight. Use the same data to calculate the texture coordinates.

The higher count of instructions of the Vertex Shader is usually not a problem, since your application won`t be transform-bound for sure (no game is these days) unless it`s just a tech-demo showing some half-million poly model.

A 256x256 heightmap shall then take 0.5 MB for Vertices and 0.25 MB for Indices.
This is less then 1 MB !
If this is still too much memory for you, you just should have already mentioned that your recommended configuration is Pentium 1-166 MHz and S3 Trio3D 2MB / 3dfx Voodoo1 4MB (You know, these days it`s normal to require a gfx card with 64MB onboard:-) ).

EDIT:Typos and smilies

[Edited by - VladR on April 22, 2006 2:21:44 AM]

VladR My 3rd person action RPG on GreenLight: http://steamcommunity.com/sharedfiles/filedetails/?id=92951596

OK, thanks for your help. I'm going to convert it to a mesh. I guess that I don't really need all those LOD and caching stuff for my game.
I was thinking about the same thing, I guess storing it in a model format would be faster for loading.
If you wanted to be able to change the height of the terrain in real time, then maybe storing it in a texture would be better.

#
I cut my terrain into n*n terainChunks, each chunk having m*m quads, then I used shader instancing to draw the chunks that were in my cameras frustrum. I dont think I will bother with LOD for now.

Pros: no locking, easier then batman
Cons: unreasonable requirements

Minimum requirements for my game, are my that of my CPU :P
Insufficent Information: we need more infromationhttp://staff.samods.org/aiursrage2k/

This topic is closed to new replies.

Advertisement