I want to take a screenshot of the game when it's running, blur it and draw it on the screen. Could you help me with taking a screenshot and blurring it?
-
2\$\begingroup\$ The XNA post-processing sample is a good starting point for this. \$\endgroup\$– Andrew RussellCommented Jun 20, 2013 at 14:56
-
1\$\begingroup\$ gamedev.stackexchange.com/a/47453/17256 \$\endgroup\$– SidarCommented Jun 20, 2013 at 15:23
2 Answers
I have no source code to provide you, but I will point you in the correct direction. "Taking a Picture" is a simple task when rendering a game, you simply need to make a copy of the back buffer before it is swapped at the end of the render stage of your game loop.
If you then want to blur it, you will need to filter your image using one of many blur functions and a convolution matrix. This is typically done as a post processing step in engines, and it involves rendering a quad the size of the screen to a texture, while sampling the original back buffer image as an input.
A note here, this isn't a trivial thing unless you have sufficient experience with your rendering pipeline, and it would be far too much code to simply demonstrate the entire process.
Here is a link to the theory behind a Gaussian filter, and how it can be used to produce a blurred/smoothed image in the general context of computer vision.
I managed to do what I've wanted with this. Code:
bool prepareToPause, first, drawn, blurredReady;
Texture2D pausedScreenshot, blurredPauseScreenshot;
RenderTarget2D renderTarget;
enum GameState
{
MainMenu,
Playing,
Paused
};
const int BLUR_RADIUS = 7;
const float BLUR_AMOUNT = 2.0f;
GaussianBlur gaussianBlur;
int renderTargetWidth, renderTargetHeight;
RenderTarget2D renderTarget1, renderTarget2;
protected override void LoadContent()
{
//
gaussianBlur = new GaussianBlur(this);
gaussianBlur.ComputeKernel(BLUR_RADIUS, BLUR_AMOUNT);
//
renderTarget = new RenderTarget2D(
GraphicsDevice,
(int)graphicsDeviceManager.PreferredBackBufferWidth,
(int)graphicsDeviceManager.PreferredBackBufferHeight);
currentGameState = GameState.MainMenu;
}
private void InitRenderTargets()
{
renderTargetWidth = pausedScreenshot.Width / 2;
renderTargetHeight = pausedScreenshot.Height / 2;
renderTarget1 = new RenderTarget2D(GraphicsDevice,
renderTargetWidth, renderTargetHeight, false,
GraphicsDevice.PresentationParameters.BackBufferFormat,
DepthFormat.None);
renderTarget2 = new RenderTarget2D(GraphicsDevice,
renderTargetWidth, renderTargetHeight, false,
GraphicsDevice.PresentationParameters.BackBufferFormat,
DepthFormat.None);
gaussianBlur.ComputeOffsets(renderTargetWidth, renderTargetHeight);
}
protected override void Draw(GameTime gameTime)
{
if (prepareToPause && !first)
{
GraphicsDevice.SetRenderTarget(renderTarget);
drawn = true;
GraphicsDevice.Clear(Color.Black);
}
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
if (currentGameState == GameState.Playing)
{
[...]
if (mouseRectangle.Intersects(nextWaveRectangle) && mouseState.RightButton == ButtonState.Pressed)
prepareToPause = true;
}
if (prepareToPause && !first && drawn)
{
pausedScreenshot = renderTarget;
GraphicsDevice.SetRenderTarget(null);
currentGameState = GameState.Paused;
}
spriteBatch.End();
if (!first && drawn && currentGameState == GameState.Paused)
{
InitRenderTargets();
blurredPauseScreenshot = gaussianBlur.PerformGaussianBlur(pausedScreenshot, renderTarget1, renderTarget2, spriteBatch);
blurRectangle = new Rectangle(0, 0, pausedScreenshot.Width, pausedScreenshot.Height);
prepareToPause = false;
blurredReady = true;
first = true;
}
if(blurredReady)
{
spriteBatch.Begin();
spriteBatch.Draw(blurredPauseScreenshot, blurRectangle, Color.White);
spriteBatch.End();
}
base.Draw(gameTime);
}
I've probably made many errors but it's working and that's important for me at this point of my game development. Criticism and suggestions are welcome.