Sign in to follow this  
mikfig

Issues reading a render target on the CPU (GPGPU)

Recommended Posts

I'm implementing a vegetation rendering system just like from GPU Gems 2: Toward Photorealism in Virtual Botany. To pick points to "plant" vegetation, I render the terrain in blocks that correspond to the cells I want, i.e. blocks of planting points just like in GPU Gems 2. I have a working shader that finds planting points and outputs 1 for planting points and 0 for non-planting points. The problem I'm having though, is when I try to read the texture on the CPU I get complete garbage. Here is the source code for reading the texture:
gd3dDevice->CreateOffscreenPlainSurface(256, 256, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &mOffscreenCPUSurface, NULL);
...
D3DLOCKED_RECT lock;

IDirect3DSurface9* tempRT = 0;
gd3dDevice->GetRenderTarget(0, &tempRT);
gd3dDevice->SetRenderTarget(0, mTopSurf);
gd3dDevice->GetRenderTargetData(mTopSurf, mOffscreenCPUSurface);
gd3dDevice->SetRenderTarget(0, tempRT);

mOffscreenCPUSurface->LockRect(&lock, NULL, D3DLOCK_READONLY);

const BYTE* src = (const BYTE*)lock.pBits;
int pixelsPrinted = 0;
char tempStr[50];
DWORD r, g, b, a;

for( int y = 255; y >= 0; --y )
{
    const DWORD* srcPtr = (const DWORD*)src;
    for(int x = 0; x <= 256; ++x)
    {
        DWORD argbCol = *srcPtr;
        r = argbCol & 0xFF000000;
        g = (argbCol & 0x00FF0000) << 8;
        b = (argbCol & 0x0000FF00) << 16;
        a = (argbCol & 0x000000FF) << 24;
        sprintf_s(tempStr, 50, "(%u, %u, %u, %u)", r, g, b, a);
        MessageBox(NULL, tempStr, "", MB_OK);

	pixelsPrinted++;
	if(pixelsPrinted > 3) break;

	++srcPtr;
    }

    if(pixelsPrinted > 3) break;
    
    src += lock.Pitch;
}

mOffscreenCPUSurface->UnlockRect();

Whenever I run this code, I always get (4278190080, 0, 0, 0). I then wrote a function that "MessageBoxes" every single bit one at a time, and I read 20 pixels to see that every single bit is zero. Can someone please help me read the render target, Thanks, Mikfig

Share this post


Link to post
Share on other sites
4278190080 is 0xFF000000. Because you're shifting left, for a reason beyond my understanding, you'll always get 000000 at the end. I think you're also reading the components in a reverse order (which would happen if you're using D3D9, which describes the formats in a little endian way). The value is probably r=0, g=0, b=0, a=255.

Share this post


Link to post
Share on other sites
Ok, I am now reading the texture just fine, but I found out that it is stored as BGR instead of RGB. So now I have to figure out how to undue perspective divide and what not because I need the world space position that corresponds with each pixel. Considering that the Z coord is discarded, I put z / zfarplane in the G channel. I know that I have to get the x/y coords from screen space and then somehow get the world space coordinates with the inverse view/projection transform. However, I have no idea how to do this...

Any advice would be greatly appreciated,
Thanks,
mikfig

Share this post


Link to post
Share on other sites
Quote:
Original post by mikfig
Ok, I am now reading the texture just fine, but I found out that it is stored as BGR instead of RGB. So now I have to figure out how to undue perspective divide and what not because I need the world space position that corresponds with each pixel. Considering that the Z coord is discarded, I put z / zfarplane in the G channel. I know that I have to get the x/y coords from screen space and then somehow get the world space coordinates with the inverse view/projection transform. However, I have no idea how to do this...


Luckily for you, I come armed with blog posts. [smile]

http://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/


Share this post


Link to post
Share on other sites
You rock my world MJP :D

Just one question:

I am reconstructing the world space position on the CPU, and I'm assuming that out_vFrustumCornerWS (from the Reconstructing Position From Depth, Continued article) is interpolated between VS/PS to give the pixel's equivalent position on the far clipping plane.

So to get that I have to do something like bicubic interpolation of the frustum corner positions, right? And if so, I'm unsure what points I would interpolate between unless it is reasonable to assume that the corners of the render target texture are equivalent to the corners of the frustum.

Thanks a ton,
mikfig

Share this post


Link to post
Share on other sites

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