1<!DOCTYPE html> 2<html> 3 <head> 4 <meta charset="UTF-8"> 5 6 <title>OpenGL - Transformations</title> 7 8 <meta name="description" content="An extensive, yet beginner friendly guide to using modern OpenGL for game development on all major platforms." /> 9 <meta name="author" content="Alexander Overvoorde" /> 10 <meta name="keywords" content="opengl, opengl 3.2, deprecated, non-deprecated, tutorial, guide, cross-platform, game, games, graphics, sfml, sdl, glfw, glut, openglut, beginner, easy" /> 11 12 <link rel="shortcut icon" type="image/png" href="/media/tag.png" /> 13 <link rel="stylesheet" type="text/css" href="/media/stylesheet.css" /> 14 15 <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" /> 16 <link rel="stylesheet" type="text/css" href="/media/mobile.css" media="screen and (max-width: 1024px)" /> 17 18
18<script type="text/x-mathjax-config"> 19 // MathJax 20 MathJax.Hub.Config( { 21 tex2jax: { inlineMath: [ [ '$', '$' ], [ '\\(', '\\)' ] ] }, 22 menuSettings: { context: "Browser" } 23 } ); 24 </script>
24 25
25<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
25 26 27 <link rel="stylesheet" href="/includes/zenburn.min.css" /> 28
28<script type="text/javascript" src="//yandex.st/highlightjs/6.1/highlight.min.js"></script>
28 29
29<script type="text/javascript" src="/includes/glmatrix.js"></script>
29 30
30<script type="text/javascript"> 31 // Syntax highlighting 32 hljs.initHighlightingOnLoad(); 33 34 // Disqus 35 var disqus_url = "http://open.gl/?content=transformations"; 36 var disqus_identifier = "transformations"; 37 38 // WebGL demos 39 var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame; 40 var callbacks = []; 41 var frame = function() { 42 var time = +new Date() / 1000; 43 44 for (var i = 0; i < callbacks.length; i++) { 45 var rect = callbacks[i].canvas.getBoundingClientRect(); 46 47 if (rect.bottom > 0 && rect.top < window.innerHeight) 48 callbacks[i].callback( time ); 49 } 50 51 requestAnimationFrame(frame); 52 } 53 function registerAnimatedCanvas(canvas, callback) { 54 callbacks.push({canvas: canvas, callback: callback}); 55 } 56 requestAnimationFrame(frame); 57 </script>
57 58 <!--[if lt IE 9]> 59
59<script src="media/html5shiv.js"></script>
59 60 <![endif]--> 61 62 <!-- Matomo --> 63
63<script type="text/javascript"> 64 var _paq = _paq || []; 65 /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ 66 _paq.push(["setDocumentTitle", document.domain + "/" + document.title]); 67 _paq.push(["setCookieDomain", "*.open.gl"]); 68 _paq.push(["setDomains", ["*.open.gl"]]); 69 _paq.push(['trackPageView']); 70 _paq.push(['enableLinkTracking']); 71 (function() { 72 var u="//matomo.while.io/"; 73 _paq.push(['setTrackerUrl', u+'piwik.php']); 74 _paq.push(['setSiteId', '4']); 75 var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; 76 g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s); 77 })(); 78 </script>
78 79 <!-- End Matomo Code --> 80 </head> 81 82 <body> 83 <div id="page"> 84 <!-- Work in progress ribbon --> 85 <a href="https://github.com/Overv/Open.GL"><img id="ribbon" src="/media/ribbon_fork.png" alt="Fork me!" /></a> 86 87 <!-- Navigation items --> 88 <input type="checkbox" id="nav_toggle" /> 89 <nav> 90 <label for="nav_toggle" data-open="≡" data-close="✕"></label> 91 <ul> 92 <li><a href="/introduction">Introduction</a></li> 93<li><a href="/context">Context creation</a></li> 94<li><a href="/drawing">Drawing polygons</a></li> 95<li><a href="/textures">Textures</a></li> 96<li class="selected">Transformations</li> 97<li><a href="/depthstencils">Depth and stencils</a></li> 98<li><a href="/framebuffers">Framebuffers</a></li> 99<li><a href="/geometry">Geometry shaders</a></li> 100<li><a href="/feedback">Transform Feedback</a></li> 101 </ul> 102 103 <blockquote style="padding-bottom: 8px; font-size: 14px"> 104 <h2 style="margin: 0">Links</h2> 105 106 <a href="https://github.com/Polytonic/Glitter" style="text-decoration: underline">OpenGL boilerplate code</a><br> 107 108 <a href="https://github.com/zuck/opengl-examples" style="text-decoration: underline">Easy-to-build code</a><br> 109 <a href="https://www.youtube.com/playlist?list=PLW3Zl3wyJwWNQjMz941uyOIq3Nw6bcDYC" style="text-decoration: underline">Matrix math tutorials</a><br> 110 <a href="http://docs.gl" style="text-decoration: underline">OpenGL reference</a> 111 </blockquote> 112 113 <div id="adbox"> 114
114<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
114 115 <!-- Open.GL Responsive --> 116 <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-4259747131061893" data-ad-slot="6609097747" data-ad-format="auto"></ins> 117
117<script> 118 (adsbygoogle = window.adsbygoogle || []).push({}); 119 </script>
119 120 </div> 121 </nav> 122 123 <!-- Content container --> 124 <main> 125 <article> 126 <h1 id="transformations">Matrices</h1> 127 128<p>Since this is a guide on graphics programming, this chapter will not cover a lot of the extensive theory behind matrices. Only the theory that applies to their use in computer graphics will be considered here and they will be explained from a programmer's perspective. If you want to learn more about the topic, <a href="https://www.khanacademy.org/math/algebra2/algebra-matrices/Basic_matrix_operations/v/introduction-to-the-matrix">these Khan Academy videos</a> are a really good general introduction to the subject.</p> 129 130<p>A matrix is a rectangular array of mathematical expressions, much like a two-dimensional array. Below is an example of a matrix displayed in the common square brackets form.</p> 131 132<span class="MathJax_Preview">[a = \begin{bmatrix} 133 1 & 2 \\ 134 3 & 4 \\ 135 5 & 6 136 \end{bmatrix}]</span>
136<script type="math/tex; mode=display">a = \begin{bmatrix} 137 1 & 2 \\ 138 3 & 4 \\ 139 5 & 6 140 \end{bmatrix}</script>
140 141 142<p>Matrices values are indexed by <code>(i,j)</code> where <code>i</code> is the row and <code>j</code> is the column. That is why the matrix displayed above is called a 3-by-2 matrix. To refer to a specific value in the matrix, for example <code>5</code>, the <span class="MathJax_Preview">[a_{31}]</span>
142<script type="math/tex">a_{31}</script>
142 notation is used.</p> 143 144<h2>Basic operations</h2> 145 146<p>To get a bit more familiar with the concept of an array of numbers, let's first look at a few basic operations.</p> 147 148<h3>Addition and subtraction</h3> 149 150<p>Just like regular numbers, the addition and subtraction operators are also defined for matrices. The only requirement is that the two operands have exactly the same row and column dimensions.</p> 151 152<span class="MathJax_Preview">[\begin{bmatrix} 153 3 & 2 \\ 154 0 & 4 155 \end{bmatrix} 156 + 157 \begin{bmatrix} 158 4 & 2 \\ 159 2 & 2 160 \end{bmatrix} 161 = 162 \begin{bmatrix} 163 3 + 4 & 2 + 2 \\ 164 0 + 2 & 4 + 2 165 \end{bmatrix} 166 = 167 \begin{bmatrix} 168 7 & 4 \\ 169 2 & 6 170 \end{bmatrix}]</span>
170<script type="math/tex; mode=display">\begin{bmatrix} 171 3 & 2 \\ 172 0 & 4 173 \end{bmatrix} 174 + 175 \begin{bmatrix} 176 4 & 2 \\ 177 2 & 2 178 \end{bmatrix} 179 = 180 \begin{bmatrix} 181 3 + 4 & 2 + 2 \\ 182 0 + 2 & 4 + 2 183 \end{bmatrix} 184 = 185 \begin{bmatrix} 186 7 & 4 \\ 187 2 & 6 188 \end{bmatrix}</script>
188 189 190<span class="MathJax_Preview">[\begin{bmatrix} 191 4 & 2 \\ 192 2 & 7 193 \end{bmatrix} 194 - 195 \begin{bmatrix} 196 3 & 2 \\ 197 0 & 4 198 \end{bmatrix} 199 = 200 \begin{bmatrix} 201 4 - 3 & 2 - 2 \\ 202 2 - 0 & 7 - 4 203 \end{bmatrix} 204 = 205 \begin{bmatrix} 206 1 & 0 \\ 207 2 & 3 208 \end{bmatrix}]</span>
208<script type="math/tex; mode=display">\begin{bmatrix} 209 4 & 2 \\ 210 2 & 7 211 \end{bmatrix} 212 - 213 \begin{bmatrix} 214 3 & 2 \\ 215 0 & 4 216 \end{bmatrix} 217 = 218 \begin{bmatrix} 219 4 - 3 & 2 - 2 \\ 220 2 - 0 & 7 - 4 221 \end{bmatrix} 222 = 223 \begin{bmatrix} 224 1 & 0 \\ 225 2 & 3 226 \end{bmatrix}</script>
226 227 228<p>The values in the matrices are individually added or subtracted from each other.</p> 229 230<h3>Scalar product</h3> 231 232<p>The product of a scalar and a matrix is as straightforward as addition and subtraction.</p> 233 234<span class="MathJax_Preview">[2 \cdot 235 \begin{bmatrix} 236 1 & 2 \\ 237 3 & 4 238 \end{bmatrix} 239 = 240 \begin{bmatrix} 241 2 & 4 \\ 242 6 & 8 243 \end{bmatrix}]</span>
243<script type="math/tex; mode=display">2 \cdot 244 \begin{bmatrix} 245 1 & 2 \\ 246 3 & 4 247 \end{bmatrix} 248 = 249 \begin{bmatrix} 250 2 & 4 \\ 251 6 & 8 252 \end{bmatrix}</script>
252 253 254<p>The values in the matrices are each multiplied by the scalar.</p> 255 256<h2>Matrix-Vector product</h2> 257 258<p>The product of a matrix with another matrix is quite a bit more involved and is often misunderstood, so for simplicity's sake I will only mention the specific cases that apply to graphics programming. To see how matrices are actually used to transform vectors, we'll first dive into the product of a matrix and a vector.</p> 259 260<span class="MathJax_Preview">[\begin{bmatrix} 261 \color{red}a & \color{red}b & \color{red}c & \color{red}d \\ 262 \color{blue}e & \color{blue}f & \color{blue}g & \color{blue}h \\ 263 \color{green}i & \color{green}j & \color{green}k & \color{green}l \\ 264 \color{magenta}m & \color{magenta}n & \color{magenta}o & \color{magenta}p 265 \end{bmatrix} 266 \cdot 267 \begin{pmatrix} 268 x \\ 269 y \\ 270 z \\ 271 1 272 \end{pmatrix} 273 = 274 \begin{pmatrix} 275 \color{red}a\cdot x + \color{red}b\cdot y + \color{red}c\cdot z + \color{red}d\cdot 1 \\ 276 \color{blue}e\cdot x + \color{blue}f\cdot y + \color{blue}g\cdot z + \color{blue}h\cdot 1 \\ 277 \color{green}i\cdot x + \color{green}j\cdot y + \color{green}k\cdot z + \color{green}l\cdot 1 \\ 278 \color{magenta}m\cdot x + \color{magenta}n\cdot y + \color{magenta}o\cdot z + \color{magenta}p\cdot 1 279 \end{pmatrix}]</span>
279<script type="math/tex; mode=display">\begin{bmatrix} 280 \color{red}a & \color{red}b & \color{red}c & \color{red}d \\ 281 \color{blue}e & \color{blue}f & \color{blue}g & \color{blue}h \\ 282 \color{green}i & \color{green}j & \color{green}k & \color{green}l \\ 283 \color{magenta}m & \color{magenta}n & \color{magenta}o & \color{magenta}p 284 \end{bmatrix} 285 \cdot 286 \begin{pmatrix} 287 x \\ 288 y \\ 289 z \\ 290 1 291 \end{pmatrix} 292 = 293 \begin{pmatrix} 294 \color{red}a\cdot x + \color{red}b\cdot y + \color{red}c\cdot z + \color{red}d\cdot 1 \\ 295 \color{blue}e\cdot x + \color{blue}f\cdot y + \color{blue}g\cdot z + \color{blue}h\cdot 1 \\ 296 \color{green}i\cdot x + \color{green}j\cdot y + \color{green}k\cdot z + \color{green}l\cdot 1 \\ 297 \color{magenta}m\cdot x + \color{magenta}n\cdot y + \color{magenta}o\cdot z + \color{magenta}p\cdot 1 298 \end{pmatrix}</script>
298 299 300<p>To calculate the product of a matrix and a vector, the vector is written as a 4-by-1 matrix. The expressions to the right of the equals sign show how the new <code>x</code>, <code>y</code> and <code>z</code> values are calculated after the vector has been transformed. For those among you who aren't very math savvy, the dot is a multiplication sign.</p> 301 302<p>I will mention each of the common vector transformations in this section and how a matrix can be formed that performs them. For completeness, let's first consider a transformation that does absolutely nothing.</p> 303 304<span class="MathJax_Preview">[\begin{bmatrix} 305 \color{red}1 & \color{red}0 & \color{red}0 & \color{red}0 \\ 306 \color{blue}0 & \color{blue}1 & \color{blue}0 & \color{blue}0 \\ 307 \color{green}0 & \color{green}0 & \color{green}1 & \color{green}0 \\ 308 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 309 \end{bmatrix} 310 \cdot 311 \begin{pmatrix} 312 x \\ 313 y \\ 314 z \\ 315 1 316 \end{pmatrix} 317 = 318 \begin{pmatrix} 319 \color{red}1\cdot x + \color{red}0\cdot y + \color{red}0\cdot z + \color{red}0\cdot 1 \\ 320 \color{blue}0\cdot x + \color{blue}1\cdot y + \color{blue}0\cdot z + \color{blue}0\cdot 1 \\ 321 \color{green}0\cdot x + \color{green}0\cdot y + \color{green}1\cdot z + \color{green}0\cdot 1 \\ 322 \color{magenta}0\cdot x + \color{magenta}0\cdot y + \color{magenta}0\cdot z + \color{magenta}1\cdot 1 323 \end{pmatrix} 324 = 325 \begin{pmatrix} 326 \color{red}1\cdot x \\ 327 \color{blue}1\cdot y \\ 328 \color{green}1\cdot z \\ 329 \color{magenta}1\cdot 1 330 \end{pmatrix}]</span>
330<script type="math/tex; mode=display">\begin{bmatrix} 331 \color{red}1 & \color{red}0 & \color{red}0 & \color{red}0 \\ 332 \color{blue}0 & \color{blue}1 & \color{blue}0 & \color{blue}0 \\ 333 \color{green}0 & \color{green}0 & \color{green}1 & \color{green}0 \\ 334 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 335 \end{bmatrix} 336 \cdot 337 \begin{pmatrix} 338 x \\ 339 y \\ 340 z \\ 341 1 342 \end{pmatrix} 343 = 344 \begin{pmatrix} 345 \color{red}1\cdot x + \color{red}0\cdot y + \color{red}0\cdot z + \color{red}0\cdot 1 \\ 346 \color{blue}0\cdot x + \color{blue}1\cdot y + \color{blue}0\cdot z + \color{blue}0\cdot 1 \\ 347 \color{green}0\cdot x + \color{green}0\cdot y + \color{green}1\cdot z + \color{green}0\cdot 1 \\ 348 \color{magenta}0\cdot x + \color{magenta}0\cdot y + \color{magenta}0\cdot z + \color{magenta}1\cdot 1 349 \end{pmatrix} 350 = 351 \begin{pmatrix} 352 \color{red}1\cdot x \\ 353 \color{blue}1\cdot y \\ 354 \color{green}1\cdot z \\ 355 \color{magenta}1\cdot 1 356 \end{pmatrix}</script>
356 357 358<p>This matrix is called the <em>identity matrix</em>, because just like the number <code>1</code>, it will always return the value it was originally multiplied by.</p> 359 360<p>Let's look at the most common vector transformations now and deduce how a matrix can be formed from them.</p> 361 362<h3>Translation</h3> 363 364<p>To see why we're working with 4-by-1 vectors and subsequently 4-by-4 transformation matrices, let's see how a translation matrix is formed. A translation moves a vector a certain distance in a certain direction.</p> 365 366<p><img src="media/img/c4_translation.png" alt="" /></p> 367 368<p>Can you guess from the multiplication overview what the matrix should look like to translate a vector by <code>(X,Y,Z)</code>?</p> 369 370<span class="MathJax_Preview">[\begin{bmatrix} 371 \color{red}1 & \color{red}0 & \color{red}0 & \color{red}X \\ 372 \color{blue}0 & \color{blue}1 & \color{blue}0 & \color{blue}Y \\ 373 \color{green}0 & \color{green}0 & \color{green}1 & \color{green}Z \\ 374 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 375 \end{bmatrix} 376 \cdot 377 \begin{pmatrix} 378 x \\ 379 y \\ 380 z \\ 381 1 382 \end{pmatrix} 383 = 384 \begin{pmatrix} 385 x+\color{red}X\cdot 1 \\ 386 y+\color{blue}Y\cdot 1 \\ 387 z+\color{green}Z\cdot 1 \\ 388 1 389 \end{pmatrix}]</span>
389<script type="math/tex; mode=display">\begin{bmatrix} 390 \color{red}1 & \color{red}0 & \color{red}0 & \color{red}X \\ 391 \color{blue}0 & \color{blue}1 & \color{blue}0 & \color{blue}Y \\ 392 \color{green}0 & \color{green}0 & \color{green}1 & \color{green}Z \\ 393 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 394 \end{bmatrix} 395 \cdot 396 \begin{pmatrix} 397 x \\ 398 y \\ 399 z \\ 400 1 401 \end{pmatrix} 402 = 403 \begin{pmatrix} 404 x+\color{red}X\cdot 1 \\ 405 y+\color{blue}Y\cdot 1 \\ 406 z+\color{green}Z\cdot 1 \\ 407 1 408 \end{pmatrix}</script>
408 409 410<p>Without the fourth column and the bottom <code>1</code> value a translation wouldn't have been possible.</p> 411 412<h3>Scaling</h3> 413 414<p>A scale transformation scales each of a vector's components by a (different) scalar. It is commonly used to shrink or stretch a vector as demonstrated below.</p> 415 416<p><img src="media/img/c4_scaling.png" alt="" /></p> 417 418<p>If you understand how the previous matrix was formed, it should not be difficult to come up with a matrix that scales a given vector by <code>(SX,SY,SZ)</code>.</p> 419 420<span class="MathJax_Preview">[\begin{bmatrix} 421 \color{red}{SX} & \color{red}0 & \color{red}0 & \color{red}0 \\ 422 \color{blue}0 & \color{blue}{SY} & \color{blue}0 & \color{blue}0 \\ 423 \color{green}0 & \color{green}0 & \color{green}{SZ} & \color{green}0 \\ 424 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 425 \end{bmatrix} 426 \cdot 427 \begin{pmatrix} 428 x \\ 429 y \\ 430 z \\ 431 1 432 \end{pmatrix} 433 = 434 \begin{pmatrix} 435 \color{red}{SX}\cdot x \\ 436 \color{green}{SY}\cdot y \\ 437 \color{blue}{SZ}\cdot z \\ 438 1 439 \end{pmatrix}]</span>
439<script type="math/tex; mode=display">\begin{bmatrix} 440 \color{red}{SX} & \color{red}0 & \color{red}0 & \color{red}0 \\ 441 \color{blue}0 & \color{blue}{SY} & \color{blue}0 & \color{blue}0 \\ 442 \color{green}0 & \color{green}0 & \color{green}{SZ} & \color{green}0 \\ 443 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 444 \end{bmatrix} 445 \cdot 446 \begin{pmatrix} 447 x \\ 448 y \\ 449 z \\ 450 1 451 \end{pmatrix} 452 = 453 \begin{pmatrix} 454 \color{red}{SX}\cdot x \\ 455 \color{green}{SY}\cdot y \\ 456 \color{blue}{SZ}\cdot z \\ 457 1 458 \end{pmatrix}</script>
458 459 460<p>If you think about it for a moment, you can see that scaling would also be possible with a mere 3-by-3 matrix.</p> 461 462<h3>Rotation</h3> 463 464<p>A rotation transformation rotates a vector around the origin <code>(0,0,0)</code> using a given <em>axis</em> and <em>angle</em>. To understand how the axis and the angle control a rotation, let's do a small experiment.</p> 465 466<p><img src="media/img/c4_rotation.png" alt="" /></p> 467 468<p>Put your thumb up against your monitor and try rotating your hand around it. The object, your hand, is rotating around your thumb: the rotation axis. The further you rotate your hand away from its initial position, the higher the rotation angle.</p> 469 470<p>In this way the rotation axis can be imagined as an arrow an object is rotating around. If you imagine your monitor to be a 2-dimensional XY surface, the rotation axis (your thumb) is pointing in the Z direction.</p> 471 472<p>Objects can be rotated around any given axis, but for now only the X, Y and Z axis are important. You'll see later in this chapter that any rotation axis can be established by rotating around the X, Y and Z axis simultaneously.</p> 473 474<p>The matrices for rotating around the three axes are specified here. The rotation angle is indicated by the theta ($\theta$).</p> 475 476<p>Rotation around X-axis:</p> 477 478<span class="MathJax_Preview">[\begin{bmatrix} 479 \color{red}1 & \color{red}0 & \color{red}0 & \color{red}0 \\ 480 \color{blue}0 & \color{blue}{\cos\theta} & \color{blue}{-\sin\theta} & \color{blue}0 \\ 481 \color{green}0 & \color{green}{\sin\theta} & \color{green}{\cos\theta} & \color{green}0 \\ 482 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 483 \end{bmatrix} 484 \cdot 485 \begin{pmatrix} 486 x \\ 487 y \\ 488 z \\ 489 1 490 \end{pmatrix} 491 = 492 \begin{pmatrix} 493 x \\ 494 \color{blue}{\cos\theta}\cdot y \color{blue}{-\sin\theta}\cdot z \\ 495 \color{green}{\sin\theta}\cdot y + \color{green}{\cos\theta}\cdot z \\ 496 1 497 \end{pmatrix}]</span>
497<script type="math/tex; mode=display">\begin{bmatrix} 498 \color{red}1 & \color{red}0 & \color{red}0 & \color{red}0 \\ 499 \color{blue}0 & \color{blue}{\cos\theta} & \color{blue}{-\sin\theta} & \color{blue}0 \\ 500 \color{green}0 & \color{green}{\sin\theta} & \color{green}{\cos\theta} & \color{green}0 \\ 501 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 502 \end{bmatrix} 503 \cdot 504 \begin{pmatrix} 505 x \\ 506 y \\ 507 z \\ 508 1 509 \end{pmatrix} 510 = 511 \begin{pmatrix} 512 x \\ 513 \color{blue}{\cos\theta}\cdot y \color{blue}{-\sin\theta}\cdot z \\ 514 \color{green}{\sin\theta}\cdot y + \color{green}{\cos\theta}\cdot z \\ 515 1 516 \end{pmatrix}</script>
516 517 518<p>Rotation around Y-axis:</p> 519 520<span class="MathJax_Preview">[\begin{bmatrix} 521 \color{red}{\cos\theta} & \color{red}0 & \color{red}{\sin\theta} & \color{red}0 \\ 522 \color{blue}0 & \color{blue}1 & \color{blue}0 & \color{blue}0 \\ 523 \color{green}{-\sin\theta} & \color{green}0 & \color{green}{\cos\theta} & \color{green}0 \\ 524 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 525 \end{bmatrix} 526 \cdot 527 \begin{pmatrix} 528 x \\ 529 y \\ 530 z \\ 531 1 532 \end{pmatrix} 533 = 534 \begin{pmatrix} 535 \color{red}{\cos\theta}\cdot x + \color{red}{\sin\theta}\cdot z \\ 536 y \\ 537 \color{green}{-\sin\theta}\cdot x + \color{green}{\cos\theta}\cdot z \\ 538 1 539 \end{pmatrix}]</span>
539<script type="math/tex; mode=display">\begin{bmatrix} 540 \color{red}{\cos\theta} & \color{red}0 & \color{red}{\sin\theta} & \color{red}0 \\ 541 \color{blue}0 & \color{blue}1 & \color{blue}0 & \color{blue}0 \\ 542 \color{green}{-\sin\theta} & \color{green}0 & \color{green}{\cos\theta} & \color{green}0 \\ 543 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 544 \end{bmatrix} 545 \cdot 546 \begin{pmatrix} 547 x \\ 548 y \\ 549 z \\ 550 1 551 \end{pmatrix} 552 = 553 \begin{pmatrix} 554 \color{red}{\cos\theta}\cdot x + \color{red}{\sin\theta}\cdot z \\ 555 y \\ 556 \color{green}{-\sin\theta}\cdot x + \color{green}{\cos\theta}\cdot z \\ 557 1 558 \end{pmatrix}</script>
558 559 560<p>Rotation around Z-axis:</p> 561 562<span class="MathJax_Preview">[\begin{bmatrix} 563 \color{red}{\cos\theta} & \color{red}{-\sin\theta} & \color{red}0 & \color{red}0 \\ 564 \color{blue}{\sin\theta} & \color{blue}{\cos\theta} & \color{blue}0 & \color{blue}0 \\ 565 \color{green}0 & \color{green}0 & \color{green}1 & \color{green}0 \\ 566 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 567 \end{bmatrix} 568 \cdot 569 \begin{pmatrix} 570 x \\ 571 y \\ 572 z \\ 573 1 574 \end{pmatrix} 575 = 576 \begin{pmatrix} 577 \color{red}{\cos\theta}\cdot x \color{red}{-\sin\theta}\cdot y \\ 578 \color{blue}{\sin\theta}\cdot x + \color{blue}{\cos\theta}\cdot y \\ 579 z \\ 580 1 581 \end{pmatrix}]</span>
581<script type="math/tex; mode=display">\begin{bmatrix} 582 \color{red}{\cos\theta} & \color{red}{-\sin\theta} & \color{red}0 & \color{red}0 \\ 583 \color{blue}{\sin\theta} & \color{blue}{\cos\theta} & \color{blue}0 & \color{blue}0 \\ 584 \color{green}0 & \color{green}0 & \color{green}1 & \color{green}0 \\ 585 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 586 \end{bmatrix} 587 \cdot 588 \begin{pmatrix} 589 x \\ 590 y \\ 591 z \\ 592 1 593 \end{pmatrix} 594 = 595 \begin{pmatrix} 596 \color{red}{\cos\theta}\cdot x \color{red}{-\sin\theta}\cdot y \\ 597 \color{blue}{\sin\theta}\cdot x + \color{blue}{\cos\theta}\cdot y \\ 598 z \\ 599 1 600 \end{pmatrix}</script>
600 601 602<p>Don't worry about understanding the actual geometry behind this, explaining that is beyond the scope of this guide. What matters is that you have a solid idea of how a rotation is described by a rotation axis and an angle and that you've at least seen what a rotation matrix looks like.</p> 603 604<h2>Matrix-Matrix product</h2> 605 606<p>In the previous section you've seen how transformation matrices can be used to apply transformations to vectors, but this by itself is not very useful. It clearly takes far less effort to do a translation and scaling by hand without all those pesky matrices!</p> 607 608<p>Now, what if I told you that it is possible to combine as many transformations as you want into a single matrix by simply multiplying them? You would be able to apply even the most complex transformations to any vertex with a simple multiplication.</p> 609 610<p>In the same style as the previous section, this is how the product of two 4-by-4 matrices is determined:</p> 611 612<span class="MathJax_Preview">[\begin{bmatrix} 613 \color{red}a & \color{red}b & \color{red}c & \color{red}d \\ 614 \color{blue}e & \color{blue}f & \color{blue}g & \color{blue}h \\ 615 \color{green}i & \color{green}j & \color{green}k & \color{green}l \\ 616 \color{magenta}m & \color{magenta}n & \color{magenta}o & \color{magenta}p 617 \end{bmatrix} 618 \cdot 619 \begin{bmatrix} 620 \color{red}A & \color{blue}B & \color{green}C & \color{magenta}D \\ 621 \color{red}E & \color{blue}F & \color{green}G & \color{magenta}H \\ 622 \color{red}I & \color{blue}J & \color{green}K & \color{magenta}L \\ 623 \color{red}M & \color{blue}N & \color{green}O & \color{magenta}P 624 \end{bmatrix} 625 = \\ 626 \begin{bmatrix} 627 \color{red}{aA} + \color{red}{bE} + \color{red}{cI} + \color{red}{dM} & 628 \color{red}a\color{blue}B + \color{red}b\color{blue}F + \color{red}c\color{blue}J + \color{red}d\color{blue}N & 629 \color{red}a\color{green}C + \color{red}b\color{green}G + \color{red}c\color{green}K + \color{red}d\color{green}O & 630 \color{red}a\color{magenta}D + \color{red}b\color{magenta}H + \color{red}c\color{magenta}L + \color{red}d\color{magenta}P \\ 631 \color{blue}e\color{red}A + \color{blue}f\color{red}E + \color{blue}g\color{red}I + \color{blue}h\color{red}M & 632 \color{blue}{eB} + \color{blue}{fF} + \color{blue}{gJ} + \color{blue}{hN} & 633 \color{blue}e\color{green}C + \color{blue}f\color{green}G + \color{blue}g\color{green}K + \color{blue}h\color{green}O & 634 \color{blue}e\color{magenta}D + \color{blue}f\color{magenta}H + \color{blue}g\color{magenta}L + \color{blue}h\color{magenta}P \\ 635 \color{green}i\color{red}A + \color{green}j\color{red}E + \color{green}k\color{red}I + \color{green}l\color{red}M & 636 \color{green}i\color{blue}B + \color{green}j\color{blue}F + \color{green}k\color{blue}J + \color{green}l\color{blue}N & 637 \color{green}{iC} + \color{green}{jG} + \color{green}{kK} + \color{green}{lO} & 638 \color{green}i\color{magenta}D + \color{green}j\color{magenta}H + \color{green}k\color{magenta}L + \color{green}l\color{magenta}P \\ 639 \color{magenta}m\color{red}A + \color{magenta}n\color{red}E + \color{magenta}o\color{red}I + \color{magenta}p\color{red}M & 640 \color{magenta}m\color{blue}B + \color{magenta}n\color{blue}F + \color{magenta}o\color{blue}J + \color{magenta}p\color{blue}N & 641 \color{magenta}m\color{green}C + \color{magenta}n\color{green}G + \color{magenta}o\color{green}K + \color{magenta}p\color{green}O & 642 \color{magenta}{mD} + \color{magenta}{nH} + \color{magenta}{oL} + \color{magenta}{pP} 643 \end{bmatrix}]</span>
643<script type="math/tex; mode=display">\begin{bmatrix} 644 \color{red}a & \color{red}b & \color{red}c & \color{red}d \\ 645 \color{blue}e & \color{blue}f & \color{blue}g & \color{blue}h \\ 646 \color{green}i & \color{green}j & \color{green}k & \color{green}l \\ 647 \color{magenta}m & \color{magenta}n & \color{magenta}o & \color{magenta}p 648 \end{bmatrix} 649 \cdot 650 \begin{bmatrix} 651 \color{red}A & \color{blue}B & \color{green}C & \color{magenta}D \\ 652 \color{red}E & \color{blue}F & \color{green}G & \color{magenta}H \\ 653 \color{red}I & \color{blue}J & \color{green}K & \color{magenta}L \\ 654 \color{red}M & \color{blue}N & \color{green}O & \color{magenta}P 655 \end{bmatrix} 656 = \\ 657 \begin{bmatrix} 658 \color{red}{aA} + \color{red}{bE} + \color{red}{cI} + \color{red}{dM} & 659 \color{red}a\color{blue}B + \color{red}b\color{blue}F + \color{red}c\color{blue}J + \color{red}d\color{blue}N & 660 \color{red}a\color{green}C + \color{red}b\color{green}G + \color{red}c\color{green}K + \color{red}d\color{green}O & 661 \color{red}a\color{magenta}D + \color{red}b\color{magenta}H + \color{red}c\color{magenta}L + \color{red}d\color{magenta}P \\ 662 \color{blue}e\color{red}A + \color{blue}f\color{red}E + \color{blue}g\color{red}I + \color{blue}h\color{red}M & 663 \color{blue}{eB} + \color{blue}{fF} + \color{blue}{gJ} + \color{blue}{hN} & 664 \color{blue}e\color{green}C + \color{blue}f\color{green}G + \color{blue}g\color{green}K + \color{blue}h\color{green}O & 665 \color{blue}e\color{magenta}D + \color{blue}f\color{magenta}H + \color{blue}g\color{magenta}L + \color{blue}h\color{magenta}P \\ 666 \color{green}i\color{red}A + \color{green}j\color{red}E + \color{green}k\color{red}I + \color{green}l\color{red}M & 667 \color{green}i\color{blue}B + \color{green}j\color{blue}F + \color{green}k\color{blue}J + \color{green}l\color{blue}N & 668 \color{green}{iC} + \color{green}{jG} + \color{green}{kK} + \color{green}{lO} & 669 \color{green}i\color{magenta}D + \color{green}j\color{magenta}H + \color{green}k\color{magenta}L + \color{green}l\color{magenta}P \\ 670 \color{magenta}m\color{red}A + \color{magenta}n\color{red}E + \color{magenta}o\color{red}I + \color{magenta}p\color{red}M & 671 \color{magenta}m\color{blue}B + \color{magenta}n\color{blue}F + \color{magenta}o\color{blue}J + \color{magenta}p\color{blue}N & 672 \color{magenta}m\color{green}C + \color{magenta}n\color{green}G + \color{magenta}o\color{green}K + \color{magenta}p\color{green}O & 673 \color{magenta}{mD} + \color{magenta}{nH} + \color{magenta}{oL} + \color{magenta}{pP} 674 \end{bmatrix}</script>
674 675 676<p>The above is commonly recognized among mathematicians as an <em>indecipherable mess</em>. To get a better idea of what's going on, let's consider two 2-by-2 matrices instead.</p> 677 678<span class="MathJax_Preview">[\begin{bmatrix} 679 \color{red}1 & \color{red}2 \\ 680 \color{blue}3 & \color{blue}4 681 \end{bmatrix} 682 \cdot 683 \begin{bmatrix} 684 \color{green}a & \color{magenta}b \\ 685 \color{green}c & \color{magenta}d 686 \end{bmatrix} 687 = 688 \begin{bmatrix} 689 \color{red}1\cdot \color{green}a + \color{red}2 \cdot \color{green}c & \color{red}1 \cdot \color{magenta}b + \color{red}2 \cdot \color{magenta}d \\ 690 \color{blue}3\cdot \color{green}a + \color{blue}4 \cdot \color{green}c & \color{blue}3 \cdot \color{magenta}b + \color{blue}4 \cdot \color{magenta}d 691 \end{bmatrix}]</span>
691<script type="math/tex; mode=display">\begin{bmatrix} 692 \color{red}1 & \color{red}2 \\ 693 \color{blue}3 & \color{blue}4 694 \end{bmatrix} 695 \cdot 696 \begin{bmatrix} 697 \color{green}a & \color{magenta}b \\ 698 \color{green}c & \color{magenta}d 699 \end{bmatrix} 700 = 701 \begin{bmatrix} 702 \color{red}1\cdot \color{green}a + \color{red}2 \cdot \color{green}c & \color{red}1 \cdot \color{magenta}b + \color{red}2 \cdot \color{magenta}d \\ 703 \color{blue}3\cdot \color{green}a + \color{blue}4 \cdot \color{green}c & \color{blue}3 \cdot \color{magenta}b + \color{blue}4 \cdot \color{magenta}d 704 \end{bmatrix}</script>
704 705 706<p>Try to see the pattern here with help of the colors. The factors on the left side (<code>1,2</code> and <code>3,4</code>) of the multiplication dot are the values in the row of the first matrix. The factors on the right side are the values in the rows of the second matrix repeatedly. It is not necessary to remember how exactly this works, but it's good to have seen how it's done at least once.</p> 707 708<h3>Combining transformations</h3> 709 710<p>To demonstrate the multiplication of two matrices, let's try scaling a given vector by <code>(2,2,2)</code> and translating it by <code>(1,2,3)</code>. Given the translation and scaling matrices above, the following product is calculated:</p> 711 712<span class="MathJax_Preview">[M_\text{translate}\cdot M_\text{scale} = 713 \begin{bmatrix} 714 \color{red}1 & \color{red}0 & \color{red}0 & \color{red}1 \\ 715 \color{blue}0 & \color{blue}1 & \color{blue}0 & \color{blue}2 \\ 716 \color{green}0 & \color{green}0 & \color{green}1 & \color{green}3 \\ 717 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 718 \end{bmatrix} 719 \cdot 720 \begin{bmatrix} 721 \color{red}{2} & \color{red}0 & \color{red}0 & \color{red}0 \\ 722 \color{blue}0 & \color{blue}{2} & \color{blue}0 & \color{blue}0 \\ 723 \color{green}0 & \color{green}0 & \color{green}{2} & \color{green}0 \\ 724 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 725 \end{bmatrix} 726 = 727 \begin{bmatrix} 728 \color{red}{2} & \color{red}0 & \color{red}0 & \color{red}1 \\ 729 \color{blue}0 & \color{blue}{2} & \color{blue}0 & \color{blue}2 \\ 730 \color{green}0 & \color{green}0 & \color{green}{2} & \color{green}3 \\ 731 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 732 \end{bmatrix}]</span>
732<script type="math/tex; mode=display">M_\text{translate}\cdot M_\text{scale} = 733 \begin{bmatrix} 734 \color{red}1 & \color{red}0 & \color{red}0 & \color{red}1 \\ 735 \color{blue}0 & \color{blue}1 & \color{blue}0 & \color{blue}2 \\ 736 \color{green}0 & \color{green}0 & \color{green}1 & \color{green}3 \\ 737 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 738 \end{bmatrix} 739 \cdot 740 \begin{bmatrix} 741 \color{red}{2} & \color{red}0 & \color{red}0 & \color{red}0 \\ 742 \color{blue}0 & \color{blue}{2} & \color{blue}0 & \color{blue}0 \\ 743 \color{green}0 & \color{green}0 & \color{green}{2} & \color{green}0 \\ 744 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 745 \end{bmatrix} 746 = 747 \begin{bmatrix} 748 \color{red}{2} & \color{red}0 & \color{red}0 & \color{red}1 \\ 749 \color{blue}0 & \color{blue}{2} & \color{blue}0 & \color{blue}2 \\ 750 \color{green}0 & \color{green}0 & \color{green}{2} & \color{green}3 \\ 751 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 752 \end{bmatrix}</script>
752 753 754<p>Notice how we want to scale the vector first, but the scale transformation comes last in the multiplication. Pay attention to this when combining transformations or you'll get the opposite of what you've asked for.</p> 755 756<p>Now, let's try to transform a vector and see if it worked:</p> 757 758<span class="MathJax_Preview">[\begin{bmatrix} 759 \color{red}{2} & \color{red}0 & \color{red}0 & \color{red}1 \\ 760 \color{blue}0 & \color{blue}{2} & \color{blue}0 & \color{blue}2 \\ 761 \color{green}0 & \color{green}0 & \color{green}{2} & \color{green}3 \\ 762 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 763 \end{bmatrix} 764 \cdot 765 \begin{pmatrix} 766 x \\ 767 y \\ 768 z \\ 769 1 770 \end{pmatrix} 771 = 772 \begin{pmatrix} 773 \color{red}2 x + \color{red}1 \\ 774 \color{blue}2y + \color{blue}2 \\ 775 \color{green}2z + \color{green}3 \\ 776 1 777 \end{pmatrix}]</span>
777<script type="math/tex; mode=display">\begin{bmatrix} 778 \color{red}{2} & \color{red}0 & \color{red}0 & \color{red}1 \\ 779 \color{blue}0 & \color{blue}{2} & \color{blue}0 & \color{blue}2 \\ 780 \color{green}0 & \color{green}0 & \color{green}{2} & \color{green}3 \\ 781 \color{magenta}0 & \color{magenta}0 & \color{magenta}0 & \color{magenta}1 782 \end{bmatrix} 783 \cdot 784 \begin{pmatrix} 785 x \\ 786 y \\ 787 z \\ 788 1 789 \end{pmatrix} 790 = 791 \begin{pmatrix} 792 \color{red}2 x + \color{red}1 \\ 793 \color{blue}2y + \color{blue}2 \\ 794 \color{green}2z + \color{green}3 \\ 795 1 796 \end{pmatrix}</script>
796 797 798<p>Perfect! The vector is first scaled by two and then shifted in position by <code>(1,2,3)</code>.</p> 799 800<h2>Transformations in OpenGL</h2> 801 802<p>You've seen in the previous sections how basic transformations can be applied to vectors to move them around in the world. The job of transforming 3D points into 2D coordinates on your screen is also accomplished through matrix transformations. Just like the graphics pipeline, transforming a vector is done step-by-step. Although OpenGL allows you to decide on these steps yourself, all 3D graphics applications use a variation of the process described here.</p> 803 804<p><img src="media/img/c4_transformation.png" alt="" /></p> 805 806<p>Each transformation transforms a vector into a new coordinate system, thus moving to the next step. These transformations and coordinate systems will be discussed below in more detail.</p> 807 808<h3>Model matrix</h3> 809 810<p>The model matrix transforms a position in a model to the position in the world. This position is affected by the position, scale and rotation of the model that is being drawn. It is generally a combination of the simple transformations you've seen before. If you are already specifying your vertices in world coordinates (common when drawing a simple test scene), then this matrix can simply be set to the identity matrix.</p> 811 812<h3>View matrix</h3> 813 814<p>In real life you're used to moving the camera to alter the view of a certain scene, in OpenGL it's the other way around. The camera in OpenGL cannot move and is defined to be located at <code>(0,0,0)</code> facing the negative Z direction. That means that instead of moving and rotating the camera, the world is moved and rotated around the camera to construct the appropriate view.</p> 815 816<blockquote> 817 <p>Older versions of OpenGL forced you to use <em>ModelView</em> and <em>Projection</em> transformations. The ModelView matrix combined the model and view transformations into one. I personally find it is easier to separate the two, so the view transformation can be modified independently of the model matrix.</p> 818</blockquote> 819 820<p>That means that to simulate a camera transformation, you actually have to transform the world with the inverse of that transformation. Example: if you want to move the camera up, you have to move the world down instead.</p> 821 822<h3>Projection matrix</h3> 823 824<p>After the world has been aligned with your camera using the view transformation, the projection transformation can be applied, resulting in the clip coordinates. If you're doing a perspective transformation, these clip coordinates are not ready to be used as normalized device coordinates just yet.</p> 825 826<p>To transform the clipping coordinate into a normalized device coordinate, <em>perspective division</em> has to be performed. A clipping coordinate resulting from a perspective projection has a number different than 1 in the fourth row, also known as <code>w</code>. This number directly reflects the effect of objects further away being smaller than those up front.</p> 827 828<span class="MathJax_Preview">[v_\text{normalized} = 829 \begin{pmatrix} 830 x_\text{clip} / w_\text{clip} \\ 831 y_\text{clip} / w_\text{clip} \\ 832 z_\text{clip} / w_\text{clip} 833 \end{pmatrix}]</span>
833<script type="math/tex; mode=display">v_\text{normalized} = 834 \begin{pmatrix} 835 x_\text{clip} / w_\text{clip} \\ 836 y_\text{clip} / w_\text{clip} \\ 837 z_\text{clip} / w_\text{clip} 838 \end{pmatrix}</script>
838 839 840<p>The <code>x</code> and <code>y</code> coordinates will be in the familiar <code>-1</code> and <code>1</code> range now, which OpenGL can transform into window coordinates. The <code>z</code> is known as the depth and will play an important role in the next chapter.</p> 841 842<p>The coordinates resulting from the projection transformation are called clipping coordinates because the value of <code>w</code> is used to determine whether an object is too close or behind the camera or too far away to be drawn. The projection matrix is created with those limits, so you'll be able to specify these yourself.</p> 843 844<h3>Putting it all together</h3> 845 846<p>To sum it all up, the final transformation of a vertex is the product of the model, view and projection matrices.</p> 847 848<span class="MathJax_Preview">[v' = M_\text{proj} \cdot M_\text{view} \cdot M_\text{model} \cdot v]</span>
848<script type="math/tex; mode=display">v' = M_\text{proj} \cdot M_\text{view} \cdot M_\text{model} \cdot v</script>
848 849 850<p>This operation is typically performed in the vertex shader and assigned to the <code>gl_Position</code> return value in clipping coordinates. OpenGL will perform the perspective division and transformation into window coordinates. It is important to be aware of these steps, because you'll have to do them yourself when working with techniques like shadow mapping.</p> 851 852<h2>Using transformations for 3D</h2> 853 854<p>Now that you know three important transformations, it is time to implement these in code to create an actual 3D scene. You can use any of the programs developed in the last two chapters as a base, but I'll use the texture blending sample from the end of the last chapter here.</p> 855 856<p>To introduce matrices in the code, we can make use of the GLM (OpenGL Math) library. This library comes with vector and matrix classes and will handle all the math efficiently without ever having to worry about it. It is a header-only library, which means you don't have to link with anything.</p> 857 858<p>To use it, add the GLM root directory to your include path and include these three headers:</p> 859 860<pre><code class="cpp">#include <glm/glm.hpp> 861#include <glm/gtc/matrix_transform.hpp> 862#include <glm/gtc/type_ptr.hpp> 863</code></pre> 864 865<p>The second header includes functions to ease the calculation of the view and projection matrices. The third header adds functionality for converting a matrix object into a float array for usage in OpenGL.</p> 866 867<h3>A simple transformation</h3> 868 869<p>Before diving straight into 3D, let's first try a simple 2D rotation.</p> 870 871<pre><code class="cpp">glm::mat4 trans = glm::mat4(1.0f); 872trans = glm::rotate(trans, glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f)); 873</code></pre> 874 875<p>The first line creates a new 4-by-4 matrix and initializes it to the identity matrix. The <code>glm::rotate</code> function multiplies this matrix by a rotation transformation of 180 degrees around the Z axis. Remember that since the screen lies in the XY plane, the Z axis is the axis you want to rotate points around.</p> 876 877<p>To see if it works, let's try to rotate a vector with this transformation:</p> 878 879<pre><code class="cpp">glm::vec4 result = trans * glm::vec4(1.0f, 0.0f, 0.0f, 1.0f); 880printf("%f, %f, %f\n", result.x, result.y, result.z); 881</code></pre> 882 883<p>As expected, the output is <code>(-1,0,0)</code>. A counter-clockwise rotation of 180 degrees of a vector pointing to the right results in a vector pointing to the left. Note that the rotation would be clockwise if an axis <code>(0,0,-1)</code> was used.</p> 884 885<p>The next step is to perform this transformation in the vertex shader to rotate every drawn vertex. GLSL has a special <code>mat4</code> type to hold matrices and we can use that to upload the transformation to the GPU as uniform.</p> 886 887<pre><code class="cpp">GLint uniTrans = glGetUniformLocation(shaderProgram, "trans"); 888glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(trans)); 889</code></pre> 890 891<p>The second parameter of the <a href="http://docs.gl/gl3/glUniform"><code>glUniformMatrix4fv</code></a> function specifies how many matrices are to be uploaded, because you can have arrays of matrices in GLSL. The third parameter specifies whether the specified matrix should be transposed before usage. This is related to the way matrices are stored as <code>float</code> arrays in memory; you don't have to worry about it. The last parameter specifies the matrix to upload, where the <code>glm::value_ptr</code> function converts the matrix class into an array of 16 (4x4) floats.</p> 892 893<p>All that remains is updating the vertex shader to include this uniform and use it to transform each vertex:</p> 894 895<pre><code class="cpp">#version 150 core 896 897in vec2 position; 898in vec3 color; 899in vec2 texcoord; 900 901out vec3 Color; 902out vec2 Texcoord; 903 904uniform mat4 trans; 905 906void main() 907{ 908 Color = color; 909 Texcoord = texcoord; 910 gl_Position = trans * vec4(position, 0.0, 1.0); 911} 912</code></pre> 913 914<p>The primitives in your scene will now be upside down.</p> 915 916<p><img src="media/img/c4_window.png" alt="" /></p> 917 918<p>To spice things up a bit, you could change the rotation with time:</p> 919 920<pre><code class="cpp">auto t_start = std::chrono::high_resolution_clock::now(); 921 922... 923 924// Calculate transformation 925auto t_now = std::chrono::high_resolution_clock::now(); 926float time = std::chrono::duration_cast<std::chrono::duration<float>>(t_now - t_start).count(); 927 928glm::mat4 trans; 929trans = glm::rotate( 930 trans, 931 time * glm::radians(180.0f), 932 glm::vec3(0.0f, 0.0f, 1.0f) 933); 934glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(trans)); 935 936// Draw a rectangle from the 2 triangles using 6 indices 937glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 938 939... 940</code></pre> 941 942<p>This will result in something like this:</p> 943 944<div class="livedemo_wrap"> 945 <div class="livedemo" id="demo_c4_rotation" style="background: url('/media/img/c4_window2.png')"> 946 <canvas width="640" height="480"></canvas> 947
947<script type="text/javascript" src="https://open.gl/content/demos/c4_rotation.js"></script>
947 948 </div> 949</div> 950 951<p>You can find the full code <a href="https://open.gl/content/code/c4_transformation.txt">here</a> if you have any issues.</p> 952 953<h3>Going 3D</h3> 954 955<p>The rotation above can be considered the model transformation, because it transforms the vertices in object space to world space using the rotation of the object.</p> 956 957<pre><code class="cpp">glm::mat4 view = glm::lookAt( 958 glm::vec3(1.2f, 1.2f, 1.2f), 959 glm::vec3(0.0f, 0.0f, 0.0f), 960 glm::vec3(0.0f, 0.0f, 1.0f) 961); 962GLint uniView = glGetUniformLocation(shaderProgram, "view"); 963glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view)); 964</code></pre> 965 966<p>To create the view transformation, GLM offers the useful <code>glm::lookAt</code> function that simulates a moving camera. The first parameter specifies the position of the camera, the second the point to be centered on-screen and the third the <code>up</code> axis. Here <code>up</code> is defined as the Z axis, which implies that the XY plane is the "ground".</p> 967 968<pre><code class="cpp">glm::mat4 proj = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 1.0f, 10.0f); 969GLint uniProj = glGetUniformLocation(shaderProgram, "proj"); 970glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj)); 971</code></pre> 972 973<p>Similarly, GLM comes with the <code>glm::perspective</code> function to create a perspective projection matrix. The first parameter is the vertical field-of-view, the second parameter the aspect ratio of the screen and the last two parameters are the <em>near</em> and <em>far</em> planes.</p> 974 975<blockquote> 976 <p><strong>Field-of-view</strong> <br /><br /> 977 The field-of-view defines the angle between the top and bottom of the 2D surface on which the world will be projected. Zooming in games is often accomplished by decreasing this angle as opposed to moving the camera closer, because it more closely resembles real life.</p> 978 979 <p><img src="media/img/c4_fov.png" alt="" /></p> 980 981 <p>By decreasing the angle, you can imagine that the "rays" from the camera spread out less and thus cover a smaller area of the scene.</p> 982</blockquote> 983 984<p>The near and far planes are known as the clipping planes. Any vertex closer to the camera than the <code>near</code> clipping plane and any vertex farther away than the <code>far</code> clipping plane is clipped as these influence the <code>w</code> value.</p> 985 986<p>Now piecing it all together, the vertex shader looks something like this:</p> 987 988<pre><code class="cpp">#version 150 core 989 990in vec2 position; 991in vec3 color; 992in vec2 texcoord; 993 994out vec3 Color; 995out vec2 Texcoord; 996 997uniform mat4 model; 998uniform mat4 view; 999uniform mat4 proj; 1000 1001void main() 1002{ 1003 Color = color; 1004 Texcoord = texcoord; 1005 gl_Position = proj * view * model * vec4(position, 0.0, 1.0); 1006} 1007</code></pre> 1008 1009<p>Notice that I've renamed the matrix previously known as <code>trans</code> to <code>model</code> and it is still updated every frame.</p> 1010 1011<div class="livedemo_wrap"> 1012 <div class="livedemo" id="demo_c4_3d" style="background: url('/media/img/c4_window3.png')"> 1013 <canvas width="640" height="480"></canvas> 1014
1014<script type="text/javascript" src="https://open.gl/content/demos/c4_3d.js"></script>
1014 1015 </div> 1016</div> 1017 1018<p>Success! You can find the full code <a href="https://open.gl/content/code/c4_3d.txt">here</a> if you get stuck.</p> 1019 1020<h2>Exercises</h2> 1021 1022<ul> 1023<li>Make the rectangle with the blended image grow bigger and smaller with <code>sin</code>. (<a href="https://open.gl/content/code/c4_exercise_1.txt">Solution</a>)</li> 1024<li>Make the rectangle flip around the X axis after pressing the space bar and slowly stop again. (<a href="https://open.gl/content/code/c4_exercise_2.txt">Solution</a>)</li> 1025</ul> 1026 </article> 1027 1028 <div id="adbox-article"> 1029 <hr /> 1030 1031
1031<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
1031 1032 <!-- Open.GL Responsive --> 1033 <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-4259747131061893" data-ad-slot="6609097747" data-ad-format="auto"></ins> 1034
1034<script> 1035 (adsbygoogle = window.adsbygoogle || []).push({}); 1036 </script>
1036 1037 </div> 1038 1039 1040 <!-- Disqus comments --> 1041 <hr /> 1042 <aside id="disqus_thread"></aside> 1043
1043<script type="text/javascript"> 1044 var dsq = document.createElement("script"); 1045 dsq.type = "text/javascript"; 1046 dsq.async = true; 1047 dsq.src = "//opengl.disqus.com/embed.js"; 1048 document.getElementsByTagName("head")[0].appendChild( dsq ); 1049 </script>
1049 1050 </main> 1051 </div> 1052 </body> 1053</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.