How to get the color of one pixel of shadow map

Started by
4 comments, last by akira32 16 years, 3 months ago
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)
			children->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]
akira32 編程之家 Yahoohttp://tw.myblog.yahoo.com/akira32-akira32
Advertisement
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]
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]
akira32 編程之家 Yahoohttp://tw.myblog.yahoo.com/akira32-akira32
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_R32Fvoid 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)			children->data.OnFrameRender_Shadowmap(pd3dDevice,bSave);	}}
akira32 編程之家 Yahoohttp://tw.myblog.yahoo.com/akira32-akira32
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).
MJP,Thank you. I had solved it by your way.


akira32 編程之家 Yahoohttp://tw.myblog.yahoo.com/akira32-akira32

This topic is closed to new replies.

Advertisement