Terrain, Part 9

By Shamus
on Feb 17, 2006
Filed under:
Programming
Diminishing texture sizes

Right now my program makes 64 different textures for the terrain, each of which fits over a particular zone. Right now all the textures are the same size, which is 256×256. This takes about 16MB of video memory. Not bad, but certainly not ideal. This means every zone, no matter how close or how far, has the same sized texture. Check it out:


In this set of textures, each one is 256×256 pixels. The entire set takes about 2 seconds to build and takes up 16MB of memory.

If you remember from previous updates, I need to rebuild all of the textures if I move the sun. (If I don’t, the terrain would look exactly the same, which would defeat the purpose of moving the sun. It needs to re-make the textures with the new shading and shadowing.) But right now it takes 2 full seconds to rebuild the textures. I have to “steal” that two seconds a few milliseconds at a time, unless I want the user to endure a long pause every time the shadows need to move.

But, we don’t need every dang texture to be 256×256. In fact, only the ones nearby do. Let’s make the texture size variable, so that the ones nearby have lots of detail and the ones far away have much less:


In this set of textures, the closest ones are 256×256 pixels, and the ones in the distance are 8×8. The entire set takes about 0.7 seconds to build, and uses just over 2MB of video memory.

I think I’m actually being too agressive here. The ones at the top that you can’t read are 16×16 and 8×8. They look pretty crappy, and I think 32×32 should be the minimum. Anyway, I need to calibrate this a bit, but it’s clear this is the way to go. I’m using a fraction of the memory I was before and the texture rebuild happens about three times faster.

However, this introduces a new problem. (Doesn’t it always?) Let’s assume this engine is being used in some sort of Sim City or RTS setting. The user may want to zip from their current location over to the other side of the map. When they get there, the area right in front of them will look like this:


Ugh. Not so nice.

So, while before I was worried about keeping shadows moving smoothly, now I have to keep these texture updates coming so the above doesn’t happen. If the user hurries accross the terrain, I think it would be a good idea to dedicate more time to the texture rebuild, so that I can come up with a new set of textures with the detail in the right place. This would mean that moving very fast from one side of the terrain to the other would lead to the framerate dropping and things getting choppy for a second until the texture rebuild gets caught up. This is acceptable in my book, as long as the game doesn’t require lots of fast hops around the terrain.

EDIT (July 6 2007): A much better idea, now that I’m thinking about this a year and a half later, for for each zone to hold onto several different resolutions. When I go to a new area of the map, it will build the higher res textures I need nearby, but it won’t throw away the high res ones I was looking at a second ago. It will just shuffle them out of use for a minute. If I come back, the textures go back into use. After a while, unused high-res textures are purged from memory. This means If I jump around between various “hotspots” the game won’t have to do a lot of texture rebuilding, and the game stays smooth.

Enjoyed this post? Please share!


7A few comments. Call it seven-ish.

From the Archives:

  1. Tsetut says:

    Ugh. Not so nice doesn’t even begin to cover it. But only because you kept 16 and 8, if you set the minimum to 32 it wouldn’t be so bad. Also, first post.

  2. Rob says:

    “unused high-res textures are purged from emeory”
    Just thought you would find it useful.

  3. Tobs says:

    Were you working at 4 bytes per pixel when you worked out you were using 16MB for the whole thing?
    64 textures at 256^2 a piece works out at 12MB if you don’t have an alpha pixel (256*256*3*64 = 12MB)
    However if you had a 256, 128 and a 64 texture for each square (like you suggested), I think you’d almost hit 16MB.
    Chances are I’ve missed something though

    Great articles though, I learnt a lot from them

  4. Steve says:

    Congratulations, you just re-invented mipmaps.

  5. Incognito says:

    @steve: Not really. With mipmaps you have to use textures of high resolution all the time, which means you will be consuming a lot of memory all the time. With his solution you can save on memory, not so with mipmaps.

  6. Neil Roy says:

    Seems to me if you’re creating several different resolutions per texture that you would be using more memory than if you just stuck with the high resolutions in the first place. ;)

    • WJS says:

      True, but the point was less about memory and more about build time. Personally, I’d probably have the textures start generating with small ones and building bigger ones later, like in progressive jpegs. Give priority to nearby textures, and when the full ones are all built just keep them all the time. At some point, I’m really going to have to put my money where my mouth is, learn OpenGL, and make a landscape myself.

Leave a Reply

Comments are moderated and may not be posted immediately. Required fields are marked *

*
*

Thanks for joining the discussion. Be nice, don't post angry, and enjoy yourself. This is supposed to be fun.

You can enclose spoilers in <strike> tags like so:
<strike>Darth Vader is Luke's father!</strike>

You can make things italics like this:
Can you imagine having Darth Vader as your <i>father</i>?

You can make things bold like this:
I'm <b>very</b> glad Darth Vader isn't my father.

You can make links like this:
I'm reading about <a href="http://en.wikipedia.org/wiki/Darth_Vader">Darth Vader</a> on Wikipedia!

You can quote someone like this:
Darth Vader said <blockquote>Luke, I am your father.</blockquote>