Sign in to follow this  

Direct3D10 implementation of glReadPixels

This topic is 2042 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

[size=4]I want to read out the color buffer (I guess it is called ID3D10RenderTargetView) into a memory block of my application in order to implement some features like showing a thumbnail view of the client area, or saving the rendering content of the client area as a disk image file. I've searched this site and the web, but the working solutions are all implemented inr D3D9. Could someone suggest how to do this in D3D10/11? Thanks.[/size]

Share this post


Link to post
Share on other sites
Here's the way I use to do this.

Firstly, IDXGISwapChain::GetBuffer to retrieve the backbuffer into an ID3D11Texture2D interface (you'll need to Release this when done).
Then call GetDesc on this texture and modify it's usage to staging, bind flags to 0 and access flags to read/write.
Then CreateTexture2D using the modified desc.

That gives you a second texture that is the same dimensions and format as the backbuffer, but is setup for reading and writing in your own program code.

So the next thing to do is CopyResource from the backbuffer texture to your new texture. You could also use CopySubresourceRegion to get a sub-rect of the backbuffer if you so wish.

Then you Map the new texture and access it's contents accordingly. Beware of your D3D11_MAPPED_SUBRESOURCE::RowPitch value here - the texture used for the back buffer may not be the same size as the back buffer dimensions!

When done, Release anything you created.

If it's something you want to do every frame, all this creating and releasing is going to get slow, so instead you'll create the texture once at startup (and destroy/recreate it when you call ResizeBuffers) and just do the copy/map/unmap part each frame.

Share this post


Link to post
Share on other sites
[quote name='mhagain' timestamp='1336915038' post='4939775']
Here's the way I use to do this.

Firstly, IDXGISwapChain::GetBuffer to retrieve the backbuffer into an ID3D11Texture2D interface (you'll need to Release this when done).
Then call GetDesc on this texture and modify it's usage to staging, bind flags to 0 and access flags to read/write.
Then CreateTexture2D using the modified desc.

That gives you a second texture that is the same dimensions and format as the backbuffer, but is setup for reading and writing in your own program code.

So the next thing to do is CopyResource from the backbuffer texture to your new texture. You could also use CopySubresourceRegion to get a sub-rect of the backbuffer if you so wish.

Then you Map the new texture and access it's contents accordingly. Beware of your D3D11_MAPPED_SUBRESOURCE::RowPitch value here - the texture used for the back buffer may not be the same size as the back buffer dimensions!

When done, Release anything you created.

If it's something you want to do every frame, all this creating and releasing is going to get slow, so instead you'll create the texture once at startup (and destroy/recreate it when you call ResizeBuffers) and just do the copy/map/unmap part each frame.
[/quote]

I tried your method and it works. But there is one annoying issue, i.e. I have to render one graphics layer at a time and use your method to get the buffer pixels for the current layer. The visual result of repeating this two-step process when creating thumbnail views for multiple layers looks like playing PowerPoint slides. So I want to know if there is a method via which I can disable rendering but still get the pixels? Just like press "Ctrl+Q" in IE9 to get thumbnail views for all web pages. I am not sure whether it is called off screen rendering. I've searched this terminology but all solutions to off screen rendering using D3D9.

Share this post


Link to post
Share on other sites
Create a render target texture, and render to that instead of the backbuffer from the swap chain.

EDIT: some code to get you started:

[code]
ID3D11Texture2D* rtTexture = NULL;

D3D11_TEXTURE2D_DESC desc;
desc.Width = width;
desc.Height = height;
desc.ArraySize = 1;
desc.BindFlags = D3D11_BIND_RENDER_TARGET;
desc.CPUAccessFlags = 0;
desc.Format = format;
desc.MipLevels = 1;
desc.MiscFlags = 0;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
device->CreateTexture2D(&desc, NULL, &rtTexture);
[/code]

You'll need to provide the width, height, and format that you want to use. Once you've created the RT texture you can create a render target view for it using CreateRenderTargetView, just like you would for the swap chain backbuffer. Then you can render to it, and then copy it to your staging texture for CPU readback. Edited by MJP

Share this post


Link to post
Share on other sites

This topic is 2042 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this