Please - ZBuffer creation problem

Started by
36 comments, last by kieren_j 24 years, 1 month ago
Hi, me again I''m having trouble setting up a z-buffer, even though I copied the code from the D3DIM tutorial "adding a depth buffer", it just doesn''t seem to work, and the IDirect3DDevice7::Clear method fails with "D3DERR_ZBUFFER_NOT_PRESENT" when called with the D3DCLEAR_ZBUFFER flag. The thing is I can''t tell where I am going wrong, because through all the stages of initialization I do error checking. Take a look at my code?: (BTW Spellbound, I''m using D3DIM in plain old C++ rather than D3DX or whatever it''s called) Enumeration Callback This code always displays the "worked" message box, and when I check the bit depth it''s 16

static HRESULT WINAPI EnumZBufferCallback( DDPIXELFORMAT* pddpf,
                                           VOID* pddpfDesired )
{
	/*
	 * Find a z-buffer
	 */
    if( pddpf->dwFlags == DDPF_ZBUFFER )
    {
		/*
		 * Copy details and we''re done
		 */
		MessageBox(GetForegroundWindow(), "Worked", "Information", MB_OK / MB_ICONINFORMATION);
        memcpy( pddpfDesired, pddpf, sizeof(DDPIXELFORMAT) );
		return D3DENUMRET_CANCEL;
    }
 
    /*
	 * Keep searching
	 */
    return D3DENUMRET_OK;
}
  
Creation code This code never displays a message box (apart from in very high resolutions, where the zbuffer can''t be created in video memory - but even then the system memory method works)

DDPIXELFORMAT ddpfZBuffer;

/*
	 * Get a buffer format
	 */
	if (D3D_OK != lpd3d->EnumZBufferFormats(pDeviceGUID, EnumZBufferCallback, (VOID*)&ddpfZBuffer))
		MessageBox(GetForegroundWindow(), "Couldn''t enumerate z-buffer formats", "Error", MB_OK / MB_ICONERROR);
	
	/*
	 * Create z-buffer description
	 */
	ZeroMemory(&ddsd, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS / DDSD_WIDTH / DDSD_HEIGHT / DDSD_PIXELFORMAT;
	ddsd.dwWidth = rScreen.right;
	ddsd.dwHeight = rScreen.bottom;
	ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
	if (IsEqualIID(pDeviceGUID, IID_IDirect3DHALDevice))
		ddsd.ddsCaps.dwCaps /= DDSCAPS_VIDEOMEMORY;
	else
		ddsd.ddsCaps.dwCaps /= DDSCAPS_SYSTEMMEMORY;
	memcpy(&ddsd.ddpfPixelFormat, &ddpfZBuffer, sizeof(DDPIXELFORMAT));

	/*
	 * Create z-buffer
	 */
	if (DD_OK != lpdd->CreateSurface(&ddsd, &lpZBuffer, NULL))
	{
		/*
		 * Failed; if in video memory, try it in system memory
		 */
		if (ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
		{
			MessageBox(GetForegroundWindow(), "Couldn''t create z-buffer in video memory, trying system memory", "Error", MB_OK / MB_ICONERROR);
			ddsd.ddsCaps.dwCaps -= DDSCAPS_VIDEOMEMORY;
			ddsd.ddsCaps.dwCaps /= DDSCAPS_SYSTEMMEMORY;
			if (DD_OK != lpdd->CreateSurface(&ddsd, &lpZBuffer, NULL))
				MessageBox(GetForegroundWindow(), "Couldn''t create z-buffer in system memory", "Error", MB_OK / MB_ICONERROR);
			else
				MessageBox(GetForegroundWindow(), "Using z-buffer in system memory", "Information", MB_OK / MB_ICONINFORMATION);
		}
	}
		
	/*
	 * Attatch the z-buffer to the backbuffer
	 */
	if (DD_OK != lpBuffer->AddAttachedSurface(lpZBuffer))
		MessageBox(GetForegroundWindow(), "Couldn''t attach z-buffer", "Error", MB_OK / MB_ICONERROR);
  
After all this, I use lpDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, TRUE); to turn on z-buffer usage. Hmm.....maybe I need to put this after a BeginScene() command? Any ideas? Thanks!
Advertisement
Ok, here''s my code, ripped straight out. Main is the IDirect3D7*/LPDIRECT3D7, Draw is DDraw, it''s part of a class so there''s probably tons of undefined stuff:

if(FAILED(hr)) return hr;
DDPIXELFORMAT ZBufferInfo;
Draw->QueryInterface(IID_IDirect3D7,(VOID**)&Main);
if(FAILED(hr=Main->EnumZBufferFormats(*DeviceGuid,ZBufferEnum,(VOID*)&ZBufferInfo))) return hr;
if(sizeof(DDPIXELFORMAT)!=ZBufferInfo.dwSize) return hr;
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS/DDSD_WIDTH/DDSD_HEIGHT/DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
ddsd.dwWidth = Width;
ddsd.dwHeight = Height;
memcpy(&ddsd.ddpfPixelFormat,&ZBufferInfo,sizeof(DDPIXELFORMAT));
if(IsEqualIID(*DeviceGuid,IID_IDirect3DRGBDevice)) {
ddsd.ddsCaps.dwCaps /= DDSCAPS_SYSTEMMEMORY;
Hardware=false;
}
else {
ddsd.ddsCaps.dwCaps /= DDSCAPS_VIDEOMEMORY;
Hardware=true;
}
hr = Draw->CreateSurface(&ddsd, &ZBuffer, NULL);
if(FAILED(hr)) return hr;
hr = FBack->AddAttachedSurface(ZBuffer);
if(FAILED(hr)) return hr;
hr = Main->CreateDevice(*DeviceGuid,FBack,&Device);
if(FAILED(hr)) return hr;
D3DVIEWPORT7 vp = {0, 0, Width, Height, 0.0f, 1.0f};
hr = Device->SetViewport(&vp);
if(FAILED(hr))
return hr;
Device->SetRenderState(D3DRENDERSTATE_ZENABLE, TRUE);


And this code works fine, tested on many different res''s and HAL+software. Did you create the Device before the zbuffer? that''s where I went wrong, took me ages to find the prob.
Create the device before you create the Z buffer and make sure that you check all your return codes. They are very helpfull especially if you start getting into re-attaching, re-creating etc.
Yep I''ve found the problem; you have to create the zbuffer before the device (thanks).
But, some a problem has popped up and I''ve got a problem with enumeration!:

New Problem #1 !!
The zbuffer seems to be working VERY STRANGELY; in fact it seems to be working in inverse.
Basically, if there''s polygons behind the one being drawn, it might be not drawn at all, or distorted quite alot. In fact, sometimes it seems that the polys nearer the viewer are clipped!
Here''s some code I use to set it up (I copied the creation code almost exactly from the d3dim framework):

	E(lpDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_TRUE), "SetRenderState(zenable,true)");	E(lpDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, TRUE), "SetRenderState(zwriteenable,true)");	E(lpDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL), "SetRenderState(zfunc,lessequal)");	E(lpDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, 0), "SetRenderState(zbias,0)"); 

P.S. The "E" function is just a minimal error-checker.

Even with all this renderstate code (a lot of them are set like this by default anyway), the view is still distorted!!


New Problem #2 !!
I''m have quite a serious problem with enumeration as well.
One of the first things I do is enumerate the DirectDraw drivers using this code:

BOOL WINAPI DriverEnumCallback(GUID* pGUID, TCHAR* strDesc, TCHAR* strName, VOID* pContext, HMONITOR hm){	LPDIRECTDRAW7 lpdd;	char kb[1024];		/*	 * Store Information	 */	sprintf(kb, "Name: %s\nDescription: %s", strName, strDesc);	MessageBox(GetForegroundWindow(), kb, "DirectDraw Driver", MB_ICONINFORMATION);	memcpy(&DirectDrawGUID, pGUID, sizeof(GUID));	/*	 * Try it out	 */	DirectDrawCreateEx(&DirectDrawGUID, (LPVOID *)&lpdd, IID_IDirectDraw7, NULL);	lpdd->Release();		return DDENUMRET_OK;}void CreateDirect3D(HWND hWnd, UINT nWidth, UINT nHeight, UINT nBPP){	/*	 * Sets up DirectDraw and Direct3D	 */	DDSURFACEDESC2 ddsd;	D3DMATRIX mat;	/*	 * Enumerate objects	 */	E(DirectDrawEnumerateEx(DriverEnumCallback, NULL, DDENUM_ATTACHEDSECONDARYDEVICES / DDENUM_DETACHEDSECONDARYDEVICES / DDENUM_NONDISPLAYDEVICES), "DirectDrawEnumerateEx"); 


After running this code, I first see a message box (from the enumeration func.) with the driver "Primary Display Driver" ("display"). Then the DirectDrawEnumerateEx function returns DDERR_INVALIDPARAMS; but no message box with enumeration data for my "3dfx Interactive DirectX 5 Driver" ("mm3dfx"). All of the other applications I run enumerate this; and the SDK samples also appear to.
This also happens on the Direct3D enumeration: it enumerates RGB, Software, Reference, and HAL, but no mm3dfx (this is probably because it wasn''t done in DD enumeration?).
Basically, it doesn''t enumerate my devices! Unfortunately, I don''t know whether it''s failing after the 1st enumeration due to a fault in the callback, or something else! (But i do know that the driver works, other apps use it).


Please, can you help?
!!Thanks!!
Agin, I also had the zbuffer problem. It took me ages to kill this pesky bug. First. Did you clear the zbuffer on each clear function (assuming classes). As in:
Device->Clear(0,NULL,D3DCLEAR_TARGET/D3DCLEAR_ZBUFFER,Color, 1.0f, 0L);
Second. just set Device->SetRenderState(D3DRENDERSTATE_ZENABLE,TRUE); not the rest. Leave D3D Alone, and it won''t bug you ( with more bugs). Ok, for the enumeration code, I suggest you read the article on enumeration here at gamedev: http://www.gamedev.net/reference/programming/features/dx7enum. That code definitely works, or if you want to use your own, you could go thro'' your code against his to see whats wrong.

I only added the flags after it stopped working - and I''ve tried everything else you said. However, I still get massive problems! Only half the triangles are drawn, and most of the ones that are drawn are distorted still!
I definitely remember getting this problem but I can''t remember what I didi to get rid of it. Let''s see now. You''ve done the D3DCLEAR_ZBUFFER. You''ve setup the zbuffer right. You''ve setup the geometry right.(i''m guessing your copying code straight from the examples).
I suggest to try to draw the triangles or whatever with the
Device->SetRenderState(D3DRENDERSTATE_ZENABLE, TRUE); commented out. If the problem is still there, it ain''t a zbuffer problem. If it is, i don''t have a clue what your''re doing wrong.
Hey all!
I just solved my enumeration problem that some of you might have read about (I was copying from the GUID pointer, even it was NULL). So now, I have proper hardware acceleration working....
But I still have this annoying z-buffer problem!
I do an error check at every single stage, it''s all fine! I get no errors whatsoever - not during enumeration, surface creation, attaching, clearing, or rendering. So why is it so distorted? Please, can anybody help me out here!

Oh, and one more thing...
If I choose to use hardware acceleration, my Vertex Fox fails to work (D3DFOG_LINEAR by the way) - but it works fine in software mode. However, in the SDK it says that Vertex Fox is calculated by Direct3D (and therefore you shouldn''t need the hardware caps to do it).
Any ideas?


Thanks again!
Oh yeah - and if anybody''s got any ideas on those radar coordinates (see my other posts) please, I need ''em for my underwater sim!

thx
Hi

Did you Check other things ?
1. Your Projection Matrix ( The near and Far Clipping Values )
2. BackfaceCulling, try turning it off
3. The order in which you are rendering (only applicable when using transparent Effects)
4. The 3D Coordinates, maybe a wrong Index List, or something similar
5. maybe something else ?(Not enough RAM ;-))

Lars

--------> http://www.larswolter.de <---------

This topic is closed to new replies.

Advertisement