When transforming vectors by matrices the w component has the effect of scaling the translational component of your matrix. Consider the vanilla transformation matrix encountered while doing graphics work:
| ux vx nx tx| |x| |(x y z) dot (ux uy uz) + tx*w|
| uy vy ny ty|* |y| = |(x y z) dot (vx vy vz) + ty*w|
| uz vz nz tz| |z| |(x y z) dot (nx ny nz) + tz*w|
| 0 0 0 1| |w| | w|
The rotation and scale of the matrix is stored in the u, v, and n vectors and the translational component is stored in the t vector. As you can in the right-hand-side the (x y z) components of the original vector where translated by w*t. For directions w is set to 0 (or implicitly interpreted as 0) since translations are irrelevant to directions. For points w is set to 1 (or implicitly interpreted as 1) treating the translation as expected.
Now for the good stuff. Consider multiplying a point by a projection matrix:
| sx 0 0 0| |x| |x*sx |
| 0 sy 0 0|*|y| = |y*sy |
| 0 0 sz tz| |z| |z*sz + tz|
| 0 0 1 1| |1| |z |
The right-hand-side is the data spit out by your vertex shader. For various mathematical reasons that I won't get into the GPU will clip data against the view frustum in this space and it is thus called clip space. To apply perspective some magic happens, the right-hand-side gets homogenized or divide by its w component:
H( |x*sx | ) = | (sx*x) / z |
|y*sy | | (sy*y) / z |
|z*sz+tz| | (sz*z+tz) / z |
|z | | 1 |
From here the right-hand-side is said to be in NDC or normalized device coordinates. The z component gets directly written to the depth buffer, the x and y component are scaled and biased to generate pixel coordinates and the w component is simply discarded (it will always be 1).
If you are hand setting the w value of your vertex in the vertex shader you must take into account that the GPU will divide (x, y, z) by w to generate NDC coordinates.
 I don't know what all that whitespace is...I can't get rid of it
Edited by nonoptimalrobot, 20 August 2013 - 04:09 PM.