3
\$\begingroup\$

I've been dabbling with XNA for a couple of days now. This chunk of code doesn't work as I expect. The goal is to render sprites individually and composite them on another rendertarget.

P = RenderTarget2D(with RenderTargetUsage.PreserveContents)
D = RenderTarget2D(with RenderTargetUsage.DiscardContents)

for all sprites:
{
    graphicsDevice.SetRenderTarget(D);
    <draw sprite i>

    graphicsDevice.SetRenderTarget(P);
    <Draw D>
}

graphicsDevice.SetRenderTarget(null);
<Draw P>

The result I get is - only the last sprite is visible. I'm sure I'm missing some piece of information about RenderTarget2D. Any hints on what that might be?

\$\endgroup\$
  • \$\begingroup\$ I'm only beginner with C#. I don't understand your code too well, but aren't you missing {} in for loop? \$\endgroup\$ – zacharmarz Apr 2 '12 at 5:19
  • \$\begingroup\$ Yes, they're missing - I just wrote some quick pseudocode. I'll add the braces. \$\endgroup\$ – Utkarsh Sinha Apr 2 '12 at 6:11
  • \$\begingroup\$ Does a DiscardContents render target get cleared to transparent when discarded? \$\endgroup\$ – John Calsbeek Apr 2 '12 at 6:38
  • 3
    \$\begingroup\$ Utkarsh, please don't cross-post questions here. It reduces the usefulness of the site, ends up with multiple answers on both sites which is confusing, etc - but mainly it just wastes your time because the StackOverflow one is going to be closed. \$\endgroup\$ – doppelgreener Apr 2 '12 at 6:53
  • 1
    \$\begingroup\$ @JohnCalsbeek in debug DiscardContents will actually fill the buffer with a dirty purple color. IIRC it should be 'undefined' (hopefully black, but no guarantees) for release. \$\endgroup\$ – Jonathan Dickinson Apr 5 '12 at 9:42
1
\$\begingroup\$

The problem was that I wasn't clearing D with Color.Transparent for every sprite. So, when I tried to overlay D onto P, the alpha channel didn't work as expected. Changing the code to this made it work:

for all sprites:
{
    graphicsDevice.SetRenderTarget(D);
    graphicsDevice.Clear(Color.Transparent);
    <draw sprite i>

    graphicsDevice.SetRenderTarget(P);
    <Draw D>
}
\$\endgroup\$
1
\$\begingroup\$

Why do you need to set rendertargets so many times? Why not just:

graphicsDevice.SetRenderTarget(D);
graphicsDevice.Clear(Color.Transparent);

for all sprites:   
{   
    <draw sprite i>   
} 
graphicsDevice.SetRenderTarget(P);
<Draw D>   
\$\endgroup\$
0
\$\begingroup\$

Well I think what's happening is that the render target is clearing the draw buffer and therefore any spritebatch calls are going to be unset. Basically, render all the render targets at once, then draw their content all at once.

\$\endgroup\$
0
\$\begingroup\$

Change this:

for all sprites:
{
    graphicsDevice.SetRenderTarget(D);
    <draw sprite i>

    graphicsDevice.SetRenderTarget(P);
    <Draw D>
}

to this:

for all sprites:
{
    graphicsDevice.SetRenderTarget(D);
    <draw sprite i>
}

graphicsDevice.SetRenderTarget(P);
<Draw D>

The problem is that D or P are being cleared somewhere (probably when they get set as a render target), so the only sprite that "survives" is the last one.

Since you have all your sprites rendered to D you only need to render D onto P once.

\$\endgroup\$
  • \$\begingroup\$ This also has the benefit of (probably) being far, far more efficient, but it's also a behavior change, if the sprite comprised multiple elements and the drawing of render target D onto P used a shader or post-processing effect of some kind. \$\endgroup\$ – John Calsbeek Apr 2 '12 at 15:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.