Difference between revisions of "Compute eye space from window space"

From OpenGL.org
Jump to: navigation, search
(First pass of this page.)
 
(Categorizing)
Line 79: Line 79:
  
 
Therefore, we must find a way to compute it from the window-space XYZ coordinate and the perspective projection matrix. This discussion will assume that your perspective projection matrix is the standard OpenGL perspective matrix, as produced by {{code|glFrustum}} or {{code|gluPerspective}}. If you are using a different matrix, you may need to change this math accordingly.
 
Therefore, we must find a way to compute it from the window-space XYZ coordinate and the perspective projection matrix. This discussion will assume that your perspective projection matrix is the standard OpenGL perspective matrix, as produced by {{code|glFrustum}} or {{code|gluPerspective}}. If you are using a different matrix, you may need to change this math accordingly.
 +
 +
[[Category:Algorithm]]

Revision as of 19:47, 24 February 2012

This page will explain how to recompute eye-space vertex positions given window-space vertex positions. This will be shown for two cases. Case 1 uses gl_FragCoord​ in its entirety. Case 2 uses only gl_FragCoord.xyz​. Both require access to the projection matrix.

Definitions

Before we begin, we need to define some symbols:

Symbol Meaning
M The projection matrix
P The eye-space position, 4D vector
C The clip-space position, 4D vector
N The normalized device coordinate space position, 3D vector
W The window-space position, 3D vector
Vx, y The X and Y values passed to glViewport
Vw, h The width and height values passed to glViewport
Dn, f The near and far values passed to glDepthRange

From gl_FragCoord

gl_FragCoord​ contains the window-space position Pwnd. This is a 3D vector quantity. gl_FragCoord.w​ however contains the inverse of the clip-space W: gl\_FragCoord_{w}={\tfrac  {1}{C_{w}}}.

Given these values, we have a fairly simple system of equations:

{\begin{aligned}{\vec  N}&={\begin{bmatrix}{\tfrac  {(2*W_{x})-(2*V_{x})}{V_{w}}}-1\\{\tfrac  {(2*W_{y})-(2*V_{y})}{V_{h}}}-1\\{\tfrac  {(2*W_{z})-D_{f}-D_{n}}{D_{f}-D_{n}}}-1\end{bmatrix}}\\{\vec  C}_{{xyz}}&={\frac  {{\vec  N}}{gl\_FragCoord_{w}}}\\C_{{w}}&={\frac  {1}{gl\_FragCoord_{w}}}\\{\vec  P}&=M^{{-1}}{\vec  C}\end{aligned}}

In a GLSL fragment shader, the code would be as follows:

vec4 ndcPos;
ndcPos.xy = ((2.0 * gl_FragCoord.xy) - (2.0 * viewport.xy)) / (viewport.zw) - 1;
ndcPos.z = (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) /
    (gl_DepthRange.far - gl_DepthRange.near);
ndcPos.w = 1.0;
 
vec4 clipPos = ndcPos / gl_FragCoord.w;
vec4 eyePos = invPersMatrix * clipPos;

This assumes the presence of a uniform called viewport​, which is a vec4​, matching the parameters to glViewport, in the order passed to that function. Also, this assumes that invPersMatrix​ is the inverse of the perspective projection matrix (it is a really bad idea to compute this in the fragment shader). Note that gl_DepthRange​ is a built-in variable available to the fragment shader.

From XYZ of gl_FragCoord

This case is mostly useful for deferred rendering techniques. In deferred rendering, we render the material parameters of our objects to images. Then, we make several passes over these images, loading those material parameters and performing lighting computations on them.

In the light pass, we need to reconstruct the eye-space vertex position in order to do lighting. However, we do not actually have gl_FragCoord​; not for the fragment that produced the material parameters. Instead, we have the window-space X and Y position, from gl_FragCoord.xy​, and we have the window-space depth, sampled by accessing the depth buffer, which was also saved from the deferred pass.

What we are missing is the original window-space W coordinate.

Therefore, we must find a way to compute it from the window-space XYZ coordinate and the perspective projection matrix. This discussion will assume that your perspective projection matrix is the standard OpenGL perspective matrix, as produced by glFrustum​ or gluPerspective​. If you are using a different matrix, you may need to change this math accordingly.