Camera projection matrix

I posted a gist on GitHub where I was playing with modifying the projection matrix for the camera in Unity.

For background, a matrix is basically a grid of numbers. A vector is a series of numbers. And you can multiply a vector by a matrix you transform that vector in some way, as defined by the matrix. For 3D graphics, you can depict a position in space as a vector and use a projection matrix to decide where that position will appear on the screen.

In normal operation in Unity, you set some parameters like the field of view and near and far clipping planes, and it auto-calculates the projection matrix for the camera.

This shows an example of shifting a tilt-shift lens to photograph a building while keeping parallel vertical lines. You can do the same thing with the projection matrix.

I think that would be suited to some games. See here, you could have a top-down camera that’s viewing the floor completely parallel to the screen, while keeping the vanishing point below the screen.

You might also use it in a platformer. For aesthetics, a lot of landscape photographers and painters prefer to have the horizon a third from the top or bottom, rather than half-way. This would allow you to do that, while keeping the vertical and horizontal lines square.

For these scenarios, I made a OnePointPerspective script. I guess I called it that because it made me think of drawing with a single point of perspective. Unity does have a lensShift property that does a similar thing, but my script also offsets position to compensate and keep the camera aimed at a given subject.

I also made a ZoomInOffset script which is geared towards zooming into a particular portion of the screen. Here you can see the original view, one where I rotate the camera to zoom in on the chef, and one where I use ZoomInOffset. Note it keeps the checkers oriented the same, while rotating the camera doesn’t.

I’ve seen people make the incorrect claim that rotating a camera at a single point will be indistinguishable from panning an image. This example shows how that isn’t quite true.

( It does work when viewing with the human eye, because the human eye doesn’t need to be displayed on a flat surface, so you don’t have single vanishing points like you do in linear perspective. But that’s another discussion. )

You can do a lot of other stuff, many of which will be disorienting. You can, for example, make things get larger in the distance instead of smaller, but I find in practice it makes me feel like everything has reversed normals.

( This is maybe where I get into James J. Gibson’s The Ecological Approach to Visual Perception where you perceive underlying 3 dimensional invariants based on correlated transformations. When multiple things on screen transform simultaneously, you respond to how those transformations correlate to one another. What people will probably be familiar with is parallax. Something near the “camera” moves quickly while something far away moves slowly, and that helps you perceive one as near and the other as far. The projection matrix is very much creating these sorts of correlations, so when the correlation was backward, such that distant things were larger, my brain instead perceived them as closer. )

Anyway, towards the end of experimenting with projection matrices, I made some more free-form scripts. ProjectionMatrixExperiments and ProjectionReplace. Both let you apply Translate, Rotate and Scale transformations, but ProjectionReplace also lets you adjust individual elements in the matrix.

Although I described the Matrix as a grid, Unity displays it like this. You can figure out where each number goes in the grid based on the name. E13 would go in column 1, row 3.

So if you play around with that, you too could make cameras like this:

This entry was posted in uncategorized. Bookmark the permalink.

Comments are closed.