'W buffering" with opengl, how to?

i get the impression that i should be utilizing ‘W buffering’ as opposed to z buffering. i found some directx initialization code, but haven’t been able to find anything for opengl. i get the impression it is a commonly supported feature though.

i’m also curious if anyone knows of a list of nvidia cards and their features. i’m mostly looking for a z depth precision comparison between cards.

are cards with 64bit depth buffers ultra expensive? is the extra precision really worth it given exponential scaling of pseudodepth? would W buffering perhaps be a more lucrative use of the extra precision.

finally is there any unecesarry performance cost in using W buffering on typical hardware?

sincerely,

michael

From hints given in personal correspondance hardware implementations exploit the screenspace 2D interpolation linearity of a zbuffer (the corollary of non linearity w.r.t. true eye Z) for features like coarse z buffer optimizations.

So the costs aren’t fully clear anymore, there was a time when folks suggested (I think mainly at 3Dfx) that hardware was up to task of using perspective correction for pathological choices for near and far clip. Now that may not be the case because it complicates popular optimizations like coarse z.

I like the non linearity of a zbuffer for reasonable clip plane values, it really only sucks when you crank the near plane in too far. There are other schemes besides w buffering that try to correct for this too.

Originally posted by dorbie:
[b]From hints given in personal correspondance hardware implementations exploit the screenspace 2D interpolation linearity of a zbuffer (caused by non linearity w.r.t. true eye Z) for features like coarse z buffer optimizations.

So the costs aren’t fully clear anymore, there was a time when folks suggested (I think mainly at 3Dfx) that hardware was up to task of using perspective correction for pathological choices for near and far clip. Now that may not be the case because it complicates popular optimizations like coarse z.

I like the non linearity of a zbuffer for reasonable clip plane values, it really only sucks when you crank the near plane in too far. There are other schemes besides w buffering that try to correct for this too.[/b]
so i take it that w buffering is not a commonly supported feature, even though D3D seems to have a built in functionality to facilitate it?

i read something before about W buffering in another forum here. i will probably try to find it, even though it sounds like a lost cause. it seems like popular games utilize it, but they may’ve been games from software rendering days.

my basic problem occurs not when the near plane is too small, but when the near per far ratio is too small. so like 1/100 is the same as 10/1000.

i’m working at the scale of a small planet, only the planet is cylindrical, so that the horizon curves up, meaning you don’t get the benefit of distant lands being lost below the horizon with curvature.

basicly the near plane is at which point the camera clips through the space… so it is the only non relative judgement of scale.

i really need to drop the size of the near plane or increase the size of the environment so that the camera can go down to a human scale.

around a 0.1 type near plane swimming seems to occur. but if you push the near and far up and the same ratio, the swimming goes away, but there is a pretty well defined point were depth values begin to merge and then actually…

i’m actually seeing a weird effect i don’t understand. it must have something to do with the z buffer though. basicly imagine rendering two cylinders one nested inside the other. the diameters are relatively close… one is actually terrain, then another a layer of atmosphere.

the atmosphere is the inside cylinder. the camera is inside the cylinders. now the crazy thing happening is the further away the surfaces are along the z axis. the inner cylinder begins to intersect the outer cylinder, and then actually goes behind the outer cylinder.

how is this possible?

it has nothing to do with the modelview matrix… if you move to the point were the cylinders invert then the effect moves.

i really don’t understand how say two identical geometries, one scaled slightly smaller, can totally intersect until the smaller is totally outside the larger increasingly in the z axis?

any thoughts?

From hints given in personal correspondance hardware implementations exploit the screenspace 2D interpolation linearity of a zbuffer (caused by non linearity w.r.t. true eye Z) for features like coarse z buffer optimizations.

oh, so w buffering can’t be linearly interpolated in screen space? still by this day and age, it seems like dedicated hardware doing a per pixel depth calculation could be fit in somewhere couldn’t it?

just to show i don’t get out much… what does w.r.t. mean btw?

It means “with respect to”.

I don’t know what’s supported out there, OpenGL intentionally isn’t explicit about what’s in the depth buffer or the system used, only what you get when you read it. Some systems have used pseudo float to adjust the precision of stored values for example but have hidden this from the observer.

There’s also this extension:

http://oss.sgi.com/projects/ogl-sample/registry/EXT/wgl_depth_float.txt

Although the preamble is somewhat bogus because it ignores scale and the resulting ramp somewhat arbirtary. This should really be to compensate for non linearity of z by ramping a float storage running in the opposite direction. The idea of using fixed point in there is just bizarre because it makes the extension do nothing. I assume (for the sake of my own sanity) that a fixed point implementation would have higher precision fixed point interpolators with a cast to float at lower precision prior to storage.

Originally posted by dorbie:
[b]It means “with respect to”.

I don’t know what’s supported out there, OpenGL intentionally isn’t explicit about what’s in the depth buffer or the system used, only what you get when you read it. Some systems have used pseudo float to adjust the precision of stored values for example but have hidden this from the observer.

There’s also this extension:

http://oss.sgi.com/projects/ogl-sample/registry/EXT/wgl_depth_float.txt

Although the preamble is somewhat bogus because it ignores scale and the resulting ramp somewhat arbirtary. This should really be to compensate for non linearity of z by ramping a float storage running in the opposite direction. The idea of using fixed point in there is just bizarre because it makes the extension do nothing. I assume (for the sake of my own sanity) that a fixed point implementation would have higher precision fixed point interpolators with a cast to float at lower precision prior to storage.[/b]
yeah, i don’t follow that extension either. the way it is written is insane… maybe its a practical joke or something? someone maybe just made a bet about whether they could get microsoft to adopt a nonsensical opengl extension?

as for my problem as far as consequentiality is concerned… sorry false alarm. i finally found a case that i could not rationalize. so i started looking through my code for anything. i actually was very lucky that i found it. it was one of those bugs that is so far out that you never could’ve believed it could go on unoticed under equally far out circumstances. the route of it all was a flag had a not operator that got stuck in front of it, and reverted to an alternative rendering mode i had done some work with to improve spatial precision at insanely high scales. it works like a charm, only flaw is in the depthbuffer it produces, which can’t be rectified with opengl so far as far as i know. (it needs some way to scale depth values) the fact that it worked so well under recent circumstances was shocking.

so everything is back to normal now. i’m just glad i only lost an entire day to this. finding the bug was shear luck.

never the less, thanks for the input dorbie.

well actually… that explained why the closer surface was disappearing behind the further surface.

but as i expected the general precision and swimming problem is still there. i was hoping the problem would’ve magicly cleared up after fixing that bug.

but trying to get to get the scale down to an acceptable human scale still produces the same issues.

that is why really it took me so long to come around to the bug… because i was expecting this issue to begin with.

so i’m still very open to discussion.

especially interested in a list of nvidia card features.

i’m not very good with internet queries i guess. i can never find anything on the internet.

yeah, i don’t follow that extension either. the way it is written is insane… maybe its a practical joke or something? someone maybe just made a bet about whether they could get microsoft to adopt a nonsensical opengl extension?

Not really, in practice I think the intention is to implement an floating point numerical precision ramp (approximately log2 ?) with high precision at the far plane due to the lower exponent (that’s why the z value is reversed) and less precision at the near as the exponent increases to compensate for the hyperbolic perspective z ramp from near to far that’s determined by the near and far clip plane locations. It’s just that some of the discussion in the extension text is utter nonsense, the idea itself makes some sense if you could implement it efficiently and you chose near and far values where the extension didn’t hose your near plane precision.

Originally posted by dorbie:
[b] [quote]yeah, i don’t follow that extension either. the way it is written is insane… maybe its a practical joke or something? someone maybe just made a bet about whether they could get microsoft to adopt a nonsensical opengl extension?

Not really, in practice I think the intention is to implement an floating point numerical precision ramp (approximately log2 ?) with high precision at the far plane due to the lower exponent (that’s why the z value is reversed) and less precision at the near as the exponent increases to compensate for the hyperbolic perspective z ramp from near to far that’s determined by the near and far clip plane locations. It’s just that some of the discussion in the extension text is utter nonsense, the idea itself makes some sense if you could implement it efficiently and you chose near and far values where the extension didn’t hose your near plane precision.[/b][/QUOTE]yeah i was just kidding naturaly. it does seem like something that would never be implimentable in hardware though unless there was some custom piece of hardware being used with some group with decent clout. i really don’t know what i’m talking about though. it just doesn’t look promising though… maybe it does work, maybe that is how directx gets a w buffer api. i might just try it to see what it does. i figure it will do nothing, that is not take.

will depth buffers be 64bit standard in near future. in my experience it isn’t really possible to render an outdoor scene with a realistic horizon and a camera near enough to some geometry in the foreground not to clip it to death… not even close actually. colour buffers don’t need depth. but i wouldn’t mind max 128bits of depth standard.

how can you find out how many depth bits a card will support? just for the sake of shopping that is. i’m thinking i want at least 64bits on my next card.

is the linear interpolation through screen space accurate numericly? or is it just a precision issue that gives the buzzsaw effect? would per pixel depth computation with the standard algorithm yield less swimming?

i have to get to sleep.

real quick the extension requires:

wglChoosePixelFormatExEXT

but if you put that into google you get nothing useful.

is this microsoft internal stuff? or something brand new? beats me.

edit: i can’t get it with wglGetProcAddress

according to the win2k API’s ChoosePixelFormat function, my card supports a 128bit depth buffer.

the msvc docs say that this function chould change the passed pixel descriptor’s attributes to the closest support match. if i give it, 128 it gives me back 128, same for 32 and 64… i can’t discern any visual improvement though.

at scales i like, i get very noticible swimming in the depth buffer when the modelview matrix is rotating. if it is just translating there is no swimming.

edit: for all i know my current card (a low end QuadroFX model) might only do a 16bit depth buffer.

according to the win2k API’s ChoosePixelFormat function, my card supports a 128bit depth buffer
i know of no card that has 128bit depth
all nvidia cards only support 16 or 24 (no 32) please correct me if im wrong.
its important to query how many bits u get given and not assume u get what u asked for.
FWIW with nvidia cards if u ask for 32 u will get back 16 (and not 24 which is closer)

the msvc docs say that this function chould change the passed pixel descriptor’s attributes to the closest support match. if i give it, 128 it gives me back 128, same for 32 and 64… i can’t discern any visual improvement though.
No it doesn’t.

Behold:

MSDN:

int ChoosePixelFormat(
HDC hdc, // device context to search for a best pixel format
// match
CONST PIXELFORMATDESCRIPTOR * ppfd
// pixel format for which a best match is sought
);
The pixel format descriptor is const.

What you actually need to do is check the return value, and if it’s valid, call DescribePixelFormat() with that pixel format.

Edit: Details can be found MSDN

Originally posted by zed:
[quote]according to the win2k API’s ChoosePixelFormat function, my card supports a 128bit depth buffer
i know of no card that has 128bit depth
all nvidia cards only support 16 or 24 (no 32) please correct me if im wrong.
its important to query how many bits u get given and not assume u get what u asked for.
FWIW with nvidia cards if u ask for 32 u will get back 16 (and not 24 which is closer)
[/QUOTE]thanks for the info. if that is true there is probably a lot of misinformation out on the internet regarding such matters.

i tried setting my pixel format to 24bits, but i can’t see any visual improvement so i assume it didn’t take.

the microsoft api is passed a pixel descriptor structure by address… it is supposed to modify the attributes to the closest support match according to the docs… but since when can you expect microsoft to live up its word. i have no idea what goes on behind the scenes though, maybe there is no way to validate the supported bits… though i assume there must be.

how can you find out what cards have what bits available? stencil buffer is shared with depth bits right? i turned off stencil bits… is there anything else i can do to try to increase depth precision?

and again, i how can you find out what cards support what with the depth buffer… that will be near the top of my list when i start looking at cards in the future.

edit: just for the record, i asked for 32 and got back 24. i could use a lot more though it seems.

[QUOTE]
Behold:

[QUOTE]

yeah, i didn’t pay enough attention i guess.

in my local docs there are remarks that say "the function returns a pixel format with [an adjusted value]… but i guess this is referring to the handle returned. it looks like DescribePixelFormat can retrieve the actual results from the handle.

thanks for pointing that out.

To get around the precision problem you’re having, may I recommend you render your scene in slices along the z axis (in back to front order), specifying a new frustum and clearing the depth buffer before each new slice. Play around to find the optimal number of slices for the depth range of your scene versus your zbuffer precision.

This is the general procedure for setting up your pixel format with the unextended pixel format functions:-

HGLRC createOpenGLContext(HDC dc, int& colourBits, int& depthBits, int& stencilBits, bool& stereo)
{
	PIXELFORMATDESCRIPTOR requested_pfd =
	{sizeof(PIXELFORMATDESCRIPTOR), 1, 0, PFD_TYPE_RGBA, colourBits, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, depthBits, stencilBits, 0, PFD_MAIN_PLANE, 0, 0, 0, 0};

	requested_pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
	if (stereo) requested_pfd.dwFlags |= PFD_STEREO;

	// get a pixel format index for a format that closely matches 'requested_pfd'

	int pixelFormatIndex = ::ChoosePixelFormat(hDC, &requested_pfd);

	if (!pixelFormatIndex)
	{
		fprintf(stderr, "Unsupported context attributes.
");
		return 0;
	}

	PIXELFORMATDESCRIPTOR chosen_pfd;

	// now get the attributes of the pixel format that was chosen for us

	if (!::DescribePixelFormat(	hDC,
					pixelFormatIndex,
					sizeof(chosen_pfd),
					&chosen_pfd))
		return 0;

	// compare our desired pixel format with the one given to us...

	if (chosen_pfd.cColorBits != requested_pfd.cColorBits)
	{
		fprintf(stderr, "Unsupported colour depth of %i. Max allowed=%i
", colourBits, chosen_pfd.cColorBits);
		colourBits = chosen_pfd.cColorBits;
	}

	if (chosen_pfd.cDepthBits != requested_pfd.cDepthBits)
	{
		fprintf(stderr, "Unsupported z depth of %i. Max allowed=%i
", depthBits, chosen_pfd.cDepthBits);
		depthBits = chosen_pfd.cDepthBits;
	}

	if (chosen_pfd.cStencilBits != requested_pfd.cStencilBits)
	{
		fprintf(stderr, "Unsupported stencil depth of %i. Max allowed=%i
", stencilBits, chosen_pfd.cStencilBits);
		stencilBits = chosen_pfd.cStencilBits;
	}

	if (stereo && !(chosen_pfd.dwFlags & PFD_STEREO))
	{
		fprintf(stderr, "Unable to support Stereo!
");
		stereo = false;
	}

	// now actually set the pixel format of the device context to the one chosen for us
	if (!::SetPixelFormat(hDC, pixelFormatIndex, &chosen_pfd))
	{
		fprintf(stderr, "Unsupported context attributes.
");
		return 0;
	}

	// create the OpenGL context from our newly modified device context

	return ::wglCreateContext(hDC);
}

Originally posted by michagl:
[quote]Originally posted by zed:
[QUOTE]…with nvidia cards if u ask for 32 u will get back 16 (and not 24 which is closer)

edit: just for the record, i asked for 32 and got back 24. i could use a lot more though it seems.
[/QUOTE]I just wanted to say that this behaviour is probably setting-dependant or driver-dependant.
I once asked for a 32bit Z and they didn’t work (witout stencil), there were no pixelformat avaiable.
So, this fallback is probably a not-so-smart driver move, recognizing you’re doing something messy.

Originally posted by knackered:
To get around the precision problem you’re having, may I recommend you render your scene in slices along the z axis (in back to front order), specifying a new frustum and clearing the depth buffer before each new slice. Play around to find the optimal number of slices for the depth range of your scene versus your zbuffer precision.
under my circumstances there is no real obvious way to do that… the geometry is all continuous.

the main problem i’m having is with distant innerpenetrating geometry. for instance, a mountain interpenetrating a cloud layer. the clouds just go through the mountains, and there is no realistic way to get around that. so you have to rely on the z buffer to work out the clipping.

at a fair distance, the clipping ‘swims’ significantly based on the rotational components of the modelview matrix.

if someone can offer an optimal environment sale and near/far plane settings to fully utilize the z buffer that might be helpful… but from my run-time modulatable expiriments it seems i’m already doing that.

i realize my needs are not comformant with the game industry right now. i’ve never seen games with realistic expansive environments. i’m thinking about using a per pixel fragment shader to manually set the depth fragments. if there is a greater cost to this than simply the necesarry computations and the loss of the early z-test please let me know.

there has been a discussion on methods somewhere around here. i think it was in the opengl wish list forum. i plan to look it up as soon as i get a chance.

i’m thinking about using a per pixel fragment shader to manually set the depth fragments.

You can’t alter the depth of fragments in a fragment shader.

Yes you can!