Orthographic Projection

In video games, we need to take a three dimensional scene and project it into two dimensions so it can be displayed on the screen. There are two main options for this:

Perspective Projection: Objects further from the camera are rendered proportionally smaller than objects closer to the camera. This is how objects appear in reality when observed with the human eye, and so is more often used in 3D rendering. We will explore perspective projection further below.
Orthographic Projection: Distance from the camera does not affect rendered size. Orthographic projections keep parallel lines parallel and faithfully represent distances. This makes them ideal for technical drawings. Orthographic projections and similar are also used in video games where 3D objects are only intended to be viewed from a small number of directions and so are stored as pre-drawn (e.g. pixel art) 2D images. With orthographic projection, these 2D images look correct regardless of how near or far the object they represent is from the camera, and so they don't need to be awkwardly stretched or shrunk. Notice when drawing the cube below, opposite faces are exactly the same size, despite one being further from the plane than the other.

Orthographic projection is also incredibly simple to implement, provided we're projecting along one of the axes: just ignore that coordinate! For instance, we can project along the z-axis by just taking the x- and y- coordinates of our points and ignoring the z-coordinate.

Rotate the shape with the controls below:
angle_x:
angle_y:
angle_z:
Click and drag to rotate scene or use controls below:
world_x:
world_y:
Shape:

Perspective Projection

When we think of 3D computer graphics, we often don't think of orthographic projection; we think of perspective projection, which simulates looking at a scene through an eyeball or camera, some device where the rays of light are all focused through a single point. To produce this sort of visual, we need to divide the x and y coordinates of our points by their distance from the camera (assuming this is the z-direction).

Intution Behind the Perspective Divide

It's worth taking a moment to understand why we need to do this division. The rough intuition is this: imagine a scene with two trees in it, both exactly the same height, but one closer to the camera, and one farther away. The farther away tree will be drawn smaller (a smaller difference in on-the-page y-coordinates between the top and bottom) corresponding to a larger z distance from the camera.

We can get a more exact intuition by drawing out our scene and the rays of light that hit the camera, as in the interactive below. The point in the center of the canvas where the dotted lines converge is the camera and the square in front of it is called the picture plane. Each point on the 3D object being rendered could just as easily be drawn where its ray of light intersects the picture plane and it wouldn't look any different to the camera: the angles where each light-ray comes into the camera would be the same. And so we find ourselves interested in calculating, for each point P in our 3D scenes, where the line between P and our camera intersects the picture plane. This may seem like a gross calculation, but it's actually not so bad if we make use of similar triangles. Once you've oriented yourself to the scene below, check the "Show triangle" box and click the "Side View" button to see the similar triangles. Here,

Note that the 3D object itself might have ideas about what coordinate system it wants to use to describing its points, usually in terms of its own center to make rotations easy to calculate. But here, y and z are given relative to the camera.We can now use similar triangles to calculate y' in terms of the other values.

The Perspective Divide with Vectors

We can get a clearer intuition if we use vector notation and set the camera to be located at the origin. Check the "Show vector" box (you can uncheck the "Show triangle" box) to draw the vector from the origin to the chosen vertex.

By playing around with the scale factor, convince yourself that the point on the picture plane corresponding to our vertex is a scaling of our original vector.

We also know that points on the picture plane have a z coordinate of -1. Check "Show" and "Label" under "Axes" to show the coordinate axes. Since we are using a right-handed coordinate system with y cooresponding to up on the canvas and x corresponding to right on the canvas, z has to be out of the page, toward the area behind the camera. As such, the picture plane will have a negative z coordinate, and we may as well choose that coordinate to be -1 for simplicity.

So, we're looking for a rescaled version of the vector (x,y,z) whose z coordinate is -1. What do we need to multiply all the components of (x,y,z) by to make the z coordinate be -1?

Picture Plane: Draw
Axes: Draw Label
Rotate the shape with the controls below:
angle_x:
angle_y:
angle_z:
transl_x:
transl_y:
transl_z:
Click and drag to rotate scene or use controls below:
world_x:
world_y:
Shape:
For vertex :
Show triangle x: Label Highlight
y: Label Highlight
z: Label Highlight
Show vector Scale factor: