Outerra forum

Outerra Engine => Technology => Topic started by: Fezzrum on August 12, 2013, 06:48:57 am

Title: Logarithmic depth buffer linearization
Post by: Fezzrum on August 12, 2013, 06:48:57 am
Hello.I am trying to develop a similar program to outtera to learn opengl/GLSL :)
I have read this great article about logarithmic depth buffer
http://outerra.blogspot.com/2012/11/maximizing-depth-buffer-range-and.html (http://outerra.blogspot.com/2012/11/maximizing-depth-buffer-range-and.html)
and implemented it in my program

vertex shader
Code: [Select]
vec4 clip = MVP * vec4(position,1.0f);
clip.z =((2.0f * log(1.0f * clip.z + 1.0f) / log(1.0f * 27000000.0f + 1.0f)) - 1.0f) * clip.w;

to linear depth buffer I use following code in fragment shader
Code: [Select]
float n = 1.0; // camera z near
  float f = 27000000.0; // camera z far
  float z = texture( DepthTex, TexCoord ).x;
  float d = (2.0 * n) / (f + n - z * (f - n));
  FragColor=vec4(d,d,d,1);

however this does not work.
Here is comparison of linear depth with and without log
(http://i.stack.imgur.com/O1u9R.png)
http://stackoverflow.com/questions/18182139/logarithmic-depth-buffer-linearization (http://stackoverflow.com/questions/18182139/logarithmic-depth-buffer-linearization)
 


 
Title: Re: Logarithmic depth buffer linearization
Post by: cameni on August 12, 2013, 06:56:19 am
I'm not sure what you are trying to achieve, what you mean by the linearization here. Do you want to reconstruct the depth value from the logarithmic depth buffer?
Title: Re: Logarithmic depth buffer linearization
Post by: Fezzrum on August 12, 2013, 07:20:01 am
If i am not wrong depth buffer is non-linear which means it is relative to the "far" and the "near" parameter. To create effects like DoF, buffer needs to be linear,and this is what I am trying to achieve.

Title: Re: Logarithmic depth buffer linearization
Post by: cameni on August 12, 2013, 08:44:12 am
Yes the mapping of depth values is nonlinear, and it actually doesn't use near values. I guess you want to reconstruct the camera space depth from the values in the depth buffer, so I've posted the code on stackoverflow.

But I'm still not sure if that's what you want, because you are using the terminology rather loosely ;)
Title: Re: Logarithmic depth buffer linearization
Post by: Almaz on March 28, 2014, 01:03:53 am
What am I doing wrong? Z-fighting doesn't give up.

http://pastebin.com/vWSBJ931 (http://pastebin.com/vWSBJ931)

OpenGL 4.4.
Title: Re: Logarithmic depth buffer linearization
Post by: cameni on March 28, 2014, 01:47:43 am
You are missing the multiply with w in the vertex shader:
Code: [Select]
gl_Position.z = (log2(max(1e-6, logz)) * Fcoef - 1.0) * gl_Position.w;
Title: Re: Logarithmic depth buffer linearization
Post by: Almaz on March 28, 2014, 11:23:22 am
I've added. And now all objects disappear. Showing yourself only when the view vector is perpendicular to the objects plane.
Title: Re: Logarithmic depth buffer linearization
Post by: cameni on March 28, 2014, 11:40:11 am
Hm, I don't see anything else wrong. ViewProj is your normal model-view-projection matrix, right?

Btw you should remove the conservative depth (line 34) - it brings no effect.
Title: Re: Logarithmic depth buffer linearization
Post by: Almaz on March 28, 2014, 02:00:22 pm
Hm, I don't see anything else wrong. ViewProj is your normal model-view-projection matrix, right?

Yes, it is.

Look, is it right?

gl_Position.z = log2(max(1e-6, 1.0 + gl_Position.w)) * Fcoef - 1.0;

clipping issues: for values smaller than or equal to 0 the log function is undefined. In cases when one vertex of the triangle lies further behind the camera (≤ -1), this causes a rejection of the whole triangle even before the triangle is clipped.
Clamping the value via max(1e-6, 1.0 + gl_Position.w) solves the problem of disappearing long triangles crossing the camera plane.
(from here (http://outerra.blogspot.ru/2013/07/logarithmic-depth-buffer-optimizations.html))

Should be gl_Position.z or I'm wrong?
Title: Re: Logarithmic depth buffer linearization
Post by: cameni on March 28, 2014, 04:30:56 pm
gl_Position.w is right, because w contains camera space depth, whereas z is already projected by the old projection matrix.

You didn't add the multiplication by w, I'm looking at test.glsl, it should be:

logz = 1.0 + gl_Position.w;
gl_Position.z = (log2(max(1e-6, logz)) * Fcoef - 1.0) * gl_Position.w;
Title: Re: Logarithmic depth buffer linearization
Post by: cameni on March 28, 2014, 04:38:21 pm
I can't launch it.
Alert    : can't create required context.
Title: Re: Logarithmic depth buffer linearization
Post by: Almaz on March 29, 2014, 03:27:03 am
I can't launch it.
Alert    : can't create required context.

I'm sorry for wasting your time. The app require OpenGL 4.4. But, it doesn't matter now.

I guess, problem might be in projection matrix.  Can I take a look at projection matrix from your project?

upd

In my case with this:

void main()
{
    gl_Position = ViewProj * vec4(inVertex, 1.0);

    logz = 1.0 + gl_Position.z;
    gl_Position.z = log2(max(1e-6, logz)) * Fcoef - 1.0;
}

Everything works fine.
Title: Re: Logarithmic depth buffer linearization
Post by: cameni on March 29, 2014, 04:30:23 am
Projection matrix is the normal one from your standard OpenGL setup, so as long as the normal projection works for you, it should work here as well.

Multiplication by gl_Position.w is required in the vertex shader to get rid of implicit division by w in the pipeline, that computes normalized device coordinates. Since you are also modifying gl_FragDepth, then it may not matter here, but it will not work without the fragment shader modification, which you should have tested first.
Title: Re: Logarithmic depth buffer linearization
Post by: ObliviousToOdds on December 03, 2014, 06:42:48 am
How would one go about reconstructing world positions from a logarithmic depth buffer using the code above:
Code: [Select]
gl_Position.z = (log2(max(1e-6, logz)) * Fcoef - 1.0) * gl_Position.w; to write depth values into the buffer then read these depth values and find the world position for each pixel? I assume that the depth values would have to be somehow linearized after reading the values back from the buffer, but then what do you do?