Sign in to follow this  
directNoob

Projection Matrix - Very high depth buffer values.

Recommended Posts

Hi. First of all, I dont use the ogl view, projection matrix stuff. Instead, I load the stuff myself. I use column vectors and a left handed coord sys. Just like D3D. I mean, the vertex's coord are defined in positive z space. When I transform the camera, everything seems to be ok. The camera goes just where I want it to be... It seems, that everything is just rendered fine. Some days ago, I implemented SSAO and realized, that the depth buffer is very bright. I mean, the depth buffer values are very high at 1.0. If I pow the depth values in the pixel shader by 30 or so, i.e. pow( depth, 30 ), the depth values looks just fine! the depth buffer just looks like a depth buffer and not as before, a white plane. So, depth values are just there. Then I observed the projection matrix. It is the one from the book Realtime Rendering. This matrix can be found nearly on every other website, including the microsoft's d3d site. It's the following:
vec4_t vcX(2.0f*n/width,0.0f,			0.0f,			0.0f) ;
vec4_t vcY(0.0f,	2.0f*n/height,		0.0f,			0.0f) ;
vec4_t vcZ(0.0f,	0.0f,			f/(f - n),		-2.0f*n*f/(f-n) ) ;
vec4_t vcW(0.0f,	0.0f,			1.0f,			0.0f ) ;


I hope the formatting is ok! Now, lets just quickly observe the values for the projected z coordinate, which goes into the depth buffer. It is
x_p = ...
y_p = ...
z_p = (z*f/(f-n)-2.0*n*f/(f-n))/w_p
w_p = z


, if you mult the view space vector with the projection matrix. z: view space z value f: far plane dist n: near plane dist Now, lets assume f=1000, n=0.1, z=1.0 Now, lets calc:
z_p = (1.0*1000.0/(1000.0)-2.0*0.1*1000.0/(1000.0-0.1))/1.0
/// I put 1000-0.1 = 1000.0
z_p = 1.0 - 2.0*0.1 = 0.8


I hope this is clear enough. But as you can see, the view space z=1.0 value maps to the depth value of z_p=0.8. If you use z=2.0, then z_p=0.9!!!! So what happening here? My depth buffer's values are defined within the space [0.8,1.0] What did I do wrong, or whats wrong with the projection matrix? Thanks Alex

Share this post


Link to post
Share on other sites
The depth buffer isn't linear and thus precision is highest at the front. Thus, depth values can raise quickly, especially if your far/near ration is high (1000 / 0.1 = 10000 in your case). See this.

Share this post


Link to post
Share on other sites
Hi and thanks.

But even if I use n=1.0 and f=100.0, the depth buffer values are still too bright!
If I put n=10.0, then the depth values are looking good.
Even with n=5.0, I get quite good results.

So, what are good values for n and f?
What do you putting those values at?

I mean, if n=10.0, then objects can never reach the camera!
This looks rather ugly.

Thanks
Alex

P.S.
I use 32 bit float depth buffer!

Share this post


Link to post
Share on other sites
Still not lucky.

Cant fix it. Is opengl doing any transformation to the z value afterwards?

And I dont realy see the relation to the precision here, because the formula still puts the depth values to the end of the depth range. See calculation I put down before.

Thanks

P.S.
I use a FBO's depth attachment to write out depth values, i.e. its written out automatically by ogl.

Share this post


Link to post
Share on other sites
As Lord_Evil told you, the values in depth buffer are not linear. They're stored as 1.0/z, from near to far plane. If you want to get the z, you need to invert each value you'll get ( 1.0/(1.0/z) == z ).

Share this post


Link to post
Share on other sites
ok. I think I couldn't point out whats wrong.

Imagine the camera is at origin. Since I use LH-Coords, z>0.

View matrix:
-------------
So the view matrix V ist the identity matrix. So it follows, that an object in world space is also in view space without transformation.

Projection matrix:
-------------
I use the projection matrix P noted above. This matrix can be found in Real Time REndering, at d3d website, in 3D Computer Graphincs(Watt) book, and many other places.

Lets do some numerical math:
-----------------------------

p: Point in projection space
v: vertex in view space.

p = P * v

View space vectors are column space and w=1.0.

Lets put v=[0.0f,0.0f,5.0f], far=100.0, near=1.0, fov=pi/4, aspect=...

This gives for v.z=5 in view space:
p = [0,0,4.04...,5.0]
After homo.div. p.z = 0.90...
----------------------------------------
Lets put v=[0.0f,0.0f,10.0f], far=100.0, near=1.0, fov=pi/4, aspect=...

This gives for v.z=10 in view space:
p = [0,0,9.09...,10.0]
After homo.div. p.z = 0.909...
----------------------------------------
Lets put v=[0.0f,0.0f,1.5f], far=100.0, near=1.0, fov=pi/4, aspect=...

This gives for v.z=1.5 in view space:
p = [0,0,0.5...,1.5]
After homo.div. p.z = 0.336...

As you can see, the projected z values(i.e. the depth buffer values) are quickly approaching 1.0!!! Is this correct?

Ok, the depth buffer values is fine graind at the beginning, but is this wanted?
Shouldn't those values be scaled?

I mean, what are those depth values worth, if I just have good precision in depth range from 1.0-2.0 and than from 2.0-100.0, the values are nearly the same?

[Edited by - directNoob on August 19, 2009 7:47:44 PM]

Share this post


Link to post
Share on other sites
To ultimately show you what I mean. Here are the pics.

BadDepth
Here is the image where the untouched depth values are visualized.
The pixel shader is:

uniform sampler2DShadow texDepth ;

void main()
{
float fDepth = shadow2D( texDepth, vec3(gl_TexCoord[0].xy,1.0) ).r;
gl_FragColor = vec4(fDepth);
}



No depth comparision is done.

Now, here is the good depth buffer:
Good Depth

The shader here is:

uniform sampler2DShadow texDepth ;
void main()
{
float fDepth = pow(shadow2D( texDepth, vec3(gl_TexCoord[0].xy,1.0) ).r,15.0) ;
gl_FragColor = vec4(fDepth);
}




As you can see, I need to power the read depth values up!
I dont need the z value itself. I just need the depth buffer values in range
[0.1].

Can someone please explain if this is the usual way or if it is possible to get the "corrected" depth buffer values from opengl itself via useing depth textures with GL_DEPTH_COMPONENT, instead of using a self backed color-depth-texture or the shader approach by pow up the values.

I dont use the texture comparison mode. So shadow2D is just returning the depth value itself. I mean


glTexParameteri(tt, GL_TEXTURE_COMPARE_MODE, GL_NONE ) ;





Would be nice if someone could clarify whats going on!

Thanks
Alex

P.S.
Oh yes, near=0.1, far=1000.0 at both pictures.
Its nearly the same for near=1.0f.

I dont want to use larger near values! Bacause this clipps the geometry away!

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