Chad Vernon
  • Home
  • Reel/Resume
  • Work
  • Resources
  • About
  • Contact
Home » Resources » Managed DirectX 2.0 » Offscreen Surfaces and Screenshots
sideBar

Search

Categories

  • CG
  • cvxporter
  • Maya
  • Personal

Archives

  • July 2010
  • May 2010
  • April 2010
  • March 2010
  • December 2009
  • October 2009
  • September 2009
  • August 2009
  • July 2009
  • June 2009
  • May 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • September 2008
  • August 2008
  • July 2008
  • June 2008
  • May 2008
  • April 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007

Rss

  • Main Entries RSS
  • Comments RSS

Offscreen Surfaces and Screenshots

  CU_MDX_OffscreenSurfaces.zip (119.2 KiB, 1,426 hits)


  CUnitFramework.zip (101.1 KiB, 15,247 hits)

Extract the C-Unit Framework
inside the project (not solution) directory.

This tutorial uses the October 2005 SDK version. Microsoft changed functionality after this version and I never got around to updating the code.

Surfaces are basically containers that hold image data. Backbuffers are surfaces and each mip level of a texture is a surface. We can use Surfaces to modify existing image data, such as Texture mip levels if the existing mip level is not detailed enough. Off-screen surfaces are useful because they do not have the same size restrictions that Textures have. Surfaces allow for the display of images that have larger dimensions than the video card’s supported maximum Texture size.

Surface

Off-screen surfaces are useful when we want to display large images such as a title or logo image or a 2d backgound image. If we were to make, for example Tetris or a 2d fighting game, off-screen surfaces would be a good way to display the background. Since off-screen surfaces are usually stored in system memory, they do not take up valuable video memory so we can store whatever size image we want.

Since surfaces are just containers for image data, we can also use them to take screenshots as we’ll see later on.

/// <summary>
/// This event will be fired immediately after the Direct3D device has been
/// reset, which will happen after a lost device scenario, a window resize, and a
/// fullscreen toggle. This is the best location to create_ Pool.Default resources
/// since these resources need to be reloaded whenever the device is reset. Resources
/// created here should be released in the OnLostDevice callback.
/// </summary>
/// <param name=”device”>The Direct3D device</param>
private void OnResetDevice( Device device )
{
   // Clip…
           
   // Create surface
   m_imageInfo = TextureLoader.ImageInformationFromFile( Utility.GetMediaFile( “cunit.jpg” ) );
   if ( m_surface != null )
   {
       m_surface.Dispose();
   }
   m_surface = device.CreateOffscreenPlainSurface( m_imageInfo.Width, m_imageInfo.Height,
       m_framework.CurrentSettings.AdapterFormat, Pool.Default );
   SurfaceLoader.FromFile( m_surface, Utility.GetMediaFile( “cunit.jpg” ), Filter.None, 0 );

   // Clip…
}

We create_ a surface by calling Device.CreateOffscreenPlainSurface. Since we want to create_ a Surface with the same dimensions as the image, we get the dimensions of the image by calling TextureLoader.ImageInformationFromFile, which stores the dimensions in a ImageInformation structure. Once the Surface is created, we load in the image data with SurfaceLoader.FromFile.

/// <summary>
/// Renders the current frame.
/// </summary>
/// <param name=”device”>The Direct3D device</param>
/// <param name=”elapsedTime”>Time elapsed since last frame</param>
private void RenderFrame( Device device, float elapsedTime )
{
   // Clip…

   device.Clear( ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0 );
   device.BeginScene();

   Surface backbuffer = device.GetBackBuffer( 0, 0, BackBufferType.Mono );
   device.StretchRectangle( m_surface, new Rectangle( 0, 0, m_imageInfo.Width, m_imageInfo.Height ),
       backbuffer, new Rectangle( 0, 0, BackBufferWidth, BackBufferHeight ),
       TextureFilter.None );
   backbuffer.Dispose();

   // Clip…

   device.EndScene();
   device.Present();
}

To display our Surface to the screen, we have to copy its image data into the backbuffer. First, we get the backbuffer Surface with Device.GetBackBuffer. Then, we copy over our image data into the backbuffer surface by calling Device.StretchRectangle. Note however that although MSDN says we can put null for the Rectangle parameters to use the entire Surface, I was getting an error when I put either null or Rectangle.Empty. As a result, I use the actual dimensions of my source and destination Surfaces.

/// <summary>Takes a screen shot</summary>
public void TakeScreenShot()
{
string fileName = DateTime.Now.ToString( “yyyyMMdd” ) + “_” + DateTime.Now.TimeOfDay.ToString();
// Remove colons and junk
fileName = fileName.Remove( 11, 1 );
fileName = fileName.Remove( 13, 1 );
fileName = fileName.Remove( 15, 1 );
Surface backbuffer = Device.GetBackBuffer( 0, 0, BackBufferType.Mono );
SurfaceLoader.Save( fileName + “.tga”, ImageFileFormat.Tga, backbuffer );
backbuffer.Dispose();

}

Surfaces are not only useful for loading image data, they can also be used to save out image data, a.k.a. take a screenshot. All we do to save a screen shot is get the backbuffer surface with Device.GetBackBuffer and then save it to a file with SurfaceLoader.Save. All the string manipulation code creates the filename based on the current time so our saved screenshot does not overwrite any previously saved screen shot.

/// <summary>
/// This function will be called after the Direct3D device has
/// entered a lost state and before Device.Reset() is called. Resources created
/// in the OnResetDevice callback should be released here, which generally includes all
/// Pool.Default resources.
/// </summary>
private void OnLostDevice()
{
if ( m_surface != null )
{
m_surface.Dispose();
m_surface = null;

}
// Clip…

}

Don’t forget to Dispose your resources!

Home » Resources » Managed DirectX 2.0 » Offscreen Surfaces and Screenshots

© 2010 Chad Vernon