Sign in to follow this  

How to get the color of one pixel of shadow map

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

How to get the color of one pixel of shadow map? I try to lock the m_pShadowMapSurf by LockRect function, but it return error of -2005530516.
	LPDIRECT3DTEXTURE9		m_pShadowMapTexQuadNode;			// shadow map objects
	LPDIRECT3DSURFACE9		m_pShadowMapSurf;
	LPDIRECT3DSURFACE9		m_pShadowMapZ;

	HRESULT hr;		

	V_RETURN(pd3dDevice->CreateTexture(
		QUADTREE_SM_SIZE,
		QUADTREE_SM_SIZE,
		1, 
		D3DUSAGE_RENDERTARGET,
		SHADOW_MAP_FORMAT, 
		D3DPOOL_DEFAULT,
		&m_pShadowMapTexQuadNode,
		NULL
		));

	V_RETURN(m_pShadowMapTexQuadNode->GetSurfaceLevel(0, &m_pShadowMapSurf));

	V_RETURN(pd3dDevice->CreateDepthStencilSurface(
		QUADTREE_SM_SIZE,
		QUADTREE_SM_SIZE, 
		D3DFMT_D24S8,
		D3DMULTISAMPLE_NONE, 
		0,
		TRUE,
		&m_pShadowMapZ,
		NULL
		));


void CALLBACK NodeData::OnFrameRender_Shadowmap(IDirect3DDevice9* pd3dDevice,BOOL bSave)
{
	HRESULT hr;
	LPDIRECT3DSURFACE9 pOldBackBuffer, pOldZBuffer;

	D3DXHANDLE hTechnique = g_pEffect->GetTechniqueByName("TShader");
	g_pEffect->SetTechnique(hTechnique);
	V(g_pEffect->Begin(NULL, 0));

	// save old render target and set new render target with depth/stencil buffer
	pd3dDevice->GetRenderTarget(0, &pOldBackBuffer);
	pd3dDevice->GetDepthStencilSurface(&pOldZBuffer);
	pd3dDevice->SetRenderTarget(0, m_pShadowMapSurf);
	pd3dDevice->SetDepthStencilSurface(m_pShadowMapZ);

	// clear render target
	pd3dDevice->Clear(
		0L,
		NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
		0xffffffff,
		1.0f,
		0L
		);

	V(g_pEffect->BeginPass(0));
	// render depth values into shadow map
	CreateShadowMap();
	V(g_pEffect->EndPass());

        CalculateShadowPixelNumber();
	
        // restore old backbuffer/stencil/depth-buffer and viewport
	pd3dDevice->SetRenderTarget(0, pOldBackBuffer);
	pd3dDevice->SetDepthStencilSurface(pOldZBuffer);
	pOldBackBuffer->Release();
	pOldZBuffer->Release();

	for (int i=0;i<4;i++)
	{
		if (children[i])
			children[i]->data.OnFrameRender_Shadowmap(pd3dDevice,bSave);
	}

}

void NodeData::CalculateShadowPixelNumber()
{
	#define WHITE   D3DCOLOR_XRGB(255, 255, 255)

	D3DLOCKED_RECT lrect;

	D3DDISPLAYMODE display;

	m_nShadowPixelNumber=0;

	HRESULT hr=m_pShadowMapSurf->LockRect(&lrect,NULL,D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_READONLY );
	//-2005530516

	for (int y=0;y<QUADTREE_SM_SIZE;y++)
	{
		for (int x=0;x<QUADTREE_SM_SIZE;x++)
		{
			DWORD dwColor = ((DWORD*)lrect.pBits)[y*(lrect.Pitch/sizeof(DWORD))+x];//Y*Width+X

			USHORT r=GetRValue(dwColor);
			USHORT g=GetGValue(dwColor);
			USHORT b=GetBValue(dwColor);

			if (dwColor!=WHITE)
			{
				m_nShadowPixelNumber++;
			}
			//DXUTOutputDebugString(L"r=%d,g=%d,b=%d\n",r,g,b);
		}
	}

	m_pShadowMapSurf->UnlockRect();


	//DWORD* p=(DWORD*)(lrect.pBits);
	//p[y*(lrect.Pitch/sizeof(DWORD))+x]=RGB(255,0,0);

}

[Edited by - akira32 on January 9, 2008 12:39:09 AM]

Share this post


Link to post
Share on other sites
1. Use the V_RETURN() or V() macro when calling LockRect. That will call DXUTTrace which in turn will call DXTrace, which will tell you the HRESULT error code that -2005530516 corresponds to. You should also use the debug runtime to get more error information.

2. Textures created with D3DUSAGE_RENDERTARGET must be assigned to D3DPOOL_DEFAULT, and textures in this pool are not lockable. You have to use IDirect3DDevice9::GetRenderTargetData to copy the data to a lockable surface.

3. Why are you checking the shadow-map pixel by pixel? It seems you're doing it for debugging purposes, in which case you should use PIX to look at the surface and debug individual pixels.

4. Please use the "source" tags when posting long sequences of code. It makes things easier for everyone. [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by MJP
3. Why are you checking the shadow-map pixel by pixel?

I want to implement the adaptive shadow maps. I must calculate the number of pixels in a shaodw map cell. I had used use GetRenderTargetData to copy the data to a lockable surface.(GetRenderTargetData return D3DERR_INVALIDCALL) But I have another problem how to get the color of pixel in surface(format is D3DFMT_R32F). I want to konw which pixel in shadow map has occluder.


void NodeData::CalculateShadowPixelNumber()
{
#define WHITE D3DCOLOR_XRGB(255, 255, 255)

IDirect3DSurface9* m_TmpSurface;

g_pd3dDevice->CreateOffscreenPlainSurface(QUADTREE_SM_SIZE,QUADTREE_SM_SIZE,D3DFMT_R32F,D3DPOOL_DEFAULT,&m_TmpSurface,NULL);
V(g_pd3dDevice->GetRenderTargetData(m_pShadowMapSurf,m_TmpSurface));//<===== D3DERR_INVALIDCALL

D3DLOCKED_RECT lrect;

m_nShadowPixelNumber=0;

HRESULT hr;
V(m_TmpSurface->LockRect(&lrect,NULL,D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_READONLY ));

for (int y=0;y<QUADTREE_SM_SIZE;y++)
{
for (int x=0;x<QUADTREE_SM_SIZE;x++)
{
DWORD dwColor = ((DWORD*)lrect.pBits)[y*(lrect.Pitch/sizeof(DWORD))+x];//Y*Width+X

USHORT r=GetRValue(dwColor);
USHORT g=GetGValue(dwColor);
USHORT b=GetBValue(dwColor);

if (b!=255)
{
m_nShadowPixelNumber++;
}
DXUTOutputDebugString(L"r=%d,g=%d,b=%d\n",r,g,b);
}
}

m_TmpSurface->UnlockRect();

SAFE_RELEASE(m_TmpSurface);
}







[Edited by - akira32 on January 9, 2008 3:52:53 AM]

Share this post


Link to post
Share on other sites
I had solveed the probelms of the CreateOffscreenPlainSurface and GetRenderTargetData.(Becuase the Pool of CreateOffscreenPlainSurface must be 3DPOOL_SYSTEMMEM).
But Now I have another problem how to get the color value of the pixel in the surface(m_TmpSurface) with the format "D3DFMT_R32F".
I must do this step for implementing the adaptive shaodw maps. Even though I know the using of D3DXSaveTextureToFile.
Becuase I wish I can never output a picture when I run my program and texture always in the memory.
So, I problem is that how to get the color of the pixel in surface with the format "D3DFMT_R32F".
There are the related code as below:

#define SHADOW_MAP_FORMAT D3DFMT_R32F

void NodeData::CalculateShadowPixelNumber()
{
#define WHITE D3DCOLOR_XRGB(255, 255, 255)

IDirect3DSurface9* m_TmpSurface;
HRESULT hr;

V(g_pd3dDevice->CreateOffscreenPlainSurface(QUADTREE_SM_SIZE,QUADTREE_SM_SIZE,SHADOW_MAP_FORMAT,D3DPOOL_SYSTEMMEM,&m_TmpSurface,NULL));
//Must be D3DPOOL_SYSTEMMEM for MSDN

V(g_pd3dDevice->GetRenderTargetData(m_pShadowMapSurf,m_TmpSurface));

D3DLOCKED_RECT lrect;

m_nShadowPixelNumber=0;
m_nWhitePixelNumber=0;

CImage MixImage;

int nBPP=32;//http://zh.wikipedia.org/wiki/%E5%83%8F%E7%B4%A0
DWORD Flag_Alpha=1;//&#26377;aplha

MixImage.Create(QUADTREE_SM_SIZE,QUADTREE_SM_SIZE,nBPP,Flag_Alpha);

V(m_TmpSurface->LockRect(&lrect,NULL,D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_READONLY ));
//-2005530516 D3DERR_INVALIDCALL

/*
D3DCOLOR t=D3DCOLOR_ARGB(255,1,2,3);
USHORT r=GetRValue(t);
USHORT g=GetGValue(t);
USHORT b=GetBValue(t);
*/


for (int y=0;y<QUADTREE_SM_SIZE;y++)
{
for (int x=0;x<QUADTREE_SM_SIZE;x++)
{
DWORD dwColor = ((DWORD*)lrect.pBits)[y*(lrect.Pitch/sizeof(DWORD))+x];//Y*Width+X

USHORT r=GetRValue(dwColor);
USHORT g=GetGValue(dwColor);
USHORT b=GetBValue(dwColor);

if (r!=255)
{
m_nShadowPixelNumber++;
}
else
{
m_nWhitePixelNumber++;
}

BYTE* byte_mix=(BYTE*)MixImage.GetPixelAddress(x,y);

int a=dwColor>>22;

*(byte_mix+0)=255;//127 blue
*(byte_mix+1)=255;//126 green
*(byte_mix+2)=a;//125 red
*(byte_mix+3)=255;//255 alpha

//DXUTOutputDebugString(L"r=%d,g=%d,b=%d\n",r,g,b);
}
}

m_TmpSurface->UnlockRect();

SAFE_RELEASE(m_TmpSurface);

WCHAR wtmp[MAX_PATH];
StringCchPrintf(wtmp , MAX_PATH , TEXT("NormalSM_%d_%d.bmp") , m_nLevel,m_nCellPosition);

hr=MixImage.Save(wtmp,Gdiplus::ImageFormatBMP);
}




The CImage class is used to save the color of the pixel in shadow map for the comparison with the result of the function of "D3DXSaveTextureToFile".


void CALLBACK NodeData::OnFrameRender_Shadowmap(IDirect3DDevice9* pd3dDevice,BOOL bSave)
{
HRESULT hr;
LPDIRECT3DSURFACE9 pOldBackBuffer, pOldZBuffer;

D3DXHANDLE hTechnique = g_pEffect->GetTechniqueByName("TShader");
g_pEffect->SetTechnique(hTechnique);
V(g_pEffect->Begin(NULL, 0));

// save old render target and set new render target with depth/stencil buffer
pd3dDevice->GetRenderTarget(0, &pOldBackBuffer);
pd3dDevice->GetDepthStencilSurface(&pOldZBuffer);
pd3dDevice->SetRenderTarget(0, m_pShadowMapSurf);
pd3dDevice->SetDepthStencilSurface(m_pShadowMapZ);

// clear render target
pd3dDevice->Clear(
0L,
NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
0xffffffff,
1.0f,
0L
);

V(g_pEffect->BeginPass(0));
// render depth values into shadow map
CreateShadowMap();
V(g_pEffect->EndPass());

// restore old backbuffer/stencil/depth-buffer and viewport
pd3dDevice->SetRenderTarget(0, pOldBackBuffer);
pd3dDevice->SetDepthStencilSurface(pOldZBuffer);
pOldBackBuffer->Release();
pOldZBuffer->Release();

if (bSave)
{
WCHAR wtmp_filename[MAX_PATH];
WCHAR wtmp_total[MAX_PATH];
WCHAR wtmp[MAX_PATH];

QuadNode* current_node=m_parent_node;

StringCchPrintf(wtmp_total,MAX_PATH,L"%d_",m_nCellPosition);

while (current_node!=NULL)
{
StringCchPrintf(wtmp , MAX_PATH , TEXT("%d_") , current_node->data.m_nCellPosition);
wcscat(wtmp_total,wtmp);
current_node=current_node->data.m_parent_node;
}

StringCchPrintf(wtmp_filename , MAX_PATH , TEXT("NormalSM_L%d_%s.png") , m_nLevel,wtmp_total);

D3DXSaveTextureToFile(wtmp_filename,D3DXIFF_PNG ,m_pShadowMapTexQuadNode,NULL);

DXUTOutputDebugString(L"%s\n",wtmp_filename);

CalculateShadowPixelNumber();
DXUTOutputDebugString(L"ShadowPixelNumber=%d,WhitePixelNumber=%d\n" ,m_nShadowPixelNumber, m_nWhitePixelNumber);
}

for (int i=0;i<4;i++)
{
if (children[i])
children[i]->data.OnFrameRender_Shadowmap(pd3dDevice,bSave);
}

}


Share this post


Link to post
Share on other sites
You're treating the texture as if it were R8G8B8A8 format, but its not. Instead of a DWORD, it's a single FLOAT value. This value can be any valid 32-bit floating-point number, and interpreting it will depend on how your shadowmap-generating pixel shader outputs to the texture. In general the depth is usually normalized to the range 0.0-1.0f, in which case a value of 1.0f would correspond to "white". Keep in mind there is no RGB color in a R32F texture, since it only has one channel (the red channel).

Share this post


Link to post
Share on other sites

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