Jump to content
  • Advertisement
Sign in to follow this  
dario_ramos

Save scene to a file

This topic is 3096 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys, I'm trying to save my current scene to a file in 24-bit RGB format. This should work in both windowed and fullscreen mode. Therefore, GetFrontBufferData doesn't work, since it gets a screenshot of the whole desktop, and I just want the contents of my app's window. This should be done outside of the render loop if possible (although I think I could set a flag so that it gets saved on the next render cycle). This is what I tried:
BYTE* CDirect3D::GetImageBuffer() const{

	// Lock backbuffer just for reading
	D3DLOCKED_RECT lockRect;
	m_pBackBuffer->LockRect(&lockRect, NULL, D3DLOCK_READONLY );
		BYTE *pBuffer = (BYTE*)lockRect.pBits;
		BYTE *pBufferCopy = new BYTE[600*400*4];	//TODO: Check when this is freed <MEM>
		memcpy(pBufferCopy, pBuffer, 600*400*4);
	m_pBackBuffer->UnlockRect();
	return pBuffer;
}


I use the function above to get the back buffer's bytes and send them to a file. Done this way, I see the same trash if I load the saved image on my app and on ImageJ. I thought the problem was that if I access the back buffer outside the render cycle, it might be not ready for display (that happens only right before the call to Present, I believe). So I tried saving right before Present(), but then I got a black image... and so I got stumped =( PS: I believe the problem is that the back buffer's format is X8R8G8B8 = 32 bits, and I need only 24 bits. Therefore, I need to trim the back buffer's bytes before sending them to the file. I'm gonna try that now. If anyone knows of a D3DX helper function which does this conversion, please tell me =)

Share this post


Link to post
Share on other sites
Advertisement
1. You can use GetBackBuffer() to get the backbuffer, but the contents are only going to be valid between EndScene() and Present().
2. You can't lock your backbuffer unless you created your device with the D3DCREATE_LOCKABLE_BACKBUFFER (Or whatever the flag is).

Have you tried using GetBackBuffer() and then D3DXSaveSurfaceToFile?

Share this post


Link to post
Share on other sites
Alright, so I'm gonna try D3DXSaveSurfaceToFile between BeginScene() and EndScene(). If that works, I'll call it from outside using a flag. If I succeed, I'll post the working code snippet.
Thanks!

Share this post


Link to post
Share on other sites
Quote:
Original post by dario_ramos
Alright, so I'm gonna try D3DXSaveSurfaceToFile between BeginScene() and EndScene(). If that works, I'll call it from outside using a flag. If I succeed, I'll post the working code snippet.
Thanks!
You want to do it between EndScene() and Present(), not BeginScene() and EndScene().

Share this post


Link to post
Share on other sites
Ok, so first I tried this:


if( SUCCEEDED( m_pd3dDevice->BeginScene() ) ) {
//Render stuff
// ...
// Save back buffer
m_pd3dDevice->GetBackBuffer(0,
0,
D3DBACKBUFFER_TYPE_MONO,
&m_pBackBuffer);
D3DXSaveSurfaceToFile( L"C:\\Fralala.bmp", //<IMG>
D3DXIFF_BMP,
m_pBackBuffer,
NULL,
NULL );



And I saw the same as before. But then I changed "Fralala.bmp" to "Fralala.jpeg" and "D3DXIFF_BMP" to "D3DXIFF_JPG" and it worked.
So my guess is that as JPEG uses 24 bits and the back buffer uses 32, that's why saving to a bmp didn't work.
The problem is that my app can't handle jpg images, only 24-bit RGB. So I'm gonna try to "trim" the back buffer bytes before sending them to a file.
Is there a D3DX way to convert a copy of the back buffer surface from 32 bits to 24 bits? That would be a lifesaver...

Share this post


Link to post
Share on other sites
Quote:

You want to do it between EndScene() and Present(), not BeginScene() and EndScene().


Woops, missed that. It works now, sorry =).
Thanks a bunch!

Share this post


Link to post
Share on other sites
Quote:
Original post by dario_ramos
Woops, missed that. It works now, sorry =).
Thanks a bunch!
So it works with BMPs as well as JPG? There really shouldn't be a reason for one to work and not another, D3DX can convert between bit depths for you.

It'd definitely be worthwhile enabling the debug runtimes, they'll highlight bugs like accessing the backbuffer at invalid times by trashing the contents (In a recognisable way, green and magenta on alternate frames) after the Present() call.

Share this post


Link to post
Share on other sites
Yeah, it works alright now. I think the problem was that when I tried to convert to BMP before EndScene(), D3DX could'nt convert the backbuffer 'cos it was still being accessed.
I got the debug runtimes active, but I must have missed a message 'cos D3D's output gets jumbled with Visual Studio's (which shows a lot of dll messages which I want to turn off someday)...

Share this post


Link to post
Share on other sites
Quote:
Original post by dario_ramos
Yeah, it works alright now. I think the problem was that when I tried to convert to BMP before EndScene(), D3DX could'nt convert the backbuffer 'cos it was still being accessed.
I got the debug runtimes active, but I must have missed a message 'cos D3D's output gets jumbled with Visual Studio's (which shows a lot of dll messages which I want to turn off someday)...
Ah cool.

You could always run DebugView, which won't show the DLL load / unload messages, but it's a bit horrible just to read some debug spew [smile]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!