Regarding Z fighting

Hello All,

i needed a small clarification w.r.t Z fighting. Say for eg i draw two triangles, with their Z coordinates being the same, and they have overlaps. So, some part of one triangle is inside the other triangle. So, my question is:

  1. This causes a Z-fighting issue since fragments generated for the overlapping region will have conflicting values of Z.
  2. How exactly is this handled by the driver? So, what fragment passes the depth test?

Could anyone please clarify this for me?
Thanks in advance!

Yes.

It isn’t handled. The fragment that comes first will win. Which comes first isn’t defined as both triangles might get rendered in parallel. The fragment creation order might change from frame to frame in an animation, this is in fact what creates the “fighting” appearance.

Is there a specific need for such a scenario? Can’t you advoid the overlap? Just curious.

Hi,

Thanks for the replies menzel, thokra.

@thokra:
Well, i was thinking on cases where we have a car’s(or more specifically a tank maybe, since there are chances that a lot of overlap is possible) wheel touching a road. So, there would be cases where there are overlaps right? Is there anyway i could avoid it? This was just an example i had thought of. I was curious as to how this is prevented in mainstream apps like games for eg.

Thanks!

It isn’t the fragment that comes first that is drawn, the normal rules still apply regarding which fragment is drawn according to which depth function is chosen with gDepthFunc. The z-fighting is due to the quantization process + numerical precision issues causing different areas on the second triangle to be quantized to either the same depth value as the fragment from the previous triangle, or +/- 1 unit of depth closer.

The only solution is not to draw planes that are close together on top of each other - give dynamic objects a depth that means the front faces won’t overlap closely (only the back face will), make sure your models don’t containing closely overlapping planes (or t-junctions) and ensure that if you are trying to do a multi-pass algorithm that you use the exact same vertices/matrices (as well as following the other rules defined in the invariance section of the OpenGL spec) or have ensured that the second pass will be drawn over the first pass in some other way (eg. glPolygonOffset, or drawing second triangle slightly closer by adjusting the projection matrix). Having your near + far plane as close together as possible gives more precision to play with too.

Sure, you can influence which fragment is drawn with the depth func.

@myk45:
When the wheel touches the road, you won’t see the piece of road intersecting with the wheel but the wheel above it, right? Maybe I didn’t understand your problem/scenario.

> When the wheel touches the road, you won’t see the piece of road intersecting with the wheel but the wheel above it, right?

Well, i was considering a scenario where in both the the wheel and part of a road might have the same Z. Well technically the wheel is expected a little above ground, but i was considering a case where there might be exact Z generated for multiple fragments. So, this would still lead to a Z fight right?

To sum it up, all i was curious to know was, if 2 generated fragments result with same Z, we have a fight, which you clarified in your first post.
Thanks!

If they intersect there might by z-fighting. However, if a few fragments in a fast moving scene are fighting no one will notice anyway. You shouldn’t pay attention to it if you have to pay close attention to it to even notice it.

The driver (really the implementation including hardware) handles this according to the specification. The fragments arrive in order and whichever one wins according to the current depth test and the interpolated depth value is the one that will have their RGB value remain or get written to the color buffer. There is never any ambiguity.

Where z fighting arises is the math rounding and general imprecision when you have post transformed screen values and interpolation. The exact depth values after interpolation for each pixel’s depth fragments down to the least significant bit can flip the result of the depth test for a given pixel caused by small variations in eye position to produce a flickering between two coplanar polygons if not handled correctly, especially if they do not share vertex values or cannot exploit depth invariance features.

This is most common with, but not limited to coplanar scenarios. If you have two intersecting surfaces and limited depth precision you can see similar results at the interface between the surfaces.

Thanks a lot dorbie, thokra, that was very helpful.