Override Texture.SetData(T, Int, Int) ?

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

Recommended Posts

Hi guys,

I'm trying to create a 2D destructible terrain in XNA and, well, I did it but I'm having a bit of a FPS problem. The way I change the terrain looks like this:

Color array = mapTexture.GetData(); - beginning

When a change needs to be made:

array[pixel-to-be-destroyed].A = 0; mapTexture.SetData(array); 

And that's where it is all ruined - the SetData method decreases the FPS horribly even on a 1024MB RAM video card, because it resets the whole texture. What I need is a way to reset only the parts of the texture that do change, worst case scenario - maybe have a grid and set individual tiles. I saw a texture.SetData(T, startIndex, num_elements) I thought would work, but after some investigation found out it's really not what I thought it would be.
Another idea I had was to extend the texture class and add a function of my own to do what I want it do, but I've no idea if that is possible, and if it is - how can I get the texture class source code to see what the setData method actually does.

If anyone can help me with that, or has another solution to the problem, I'll be forever in your debt
Thanks a lot!

Share on other sites
First off, you're not going to be able to extend Texture2D (or any of the Texture classes) and modify SetData in any fashion because of its nature - the texture classes encapsulate the underlying D3D9 surfaces to read/write to for the Get/Set methods, which you won't have access to.

At the very least, eliminate the GetData() by keeping a working copy in CPU memory. GetData() and SetData() both will read/write texture data from the GPU, which are slow operations to be doing every frame. So keep the color array in memory, update it, then write doing SetData(). The overloaded SetData() method where you're able to specify the range of elements to set, probably would be helpful here as that would allow you to update a portion of the texture. And maybe some use of batching (I imagine destroying a hole in a terrain would imply a large chunk that is rather localized) and limiting to updating the texture not every frame, but every so often.

Share on other sites
@Starnick, thanks a lot!

One more thing to ask, and one I should clarify:

1. How do I tell XNA to keep an array always in memory?
2. I could not figure out the way the overloaded SetData works... I know it sounds bad, but I really could not. When I tried to use it like this:

mapTexture.SetData(mapColorArray, pixel-to-set, 1)

an error kept blowing in my face that said I was either sending the function too much or too little information. The only way I got it running was by typing this:

mapTexture.SetData(mapColorArray, 0, size_of_array)

which is obviously the same as the default SetData, not what I need. I don't know what I'm missing, but I can't get it to work the way I want it to.

Share on other sites
1) Keep in mind C# is not XNA and vice versa - C# is the language, XNA a library. So keeping a reference to the array is a language question, not an XNA question. An array is an object (therefore a reference type), when I mean "keep in memory" I mean you keep the reference around so it doesn't get garbage collected. I don't know how you setup your code, but if you have an object that manages your destructable terrain then it can be as simple as having that class get the color data when you load up your terrain content, store it as a class field, then use it as I described above during your application updates.

2) What's the texture format? Is it of SurfaceFormat.Color? Wondering if your texture is in a compressed format (DXT) or not.

Also another way of doing this would be avoiding Get/SetData completely and using rendertargets. E.g. You have the texture2D that represents your terrain, and you have several other texture2Ds representing holes (or maybe just one - I'm thinking if you have it where you're blowing up holes in a terrain, you might want a few different looking craters). You can keep track where each hole would be, then you draw the terrain texture to the render target, then each hole texture (this can easily be batched by texture, reducing the draw calls to one or however many different hole textures you use). It could just be crater decals, or you could use those hole textures to do what you're doing and change the alpha value of the terrain (and literally creating a hole) through blending. But the key difference is now that is being done on the GPU (and most likely entirely by using a SpriteBatch to do the render-to-texture). It may not be pixel perfect (although it may look smoother), and it's definitely going to be harder to setup.

Share on other sites
Hi again, and thanks for the detailed answer!

As for 1 - yes, I keep my map texture and color arrays as class variables, I knew it was an optimization, just didn't know the words to describe it ;)

And 2 - not sure on how to check the format of the texture, it's default I guess? Anyways, from what I read I'm positive it's not DXT. I also read some articles on rendertargets, and at first I thought it was a great idea, but then an issue popped in my mind: setting aside the fact that it would be harder to set up (I don't know much, if anything about HLSL) because after all the main reason for me to make the game is learn, I think as the game progresses it would put an even greater strain on the machine that runs it, than what I've got now. If all that could change the terrain were large explosions, that would have been OK, because there wouldn't be more than, let's say a dozen on the screen, but for bullets I'd like to have small holes which could amount to maybe even a hundred, and that probably would not run too well.

Thanks again for your time, if you have any other suggestion I'd be more than glad to hear them.

1. 1
2. 2
Rutin
19
3. 3
4. 4
5. 5

• 13
• 26
• 10
• 11
• 9
• Forum Statistics

• Total Topics
633736
• Total Posts
3013598
×