Game Development Community

How big of a texture do I need for a huge 2D terrain?

by John Klimek · in Torque X 2D · 08/20/2007 (1:07 pm) · 10 replies

I've been trying to create my Scorched Earth clone for several years now (I'll try to figure out some stuff for a couple of weeks and then quit and then will go back, etc, etc...)

Anyways, here is a link to a previous discussion about creating deformable terrain for a 2D scorched earth clone: http://www.garagegames.com/mg/forums/result.thread.php?qt=56363

I think I understand everything about quad trees and the ideas from that thread but I have one problem:

How do I create my initial terrain bitmap?

If you've have ever played Worms (or Gunbound) then you know what I'm referring to. The terrain itself is a bunch of hills filled with a texture and then objects are placed on top of the texture, but those objects actually become a part of the texture (eg. you can destroy them).

Here is an example of what I'm talking about: http://content.answers.com/main/content/wp/en/7/72/Worms_xbox_live_hd.jpg

Do you see how the terrain is brown but has a surfboard (which is partially destroyed)? That's the effect I'm trying to achieve.

Now, I think I understand everything except the size of my main bitmap/texture that represents the entire landscape.

What I was planning on doing is creating a MASSIVE texture like 10000x5000 pixels and storing the entire terrain in there but this is obviously too big for even modern video cards. The reason I was thinking about 10000x5000 is because I want the terrain to look good even in 1920x1200 resolution (and I want the terrain to span about 3 screens wide and maybe 3 screens high).

Any help is greatly appriciated :)

#1
08/28/2007 (10:16 am)
Anybody? :(
#2
08/28/2007 (12:23 pm)
You're going to have to break up the scene into contiguous blocks of a smaller size. It's simply not practical/possible to use massive images like that with 3d hardware.

Anyway, the surfboard and ground look like simple layered images, one on top of the other. Check out Tank Buster for something similar.

Note that I haven't read the post you referred to, but as for making the terrain destructable as in Worms, you will have to develop your own custom solution. I would suggest using pixel shaders for that as you will need to mask out various bits of your images and that can be done quite easily with a pixel shader. Just generate a mask image and render it with a pixel shader that masks out the texture.

It also looks like you will need per-pixel collision, so you will either need to read the image or store bitflags for which pixels are solid. For representing the collisions and holes in the geometry, I would utilize the collision polys in TorqueX first and when I've identified with what object something is colliding, go down to the pixel level to check where things are really colliding. This will require you to convert from world space to object space, which is no big deal. I think there's even a function that does it for you now in the engine.

There is one thing to note. Retrofitting this engine with per-pixel collision might be an undertaking that is pretty difficult, unless you have the source code and you know enough to modify the collision and physics systems. You might want to try faking it by using collision images instead.

There might be better ways to do all this but that is how I would approach it on first thought. I hope I've given you some tips that will help you to succeed in your project. Good luck.
#3
08/28/2007 (12:34 pm)
Quote:You're going to have to break up the scene into contiguous blocks of a smaller size. It's simply not practical/possible to use massive images like that with 3d hardware.
Thanks for the reply! I'm not sure if I'm going to use TorqueX or custom-write my own engine, but I might end up writing my own engine for this purpose.

Anyways, what do you mean by breaking up the scene into contiguous blocks of a smaller size?

Do you mean that I create a quad-tree and if two (or more) quads are the same that they share a single texture? That sounds like a really good approach, but how do I initially create the image?

What I was hoping to do was create a gigantic 5000x3000 ARGB texture (as a render target) and then draw my terrain onto it. This way I could draw tunnels through my terrain, apply grass on top of it, etc, etc. After it was created I could then create a quad-tree and analyze tiles to see if they were the same, but I still need to create the initial 5000x3000 image, right? (which isn't possible...)
#4
08/28/2007 (1:01 pm)
Ah. I was thinking your approach would be to create pre-made terrain artwork as giant, layered images, not drawing them on the fly. I probably should've read the post you linked to to get some more context.

What you should probably do is work on abstracting away from the graphics hardware limitations. You can do all the drawing you want (except rendering with XNA/Direct3D) to a bitmap in memory of any size. What you will want to do is convert the result to several smaller textures. What you will end up with is a bunch of textures that can be placed next to eachother to form the massive terrain. I would not even bother with trying to save memory by creating repeating tiles in this type of game. It's way more trouble than it's worth and I doubt that's how Worms works anyway. But whatever you do, absolutely do not attempt to create a massive texture and upload it to the video card. It won't work.

As for creating the holes and tunnels, I suppose if you're doing it the way you describe, you are working directly with pixels and you can do everything you want while drawing them without the pixel shader method I described for creating holes in existing artwork. But each time part of the terrain needs to be updated, you will have to draw to your bitmap in memory and re-upload the relevant texture(s) to the GPU. Oh, and by the way, I forgot to mention that the stencil buffer might also be a good tool for accomplishing what I described earlier with the pixel shader, but I digress.
#5
08/28/2007 (1:27 pm)
Thanks again for your help!

I've thought about that idea too, but let me re-describe it just to make sure I understand:

What I would need is enough tiles to cover the resolution (eg. 1920x1200) plus a couple more in case the user scrolled the screen (eg. to view more of the terrain).

I like this approach and it doesn't require much VRAM (9.2 MB for a 1920x1200 @ ARGB-8). However, it does require re-uploading of texture images as the user scrolls around.

However, my main problem with this approach is that if I store my massive bitmap in system memory, I cannot use DirectX drawing functions on it. (right?)

For example, I wouldn't be able to draw anti-aliased circles (for my explosion holes) nor would I be able to use any other DirectX functions... (right?) Basically I would be using GDI (?) to draw onto my bitmap and then upload it to the video card as needed.

I like that solution the best if I could overcome the problem I mentioned above. I also don't think it would have too steep of a requirement (128+ MB of system ram and perhaps 12 MB of VRAM)...
#6
08/28/2007 (1:31 pm)
Yes, you're right about not being able to draw to the bitmap with Direct3D.

Maybe try virtualizing your drawing by abstracting out the low-level technical limitations so you can just treat multiple textures as a single large canvas. Then you can draw with Direct3D.
#7
08/28/2007 (2:02 pm)
Hmmm, can you explain a little bit more about what you mean?

I still need to store the "main" texture is system memory because it's very large... (128+ MB)

...and if I understand correctly, I can only manipulate textures once they are already uploaded to the video card, or are you suggesting I can create a DirectX texture stored in system memory?
#8
08/28/2007 (2:41 pm)
Well, you can't create a render target in system memory. But you can hide all the nasty details behind an interface and render your objects to multiple textures. You then just have to do some conversion of coordinates. So your high-level interface would just allow you to pretend you were drawing to a large canvas, but your low-level interface would then do all the work however it needs to, which in this case would be to render to a bunch of render target textures.
#9
08/28/2007 (3:41 pm)
Ahhh! Can I create a texture in D3DPOOL_SYSTEMMEM or D3DPOOL_SCRATCH and then transfer pieces of it to the video card?

Both of those memory pools seem to allow non-power-of-two textures and I think infinite (well, according to your system ram) texture sizes.

Do you know the difference between them or how I would transfer them from that memory pool to the video card (eg. as a real texture)?

...or is this not what you are referring to?
#10
08/28/2007 (8:39 pm)
I don't think you can render to a texture that isn't a render target. You can of course manipulate the bits of said texture, but not render.

What I'm referring to is creating a layer of abstraction that actually does all the work of splitting up the drawing between multiple textures so that they appear to the user to be one large canvas. This would involve translating coordinates and swapping render targets on the low level, but ideally you would expose a high-level interface that makes it completely transparent to the user.

Or you can save yourself a lot of work and just pre-render your art in an art package, then stick to decimating the textures. That is what I would do. You are then no longer trying to create a composite of a very large scene all at once and you have much better tools at your disposal for painting the scenery. And you have the ability to organize it all and split it all up into layers. I can't think of any disadvantages with this method...