-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmath.tex
84 lines (50 loc) · 3.09 KB
/
math.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
How to go from device coordinates back to worldspace in OpenGL (with explanation)
\documentclass{article}
\usepackage{hyperref}
\begin{document}
So you're writing a 3D engine or somesuch in OpenGL (modern or legacy), and you're not a beginner
so you know that the worldspace coordinates get transformed using your modelview/projection matrix (which
we'll treat as one for the purpose of this article) into clip space, which gets transformed by the
perspective division into normalized device coordinates.
If you don't, go read \url{http://unspecified.wordpress.com/2012/06/21/calculating-the-gluperspective-matrix-and-other-opengl-matrix-maths/}, it's really good.
So you end up with $x$, $y$ and $z$ (depth buffer) values; that is, device coordinates.
But for some occasions, like shadow mapping or deferred lighting, it's useful to do this transformation
backwards - going from device coordinates back to worldspace. In this article, I'm going to walk you
through the math of it.
Let's start with what we have. We start out with our world space position, $world$. \textbf{Note that $world_w$
is assumed to be 1} - for the rationale, see the article linked above.
We transform it to clip space by multiplying it with our projection/modelview matrix.
$$clip = Matrix\text{ }world$$
Then move on to device coordinates by dividing with $w$.
$$device = clip_{xyz} / clip_w$$
So the problem we face is: given $clip = Matrix\text{ }world$, $device = clip_{xyz} / clip_w$, $world_w = 1$,
and given $device$ as an input and $Matrix$ as a constant, calculate $world$.
Let's walk through it. Invert the first step:
$$Matrix^{-1}\text{ }clip = Matrix^{-1}\text{ }Matrix\text{ }world$$
$$Matrix^{-1}\text{ }clip = world$$
Now let's see what we can do with the second equation.
$$device = clip_{xyz} / clip_w$$
$$clip_w\text{ }device = clip_{xyz}$$
Let's use this syntax to indicate a 4-vector formed by combining a 3-vector and a fourth number:
$$clip = clip_{xyzw} = (clip_{xyz}, clip_w)$$
substitute $clip_{xyz}$
$$clip = (clip_w\text{ }device, clip_w)$$
insert into our earlier equation
$$Matrix^{-1}\text{ }clip = world$$
$$Matrix^{-1}\text{ }(clip_w\text{ }device, clip_w) = world$$
$$Matrix^{-1}\text{ }clip_w\text{ }(device, 1) = world$$
And note that since matrices are linear transforms, we can pull that $clip_w$ in front of the matrix multiply:
$$clip_w\text{ }Matrix^{-1}\text{ }(device, 1) = world$$
So it seems we run into a wall. $clip_w$ is lost, right? Don't give up hope: we haven't used the
third of our initial givens yet.
$$world_w = 1$$
So let's look at just the $w$ component of that last equation there:
$$clip_w\text{ }\left(Matrix^{-1}\text{ }(device, 1)\right)_w = world_w = 1$$
Divide:
$$clip_w = \frac 1 {\left(Matrix^{-1}\text{ }(device, 1)\right)_w}$$
And insert into the equation that previously gave us trouble:
$$\frac{Matrix^{-1}\text{ }(device, 1)}{\left(Matrix^{-1}\text{ }(device, 1)\right)_w} = world$$
Or in other words:
$$\left(Matrix^{-1}\text{ }(device, 1)\right)_{xyz/w} = world\text{ ... and done.}$$
You've probably seen that equation in shader code before. Well, now you know why.
\end{document}