VOGONS


Example of z-fighting with 16 bit z-buffer

Topic actions

First post, by PhilsComputerLab

User metadata
Rank l33t++
Rank
l33t++

So some graphics cards, when in 32 bit colour mode, use a 16 bit z-buffer for added performance.

I've never seen this z-fighting in action, does anyone know a scene in a game that I can try out?

Ideally something that is quick to get into. Games I have ready to go are Quake II, Quake III arena, MDK2 and Drakan. If it's not one of those that's fine too 😀

So yea, what game, where in the game, that sort of information.

EDIT:

This looks like Quake III, but what map is it?

http://www.tomshardware.co.uk/review-of-the-m … view-114-2.html

YouTube, Facebook, Website

Reply 1 of 22, by clueless1

User metadata
Rank l33t
Rank
l33t

Maybe this page has some helpful info for you?
http://www.tomshardware.com/reviews/nvidia-ge … efx,581-12.html

The more I learn, the more I realize how much I don't know.
OPL3 FM vs. Roland MT-32 vs. General MIDI DOS Game Comparison
Let's benchmark our systems with cache disabled
DOS PCI Graphics Card Benchmarks

Reply 2 of 22, by PhilsComputerLab

User metadata
Rank l33t++
Rank
l33t++

Yea I found that article. That game is quite new.

Now I think I found a scene in Unreal Tournament that shows the issue. But enabling 32-z buffer in the driver still shows the issue, but performance is reduced. It could be just a driver bug, so not a big deal. I might try a few drivers but not spend too much time on it.

YouTube, Facebook, Website

Reply 3 of 22, by Scali

User metadata
Rank l33t
Rank
l33t
PhilsComputerLab wrote:

Yea I found that article. That game is quite new.

Probably not a coincidence.
Older games such as Quake were designed when 16-bit zbuffers were a given. So they use limited depth to make sure that they have enough precision.
You're more likely to find zfighting issues on games that were designed for 24-bit zbuffers and are retrofitted to 16-bit.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 4 of 22, by PhilsComputerLab

User metadata
Rank l33t++
Rank
l33t++

Quake III and Unreal Tournament do support 32 bit z-buffer. The logs in UT and driver info in Quake III show it.

In UT I found this spot:

qx6pUv3.png

erOMsrs.png

YouTube, Facebook, Website

Reply 5 of 22, by Gemini000

User metadata
Rank l33t
Rank
l33t

Quake II and III were designed extremely well so z-fighting is practically non-existent in those games. MDK2 and Drakan I have no idea.

Star Wars Jedi Knight II: Jedi Outcast has some extreme examples of z-fighting when running a 16-bit z-buffer, especially when looking at objects far away. This is because this is one of the few games to not only support a 16-bit z-buffer, but to also use fully articulated facial models in regular gameplay, so at long range with a 16-bit z-buffer you can routinely see the eyeballs and jaws+teeth straight through people's heads! :O

Interestingly though, you may've seen z-fighting in a more modern game and not even realized it. z-fighting can happen ANYWHERE where two 3D objects intersect. The trick is how much z-buffer depth is available where those two objects are intersecting, given how close to the camera they are. A 16-bit z-buffer can only handle 65,536 levels of depth, whereas a 24-bit z-buffer can handle over 16,000,000 and a 32-bit z-buffer over 4,000,000,000, thus if ANY z-buffer is tasked to handle two objects intersecting across a large distance, and the z-buffer itself is stretched over a MUCH longer distance, you'll see a sort of sawtooth effect along the edge where the two objects intersect, representing where the z-buffer is preferring one object over the other.

Typically though, when people discuss z-fighting, they're referring to when two objects are so close together with similar geometry but different texturing that they both flicker around within each other while the camera/player moves. Typically, when this is discovered in a commercial game by testers during development, efforts are made to adjust the z-buffer in those areas to prevent it and/or the models are adjusted to compensate, such as by pulling them further apart or making one larger or smaller. You generally want the z-buffer to only go out as far as the furthest object you have to render so that each numerical value of the z-buffer accounts for as little depth as possible, thus increasing its visual accuracy.

--- Kris Asick (Gemini)
--- Pixelmusement Website: www.pixelships.com
--- Ancient DOS Games Webshow: www.pixelships.com/adg

Reply 6 of 22, by leileilol

User metadata
Rank l33t++
Rank
l33t++

The Tom example map is q3dm7, however Tom's article is actually covering Q3test 1.05

The zbuffer can be adjusted with the r_depthBits cvar. with 0 being default (your default depth)

Last edited by leileilol on 2016-04-25, 21:37. Edited 1 time in total.

apsosig.png
long live PCem

Reply 7 of 22, by PhilsComputerLab

User metadata
Rank l33t++
Rank
l33t++
leileilol wrote:

The Tom example map is q3dm7.

The zbuffer can be adjusted with the r_depthBits cvar. with 0 being default (your default depth)

Thank you!

Will check out Star Wars Jedi Knight II: Jedi Outcast Kris.

YouTube, Facebook, Website

Reply 8 of 22, by leileilol

User metadata
Rank l33t++
Rank
l33t++

r_znear is also another cvar to adjust for the precision of Z by altering the clipping plane. A low value like 0.01 can induce some nice zfighting in the distance

apsosig.png
long live PCem

Reply 9 of 22, by DracoNihil

User metadata
Rank Oldbie
Rank
Oldbie

I thought GPU's don't support 32-bit zbuffer but instead only handle 24-bit zbuffer? Atleast everything I've tried can only request a 24-bit Z, options for 32-bit Z are grayed out.

There are quite a few maps in Unreal and UT99 that have zfighting problems, but I don't remember their names off hand. I think even Tom Clancy's Ghost Recon had bad zfighting issues too.

“I am the dragon without a name…”
― Κυνικός Δράκων

Reply 10 of 22, by PhilsComputerLab

User metadata
Rank l33t++
Rank
l33t++
DracoNihil wrote:

I thought GPU's don't support 32-bit zbuffer but instead only handle 24-bit zbuffer? Atleast everything I've tried can only request a 24-bit Z, options for 32-bit Z are grayed out.

There are quite a few maps in Unreal and UT99 that have zfighting problems, but I don't remember their names off hand. I think even Tom Clancy's Ghost Recon had bad zfighting issues too.

Well on the Matrox Quake III reports 32 bit z-buffer, but on a modern Intel onboard graphics it shows 24 bit z-buffer + 8-bit stencil.

I've got a few scenes to test now and will check what it looks like on a TNT2. Then I know if it's just a glitch.

YouTube, Facebook, Website

Reply 11 of 22, by Scali

User metadata
Rank l33t
Rank
l33t
DracoNihil wrote:

I thought GPU's don't support 32-bit zbuffer but instead only handle 24-bit zbuffer? Atleast everything I've tried can only request a 24-bit Z, options for 32-bit Z are grayed out.

There are (were?) GPUs that actually support 32-bit zbuffer. But the most popular variation is a 32-bit buffer where 24-bit is allocated for per-pixel z values, and 8-bit for per-pixel stencil.
With the 32-bit zbuffer, no stencil was available, so it was not an option for rendering algorithms that required stencil. So 24-bit became the go-to zbuffer depth, and 32-bit zbuffers moved into obscurity.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 12 of 22, by DracoNihil

User metadata
Rank Oldbie
Rank
Oldbie

Oh I see, but then what about for applications that don't require a stencil buffer? You're still SOL to request 32-bit Z?

“I am the dragon without a name…”
― Κυνικός Δράκων

Reply 13 of 22, by Scali

User metadata
Rank l33t
Rank
l33t
DracoNihil wrote:

Oh I see, but then what about for applications that don't require a stencil buffer? You're still SOL to request 32-bit Z?

Well, on some hardware there indeed won't be 32-bit Z support (you can check with the DXCapsViewer utility from the DirectX SDK, now Windows SDK. I'm not sure what present-day hardware supports actually, but I'm fairly sure that back in the day, Radeon 8500 had 32-bit support, where GeForce2/3 did not). They will have a 24-bit variation with no stencil though. In that case, the remaining 8 bits are just "don't care" (similar to how RGB is often stored as 32-bit with 8:8:8-bit pixels, and 8-bits not used, when no alphachannel is required).
So if you want to write robust software, you should not rely on 32-bit Z support, but you'll want a fallback to 24-bit or even 16-bit.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 14 of 22, by PhilsComputerLab

User metadata
Rank l33t++
Rank
l33t++

Here screenshots from the game on a G400.

The "use 32 bit z-buffer" is NOT ticked by default and the game reports z-buffer as 16 bit.

Tick the box and restart the machine and it shows 32 bit.

YouTube, Facebook, Website

Reply 15 of 22, by Gemini000

User metadata
Rank l33t
Rank
l33t

Even a 16-bit z-buffer can be good enough depending on the nature of your game. Indoor environments with few objects overlapping? No problem! :B

Once you start getting into things like decals, outdoor environments, complex models with multiple internal parts... suddenly, a 16-bit z-buffer ain't so great anymore. :P

I think the reason modern GPUs cap at a 24-bit z-buffer and 8-bit stencil is so that the entirety of colour, depth and stencil for each pixel can be processed with a single 64-bit operation. If you were to use a 32-bit z-buffer and needed a stencil buffer as well, every pixel would have to be addressed with three 32-bit reads/writes or two 64-bit reads/writes and it would kinda be a mess. :/

Fortunately, the way the stencil buffer works, needing more than 8-bits for it is extraordianrily rare, since you primarily use it for masking drawing operations to achieve various effects like shadow mapping, reflections, and portal rendering, just to name a few.

--- Kris Asick (Gemini)
--- Pixelmusement Website: www.pixelships.com
--- Ancient DOS Games Webshow: www.pixelships.com/adg

Reply 16 of 22, by Scali

User metadata
Rank l33t
Rank
l33t
Gemini000 wrote:

Once you start getting into things like decals

Problem with decals or other types of overlays is that you want to render the EXACT same pixels multiple times.
This means your rendering needs to be completely deterministic. So you want to feed the exact same polygon, and use the exact same transform on that polygon.
If you do that, the z-values will be exactly the same as well, and you won't have z-fighting, no matter how poor your zbuffer resolution is.

However, in practice this doesn't always happen. Sometimes because the modelers screwed up, sometimes because the programmers screwed up, and sometimes because even though the same model is fed, and the transform of the vertices is exactly the same, when a different shader is used, the driver might optimize the shader in a slightly different way, so you still don't get 100% the same results.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 17 of 22, by swaaye

User metadata
Rank l33t++
Rank
l33t++

I would load up flight or space games and look for depth issues. They usually deal with large distances.

UT certainly had some quirks indeed. I have a feeling that varies by card for other reasons than just Z precision though.

An interesting thing to ponder is Tegra 2 and 3 were limited to 16bit Z. It seems many games managed to deal with this well enough, but I played and beat Dead Space on Android and that certainly had issues with even medium distance flickering. It seems to depend on hardware though because Baytrail looks fine whereas Tegra 4 flickers (and Tegra 4 supports 24bit Z). Perhaps the game still uses 16bit Z on Tegra 4.

PPSSPP for Android displayed similar issues compared to its Windows version when I was experimenting with that recently (even on Tegra K1). I suppose related to concessions for other OpenGL ES hardware.

Reply 18 of 22, by Gemini000

User metadata
Rank l33t
Rank
l33t
Scali wrote:
Problem with decals or other types of overlays is that you want to render the EXACT same pixels multiple times. This means your […]
Show full quote
Gemini000 wrote:

Once you start getting into things like decals

Problem with decals or other types of overlays is that you want to render the EXACT same pixels multiple times.
This means your rendering needs to be completely deterministic. So you want to feed the exact same polygon, and use the exact same transform on that polygon.
If you do that, the z-values will be exactly the same as well, and you won't have z-fighting, no matter how poor your zbuffer resolution is.

However, in practice this doesn't always happen. Sometimes because the modelers screwed up, sometimes because the programmers screwed up, and sometimes because even though the same model is fed, and the transform of the vertices is exactly the same, when a different shader is used, the driver might optimize the shader in a slightly different way, so you still don't get 100% the same results.

From what I understand, the stencil buffer is typically used to handle decals nowadays since you can just mask out where you need the stencil to go using the current z-buffer state and then ignore the z-buffer while rendering it, but before this was common practice, the typical approach was to have decals "float" off of the surface they were attached to just enough so that they would render at least one z-buffer unit closer to the player at most visual ranges.

--- Kris Asick (Gemini)
--- Pixelmusement Website: www.pixelships.com
--- Ancient DOS Games Webshow: www.pixelships.com/adg

Reply 19 of 22, by Scali

User metadata
Rank l33t
Rank
l33t
Gemini000 wrote:

From what I understand, the stencil buffer is typically used to handle decals nowadays since you can just mask out where you need the stencil to go using the current z-buffer state and then ignore the z-buffer while rendering it

You'll still need to use the zbuffer in case you want to render decals that are partially occluded by closer objects.

Gemini000 wrote:

but before this was common practice, the typical approach was to have decals "float" off of the surface they were attached to just enough so that they would render at least one z-buffer unit closer to the player at most visual ranges.

That would be the wrong way to do it, as said above 😀
Since the resolution of the zbuffer is not constant, there is no way to ensure that you are 'at least one z-buffer unit closer' in all cases.
The proper way is to generate the EXACT zbuffer values, and set the ztest to function to equal (or actually less/equal in practice, since that enables hierarchical zbuffer optimizations, even though you should never have zvalues that are less).

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/