Abstracting the Eye
One stop on the graphics pipeline is eye space, the coordinate system in which the viewer's eye is assumed to be at the origin looking down the negative z-axis. We learned that this space is convenient for lighting. In particular, by having the eye at \(\begin{bmatrix}0&0&0\end{bmatrix}\), we simplify the calculation of a fragment's specular term, which requires a vector from the fragment to the eye. However, parking the eye permanently at the origin and fixing its gaze to the negative z-axis is limiting. Must we arrange the whole world around the inflexible eye? That seems backward. Isn't the eye just another entity in the world like the models? We want to be able to place the eye anywhere in the world and have it look in any direction.
We open up all of world space to the viewer through a camera abstraction. The camera is positioned at an arbitrary location and oriented so it points in any desired direction. The abstraction builds a translation matrix that turns the camera's location into the origin. It also builds rotation matrix that turns the line of sight into the negative z-axis.
In this chapter we will learn how to build this abstraction and move it around on a terrain. By its end, you will be able to answer the following questions:
- How do we position and orient the eye in the world of a renderer?
- What mouse and keyboard behaviors does a first-person camera abstraction support?
- How can a third-person camera be attached to a model and follow it around?
- How is terrain data represented, reconstructed into geometry, and navigated by a camera?
The camera abstractions that we'll build are something of an illusion, just like the orthographic and perspective projection matrices. None of these change the fundamental fact that WebGL only renders whatever's inside the unit cube centered at the origin. The abstractions just make us think that the world is bigger and that the eye is mobile. In truth, they just build matrices that transform the chunk of the world that we want to see into the small box that WebGL expects.