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

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?

  • $\begingroup$ 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). $\endgroup$
    – Thomas
    Dec 14 '21 at 10:33
  • $\begingroup$ 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. $\endgroup$
    – pmw1234
    Dec 14 '21 at 12:02
  • $\begingroup$ @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. $\endgroup$
    – Thomas
    Dec 14 '21 at 12:28
  • $\begingroup$ 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 $\endgroup$
    – pmw1234
    Dec 14 '21 at 12:54
  • $\begingroup$ @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. $\endgroup$
    – Thomas
    Dec 14 '21 at 13:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.