Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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?

share|improve this question
    
I'm only beginner with C#. I don't understand your code too well, but aren't you missing {} in for loop? –  zacharmarz Apr 2 '12 at 5:19
    
Yes, they're missing - I just wrote some quick pseudocode. I'll add the braces. –  Utkarsh Sinha Apr 2 '12 at 6:11
    
Does a DiscardContents render target get cleared to transparent when discarded? –  John Calsbeek Apr 2 '12 at 6:38
3  
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. –  Jonathan Hobbs Apr 2 '12 at 6:53
1  
@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. –  Jonathan Dickinson Apr 5 '12 at 9:42
add comment

4 Answers

up vote 1 down vote accepted

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>
}
share|improve this answer
add comment

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>   
share|improve this answer
add comment

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.

share|improve this answer
add comment

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.

share|improve this answer
    
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. –  John Calsbeek Apr 2 '12 at 15:52
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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