Jump to content
  • Advertisement
Sign in to follow this  
evolutional

[XNA] Pixel-based terrain deformation

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Howdy, I'd like to get your opinions about the best way to implement terrain deformation in my 2D game. I am using a TileMap to display a 2D landscape on the screen. I have implemented per-pixel collision against the terrain with no issues and am now looking to implement the deformation routines. Whenever an explosion or collision occurs on the landscape it will become deformed, essentially a crater is carved out of the terrain and the collision map is affected accordingly. I have achieved this once in my original prototype that effectively had the terrain as a single texture; I would call Texture2D.GetData() into a Color [] array, modify the texture and send the data back to the texture using SetData. However, this method was slow and often caused issues due to the texture being in use by the graphics card. It also doesn't apply very well to a tile-based landscape unless I did something ugly like render out the tilemap to a large texture and worked with it from there. I've tried a new solution but I didn't like it - that was to manually build another texture from the destruction map each time the camera moved (or there was another destruction) that was used in the pixel shader to erode the landscape. This worked to a degree, but I was still creating a texture most frames and building it from a Color map using SetData - ugly. A twisted version of this would be do the opposite and render the visible landscape to a separate render target each frame, get the color data, modify it and push it back - but again, this is what I am trying to avoid. I'd like a better way of doing it. So far, I've seen two other ways that boil down to me storing a list of the deformation objects and rendering their textures to either the stencil buffer or another texture and combining it with the 'normal' background in the pixel shader. The main issue I have with this approach is that deformations will actually be common and with lots of small objects (bullets) - it is possible that I'd spend an age rendering the deformation texture and my memory usage would skyrocket as all these small objects hang around until the tile has been eroded completely or the game ends. Some tips or guidance would be much appreciated - I'm fairly new to graphics dev, especially shaders.

Share this post


Link to post
Share on other sites
Advertisement
Depending on how large the entire level is, would it be possible to store the whole thing in one texture? From there, you could have one static "explosion texture", and use Render-To-Texture to draw onto the level texture. Since you'd only be rendering on it, it'd be completely GPU based, and would avoid all stalls you have with any Lock or SetData solution.

This seems very similar to the original "prototype" you had, except you'd be using GPU rendering to modify the "level" texture instead of having the CPU do it.

Share this post


Link to post
Share on other sites
I've not decided on the exact dimensions of the level, but it's going to be at least 1600x3000 - probably more. This seems a bit too big for a single texture - although the 360 can apparently handle 8192x8192 - I've got no idea of performance with textures this big though :)

So the steps of this implementation would be:

1) On init - render all tiles into a single texture
2) Display as normal
3) When explosion occurs render the original texture first, render explosion onto it and then store off the texture
4) Repeat 2-4 as required

Hmm. Interesting. Thanks - you've given me something else to think about.

Share this post


Link to post
Share on other sites
Quote:
Original post by evolutional
3) When explosion occurs render the original texture first, render explosion onto it and then store off the texture

Re-rendering the original is not needed - you can render on top of the original and possibly use alphablending to modify the original to whatever you want it to look.

In addition, storing in one texture isn't the actual requirement, using several textures is fine too, so long as you can keep them all in GPU memory at once. If you can't, you'll need to find a way to offload them back to the CPU in the background, which might be more complex.

In addition, remember any GPU-only resource's data will be lost if the device is lost. Perhaps keeping a moderately-up-to-date CPU copy would be required if you need to handle lost devices (Windows, really).

Share this post


Link to post
Share on other sites
">The technique seems to work perfectly.

I rendered out the landscape to a texture at the level init phase and then subsequent destructions were rendered on top of it. I then kept hold of the new texture and used that for the next version.

Effectivley:


// Render out to texture once
GraphicsDevice.SetRenderTartget(0, landscapeTarget);
spriteBatch.Draw(tileMap, Vector.Zero, Color.White);
GraphicsDevice.SetRenderTarget(0, null);

landscapeTexture = landscapeTarget.GetTexture();



And then when new deformations are to be rendered:


GraphicsDevice.SetRenderTartget(0, landscapeTarget);
spriteBatch.Draw(landscapeTexture , Vector.Zero, Color.White);
foreach(Destruction in Destructions)
{
// NB: this is simplified
spriteBatch.Draw(Destruction.Texture, Destruction.Position, Color.Black);
}
GraphicsDevice.SetRenderTarget(0, null);
landscapeTexture = landscapeTarget.GetTexture();



Then when I'm showing the game image, I render the visible portion of the landscapeTexture with players/etc on it.


Thanks very much - I like this way of doing it :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!