4
\$\begingroup\$

I am trying to implement do some screen space rendering but after looking over the web I still don't find answers to some doubts.

First, I need to compute the point in view space from a value in the depth buffer.

  1. View-space means the camera-space or the clip-space?

I also found that, inverting the projection transformation I can get a point from the depth with a formula like

P(x,y) = [(2x/Vx-1.0)/Fx , (2y/Vy-1.0)/Fy , 1] * z(x,y)

where Vx/Vy are the dimensions of the viewport and Fx/Fy are the focal lengths

  1. I don't understand where does this formula comes from, if I have it correctly the perspective projection formula is different. Can someone explain me this?
  2. A point in view-space is a 3D-point, but why is the third coordinate 1?
\$\endgroup\$
1
  • 2
    \$\begingroup\$ View-space means "camera-space" or often "eye-space". Clip-space is actually the coordinate space that results after multiplying eye-space coordinates by the projection matrix. It is what you output in a vertex shader, but pretty much immediately after you output clip-space coordinates, GL will divide them by W to go from clip-space to NDC-space. The thing is... the depth buffer stores window-space Z, that's actually an additional step beyond NDC-space - it relies on your glDepthRange (by default NDCz -1 maps to window-space 0.0 and NDCz 1 maps to window-space 1.0). \$\endgroup\$ Dec 7 '14 at 19:42
4
\$\begingroup\$

1: camera space, like Andon said.

2: the projection matrix contains those Fx,Fy values (f and f/aspect) at cells [0][0] and [1][1] see https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml

2x/Vx-1.0 is to convert from screen pixel coordinates which are from (0, 0) to (WIDTH, HEIGHT) to 3D projected coordinates that are from -1 to 1.

3: the "real" formula is

P(x,y) = [(2x/Vx-1.0)/Fx * z(x,y), (2y/Vy-1.0)/Fy * z(x,y), z(x,y)]

Because the x,y coordinates are divided by z when projected to the screen, you need to multiply by z to retrieve the 3D position.

Putting 1 as the 3rd value and multiplying the whole vector by z is shorter to type.

if I remember correctly, with x and y being the -1 to 1 screen coordinates, z being the depth buffer value:

vec4 temp = vec4(screen_x, screen_y, depth_buffer_value, 1);
temp *= projection_inverse;
vec3 camera_space = temp.xyz / temp.w;
vec3 world_space = camera_space * view_inverse; // if needed

depending on glDepthRange (or Direct3D equivalent) you might need to adjust depth_buffer_value if you changed the range and/or how the depth buffer values are sampled.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .