Standard Perspective Matrix¶
Purpose¶
Derive the standard perspective matrix that OpenGL expects.
Description¶
Matrix form of perspective projection¶
Scale Camera-space x by Camera-space z¶
resulting in
Scale Camera-space y by Camera-space z¶
resulting in
Translate Rectangular Prism’s Center to Center¶
// centered on x
// centered on y
;
Scale by inverse of the dimensions of the Rectangular Prism¶
;
;
;
Pre-multiply the matricies¶
Multiply them all together to get the following. The elements of this premultiplied matrix have no geometric meaning to the author, and that’s ok. The matricies above all of geometric meaning, and we premultiply them together for computational efficiency, as well as being able to do the next step in clip space, which we couldn’t do without having the premultiplied matrix.
As a quick smoke test to ensure that the aggregate matrix works correctly, let’s test the bounds of the frustum and make sure that they map to the NDC cube.
Given that is negative, assuming is equal to , goes to , which is goes to .
Given that is negative, assuming is equal to , goes to , which is goes to .
Given that is , if , . Given that is , if , .
Clip Space¶
convert the data from NDC to clip-space.
We have never used clip-space in the class, only NDC, because 4D space is confusing geometrically, nevermind the fact that (NDCx NDCy NDCz) = (Clipx/Clipw, Clipy/Clipy, Clipz/Clipz)
The purpose of going to clip space is that eventually we will be able to remove the camera space’s z coordinate from the matrix. This will allow us to use one perspective projection matrix for all vertices, independent of the z coordinate of each input vertex.
I assume, without any evidence to support me, that this was done for efficiency reasons when using OpenGL’s fixed function pipeline. (Side note, the standard perspective projection matrix, which we will get to by demo 25, does not linearly position the to data into NDC. Everything we’ve done so far in the class does. The standard perspective matrix ends up having less Z-fighting close to , and more problems with Z-fighting near farZ_c)
OpenGL will automatically convert from clip space to NDC such as follows.
So to put our NDC data into clip space, knowing what OpenGL is going to do in the equation above, we need to decide what we want our clip space value, to be, and do the inverse of the equation above
Since we want to get the relative to camera space out of the premultiplied matrix above, we choose the following
because multiplying by this matrix will remove the out of the upper left quadrant.
Remove Z of Camera Space from Part of the Matrix¶
To get camera z out of the matrix, where it’s currently in two denominators, we can use knowledge of clip space, wherein we put cameraspace’s z into W. because cameraSpace’s z coordinate is negative, we want to scale all dimensions without reflecting over the origin, hence the negative sign in .
The result of this is in clip space, where for the first time, our w component is not 1, but .
Turning clip space back into NDC
To test a corner of the frustum as a smoke test, say
And that’s what we’d expect and the top right corner of the near plane of the frustum should go to the upper right corner with a z value of 1, as -1 is where the back plane must go.
If we had used , then , which is what we want, as negative axis goes into the monitor.
Remove Z of Camera Space from the Rest of the Matrix¶
We successfully moved out of the upper left quadrant, but in doing so, we moved it down to the lower right. Can we get rid of it there too? Turn out, we can.
Since the vector multiplied by this matrix will provide as it’s third element, we can put into the by taking the explicit version of it out of the fourth column, and put into the third column’s .
To remove from the matrix, all that to do is remove it from row 3, somehow. We’re about to ride dirty.
If we were to change row three, it would not be the same transformation. But if we ensure the following two properties of our changes, everything will be alright
We need the
Ordering is preserved after the function is applied, i.e. monotonicity. if , then .
If we can make a function, that like the third row of the matrix, has those properties, we can replace the third row and remove camera space’s z, , from the matrix. This is desirable because, if it were to exist, would would not need per vertex to create a custom perspective matrix.
Towards that, let’s look at these jibronies.