How to perform inverse transformations in GLSL?

I have read:

matrix - Screen space coordinates to Eye space conversion - Computer Graphics Stack Exchange

In the posting it is stated:

  • You get from Window Space to Normalized Device Space by performing the inverse of the Viewport and Depth Range transform.

  • You can get from Normalized Device Space to Clip Space by performing the inverse of the perspective divide (multiply by w). This is a non-linear transformation requiring a multiply, and is not represented by a matrix. In general this operation doesn’t magically recover 3D data from 2D data. You must know something about the depth externally to be able to recover the 3D position of a point on the 2D screen.

Could I see an example of what those two inverse transformations look like in GLSL language as far as how to perform them with GLSL as far as window space to NDC and NDC to clip space?

Window space to NDC is:

xNDC = 2*(xwin - viewport.x)/viewport.width - 1
yNDC = 2*(ywin - viewport.y)/viewport.height - 1
zNDC = 2*depth - (gl_DepthRange.near + gl_DepthRange.far) / gl_DepthRange.diff

You can’t recover clip coordinates from NDC because projective division loses information; clip space has 4 components, NDC only has 3.

If you’re trying to re-create the texture-mapping calculation, you can recover barycentric coordinates given the clip-space x, y and w coordinates for the three vertices of a triangle plus the window-space (or NDC) x and y coordinates of a point within a triangle. From there, you can recover the clip-space z coordinate or any other attribute value obtained by interpolation.

If (α,β,γ) are barycentric coordinates subject to α+β+γ=1, and (x1,y1,z1,w1), (x2,y2,z2,w2) and (x3,y3,z3,w3) are the vertices of a triangle, then

\begin{pmatrix}x_{clip} \\ y_{clip} \\ w_{clip} \end{pmatrix} = \begin{pmatrix}x1 & x2 & x3 \\ y1 & y2 & y3 \\ w1 & w2 & w3 \end{pmatrix} \begin{pmatrix}\alpha \\ \beta \\ \gamma \end{pmatrix}

(note that we don’t care about Z here). Given clip-space x,y,w, we can recover barycentric coordinates using the inverse of the above 3×3 matrix:

\begin{pmatrix}\alpha \\ \beta \\ \gamma \end{pmatrix} = \begin{pmatrix}x1 & x2 & x3 \\ y1 & y2 & y3 \\ w1 & w2 & w3 \end{pmatrix}^{-1} \begin{pmatrix}x_{clip} \\ y_{clip} \\ w_{clip} \end{pmatrix}

The transformation from clip-space to NDC is just

xNDC = xclip / wclip
yNDC = yclip / wclip

Note that we can’t recover clip coordinates from NDC because the transformation loses information. However, we can say that

xclip = wclip xNDC
yclip = wclip yNDC

without actually knowing the value of wclip. And from that:

\begin{aligned} \begin{pmatrix}\alpha \\ \beta \\ \gamma \end{pmatrix} & = \begin{pmatrix}x1 & x2 & x3 \\ y1 & y2 & y3 \\ w1 & w2 & w3 \end{pmatrix}^{-1} \begin{pmatrix}w_{clip} \, x_{NDC} \\ w_{clip} \, y_{NDC} \\ w_{clip} \end{pmatrix} \\ & = w_{clip} \begin{pmatrix}x1 & x2 & x3 \\ y1 & y2 & y3 \\ w1 & w2 & w3 \end{pmatrix}^{-1} \begin{pmatrix}x_{NDC} \\ y_{NDC} \\ 1 \end{pmatrix} \\ & = w_{clip} \begin{pmatrix}\alpha' \\ \beta' \\ \gamma' \end{pmatrix} \\ \text{where} \\ \begin{pmatrix}\alpha' \\ \beta' \\ \gamma' \end{pmatrix} & = \begin{pmatrix}x1 & x2 & x3 \\ y1 & y2 & y3 \\ w1 & w2 & w3 \end{pmatrix}^{-1} \begin{pmatrix}x_{NDC} \\ y_{NDC} \\ 1 \end{pmatrix} \end{aligned}

And wclip can be found from the fact that α+β+γ=1

=> wclip = 1/(α’+β’+γ’).

1 Like