Math for Game Development and WebGL Part 1: Vectors
After rekindling my interest in 3D game development, I looked at WebGL. Being a web dev, this made sense. Unfortunately resources for this are mediocre at best. While WebGL2Fundamentals and the Introduction to Computer Graphics book do cover some of what’s needed, they largely skip the actual math and just tell you to do something. As an example, when rotating a vector, Intro to Computer Graphics says the formula isn’t intuitive, and then just gives you the formula with no explanation. You’re right, its not intuitive. Maybe explain it. WebGL2Funamentals says, “How does it work? Lets look at the math” and then just shows examples of the math working. That is not an explanation of how it works, that’s just showing it working.
This pattern of just showing something rather than explaining continues. I realize these aren’t necessarily supposed to be full math courses, but their lacking or just incorrect explanations were frustrating to me. I then spent many hours on Khan Academy math courses, and have come back to write a series of tutorials that start with math and work up to a full WebGL game engine. I also cannot show ever single theory and detail behind every piece of math we do, but I will always show how it works and how it applies, which is more than can be said for other resources I’ve found.
As a note, we will be building our own vector and matrix classes in these posts for the purposes of learning. This is not something that should be done in real development, as they are already built into the browser (DOMMatrix and DOMPoint). However these hide the details from us, so to learn how everything works, we will make our own.
What are vectors? A vector is a quantity that has magnitude (or size) and direction. A regular number, or as you’ll hear mathematically, a scalar, only shows magnitude.
If I have a square drawn on canvas, and I want to move it, knowing only the distance to move is not helpful. If I say “move that square five pixels”, you may ask, “but in what direction?”. And that is where vectors come in. Instead I might say, “move that square up three pixels and right four pixels”. Now you know both the magnitude and direction. So there are actually two values there, a horizontal distance and a vertical distance. Or the x distance and the y distance. We could view this on a graph as:
You might be asking, “isn’t this just the position of something?”, and the answer is…it can be. You can think of a “position vector” as the magnitude and direction from the origin (0, 0). Just keep in mind that vectors themselves don’t have a starting point, only a magnitude and direction, so all of the following vectors are the same:
All of those vectors go to the right three and up four regardless of their starting point, so they can all be represented as the vector
With our definition in place, lets create a Vector2 class and use it to draw a rectangle on a canvas. We call this class Vector2 as it only has two dimensions, x and y. We will eventually create vectors with more dimension, as we eventually want to do 3D game development. But for now while learning the math we will stay at two dimensions.
In this case we are using position vectors to position the square at the upper right corner of the canvas, as you can see in the results tab.
Adding and Subtracting Vectors
To add vectors together, you simply add each vector’s components together:
(3, 4) + (1, 2) = (4, 6)
Subtraction works the same way:
(3, 4) - (1, 2) = (2, 2)
This math is pretty straightforward, but sometimes it can help to visualize how this is working in 2d space. You can visualize addition as joining two vectors nose to tail, and subtraction as joining tail to tail.
In the equation above we show these two vectors, drawn here from the origin (0, 0)
If we move the nose (the part currently at the origin) to the tail (the part with the arrow), we have added the vectors:
If we move the tail of one vector to the tail of the other, we have subtracted the vectors:
This is simply a visual representation of how addition and subtraction work with vectors.
Now lets give our Vector2 class an plus method. While we could also give it a minus method, adding a negative value is the same as subtraction, so for our purposes right now we will simply use add and pass in negative values if we want to subtract. We will then use this plus method to add one “translation” vector, or in less fancy terms “move” vector to the vectors that make up our rectangle:
Try changing the x and y values in our translation vector. Notice that by changing the x and y values, you can change how far the square moves in each direction. We were able to move our square around without using the canvas translate() method. While our points are position vectors, the translation vector is a vector in the purest sense, it’s only a direction and magnitude. By adding vectors, we move our position in the direction of the translation vector, and the distance we move it is the magnitude of the translation vector.
Finding the Magnitude of a Vector
So far when talking about vectors we’ve only been talking about their x and y values. When we think of the vector (3, 4), we think of it as a vector that moves to the right three and up four. But how far total have you moved if you move to the right three and up four? Another way of saying that is, what is the magnitude of the vector (3, 4). You can visualize that by saying, what is the length of this line?
Well, if we draw lines representing the width and height we can form a triangle:
If we know two sides of a triangle, we can solve for the other with the Pythagorean theorem.
a² + b² = c²
So the magnitude of the vector is
3² + 4² = c² 9 + 16 = c² 25 = c² √25 = c c = 5
Or, the magnitude of the vector is five. Our final task for this post is to add a magnitude method to our Vector2 class and then log the magnitude of our translation vector:
If you check the log, you can see the magnitude of the translation vector, and see that we moved the rectangle about 223.6 pixels.
Here are the key takeaways for this post:
- A vector is a quantity that has a magnitude and direction
- To add two vectors, simply add each component of the vector to the other
- Adding to a vector moves that vector in the direction of and by the magnitude of the vector you add
- To find the magnitude of a vector, use the Pythagorean theorem and add it’s component’s value squared and take the square root of that
- While we only used x and y for our vector, a vector can have any number of dimension and these same concepts will still apply
As mentioned, I want to try to keep these posts as relevant as possible while still explaining the underlying math. If you’d like a deeper understanding, I recommend these: