Questions about RenderTargets...

So, questions about RenderTarget2Ds.


  1. Can I set RenderTarget’s position somehow? As far as I know RenderTarget is always positioned at “Zero”, but my camera and game moves in wide area. This would be a problem if I move outside of RenderTargets limits…

  2. Is there size limit for RenderTargets, or does it depend of device?

  3. Do I have to dispose them manually?

  4. Should I use RenderTargets for all of the game’s layers? I have background, gameobjects, foreground and particles in separate spritebatch.begins, so four RenderTargets.

  5. Why should I use rendertargets?

  1. Think of a render target as a regular texture except you can draw to it. So it doesn’t have a position, but that’s not a problem. You can’t set the position of the back buffer either, the top left is (0,0).
    What people do is instead of drawing your objects at their actual location you transform that position by a transformation matrix. In 2d that usually means just translating the sprites by the inverse of the camera position. E.g. When the camera is at (100,200) and you draw a sprite at (300,300) you’d instead draw it at (200,100). Essentially your camera is static at (0,0) and you need to move your game so the stuff you want to be visible is in it’s sight.

  2. I think the size isn’t capped in modern hardware, so that would mean you can create render targets so large it fills up the gpu memory. Mobile devices in general have some restrictions though. (E.g. 2048x2048 or something).

  3. Yes. Since they allocate space in VRAM (gpu memory) they can’t be cleaned up by the garbage collector, so you need to expliitly dispose of a rendertarget when you no longer need it.

  4. You can choose for what you use render targets and for what not. Without more context it’s hard to say if you would benefit from using them. They’re useful for certain effects or for combining multiple draw calls into a single texture so you can cheaply redraw them later in one call.

  5. This is hard to answer because of how general the question is. If you just think of a render target as a texture that you can draw to you should be able to figure out when it’s beneficial to use. As an example imagine having water reflection in a 2d game. You could draw your scene to a render target first without the reflection. Then you can draw that render target to the back buffer and redraw part of that render target mirrored for the reflection in the water.
    There’s more advanced use cases when you see a render target not as an image, but just as a 2D array of some data. You can then access that data in custom shaders. Don’t worry if you don’t know how that works. You can perfectly make a 2d game without custom shaders (or render targets for that matter)

2 Likes

D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION (16384)

16k

2 Likes

Okay, I guess that this is where the transformMatrix is used in Spritebatch.Begin()? I don’t know much about matrices so how can I calculate the transformMatrix to have my textures in visible area?
It could also be done by going through each of the dozens, maybe hundreds spritebatch.Draw calls I have and giving them offset but it sounds like a bad idea…

I don’t think that this is going to be problem then :slight_smile:

Should this be done UnloadContent() function? I have never unloaded Content.

I think that I’ll go with one now. Maybe I’ll try combining background assets into single textures, who knows…

Yeah, the question is vague but I can’t think any reason other than creating effects…

Think of it like this:

When you just draw your stuff as usual, you use a rendertarget - the backbuffer. The backbuffer is what’s shown on your monitor when the gpu has finished with the frame.

It is also treated the same way and has the same relevant properties, like width/height, format etc.

So for example if you have a 800x600 window.

You can draw your stuff as usual

SpriteBatch.Begin();

SpriteBatch.Draw(…)
[…]

SpriteBatch.End();

But you could also draw your stuff to a rendertarget and achieve the same effect

GraphicsDevice.SetRenderTarget(myRenderTarget);
SpriteBatch.Begin();

SpriteBatch.Draw(…)
[…]

SpriteBatch.End();

Now all our things are drawn to the rendertarget, but we need to draw the RenderTarget back to the screen

GraphicsDevice.SetRenderTarget(null); //Set backbuffer as rendertarget
SpriteBatch.Begin();

SpriteBatch.Draw(myRenderTarget, new Rectangle(0,0, WindowWidth , WindowHeight), Color.White);

SpriteBatch.End();

Done!


In this case it already makes sense to use a rendertarget - for example if you want your game to work with any resolution!

You can resize your window as you please, but the game will always function the same way and the output is always the same - but stretched to fit your window.

This might not look pretty but sometimes you already made a game without thinking about possibly scaling the output window and this works on every machine, with every monitor resolution.

Another neat thing you can do is for example draw your game as usual to the rendertarget (as above).
But when drawing it to the backbuffer you can manipulate the color of the whole image if you change the spritebatch.draw(… color)

So you can easily make the screen turn red or black etc.

Plus you can reuse your rendertarget in other shaders, or for example flip it vertically to simulate reflection off of some floor or water.

That’s a good way to do it. It’s generally not hard to do and it’s flexible. There’s other options, but what’s best for your game really depends on what you want to be able to do. What kind of game are you trying to make?
That said, if you already have SpriteBatch.Draw calls all over the place passing a matrix to Begin may be the easiest solution.

No, classes that have unmanaged resources usually implement the IDisposable interface. That interface defines a function Dispose that should be called to release the unmanaged resources. For RenderTargets that means releasing the VRAM they use. So when you no longer need a render target, you need to call Dispose on it before removing the reference.
ContentManager.Unload is used in a ContentManager to release all assets it loaded using ContentManager.Load. For assets that implement IDisposable it calls Dispose before releasing them so you don’t have to. But since you don’t create RenderTargets using a ContentManager this doesn’t apply here.

You can make a 2d game without touching RenderTargets at all, so don’t worry about it too much. If you have specific things you want to implement and don’t know how or run into performance issues or whatever, just post here on the forum and someone will surely help out :slight_smile: