# split Depthbuffer values to distance

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.

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?

• 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: stackoverflow.com/questions/6652253/… (second answer). Dec 14 '21 at 10:33
• 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. Dec 14 '21 at 12:02
• @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. Dec 14 '21 at 12:28
• Reverse Z is a different thing, take a look at this link for a detailed explanation: nlguillemot.wordpress.com/2016/12/07/reversed-z-in-opengl Dec 14 '21 at 12:54
• @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. Dec 14 '21 at 13:28