Sunday, August 4, 2013

A Grand Adventure - Perspectives and Projections

The past few weeks or so I've begun a conquest to teach myself OpenGL graphics programming. It occurred to me that I should probably be sharing this experience. I have a fairly limited knowledge of lower level graphics and, although I intend to change it shortly, linear algebra. I have some basic knowledge of each, but not enough to do anything all that exciting. What I intend to do with this and potential future entries is to explain the concepts of graphics programming in a more intuitive sense. I'm less worried about the mathematics behind it. Although it is incredibly important, sometimes intuition should lead to the mathematics, rather than the mathematics leading to intuition.

The first stop on this journey will try to go into some detail about the viewing plane. Since computers and other output devices are two dimensional, well, this makes it a bit of a challenge for 3D graphics. OpenGL handles a lot of the math for us. We provide the world in three dimensional coordinates, but the world is then projected onto the two dimensional screen.

First, I'd like to give a small overview on a basic and inherently intuitive concept of depth that we all share. For example, if you have two objects, and one is "in front" of the other, how would you see this in real life? Think of two tree's, one nearby and one further away. The tree further away would appear smaller then the tree in front of the other. Further, the tree closer could obstruct part of the view of the one further away. This is the magic of depth.

There are two primary modes of rendering in OpenGL that project onto the screen differently. There's orthogonal mode and perspective mode. I'll start with orthogonal since that's really what we deal with intuitively using the typical x,y plane. There are some differences, but we'll get to that.

An orthogonal projection is really a mode that lacks any real depth. While depth is present, it's not distinguished when being rendered in terms of the objects size. Still, orthogonal can give primitive versions of depth. We may still specify that an object is in front of or behind an object, but the size of the object will be the same, no matter how close or how far away. The depth and size calculations are not present here. The only thing is that one will render "over" the other object. Take the example below:


Notice how there is a small illusion of depth here. It's clear that the sore to the eye smile face is rotated about the y axis. The cubes to the right have some idea of being "behind" the ones to the left. This is an orthogonal projection. The cubes, regardless of where they are, are all the same size. The illusion of depth is not completely satisfied here. However, orthogonal projections do exist for a reason. If you want some static information displayed that isn't really part of the world, such as the health bar or other characterizations, there's no need for depth. Additionally, if we were to create a 2D game, well, orthogonal is more than satisfactory.

Now, perspective projections are a little different. Many of the mechanics are the same, but the addition is that as objects are further away, then their size is smaller. For example, you might see layers of trees on a mountain top that, as those layers get further away, they appear smaller. That's not all, however, they also appear to move slower. This effect is generally called parallax scrolling. Perspective gives us this ability with very little extra work. Lets go right to the example.


Notice how in this case, the cubes that are rotated appear smaller or larger depending on where they are in relation to the viewer. Here, the illusion of depth is more or less enhanced. Without going into a lot of extra detail, the major difference behind the scenes here is that OpenGL scales the objects further away based on the depth of an object in relation to the viewer. Of course, depth is based on the current rotation, among other things.

I've tried to keep this as intuitive as possible, and perhaps it's a little wordy, but really, the only reason I've finally managed to learn this is by doing. Anyone interested in this type of work needs to spend a healthy amount of time just playing around as I have with the above examples.

Until next time!