Sign in to follow this  
0m3g4

How to render linearized depth?

Recommended Posts

Hallo,

I want to render my scene depending on the objects distance to the near and far clipping plane. Points on the near plane should be white, those on the far plane black and everything in between should be mapped linearly between white and black.

For reference, my projection:

[font="Courier New"]glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (50.0, (float)width/(float)height, 1, 7);
glMatrixMode(GL_MODELVIEW);[/font]

I wrote the following shaders:

[font="Courier New"]varying float depth;
void main()
{
vec4 v = (gl_ModelViewMatrix * gl_Vertex);
depth = -(v.z-1.0)/(7.0-1.0);
gl_Position = ftransform();
}

varying float depth;
void main()
{
gl_FragColor.r = 1-depth;
gl_FragColor.g = 1-depth;
gl_FragColor.b = 1-depth;
gl_FragColor.a = 1;
}[/font]

But, while objects tend to get darker the further away they are, it somehow doesn't look right. Objects at the near clipping plane appear light-gray, not white

Share this post


Link to post
Share on other sites
[quote]What people often fail to realise is that in nearly all machines, the Z buffer is non-linear.[/quote]


Read this: [url="http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html"]http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html[/url]

Share this post


Link to post
Share on other sites
Looks like your order of operations might be wrong

[font="Lucida Console"]-(-1 - 1) / 6 == 0.3333[/font]
[font="Lucida Console"]-(-7 - 1) / 6 == 1.3333[/font]

[font="Lucida Console"](- -1 - 1) / 6 == 0.0[/font]
[font="Lucida Console"](- -7 - 1) / 6 == 1.0[/font]

Share this post


Link to post
Share on other sites
[quote name='n3Xus' timestamp='1307362834' post='4820049']
[quote]What people often fail to realise is that in nearly all machines, the Z buffer is non-linear.[/quote]


Read this: [url="http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html"]http://www.sjbaker.o...r_z_buffer.html[/url]
[/quote]

While I do know that site, I don't see how it helps me in my situation. So[font="Courier New"] (gl_ModelViewMatrix * gl_Vertex).z[/font][font="Arial"] is in fact the non-linear content of the [/font]Z-Buffer? If yes, how do I get what I want? Could you please elaborate further?


[quote name='Hodgman' timestamp='1307362855' post='4820050']
Looks like your order of operations might be wrong

[font="Lucida Console"]-(-1 - 1) / 6 == 0.3333[/font]
[font="Lucida Console"]-(-7 - 1) / 6 == 1.3333[/font]

[font="Lucida Console"](- -1 - 1) / 6 == 0.0[/font]
[font="Lucida Console"](- -7 - 1) / 6 == 1.0[/font]
[/quote]

Thank you very much, you are of course right. It looks way better now. Now, however, I'm concerned about what n3xus said.

Share this post


Link to post
Share on other sites
No, "[font="Courier New"]output.z / output.w[/font]" is the non-linear value that's talked about in that article ([i]this division is done by the hardware in-between vertex and pixel shaders, and used for the depth-test[/i]). "[font="'Courier New"]output.z[/font]" by itself is linear.

Share this post


Link to post
Share on other sites
There's sample code here for using a vertex shader to get linear depth: http://www.mvps.org/directx/articles/linear_z/linearz.htm

Advance warning that it's HLSL, not GLSL, but you should be able to convert very easily.

Share this post


Link to post
Share on other sites
[quote name='mhagain' timestamp='1307366428' post='4820066']
There's sample code here for using a vertex shader to get linear depth: [url="http://www.mvps.org/directx/articles/linear_z/linearz.htm"]http://www.mvps.org/...r_z/linearz.htm[/url]

Advance warning that it's HLSL, not GLSL, but you should be able to convert very easily.
[/quote]
Okay, with that code I would get a linearized Z-Buffer and could then render that to the screen. But it should have the same result as my current approach with the additional fragment shader?

Share this post


Link to post
Share on other sites
That article sounded similar to what I was doing a while back.

Also, you could write eye space z values instead, which I have also done in some cases. You just need a float32 buffer like GL_RGBA32F or something like that.
In the vs,
varying float EyeVertexZ;
eyeVertex = Modelview* Vertex;
EyeVertexZ= eyeVertex.z;

and in your fs
varying float EyeVertexZ;
gl_FragColor = vec4(EyeVertexZ);

The results would be far more accurate than anything else and you aren't restricted to 0.0 to 1.0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this