Reading Pixels Back

Started by
10 comments, last by LeGreg 18 years ago
How to read pixels from the render target at a certain screen location? Is there any method equivalent to glReadPixels? or is it a bit more tricky?
Advertisement
It is more trickier. If you don't have access to the render target, you can obtain it through calling GetSwapChain() on the device and subsequently GetBackBuffer() on the obtained swap chain. Once you have a render target you can lock it and read the raw data -- this requires you to know the back buffer format and how to compute the correct access location. Don't forget to release all the obtained interfaces.

But perhaps there is a simpler approach, I don't know.

Illco
And how can I tell the exact order of the color format, bytes are laid out, and what about the pitch thing? All these sound scary to me, as a beginner.

Thanks.
Quote:Original post by quaker
And how can I tell the exact order of the color format, bytes are laid out, and what about the pitch thing? All these sound scary to me, as a beginner.

Thanks.
The pitch you get told when you lock the backbuffer (You get a D3DLOCKED_RECT structure back, which contains the pointer to the data and the pitch). As for the format - you told D3D what format it was in when you created the device, so you should know [smile]. The format is the same as the format of your presentation parameter's BackBufferFormat member. For instance, if you're using D3DFMT_X8R8G8B8, then each pixel is made up of 32 bits (4 bytes). The first byte is unused, the second contains the red value, the third is the green, and the fourth is the blue.

If you intend to lock the backbuffer, you'll also have to specify D3DPRESENTFLAG_LOCKABLE_BACKBUFFER as the Flags member of your presentation parameters.

Bear in mind that this is very slow (I'd imagine it's probably slow in OpenGL too), and you definitely should avoid doing this every frame unless you want to take a severe performance hit.
Quote:Original post by Evil Steve
Bear in mind that this is very slow (I'd imagine it's probably slow in OpenGL too), and you definitely should avoid doing this every frame unless you want to take a severe performance hit.


Yeah doing a glReadPixels isn't exactly the fastest thing in the world.

I had this problem a while back and what I did at first was I created an offscreen surface and rendered to that, locked it and read the data back. Later I changed the program to use a lockable backbuffer instead. In my case, rendering speed didn't mean a thing since it was for a regression test app. I changed to a lockable backbuffer just to simplify the regression tests.

I suggest you try both ways and see which is best for your app like I did.


-SirKnight

I'm not intending to read more than a pixel per frame so there will be no performance hit i guess.

But do I have to take into account the pitch value returned by LockRect in order to get correct RGBA values? How? Or does it only return the pixels within the specified screen rect?
Quote:Original post by quaker
I'm not intending to read more than a pixel per frame so there will be no performance hit i guess.
So very wrong unfortunately [sad]

Much of the overhead with reading data back is the pipeline flush it requires (before you can read any data all pending rendering operations must be completed), then any internal memory movement - it's possible that the driver will have to move/copy Render Targets to AGP addressable VRAM before it can initate a transfer. Then you have to wait for the AGP bus to be ready and transfer that data.

Also, whilst you hold the lock on a render target you can't use that data as an input or output (especially bad if its the back buffer) and your application isn't going to be making any concurrent use of the GPU...

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

It's still not a big hit when it comes to only one pixel per frame.

What should be the equation to read say A8R8G8B8 format from a 1x1 rect (1 pixel)? Thanks alot.
Quote:Original post by quaker
It's still not a big hit when it comes to only one pixel per frame.
Make sure you check that assumption [wink]

Quote:Original post by quaker
What should be the equation to read say A8R8G8B8 format from a 1x1 rect (1 pixel)? Thanks alot.
Well casting it to a DWORD should work for a 1x1 rect. Anything beyond a 1x1 rect will be more complex though [smile]

EDIT:

DWORD pix = *reinterpret_cast< DWORD* >( pLockedRect.pBits );

or, to be a bit more clever...
unsigned __int8 p[4] = reinterpret_cast< unsigned __int8* >( pLockedRect.pBits );
// p[0], p[1], p[2] and p[3] should be the individual ARGB's...

Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

Thanks maite!

The Rect for one pixel should be set to:

left = pixel.x
top = pixel.y
right = pixel.x + 1
bottom = pixel.y + 1

right?????

This topic is closed to new replies.

Advertisement