<p>There are explicit rules in the OpenGL specification about invariance guarantees. For the purpose of this discussion, these rules boil down to the following.</p>

<p>Given a particular series of vertex processing shaders (VS, tessellation, and GS), there are some set of input values, uniforms, and the like which lead to the computation of the final <code>gl_Position</code> value for the primitives in that process. If all of these values are <em>binary identical</em> (including the way the vertex format leads to any VS inputs), then you're guaranteed that <code>gl_Position</code> will have binary identical values. And if two primitive of the same type have binary identical positions, the rasterizer is <em>required</em> to generate binary identical fragment positions.</p>

<p>And thus, no z-fighting.</p>

<p>Now, that's kind of restrictive, as it only works with the same shaders. You can use different shaders, so long as:</p>

<ol>
<li>all shaders involved get binary identical values on expressions leading to the computation of <code>gl_Position</code>,</li>
<li>all shaders involved use the exact same expressions (and I mean <em>exact</em>; <code>a + b</code> isn't the "same expression" as <code>b + a</code>, no matter what mathematics says) to compute <code>gl_Position</code>, and</li>
<li><code>gl_Position</code> and any inter-shader in/out variables leading to its computation are qualified with the <code>invariant</code> qualifier in all shaders. This tells the compiler not to optimize certain things away in expressions leading to the computation of such values.</li>
</ol>

CC BY-SA 4.0
2021-05-19T09:02:09.293Z
But why there's no z-fighting in the case of identical vertices? As I understand the fragments can be processed in parallel, i.e. primitives A and B are processed at the same time and it's possible that the depths of two neighboring fragments will be calculated for different promitives so they will be colored differently.
nikitablack
CC BY-SA 4.0
2021-05-19T13:17:54.423Z
@nikitablack: While fragments can be generated, and the FS executed, in any order, writing operations must process the fragments as if they were generated in primitive order. One of those triangles was sent before the other, and therefore it will write all of its fragment data before the other.
Nicol Bolas
CC BY-SA 4.0
2019-06-26T17:06:01.140Z
2019-06-26T17:06:01.140Z
Nicol Bolas
<p>That would be because the GPU is deterministic. For the same inputs (vertex positions) it should produce the exact same per pixel depth outputs. </p>

<p>Z-Fighting usually occurs with polygons with different vertex positions but still on the same plane, so interpolation rounding errors show up as differences and hence Z-fighting.</p>

CC BY-SA 4.0
2019-06-26T09:43:28.903Z
So it would be safe to rely on this behavior across different implementations and GPUs for example when rendering texture overlays in game programming?
Quantum64
CC BY-SA 4.0
2019-06-26T09:47:13.230Z
I would say its down to the internals of the GPU, I've seen some mobile SOC GPUs with terrible interpolation precision. I'm not sure, but I don't think this precision is exposed to openGL either, given that it could be performed in floating point units of fixed point integer units inside the GPU silicon.
PaulHK
CC BY-SA 4.0
2019-06-26T09:53:18.120Z
That comment is casting doubt on whether or not I should use this in my game.  My alternative is to generate alpha masks for the textures I want to apply overlays to, but I would like to avoid this to save space on the texture atlas if possible. I am only concerned with desktop GPUs, should it be safe for those?
Quantum64
CC BY-SA 4.0
2019-06-26T12:26:13.110Z
@Quantum64 No, this doesn't come down to the internals of the GPU alone, the OpenGL standard actually makes certain guarantees for invariance and this is one of that. For the same inputs the same calculations will return the same results. This holds for pipeline transformations and interpolations as much as it holds for any deterministic program...
Christian Rau
CC BY-SA 4.0
2019-06-26T12:27:17.103Z
...What could result in differences here would be if you have different vertex transformation operations in the vertex shaders (i.e. an MVP multiply vs. a separate P * MV multiplication). Make sure you use the same computations. Even then there could *theoretically* be different results (practically not, though), but even that is resolvable with declaring the vertex position `invariant`. So yes, drawing your mesh multiple times for stuff like texture layering is a perfectly reasonable and common use-case that, when handled properly, can be done in a 100% standard compliant and reliable way.
Christian Rau
CC BY-SA 4.0
2019-06-26T12:35:41.117Z
At the end of the day, this comes down to the same issue as the common misunderstandings about floating point computations. Lack of precision or inaccurate interpolations is not the same as *randomly* noisy results. As long as your computations are deterministic the results will be the same, no matter how they differ from any possible (but entirely irrelevant) exact ground truth. And the OpenGL standard, under the above constraints, guarantees this determinism.
Christian Rau
CC BY-SA 4.0
2019-06-26T20:29:35.787Z
@Christian Rau Thank you for your very helpful and informative answer.
Quantum64
CC BY-SA 4.0
2019-06-26T09:39:57.580Z
2019-06-26T09:39:57.580Z
PaulHK
<p>Typically when coplanar or nearly coplanar polygons are rendered in OpenGL, the textures of each polygon mix together in a non-deterministic way. My understanding is that this is caused by the limited precision of the z-buffer as it uses floating point values. However, there seems to be an exception to this case. I've noticed that when two polygons are rendered with the exact same vertex positions, z-fighting does not occur. The polygon that was rendered last appears on top of the other coplanar polygon.</p>

<p>Why does this occur? Does this behavior always occur? Is this behavior guaranteed across all OpenGL implementations?</p>

<opengl><rendering>
Why do identical polygons not z-fight in OpenGL?
Quantum64
# Why do identical polygons not z-fight in OpenGL?

(Asked by: username_0 on 2019-06-26)

Typically when coplanar or nearly coplanar polygons are rendered in OpenGL, the textures of each polygon mix together in a non-deterministic way. My understanding is that this is caused by the limited precision of the z-buffer as it uses floating point values. However, there seems to be an exception to this case. I've noticed that when two polygons are rendered with the exact same vertex positions, z-fighting does not occur. The polygon that was rendered last appears on top of the other coplanar polygon.

Why does this occur? Does this behavior always occur? Is this behavior guaranteed across all OpenGL implementations?

**Tags:** opengl, rendering


---

## 2 answers

### Answer by username_1 on 2019-06-26. Score: 6 | Accepted answer

There are explicit rules in the OpenGL specification about invariance guarantees. For the purpose of this discussion, these rules boil down to the following.

Given a particular series of vertex processing shaders (VS, tessellation, and GS), there are some set of input values, uniforms, and the like which lead to the computation of the final `gl_Position` value for the primitives in that process. If all of these values are *binary identical* (including the way the vertex format leads to any VS inputs), then you're guaranteed that `gl_Position` will have binary identical values. And if two primitive of the same type have binary identical positions, the rasterizer is *required* to generate binary identical fragment positions.

And thus, no z-fighting.

Now, that's kind of restrictive, as it only works with the same shaders. You can use different shaders, so long as:

1. all shaders involved get binary identical values on expressions leading to the computation of `gl_Position`,
2. all shaders involved use the exact same expressions (and I mean *exact*; `a + b` isn't the "same expression" as `b + a`, no matter what mathematics says) to compute `gl_Position`, and
3. `gl_Position` and any inter-shader in/out variables leading to its computation are qualified with the `invariant` qualifier in all shaders. This tells the compiler not to optimize certain things away in expressions leading to the computation of such values.

> **Comments:**
> **username_2**: But why there's no z-fighting in the case of identical vertices? As I understand the fragments can be processed in parallel, i.e. primitives A and B are processed at the same time and it's possible that the depths of two neighboring fragments will be calculated for different promitives so they will be colored differently.  
> **username_1**: @username_2: While fragments can be generated, and the FS executed, in any order, writing operations must process the fragments as if they were generated in primitive order. One of those triangles was sent before the other, and therefore it will write all of its fragment data before the other.  

---

### Answer by username_3 on 2019-06-26. Score: 2

That would be because the GPU is deterministic. For the same inputs (vertex positions) it should produce the exact same per pixel depth outputs.

Z-Fighting usually occurs with polygons with different vertex positions but still on the same plane, so interpolation rounding errors show up as differences and hence Z-fighting.

> **Comments:**
> **username_0**: So it would be safe to rely on this behavior across different implementations and GPUs for example when rendering texture overlays in game programming?  
> **username_3**: I would say its down to the internals of the GPU, I've seen some mobile SOC GPUs with terrible interpolation precision. I'm not sure, but I don't think this precision is exposed to openGL either, given that it could be performed in floating point units of fixed point integer units inside the GPU silicon.  
> **username_0**: That comment is casting doubt on whether or not I should use this in my game.  My alternative is to generate alpha masks for the textures I want to apply overlays to, but I would like to avoid this to save space on the texture atlas if possible. I am only concerned with desktop GPUs, should it be safe for those?  
> **username_4**: @username_0 No, this doesn't come down to the internals of the GPU alone, the OpenGL standard actually makes certain guarantees for invariance and this is one of that. For the same inputs the same calculations will return the same results. This holds for pipeline transformations and interpolations as much as it holds for any deterministic program...  
> **username_4**: ...What could result in differences here would be if you have different vertex transformation operations in the vertex shaders (i.e. an MVP multiply vs. a separate P * MV multiplication). Make sure you use the same computations. Even then there could *theoretically* be different results (practically not, though), but even that is resolvable with declaring the vertex position `invariant`. So yes, drawing your mesh multiple times for stuff like texture layering is a perfectly reasonable and common use-case that, when handled properly, can be done in a 100% standard compliant and reliable way.  
> **username_4**: At the end of the day, this comes down to the same issue as the common misunderstandings about floating point computations. Lack of precision or inaccurate interpolations is not the same as *randomly* noisy results. As long as your computations are deterministic the results will be the same, no matter how they differ from any possible (but entirely irrelevant) exact ground truth. And the OpenGL standard, under the above constraints, guarantees this determinism.  
> **username_0**: @username_4 Thank you for your very helpful and informative answer.  

---

