Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


[Depth buffer] From linear -> non-linear depth values


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
7 replies to this topic

#1 JoeyDewd   Members   -  Reputation: 543

Like
0Likes
Like

Posted 20 July 2014 - 02:38 PM

I'm currently trying to figure with what equation the non-linear depth value of the fragment's gl_FragCoord.z value is calculated. I know how to transform the fragment's depth values back to their linear equivalent, but I couldn't find any good resource on the reverse operation.

 

Currently my shader uses the following function to transform the gl_FragCoord's z-component to its linear variant, but what equation is used for transforming from the linear to the non-linear value? So from view-space z value --> screen-space z value.

 

Shader code:

float LinearizeDepth(float depth)
{
  float near= 0.1; // camera z near
  float far = 100.0; // camera z far
  float z = depth * 2.0 - 1.0; // Back to NDC 
  return (2.0 * near) / (far + near - z * (far - near));	
}

void main()
{             
    float depth = LinearizeDepth(gl_FragCoord.z);
    // <-- Some equation that transforms it back to the original gl_FragCoord.z value?
    color = vec4(vec3(depth), 1.0f);
}

Any insight would be appreciated.



Sponsor:

#2 Waterlimon   Crossbones+   -  Reputation: 2596

Like
3Likes
Like

Posted 20 July 2014 - 02:58 PM

You should be able to just do the inverse operations in the exact reverse order to do that (+ becomes -, / becomes * and apply operations in reverse order)


o3o


#3 JoeyDewd   Members   -  Reputation: 543

Like
0Likes
Like

Posted 20 July 2014 - 03:37 PM

Hey Waterlimon,

 

That makes sense though, although I never really polished any of my algebraic skills (should probably start doing that soon). 

I've switched the operators, and applied the operations in reverse order. I then return the (supposed to be) original value of the depth buffer, but the visual output is an all white terrain where the depth value does not seem to get any less than 1.0 (used to do that) so it's probably not correct:

float near= 0.1; // camera z near
float far = 100.0; // camera z far
float z = depth * 2.0 - 1.0; // Back to NDC 
float dep = (2.0 * near) / (far + near - z * (far - near));	
float v = (far + near / (far - near + dep)) * (2.0 / near);
return (v + 1.0) / 2; // Back to [0,1] range.

Is there any error I made with the inversion of the function?



#4 MJP   Moderators   -  Reputation: 11567

Like
1Likes
Like

Posted 20 July 2014 - 04:58 PM

You can also just apply your original projection matrix and then divide the result by w



#5 JoeyDewd   Members   -  Reputation: 543

Like
0Likes
Like

Posted 21 July 2014 - 04:29 AM

Retrieving the result via the original projection matrix is an option yes, but for educational purposes I was interested in the equation.

I managed to retrieve the inverse equation for the linear -> non-linear case:

z_non_linear = -((near + far) * z_linear - (2 * near)) / ((near - far) * z_linear)

Testing the equation on a single test value should eventually return the same value which it does:

z = 0.9, near = 0.1, far = 100
z_linear = 0.2 / (100.1 - 0.9 * 99.9) = 0.01962708537782143   // from non-linear -> linear
z_non_linear = -(100.1 * 0.01962708537782143 - 0.2) / (-99.9 * 0.01962708537782143) = 0.9   // from linear -> non-linear
So the equation works out :) Although I'm not sure if there are any more simplifications left to make the function a bit more aesthetically pleasing?
 
Thanks for the help


#6 Jason Z   Crossbones+   -  Reputation: 5147

Like
1Likes
Like

Posted 22 July 2014 - 04:52 AM


Retrieving the result via the original projection matrix is an option yes, but for educational purposes I was interested in the equation.
This is obtained by using the original projection matrix, and just taking the z component.  As long as you know how your projection matrix is constructed, then you would have the symbolic equivalent of your equation quickly and easily!

#7 JoeyDewd   Members   -  Reputation: 543

Like
0Likes
Like

Posted 22 July 2014 - 04:55 AM

Yeah, I'll be sure to invest some time into properly understanding the projection matrix's inner workings. That'll save me questioning this kind of stuff smile.png



#8 JohnnyCode   Members   -  Reputation: 259

Like
0Likes
Like

Posted 22 July 2014 - 07:13 PM

Try to multiply view matrix with projection matrix by hand and see the 4th row of the result- the w component construting row. You will notice it just contains the third view matrix row in the very resulted matrix 4th row:

 

view matrix   projection matrix

[a,b,c,p1    ]  

[a,b,c,p2    ]

[vx,vy,vz,vp]         BLA

[0,0,0,1      ]         [0,0,1,0]

 

if we consider column matricies and multiplication order  , then we multiply view column with projection row.

 

first component in 4th row of result:

[a,a,vx,0]*[0,0,1,0]=vx

 

second component in 4th row of result:

[b,b,vy,0]*[0,0,1,0]=vy

 

third component in 4th row of result:

[c,c,vz,0]*[0,0,1,0]=vz

 

fourth component in 4th row of result:

[p1,p2,vp,1]*[0,0,1,0]=vp

 

thus, bottom 4th row of view*projection matrix is actualy the third row of the view matrix.

 

If a vector gets tranformed by this matrix, it actualy remembers its previous pre-projection transformations z component in its final w component. That is  the linear z- the w komponent.

 

And the final vector that gets rasterized (depth tested and so on )is (x/w,y/w,z/w,w) - this should be glFragCoord value, but of course interpolated across triangle after vertex function.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS