• entries
316
485
• views
322903

# D3D11 Programming Tip #2

1059 views

I'm pretty excited about the progress that I'm making on using D3D11 - my renderer is more or less feature complete, although I'll be adding some helpers and cleaning things up as I go. There are just under 50 D3D11 specific classes, and I'm happy with the overall design thus far. Now it's time to start integrating the new renderer into the higher level systems of my engine, such as the scene management system, material systems, and the next iteration of my render view system. Stay tuned - I'm nearing content completion for my thesis as well, so my free time is about to get the biggest boost it's had in 3+ years of grad school! Anyhow, on to the programming tip...

D3D11 Programming Tip #2

The second tip that I'd like to share is how to take screen shots of a rendered image in D3D11. This is important for several reasons - the most important of which is that D3D11 hardware still isn't available yet so most of us are using the reference rasterizer to get a sequence of images rendered which can later be assembled into a video to see what is happening. It is also important for debugging, as it is often helpful to see the contents of several rendered images leading up to the final rendering to understand what is coming down the pipeline. This also seems to be a common question for beginning graphics programmers, so I thought it would be a good topic to cover.

A function to serve this purpose doesn't need to be too complex, since the D3DX library does the heavy lifting for you and actually saves your resource information to file in a variety of formats. The basic concept is to allow the application to pass in a texture reference (which in my case is an integer ID handle), a base file name, and a format to store it in and then take care of creating the filename and store it. It is relatively straight forward, as seen here from my renderer code:

//--------------------------------------------------------------------------------void RendererDX11::SaveTextureScreenShot( int index, std::string filename, D3DX11_IMAGE_FILE_FORMAT format ){	// Get the index from the handle	int TYPE	= index & 0x00FF0000;	int ID		= index & 0x0000FFFF;	if ( ( ID >= 0 ) && ( ID < m_vResources.count() ) )	{		// Increment the file number for allowing a sequence of images to be stored...		static int iScreenNum = 100000;		iScreenNum++;		// Build the output file name		std::stringstream out;		out << filename << iScreenNum;		// Select the appropriate format to add the extension to the name.  DDS format		// may be the only one that can handle certain texture formats, so it may be a 		// backup format later on.		switch ( format )		{		case D3DX11_IFF_BMP:			out << ".bmp";			break;		case D3DX11_IFF_JPG:			out << ".jpg";			break;		case D3DX11_IFF_PNG:			out << ".png";			break;		case D3DX11_IFF_DDS:			out << ".dds";			break;		case D3DX11_IFF_TIFF:			out << ".tiff";			break;		case D3DX11_IFF_GIF:			out << ".gif";			break;		case D3DX11_IFF_WMP:			out << ".wmp";			break;		default:			CLog::Get().Write( "Tried to save a texture image in an unsupported format!" );		}		// Get the texture as a resource and save it to file		ID3D11Resource* pResource = m_vResources[ID]->GetResource();		HRESULT hr = D3DX11SaveTextureToFile(		  m_pContext,		  pResource,		  format,		  out.str().c_str()		);		if ( FAILED( hr ) )			CLog::Get().Write( "D3DX11SaveTextureToFile has failed!" );	}}//--------------------------------------------------------------------------------

The base file name is appended with the file number (starting at a large number to allow for the same number of digits in each stored file) and the appropriate file extension for the format being used. The file number is automatically incremented so the application doesn't need to keep track of the current frame number.

The nice thing about using the D3DX function for saving the images is that it supports the DDS format. It may not always be obvious, but certain resource formats aren't supported for a particular file format. For instance, a single channel DXGI_FORMAT_R32_FLOAT render target can't be saved as a PNG file, but is easily stored as a DDS. The resulting DDS file can then be viewed with the DirectX Texture Tool, and converted to another format as needed.

Being able to save intermediate rendering results can save a significant amount of time and headache while debugging, so get a function similar to this one put into your renderer at an early stage to make things easier to test. Of course, since this is a post about taking screenshots, I am obliged to post a screenshot [wink]! So here is the Tusk model from last time, with a slight bit of shading added in:

There are no comments to display.