How can I clean only a partial area of a RenderTarget2D?

Hello, how can I clean only a partial area of a RenderTarget2D?

Is that partial area a rectangle or a more complicated shape? Do you also need to clear the depth buffer, or do you just want to paint that area in a solid color?

The partial area is a rectangle, I need to draw a sprite in that area, but keeping the rest of the rendertarget. I do not want to draw all the sprites (rectangle cells) within the rendertarget in each cycle, because they are many.

You can render to textures.
Divide your screen into rectangles (or even a quadtree). Then draw each rectangle to a texture and draw those textures.
Now you can only redraw the rectangles that need a redraw

So you have some sort of a static background image, and by cleaning you mean putting that back on the screen in a rectangular area. Did I get this right?

Just make sure that background image is in a separate texture/rendertarget. Then use SpriteBatch.Draw to draw your little rectangle using that background texture. Just make sure to use the correct overload of Draw() that let’s you specify a texture region, so you are not drawing the entire texture, but only the portion you are interested in.

Finnhax, I can not redraw only the part that changes on the screen, since at the beginning of each cycle I have to clean the screen. The alternative I do is put everything in a rendertarget and redraw it (using a single draw and without having to go through all the textures that go inside and draw them) when necessary, but I would like to only draw the part that changes and not everything. That is why I ask if it is possible to clean only part of the rendertarget.

Markus, with cleaning I mean .Clear

I do not have a static background image. Imagine a chess board, but with a lot more squares (7000). I need to draw them all in each frame (because it is possible to zoom the board and it is possible that in small zooms all the squares are visible in the interface). The player can click on the squares and modify them, so I need to re-render the entire board so that the rendertarget can update the changes. What I want is just to update that piece of rendertarget.

If you want to update just one piece of the RenderTarget, you can draw something onto the portion of the RenderTarget you want. There is a SpriteBatch overload that takes in a sourceRectangle. You can use your RenderTarget as the texture and the sourceRectangle as the region on the RenderTarget you wish to draw over.

If you want to clear the portion of the RenderTarget, you can either use Get/Set Data (not recommended) or a shader that makes all pixels in a designated region of the RenderTarget transparent.

This may also be relevant to your needs.

1 Like

I don’t understand why you need to clear anything before drawing your changes to the rendertarget. Why can’t you just draw over the region you want to change? This is purely 2D, right?

If you want to keep your rendered scene between frames, just draw everything to a rendertarget, and at the end of the frame copy this rendertarget to the backbuffer. If you rendertarget doesn’t need to change next frame, you just copy to the backbuffer again, otherwise you first draw over the portion you want to change, and then copy.

Am I misunderstanding something, or are you overcomplicating things?

Yeah, if you’re drawing over a solid background (you said a chessboard) then you can set a clipping rectangle in the SpriteBatch call and use that.

If you actually want to clear the area (ie make it transparent) before drawing then I’m not sure that’s possible but, if it is, I’d also be interested to know!

Realistically you should just re-render the whole rendertarget when you need to update it.

Doing incremental updates is going to have erratic performance characteristics if you ever have to update more than 1 region at a time. In effect, you’re just doing immediate mode rendering without clearing as you have to setup a scissor -> draw into that (or worse, as you describe, set a viewport, clear, and draw into that).

If you have to update 6 tiles it’s going to be 5x worse than drawing a well-atlased collection of tiles.

Clearing then drawing isn’t a good choice unless you can 100% guarantee that your draw will cover EVERY single row and column in the cleared area (ie. floor all lowerbound and ceil all upperbound floats), or that cleared status is okay (like a SNES sprite layer). Scissor is much safer, you’ll at least have something there in the case of a substrate.

I’d just do it exactly like modern virtual-textures for terrain: subdivide to a reasonable scope and invalidate whole rendertarget tiles, completely rerender the rendertarget, and be done with it. Then I’d tweak for project specific needs, terrain for instance never needs instant feed back so tiles can be late a few frames - but other things might not be able to wait.