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 have an app that plays back a video and draws the video onto the screen at a moving position. When I run the app, the video moves around the screen as it plays. Here is my Draw method...

    protected override void Draw(GameTime gameTime)
    {
        Texture2D videoTexture = null;

        if (player.State != MediaState.Stopped)
            videoTexture = player.GetTexture();

        if (videoTexture != null)
        {
            spriteBatch.Begin();
            spriteBatch.Draw(
                    videoTexture,
                    new Rectangle(x++, 0, 400, 300),  /* Where X is a class member */
                    Color.White);
            spriteBatch.End();
        }

        base.Draw(gameTime);
    }

The video moves horizontally acros the screen. This is not exactly as I expected since I have no lines of code that clear the screen. My question is why does it not leave a trail behind?

Also, how would I make it leave a trail behind?

share|improve this question
    
Out of curiosity, why would you want the video to smear across the screen that way? –  Josh Petrie Feb 10 '11 at 7:38
    
It's not for a game, but rather to produce a type of graphics effect. Imagine a video of someone's head rotating. If you smear this video and clip it so that one half of the video is not drawn, you will plot an image of their head 'unwrapped' so to speak. Then take a screenshot and paste into photoshop to use elsewhere. I guess it might be a way to make a texture map of someone's head, game-wise. –  izb Feb 13 '11 at 11:20
1  
.. And see my avatar for the effect :) –  izb Feb 14 '11 at 10:51
add comment

3 Answers

up vote 1 down vote accepted

Drawing in the screen is much more than just drawing in it. A system called "double buffering" is commonly used. In double buffering, you have two canvases: a front and a back one.

Whenever you're drawing, you draw onto the back canvas, and when you're done and ready to show it into the screen, you flip the back and front canvases. If canvases weren't cleared automatically before you started drawing on them, you'd end with even frame trails on one canvas and odd frame trails on the other. Sometimes the back canvas is cleared by the video card when you flip it, sometimes it's not. Sometimes it's actually filled with garbage so you can know you didn't clear it.

However, that is not the only way to implement a graphics pipeline. There are many more, such as triple buffering, and many more esoteric ones. So you should never assume anything about data you don't explicitly save from one frame to another.

Instead, if you want to have trails as you explained, you should capture your output, store it, and when you start the next frame, draw it at the very back.

share|improve this answer
    
This turned out to be the working answer. You need to get the back buffer data and then draw it back onto the screen before drawing anything else. –  izb Feb 14 '11 at 10:51
add comment

Just a bit of a guess here (after answering this question): It's possible that the video renderer is clearing the graphics memory. Perhaps it has to emulate a quirk of the Xbox GPU hardware to remain consistent on Windows. I'm not entirely sure.

But try using:

GraphicsDeviceManager.PreparingDeviceSettings

to modify:

GraphicsDeviceInformation.PresentationParameters.RenderTargetUsage

And setting it to RenderTargetUsage.PreserveContents.


I'm pretty sure you don't need to fiddle with BeginDraw (as Josh mentioned). Unless you've change it yourself, it should have no effect.

However you should be aware of double-buffering (as Oscar mentions) - this will probably cause the trail your video leaves behind to flicker. The simple way to solve this is to disable double-buffering. The more complicated way is to use render targets (as Roy mentions) to store your video trail (this also solves the clearing problem).

share|improve this answer
    
Yup, I don't know what I was thinking when I posted my answer that you are referring to -- it was blatantly wrong, so I've deleted it. Thanks for the correction :D –  Josh Petrie Feb 10 '11 at 16:53
    
I'd really advice against disabling double buffering or messing with anything in your device configuration in order to get graphical effects to work. If you want trailing, it should work because its' an integral part of your drawing algorithm, not because it's a side effect of the device configuration. –  slcpfmmm Feb 11 '11 at 5:27
    
@Oscar There's nothing at all "evil" about selecting a graphics device setup that makes a core effect work, as long as you are aware of the trade-offs involved (and admittedly there are some fairly serious downsides to the simple, disable-the-double-buffer approach). –  Andrew Russell Feb 11 '11 at 8:11
    
It depends. Usually the behavior of side effects of certain device configurations are not standard across vendors, devices and even driver versions. So you're risking a great deal in portability. The trade-offs are usually unknown and unpredictable, so unless you're doing a prototype, or you can guarantee a specific hardware model/driver version (such as for console or arcade development), I'd strongly advice against side-effect programming. This site has a nice explanation with an example: webster.cs.ucr.edu/AoA/Windows/HTML/… –  slcpfmmm Feb 15 '11 at 2:53
    
Treating a buffer as a single buffer by configuring it as single buffer is clearly not a "side-effect". Don't be stupid. But this whole thing is moot - because it looks like you can't actually disable double-buffering in XNA anyway. –  Andrew Russell Feb 15 '11 at 7:17
add comment

This will probably give you the correct effect without having to override BeginDraw which as Oscar Rodriguez rightfully said, is a bad idea.

RenderTarget2D smearRT;

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.Black);

    Texture2D videoTexture = null;

    if (player.State != MediaState.Stopped)
        videoTexture = player.GetTexture();

    if (videoTexture != null)
    {
        GraphicsDevice.SetRenderTarget(smearRT);
        spriteBatch.Begin();
        spriteBatch.Draw(
                videoTexture,
                new Rectangle(x++, 0, 400, 300),  /* Where X is a class member */
                Color.White);
        spriteBatch.End();
        GraphicsDevice.SetRenderTarget(null);
    }

    spriteBatch.Begin();
    spriteBatch.Draw(smearRT, new Rectangle(0,0, 800, 600), Color.White);
    spriteBatch.End();

    base.Draw(gameTime);
}
share|improve this answer
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.