<p>If you are taking about this occurring within a single draw call for a single object then you are talking about rasterization not Z fighting.  So the real question is, &quot;how are two triangles rasterized that are right next to each other&quot;. And the answer to that question boils down to rasterization rules. Which must be enforced, on GPU's that happens in hardware, for your software rasterizer you need to pick a rule set, then enforce it in code. Generically a rasterizer can leave no holes, and each pixel is only drawn once. You may want to always add colors when drawing your triangles, start with a color of zero and just add new colors drawn to that pixel, this will make your overdraw stand out like a sore thumb.</p>
<p>The most widely know rule set for handling this is the &quot;top left rule&quot; which states: The center of every pixel must lie completely inside the triangle, (you are computing pixel centers right?) or it center lies <em>exactly</em> on a triangle edge or on multiple edges in the case of corners, and a left edge is a non-horizontal edge that is on the left side of the triangle.</p>
<p>This last bit is directly from <a href="https://en.wikipedia.org/wiki/Rasterisation" rel="nofollow noreferrer">Wikipedia</a>.</p>

CC BY-SA 4.0
2021-03-11T15:20:38.183Z
This is correct as far as it goes, but does not address the problem. Raster rules (and so, sample coverage) is already correctly implemented.
geometrian
CC BY-SA 4.0
2021-03-11T15:25:39.517Z
Rasterization rules do in fact cover this situation, I suggest you look at it more closely, Z fighting doesn't occur on triangles that share an edge because they the edges do not overlap when implemented correctly.
pmw1234
CC BY-SA 4.0
2021-03-11T15:40:19.693Z
@pmw1234: Think of the letter V. Imagine that represents looking down at two triangles sharing an edge at the point of the "V". If you look from the right, one face faces towards you and the other away. Both triangles at the tip of the "V" rasterize the same samples (relative to the camera). That is, both triangles own the same "top-left" parts of each pixel, so they rasterize on top of each other. The samples from the tip can be arbitrarily close to each other in depth space.
Nicol Bolas
CC BY-SA 4.0
2021-03-11T15:56:08.610Z
I think this is the wording of this question, which is starting to become circular. There are the edges of triangles and the process drawing that edge such that no fragments are drawn twice, and two triangles that are essentially coplanar whose fragments effectively overlap. Your response answers the second case, my response answers the edge case, in either case the original question has been answered.
pmw1234
CC BY-SA 4.0
2021-03-11T13:14:39.890Z
2021-03-11T13:14:39.890Z
pmw1234
<p>The way this is &quot;handled by real GPUs&quot; is that most models are closed. As such, surfaces facing away from the camera are definitely not closer than some other surface of that object. To prevent throwing away performance rasterizing triangles that definitely do not contribute to the final image, most users turn on backface culling.</p>
<p>And thus, there is no problem.</p>
<p>In the absence of backface culling, what you describe is effectively just a form of z-fighting. But note that z-fighting almost always happens very far away from the camera and/or with co-planar objects that are very close together. To achieve the circumstance you describe, the angle between the two triangles would have to be extremely small, very close to 0.0. And they have to be so far away that the depth buffer lacks sufficient precision to deal with it.</p>
<p>So, in order for the phenomenon you describe to even be possible, you would need for all three of these to be the case:</p>
<ol>
<li>Turning off backface culling.</li>
<li>Two triangles that share an edge, with the angle between those triangles being <em>extremely</em> small.</li>
<li>The shared edge being very far away from the camera.</li>
</ol>
<p>This intersection of models and rendering state is vanishingly uncommon.</p>

CC BY-SA 4.0
2021-03-11T05:00:04.433Z
(1) is correct but irrelevant—one cannot assume backface culling is enabled, and real GPUs do not require it to correctly handle this case. Your points (2) and (3) are incorrect: the angle in question here is actually pretty close to 180°, and the surface is close to the camera; this occurred in multiple pixels in a fairly "usual" rendering. Just like consistent raster rules end up being required for real scenes, even though they feel like a "too rare to happen" case, this is another numerical edge case that *must* be solved to get acceptable results.
geometrian
CC BY-SA 4.0
2021-03-11T07:10:29.970Z
@imallett: "*this occurred in multiple pixels in a fairly "usual" rendering*" Prove it. Show me a circumstance where you wouldn't naturally turn off backface culling, you're looking at the scene with a reasonable perspective matrix and from a distance where numerical depth buffer precision, on a 24-bit depth buffer, would cause this problem.
Nicol Bolas
CC BY-SA 4.0
2021-03-11T07:11:50.237Z
There is no special handling in "real GPUs". The confluence of circumstances needed for this to take place just doesn't happen.
Nicol Bolas
CC BY-SA 4.0
2021-03-11T15:12:06.077Z
As I said previously, whether or not backface culling is enabled, as it would be in a production application, is immaterial because real GPUs handle this case correctly regardless. As for proving it—that's really disingenuous, but I mean, I have a scenefile. This came up in testing. This *absolutely* happens—with my 32-bit depth buffer and everything. The difference image with an OpenGL ground truth has only that one pixel different.
geometrian
CC BY-SA 4.0
2021-03-11T15:12:13.220Z
Look—easy example: put one silhouette vertex / edge of a model exactly on a pixel center. Voilà—the depths for all triangles at that sample are the same! The angles don't matter. Your depth precision and projection matrix don't matter. The same depth value is actually the "right" answer, even. Even besides any empirical evidence, do you legitimately believe that that case never, *ever* happens? This case *already* has to be handled by raster rules for computing sample coverage!
geometrian
CC BY-SA 4.0
2021-03-11T03:17:27.293Z
2021-03-11T03:17:27.293Z
Nicol Bolas
<p>I have written a software rasterizer, and have encountered a (literal) edge case.</p>
<p>At the silhouette edge of a typical object, you have two triangles—the front face and the back face.  They are not coplanar, but they of course share that single edge.  Say the pixel center / subpixel sample happens to lie very close to this edge—so close that the depth value computed for both triangles is actually <em>exactly</em>, bit-for-bit, identical.</p>
<p>Without special handling for this case, sometimes the &quot;wrong&quot; fragment will get through.  For example, with the <code>&lt;</code> depth function, if the backface renders first, then the depth test for the frontface will fail and the backface will show through.   If the frontface renders first, then the depth test for the backface will fail and the frontface will show.  The former case produces the wrong image—sometimes quite objectionably so.</p>
<p>I have thought about hacks to fix this like trying to handle the &quot;equals&quot; case explicitly, depending upon the depth function and whether the fragment came from a front face, but it's not clear, especially for the <code>≤</code> and <code>≥</code> depth functions, what the &quot;right&quot; answer is.  Still, it's about the only thing I can think of trying.</p>
<p>This is basically Z-fighting, but <em>unlike</em> the usual Z-fighting graphics newbies encounter when they don't set the clipping planes right or whatever (and which makes this issue almost ungoogleable), existing hardware <em>definitely does</em> provide <em>some</em> kind of solution to handle this particular case, because this problem does <em>not</em> occur on real GPUs.</p>
<p>So my question is—how <em>is</em> this handled by real GPUs?  If that's unanswerable, then how <em>can</em> it be handled consistently?</p>

CC BY-SA 4.0
2021-03-11T18:13:09.993Z
Doesn't this just fall back to triangle submission order, i.e. whichever triangle was later in the index buffer wins, for depth functions that include "equals", and whichever was earlier wins, for depth functions that don't include "equals"? GPUs are required to respect submission order in terms of the final contents of the framebuffer, even if they process things in parallel and out-of-order along the way through the pipeline. It's a similar case to rendering transparent objects back-to-front, with depth writes disabled.
Nathan Reed
CC BY-SA 4.0
2021-03-13T01:46:38.653Z
@NathanReed I thought of that; I think there must be some sort of exception for submission order here. Consider `<`. If fragments from later indices lose, then we could get the wrong fragment on edges just by having the front triangle happen to render after the back triangle. This would expose the problem in most engines just by rotating the model around.
geometrian
CC BY-SA 4.0
2021-03-13T19:07:10.097Z
I guess there could be some extra rule like that, but I've never heard of it; nor can I find anything like that in either the Direct3D or OpenGL rasterizer and depth-test specs. There's no hint in there of any interaction between face orientation and either rasterization rules or depth testing. Honestly I think in practice we almost always have backface culling enabled and so in most use cases / engines you would not see this problem. I would test it directly but my home codebase isn't well set-up to do that right now.
Nathan Reed
CC BY-SA 4.0
2021-03-16T14:05:14.403Z
This would appear to be a related question:  https://computergraphics.stackexchange.com/q/3619/209
Simon F
<rasterizer><hardware><silhouette><z-fighting>
Rasterization: How does hardware disambiguate identical Z values at silhouette edges?
geometrian
# Rasterization: How does hardware disambiguate identical Z values at silhouette edges?

(Asked by: username_0 on 2021-03-11)

I have written a software rasterizer, and have encountered a (literal) edge case.

At the silhouette edge of a typical object, you have two triangles—the front face and the back face. They are not coplanar, but they of course share that single edge. Say the pixel center / subpixel sample happens to lie very close to this edge—so close that the depth value computed for both triangles is actually *exactly*, bit-for-bit, identical.

Without special handling for this case, sometimes the "wrong" fragment will get through. For example, with the `<` depth function, if the backface renders first, then the depth test for the frontface will fail and the backface will show through. If the frontface renders first, then the depth test for the backface will fail and the frontface will show. The former case produces the wrong image—sometimes quite objectionably so.

I have thought about hacks to fix this like trying to handle the "equals" case explicitly, depending upon the depth function and whether the fragment came from a front face, but it's not clear, especially for the `≤` and `≥` depth functions, what the "right" answer is. Still, it's about the only thing I can think of trying.

This is basically Z-fighting, but *unlike* the usual Z-fighting graphics newbies encounter when they don't set the clipping planes right or whatever (and which makes this issue almost ungoogleable), existing hardware *definitely does* provide *some* kind of solution to handle this particular case, because this problem does *not* occur on real GPUs.

So my question is—how *is* this handled by real GPUs? If that's unanswerable, then how *can* it be handled consistently?

**Tags:** rasterizer, hardware, silhouette, z-fighting

> **Comments:**
> **username_1**: Doesn't this just fall back to triangle submission order, i.e. whichever triangle was later in the index buffer wins, for depth functions that include "equals", and whichever was earlier wins, for depth functions that don't include "equals"? GPUs are required to respect submission order in terms of the final contents of the framebuffer, even if they process things in parallel and out-of-order along the way through the pipeline. It's a similar case to rendering transparent objects back-to-front, with depth writes disabled.  
> **username_0**: @username_1 I thought of that; I think there must be some sort of exception for submission order here. Consider `<`. If fragments from later indices lose, then we could get the wrong fragment on edges just by having the front triangle happen to render after the back triangle. This would expose the problem in most engines just by rotating the model around.  
> **username_1**: I guess there could be some extra rule like that, but I've never heard of it; nor can I find anything like that in either the Direct3D or OpenGL rasterizer and depth-test specs. There's no hint in there of any interaction between face orientation and either rasterization rules or depth testing. Honestly I think in practice we almost always have backface culling enabled and so in most use cases / engines you would not see this problem. I would test it directly but my home codebase isn't well set-up to do that right now.  
> **username_2**: This would appear to be a related question:  https://computergraphics.stackexchange.com/q/3619/209  

---

## 2 answers

### Answer by username_3 on 2021-03-11. Score: 1

If you are taking about this occurring within a single draw call for a single object then you are talking about rasterization not Z fighting. So the real question is, "how are two triangles rasterized that are right next to each other". And the answer to that question boils down to rasterization rules. Which must be enforced, on GPU's that happens in hardware, for your software rasterizer you need to pick a rule set, then enforce it in code. Generically a rasterizer can leave no holes, and each pixel is only drawn once. You may want to always add colors when drawing your triangles, start with a color of zero and just add new colors drawn to that pixel, this will make your overdraw stand out like a sore thumb.

The most widely know rule set for handling this is the "top left rule" which states: The center of every pixel must lie completely inside the triangle, (you are computing pixel centers right?) or it center lies *exactly* on a triangle edge or on multiple edges in the case of corners, and a left edge is a non-horizontal edge that is on the left side of the triangle.

This last bit is directly from [Wikipedia](https://en.wikipedia.org/wiki/Rasterisation).

> **Comments:**
> **username_0**: This is correct as far as it goes, but does not address the problem. Raster rules (and so, sample coverage) is already correctly implemented.  
> **username_3**: Rasterization rules do in fact cover this situation, I suggest you look at it more closely, Z fighting doesn't occur on triangles that share an edge because they the edges do not overlap when implemented correctly.  
> **username_4**: @username_3: Think of the letter V. Imagine that represents looking down at two triangles sharing an edge at the point of the "V". If you look from the right, one face faces towards you and the other away. Both triangles at the tip of the "V" rasterize the same samples (relative to the camera). That is, both triangles own the same "top-left" parts of each pixel, so they rasterize on top of each other. The samples from the tip can be arbitrarily close to each other in depth space.  
> **username_3**: I think this is the wording of this question, which is starting to become circular. There are the edges of triangles and the process drawing that edge such that no fragments are drawn twice, and two triangles that are essentially coplanar whose fragments effectively overlap. Your response answers the second case, my response answers the edge case, in either case the original question has been answered.  

---

### Answer by username_4 on 2021-03-11. Score: 0

The way this is "handled by real GPUs" is that most models are closed. As such, surfaces facing away from the camera are definitely not closer than some other surface of that object. To prevent throwing away performance rasterizing triangles that definitely do not contribute to the final image, most users turn on backface culling.

And thus, there is no problem.

In the absence of backface culling, what you describe is effectively just a form of z-fighting. But note that z-fighting almost always happens very far away from the camera and/or with co-planar objects that are very close together. To achieve the circumstance you describe, the angle between the two triangles would have to be extremely small, very close to 0.0. And they have to be so far away that the depth buffer lacks sufficient precision to deal with it.

So, in order for the phenomenon you describe to even be possible, you would need for all three of these to be the case:

1. Turning off backface culling.
2. Two triangles that share an edge, with the angle between those triangles being *extremely* small.
3. The shared edge being very far away from the camera.

This intersection of models and rendering state is vanishingly uncommon.

> **Comments:**
> **username_0**: (1) is correct but irrelevant—one cannot assume backface culling is enabled, and real GPUs do not require it to correctly handle this case. Your points (2) and (3) are incorrect: the angle in question here is actually pretty close to 180°, and the surface is close to the camera; this occurred in multiple pixels in a fairly "usual" rendering. Just like consistent raster rules end up being required for real scenes, even though they feel like a "too rare to happen" case, this is another numerical edge case that *must* be solved to get acceptable results.  
> **username_4**: @imallett: "*this occurred in multiple pixels in a fairly "usual" rendering*" Prove it. Show me a circumstance where you wouldn't naturally turn off backface culling, you're looking at the scene with a reasonable perspective matrix and from a distance where numerical depth buffer precision, on a 24-bit depth buffer, would cause this problem.  
> **username_4**: There is no special handling in "real GPUs". The confluence of circumstances needed for this to take place just doesn't happen.  
> **username_0**: As I said previously, whether or not backface culling is enabled, as it would be in a production application, is immaterial because real GPUs handle this case correctly regardless. As for proving it—that's really disingenuous, but I mean, I have a scenefile. This came up in testing. This *absolutely* happens—with my 32-bit depth buffer and everything. The difference image with an OpenGL ground truth has only that one pixel different.  
> **username_0**: Look—easy example: put one silhouette vertex / edge of a model exactly on a pixel center. Voilà—the depths for all triangles at that sample are the same! The angles don't matter. Your depth precision and projection matrix don't matter. The same depth value is actually the "right" answer, even. Even besides any empirical evidence, do you legitimately believe that that case never, *ever* happens? This case *already* has to be handled by raster rules for computing sample coverage!  

---

