Deprecated: Creation of dynamic property wpdb::$categories is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$post2cat is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$link2cat is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Return type of WP_Theme::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 554

Deprecated: Return type of WP_Theme::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 595

Deprecated: Return type of WP_Theme::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 535

Deprecated: Return type of WP_Theme::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 544

Deprecated: Return type of WP_REST_Request::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 960

Deprecated: Return type of WP_REST_Request::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 980

Deprecated: Return type of WP_REST_Request::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 992

Deprecated: Return type of WP_REST_Request::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 1003

Deprecated: Return type of WP_Block_List::current() should either be compatible with Iterator::current(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 151

Deprecated: Return type of WP_Block_List::next() should either be compatible with Iterator::next(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 175

Deprecated: Return type of WP_Block_List::key() should either be compatible with Iterator::key(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 164

Deprecated: Return type of WP_Block_List::valid() should either be compatible with Iterator::valid(): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 186

Deprecated: Return type of WP_Block_List::rewind() should either be compatible with Iterator::rewind(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 138

Deprecated: Return type of WP_Block_List::offsetExists($index) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 75

Deprecated: Return type of WP_Block_List::offsetGet($index) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 89

Deprecated: Return type of WP_Block_List::offsetSet($index, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 110

Deprecated: Return type of WP_Block_List::offsetUnset($index) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 127

Deprecated: Return type of WP_Block_List::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 199

Deprecated: Creation of dynamic property Automattic\Jetpack\Connection\Manager::$error_handler is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-connection/src/class-manager.php on line 91

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Instagram_Gallery::$is_wpcom is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-instagram-gallery.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Mailchimp::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php on line 17

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 21

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$is_wpcom is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 22

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Gutenberg_Available_Extensions::$wpcom_is_site_specific_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php on line 20

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_site_specific_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 24

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Subscribers::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php on line 15

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property WPCOM_Widget_Goodreads::$shelves is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/modules/widgets/goodreads.php on line 33

Deprecated: DateTime::__construct(): Passing null to parameter #1 ($datetime) of type string is deprecated in /var/www/twodee/blog/wp-includes/script-loader.php on line 348

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_classic_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 347

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 349

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_block_side is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 350

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$panels_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 351

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$used_block_buttons is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 354

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198
» CS 488: Lecture 3 – Vectors and Matrices

teaching machines

CS 488: Lecture 3 – Vectors and Matrices

January 27, 2021 by . Filed under
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383
graphics-3d, lectures, spring-2021.

Dear students:

Last time we explored the three common transformations that we use to move objects around the screen. We saw how to apply one transformation at a time using slow mathematical operations. Today we will learn a system for applying an arbitrarily long sequence of transformations in constant time. The system is built on two mathematical ideas: vectors and matrices.

Vectors

When we ship our vertex positions off to the GPU in a vertex buffer object, they arrive in the vertex shader as a vector. A vector is an array or sequence of numbers. In computer graphics and linear algebra, a vector has a fixed length. It’s not a growable array like std::vector in C++. In contrast, a solitary number is called a scalar.

Generally, the number of elements in the vector matches the number of dimensions you are working in. In 3D, we use 3-vectors. In 2D, we use 2-vectors. This is a lie, as you shall see.

Sometimes we write vectors as row vectors, like this:

$$\begin{array}{rcl}\mathbf{p} &=& \begin{bmatrix}x & y & z\end{bmatrix}\end{array}$$

Sometimes we write vectors as column vectors, like this:

$$\begin{array}{rcl}\mathbf{p} &=& \begin{bmatrix}x \\ y \\ z\end{bmatrix}\end{array}$$

Vectors are important because the GPU has hardware that can operate on all of a vector’s elements at the same time.

Physics has a different definition of vectors. A physics-vector is a direction and magnitude. The two definitions are related, and we’ll need both. For today, however, we are talking about absolute positions represented as a mathematical vector.

Dot Product

Just as scalars support operations like addition, subtraction, multiplication, and so on, vectors too have operations. The only one we care about today is called the dot product. The dot product of two vectors is the sum of the corresponding elements’ products:

$$\begin{array}{rcl}\mathbf{p} &=& \begin{bmatrix}a & b & c\end{bmatrix} \\\mathbf{q} &=& \begin{bmatrix}d & e & f\end{bmatrix} \\\mathbf{p} \cdot \mathbf{q} &=& ad+be+cf\end{array}$$

The dot product is a scalar value. It has some significance that we’ll discuss later. For now, we need only consider it as a mechanism for carrying out some multiplications and sums.

We now will recast our transforms by considering the vertex position as a vector.

Scale

Recall that we scale a vertex position $\mathbf{p}$ by multiplying to arrive the scaled vertex position $\mathbf{p’}$:

$$\begin{array}{rcl}x’ &=& s_x \cdot x \\y’ &=& s_y \cdot y \\z’ &=& s_z \cdot z \\\end{array}$$

This is the math we want to accelerate by using vector operations instead of scalar operations. We want to find a vector that when dotted with $\mathbf{p}$ will produce $x’$. The operation should look something like this:

$$\begin{array}{rcl}\begin{bmatrix} ? & ? & ? \end{bmatrix} \cdot \begin{bmatrix} x & y & z \end{bmatrix} &=& s_x \cdot x \\\end{array}$$

Given the mechanics of dot products, what values do we put in that first vector? We know that $x$ needs to get multiplied by $s_x$, and we know that the other two terms are not present in the result. Then our vector must be this:

$$\begin{array}{rcl}\begin{bmatrix} s_x & 0 & 0 \end{bmatrix} \cdot \begin{bmatrix} x & y & z \end{bmatrix} &=& s_x \cdot x \\\end{array}$$

Similarly, we have this operation to compute $y’$:

$$\begin{array}{rcl}\begin{bmatrix} 0 & s_y & 0 \end{bmatrix} \cdot \begin{bmatrix} x & y & z \end{bmatrix} &=& s_y \cdot y \\\end{array}$$

And this operation to compute $z’$:

$$\begin{array}{rcl}\begin{bmatrix} 0 & 0 & s_z \end{bmatrix} \cdot \begin{bmatrix} x & y & z \end{bmatrix} &=& s_z \cdot z \\\end{array}$$

Expressing these as dot products probably seems wasteful to you right now. The little bit of waste we see will get erased in due time.

Rotation

Recall that these are the operations we want to rotate a position around the z-axis:

$$\begin{array}{rcl}x’ &=& \cos a \cdot x-\sin a \cdot y \\y’ &=& \sin a \cdot x+\cos a \cdot y \\z’ &=& z \\\end{array}$$

Can we do the same recasting to the dot product machinery? Yes, the following vectors will do:

$$\begin{array}{rcl}\begin{bmatrix} \cos a & -\sin a & 0 \end{bmatrix} \cdot \begin{bmatrix} x & y & z \end{bmatrix} &=& \cos a \cdot x-\sin a \cdot y \\\begin{bmatrix} \sin a & \cos a & 0 \end{bmatrix} \cdot \begin{bmatrix} x & y & z \end{bmatrix} &=& \sin a \cdot x+\cos a \cdot y \\\begin{bmatrix} 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} x & y & z \end{bmatrix} &=& z \\\end{array}$$

Translation

Recall these are the operations we want to translate a position:

$$\begin{array}{rcl}x’ &=& x+\Delta_x \\y’ &=& y+\Delta_y \\z’ &=& z+\Delta_z \\\end{array}$$

Can we recast the calculation of $x’$ as a dot product?

$$\begin{array}{rcl}\begin{bmatrix} ? & ? & ? \end{bmatrix} \cdot \begin{bmatrix} x & y & z \end{bmatrix} &=& x+\Delta_x \\\end{array}$$

Uhh, no. We can’t. That $\Delta_x$ term has no coefficient, so there’s no way the dot product can produce it. But hold on. Let’s apply a little trick that mathematicians of yore stumbled upon. We will add a fourth coordinate of 1 to our position:

$$\begin{array}{rcl}\begin{bmatrix} ? & ? & ? & ? \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& x+\Delta_x \\\end{array}$$

Now we can find vectors that dot with the position to produce the translated coordinates:

$$\begin{array}{rcl}\begin{bmatrix} 1 & 0 & 0 & \Delta_x \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& x+\Delta_x \\\begin{bmatrix} 0 & 1 & 0 & \Delta_y \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& y+\Delta_y \\\begin{bmatrix} 0 & 0 & 1 & \Delta_z \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& z+\Delta_z\end{array}$$

Homogeneous Coordinates

This extra coordinate is called the homogeneous coordinate or the w-coordinate. It pushes us to use 4-vectors even though we’re really dealing with 3D space. To make a uniform system of transformations built on dot products, we need to add the coordinate to our scaling and rotation schemes too. Also, since we want to eventually apply sequences of transformations, we need our dot products to compute $w’$.

Let’s enumerate our complete system of dot product transformations. Here are our scaling calculations:

$$\begin{array}{rcl}\begin{bmatrix} s_x & 0 & 0 & 0 \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& s_x \cdot x \\\begin{bmatrix} 0 & s_y & 0 & 0 \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& s_y \cdot y \\\begin{bmatrix} 0 & 0 & s_z & 0 \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& s_z \cdot z \\\begin{bmatrix} 0 & 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& 1 \\\end{array}$$

Here are our rotation calculations:

$$\begin{array}{rcl}\begin{bmatrix} \cos a & -\sin a & 0 & 0 \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& \cos a \cdot x-\sin a \cdot y \\\begin{bmatrix} \sin a & \cos a & 0 & 0 \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& \sin a \cdot x+\cos a \cdot y \\\begin{bmatrix} 0 & 0 & 1 & 0 \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& z \\\begin{bmatrix} 0 & 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& 1 \\\end{array}$$

Here are our translation calculations:

$$\begin{array}{rcl}\begin{bmatrix} 1 & 0 & 0 & \Delta_x \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& x+\Delta_x \\\begin{bmatrix} 0 & 1 & 0 & \Delta_y \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& y+\Delta_y \\\begin{bmatrix} 0 & 0 & 1 & \Delta_z \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& z+\Delta_z \\\begin{bmatrix} 0 & 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix} &=& 1 \\\end{array}$$

Matrix-Vector Multiplication

The GPU can perform all four dot products for a transformation in parallel if we merge the left operand vectors together into a matrix. We can think of a matrix as a stack of vectors. We write the transformations not as a sequence of four dot products, but as a matrix-vector multiplication. The product is a vector.

Our scaling operation becomes this matrix-vector multiplcation:

$$\begin{array}{rcl}\begin{bmatrix}s_x & 0 & 0 & 0 \\0 & s_y & 0 & 0 \\0 & 0 & s_z & 0 \\0 & 0 & 0 & 1\end{bmatrix} \cdot \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} &=& \begin{bmatrix}s_x \cdot x \\s_y \cdot y \\s_z \cdot z \\1\end{bmatrix}\end{array}$$

Our rotation around the z-axis operation becomes this matrix-vector multiplcation:

$$\begin{array}{rcl}\begin{bmatrix}\cos a & -\sin a & 0 & 0 \\\sin a & \cos a & 0 & 0 \\0 & 0 & 1 & 0 \\0 & 0 & 0 & 1\end{bmatrix} \cdot \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} &=& \begin{bmatrix}\cos a \cdot x-\sin a \cdot y \\\sin a \cdot x+\cos a \cdot y \\z \\1\end{bmatrix}\end{array}$$

Our translation becomes this matrix-vector multiplication:

$$\begin{array}{rcl}\begin{bmatrix}1 & 0 & 0 & \Delta_x \\0 & 1 & 0 & \Delta_y \\0 & 0 & 1 & \Delta_z \\0 & 0 & 0 & 1\end{bmatrix} \cdot \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} &=& \begin{bmatrix}x + \Delta_x \\y + \Delta_y \\z + \Delta_z \\1\end{bmatrix}\end{array}$$

Matrices in WebGL and GLSL

Suppose we go and implement methods for generating these matrices in helpful Matrix class, which you’ll do in Friday’s lab. We can use these matrices to transform our objects by making these adjustments to our code:

let transform;

function initialize() {
  transform = Matrix.scale(2, 0.5, 1);
  // transform = Matrix.translate(0.3, -0.5);
  // transform = Matrix.rotateZ(45);
  // ...
}

function render() {
  // ...
  shaderProgram.bind();
  shaderProgram.setUniformMatrix4('transform', transform);
  // ...
}

In the vertex shader, which is responsible for computing the clip space position of the vertex, we apply the transformation:

uniform mat4 transform;

in vec3 position;

void main() {
  gl_Position = transform * vec4(position, 1.0);
}

These transforms get more interesting when we tie them to user actions. Let’s rotate our object based on the mouse’s x-coordinate by adding a mouse event listener at the end of initialize:

window.addEventListener('mousemove', event => {
  const degrees = event.clientX;
  transform = Matrix4.rotateZ(degrees);
  render();
});

This code uses JavaScript’s arrow function syntax. We’re passing a function body directly as a parameter without naming it.

Horizon

We now have a unified system for expressing transformations. We will use this system for animation, for arranging a complete world of objects, for situating a camera inside the world, and for fixing the distortion that we currently see when the window isn’t square. Right now we’re still only applying one matrix transformation at a time, but soon we’ll look at how to combine many transforms into a single matrix.

TODO

Here’s your very first TODO list:

See you next time.

Sincerely,

P.S. It’s time for a haiku!

I get a * b
But a * b * c * ...?
Dot-dot-dot product