<p>My scenario is a Solar system with satellites. Therefor objects can be very close to the camera while a planet for example is in background far away. This setup causes problems with the depthbuffer precision, because to render the whole scenario I would need to put my nearplane of the projection matrix very close to zero to capture the satellite, while the farplane is extremely far away. This causes depth fighting (flickering). To better use the depthbuffer I calculated for different areas the optimal near and far plane values (span) shown in figure below.</p>
<p><a href="https://i.sstatic.net/R9FO1.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/R9FO1.png" alt="enter image description here" /></a></p>
<p><strong>Depending on the number of spans the depthbuffer is split in the following way:</strong>
The depthbuffer values which go from 0 to 1 is equally split into #number of spans with equal size. That means for 2 spans the first goes from 0 to 0.5 and the second starts from &gt;0.5 to 1.
With 3 spans it would be 0 to 0.33, 0.33 to 0.66 and 0.66 to 1.</p>
<p>This is done with the <code>glDepthRange()</code> function. I also change the projection matrix's near and far plane values to the boundaries</p>
<p>When rendering the scenario, the depthbuffer is used very good now. All the flickering has gone.</p>
<p><strong>But now I try to convert the depthbuffer values back to distance values.</strong></p>
<p>To do so, I stored the span information into an vec4 array &quot;u_depthSpans[]&quot; in the following way:
x: depthbuffer near value [0,1]. y: depthbuffer far value [0,1]. z: real distance near value. w: real distance far value. Each vec4 item in the array is one span.</p>
<p>To calculate the distance I wrote this:</p>
<pre><code>float linearDepth(float depthSample, float zNear, float zFar)                
{
    depthSample = 2.0 * depthSample - 1.0;                                   
    float zLinear = 2.0 * zNear * zFar / (zFar + zNear - depthSample * (zFar - zNear));
    return zLinear;                                                          
}                                                                           

for(uint i = 0; i &lt; u_countDepthSpans; ++i)
{
    if(depthBufferValue &gt;= u_depthSpans[i].x &amp;&amp; depthBufferValue &lt;= u_depthSpans[i].y)//is depth value inside span?
    {
        float factorDepth = (depthBufferValue - u_depthSpans[i].x) / (u_depthSpans[i].y - u_depthSpans[i].x);
        depthReal = linearDepth(factorDepth, u_depthSpans[i].z, u_depthSpans[i].w);
    }
}
</code></pre>
<p>But it gives me wrong results. What am I doing wrong?</p>

CC BY-SA 4.0
2021-12-14T10:33:57.687Z
The factorDepth variable is a value between 0 (the depthvalue lies at the near plane of the span) to 1 (the depthvalue lies at the far plane of the span). From There on, I use this value to calculate the real position in a way not thinking about spans anymore. Could this be the problem? Because the "linearDepth" function I've found here: https://stackoverflow.com/questions/6652253/getting-the-true-z-value-from-the-depth-buffer (second answer).
Thomas
CC BY-SA 4.0
2021-12-14T12:02:17.163Z
Just a quick observation: The linearDepth functions looks like it is expecting -1 to 1 (OpenGL default Z range) but your comments are using a range of 0 to 1. Also, did you consider reverse Z (1...0) if you are using OpenGL default depth range of -1 to 1 then  the depth distribution can be improved significantly just by switching to reverse Z.
pmw1234
CC BY-SA 4.0
2021-12-14T12:28:55.813Z
@pmw1234 thank you for your fast response. But even when I pass the data from -1 to 1 to the function, the values are still wrong (1meter correspond to 1.7 meter). When the distance shrinks, the result value shrinks as well. So reverse Z seems to be not the problem.
Thomas
CC BY-SA 4.0
2021-12-14T12:54:43.990Z
Reverse Z is a different thing, take a look at this link for a detailed explanation: https://nlguillemot.wordpress.com/2016/12/07/reversed-z-in-opengl/
pmw1234
CC BY-SA 4.0
2021-12-14T13:28:36.657Z
@pmw1234 I did not implemented that... very nice technique! But this seems to be not my problem... I think it must be a tiny thing I forgot to bring into calculation.
Thomas
CC BY-SA 4.0
2021-12-14T13:33:57.423Z
So I rendered each span separately by setting the range and the projection matrix near/far plane described above. Then my depthbuffer value is read out of the depthbuffer texture. So it is a value between 0 and 1. 0: something is very close, 1: something is very far. This value is checked to which span it belongs and then the code above is used to get the distance instead of the depthbuffer value which is not linear distributed.
Thomas
<opengl>
split Depthbuffer values to distance
Thomas
# split Depthbuffer values to distance

(Asked by: username_0 on 2021-12-14)

My scenario is a Solar system with satellites. Therefor objects can be very close to the camera while a planet for example is in background far away. This setup causes problems with the depthbuffer precision, because to render the whole scenario I would need to put my nearplane of the projection matrix very close to zero to capture the satellite, while the farplane is extremely far away. This causes depth fighting (flickering). To better use the depthbuffer I calculated for different areas the optimal near and far plane values (span) shown in figure below.

[![enter image description here](https://i.sstatic.net/R9FO1.png)](https://i.sstatic.net/R9FO1.png)

**Depending on the number of spans the depthbuffer is split in the following way:**
The depthbuffer values which go from 0 to 1 is equally split into #number of spans with equal size. That means for 2 spans the first goes from 0 to 0.5 and the second starts from >0.5 to 1.
With 3 spans it would be 0 to 0.33, 0.33 to 0.66 and 0.66 to 1.

This is done with the `glDepthRange()` function. I also change the projection matrix's near and far plane values to the boundaries

When rendering the scenario, the depthbuffer is used very good now. All the flickering has gone.

**But now I try to convert the depthbuffer values back to distance values.**

To do so, I stored the span information into an vec4 array "u\_depthSpans[]" in the following way:
x: depthbuffer near value [0,1]. y: depthbuffer far value [0,1]. z: real distance near value. w: real distance far value. Each vec4 item in the array is one span.

To calculate the distance I wrote this:

```
float linearDepth(float depthSample, float zNear, float zFar)                
{
    depthSample = 2.0 * depthSample - 1.0;                                   
    float zLinear = 2.0 * zNear * zFar / (zFar + zNear - depthSample * (zFar - zNear));
    return zLinear;                                                          
}                                                                           

for(uint i = 0; i < u_countDepthSpans; ++i)
{
    if(depthBufferValue >= u_depthSpans[i].x && depthBufferValue <= u_depthSpans[i].y)//is depth value inside span?
    {
        float factorDepth = (depthBufferValue - u_depthSpans[i].x) / (u_depthSpans[i].y - u_depthSpans[i].x);
        depthReal = linearDepth(factorDepth, u_depthSpans[i].z, u_depthSpans[i].w);
    }
}

```

But it gives me wrong results. What am I doing wrong?

**Tags:** opengl

> **Comments:**
> **username_0**: The factorDepth variable is a value between 0 (the depthvalue lies at the near plane of the span) to 1 (the depthvalue lies at the far plane of the span). From There on, I use this value to calculate the real position in a way not thinking about spans anymore. Could this be the problem? Because the "linearDepth" function I've found here: https://stackoverflow.com/questions/6652253/getting-the-true-z-value-from-the-depth-buffer (second answer).  
> **username_1**: Just a quick observation: The linearDepth functions looks like it is expecting -1 to 1 (OpenGL default Z range) but your comments are using a range of 0 to 1. Also, did you consider reverse Z (1...0) if you are using OpenGL default depth range of -1 to 1 then  the depth distribution can be improved significantly just by switching to reverse Z.  
> **username_0**: @username_1 thank you for your fast response. But even when I pass the data from -1 to 1 to the function, the values are still wrong (1meter correspond to 1.7 meter). When the distance shrinks, the result value shrinks as well. So reverse Z seems to be not the problem.  
> **username_1**: Reverse Z is a different thing, take a look at this link for a detailed explanation: https://nlguillemot.wordpress.com/2016/12/07/reversed-z-in-opengl/  
> **username_0**: @username_1 I did not implemented that... very nice technique! But this seems to be not my problem... I think it must be a tiny thing I forgot to bring into calculation.  
> **username_0**: So I rendered each span separately by setting the range and the projection matrix near/far plane described above. Then my depthbuffer value is read out of the depthbuffer texture. So it is a value between 0 and 1. 0: something is very close, 1: something is very far. This value is checked to which span it belongs and then the code above is used to get the distance instead of the depthbuffer value which is not linear distributed.  

---

## 0 answers

