<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hadi</title>
    <description>The latest articles on DEV Community by Hadi (@hadicya).</description>
    <link>https://dev.to/hadicya</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1140584%2F99cd6a41-c6f9-41f9-b981-7f06d3528aff.png</url>
      <title>DEV Community: Hadi</title>
      <link>https://dev.to/hadicya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hadicya"/>
    <language>en</language>
    <item>
      <title>&lt;Part 3&gt; Make spinning 3D shapes in SDL2 and OpenGL</title>
      <dc:creator>Hadi</dc:creator>
      <pubDate>Tue, 19 Dec 2023 05:54:52 +0000</pubDate>
      <link>https://dev.to/hadicya/make-spinning-3d-shapes-in-sdl2-and-opengl-992</link>
      <guid>https://dev.to/hadicya/make-spinning-3d-shapes-in-sdl2-and-opengl-992</guid>
      <description>&lt;p&gt;Up to now, we've created a window in SDL2 using OpenGL, built a Mesh, and began writing shaders in GLSL to get a stretched-out square. In this final part, we will explain rendering in 3D, making things spin, and the Linear Algebra behind it!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;DISCLAIMER: This walkthrough assumes knowledge from Part 1 and Part 2 and a working knowledge of C++ and how to compile it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;GitHub Repo: &lt;a href="https://github.com/HadiCya/spinning_shapes"&gt;https://github.com/HadiCya/spinning_shapes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;YouTube Version:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/ac6mf05O_qw"&gt;https://youtu.be/ac6mf05O_qw&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Getting Mathematical!
&lt;/h1&gt;

&lt;p&gt;We're going to be running these calculations in our &lt;code&gt;main.cpp&lt;/code&gt; file, and we'll get started by updating our includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;#include &amp;lt;SDL.h&amp;gt;#include "mesh.h"#include "loadShader.h"#include &amp;lt;glm/glm.hpp&amp;gt;#include &amp;lt;glm/gtc/matrix_transform.hpp&amp;gt;#include &amp;lt;glm/gtc/type_ptr.hpp&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, we will include the necessary headers for linear algebra operations using the GLM library. This enables the main application to work with vectors and matrices required for 3D transformations.&lt;/p&gt;

&lt;p&gt;We're going to now create and configure matrices for transforming the object in 3D space. We're going to write this code after we call &lt;code&gt;glClear()&lt;/code&gt; in our while loop.&lt;/p&gt;
&lt;h2&gt;
  
  
  Model Matrix
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;glm::mat4 model = glm::mat4(1.0f);model = glm::rotate(model, glm::radians(50.0f), glm::vec3(0.5f, 1.0f, 0.0f));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This line of code creates a rotation matrix. In computer graphics, rotation matrices are used to rotate objects around a specified axis.&lt;/p&gt;
&lt;h3&gt;
  
  
  Let's get into the math behind the code:
&lt;/h3&gt;

&lt;p&gt;Initially, we define &lt;code&gt;model&lt;/code&gt; as an Identity matrix, which, in linear algebra, is practically 1.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;model=[1000 0100 0010 0001]model = \begin{bmatrix} 1 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \ 0 &amp;amp; 1 &amp;amp; 0 &amp;amp; 0 \ 0 &amp;amp; 0 &amp;amp; 1 &amp;amp; 0 \ 0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1 \end{bmatrix} &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;l&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size1"&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size1"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;&lt;code&gt;glm::vec3(0.5f, 1.0f, 0.0f)&lt;/code&gt; defines the axis of rotation. Here, it's a vector pointing partially up and partially towards the x-axis:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;u⃗=&amp;lt;0.5,1,0&amp;gt;\vec{u} = \left&amp;lt;0.5, 1, 0 \right&amp;gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="overlay"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;⟨&lt;/span&gt;&lt;span class="mord"&gt;0.5&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;⟩&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;We need to normalize the axis:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;u′⃗=&amp;lt;0.50.52+12,10.52+12,0&amp;gt;\vec{u'} = \left&amp;lt; \frac{0.5}{\sqrt{0.5^2 + 1^2}}, \frac{1}{\sqrt{0.5^2 + 1^2}}, 0 \right&amp;gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="overlay"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size3"&gt;⟨&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord sqrt"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class="svg-align"&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0.&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;5&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="hide-tail"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0.5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord sqrt"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class="svg-align"&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0.&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;5&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="hide-tail"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size3"&gt;⟩&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;glm::radians(50.0f)&lt;/code&gt; converts 50 degrees into radians, as trigonometric functions in GLM use radians:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θ=radians(50)=50π180\theta = \text{radians}(50) = \frac{50 \pi}{180}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;radians&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;50&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;180&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;50&lt;/span&gt;&lt;span class="mord mathnormal"&gt;π&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;glm::rotate&lt;/code&gt; function creates a 4x4 matrix that rotates points in 3D space around the given axis by the specified angle. The rotation matrix is derived from Rodrigues' rotation formula, combining the components of the axis vector and the sine and cosine of the angle.&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;R=[cos⁡(θ)+ux2(1−cos⁡(θ))uxuy(1−cos⁡(θ))−uzsin⁡(θ)uxuz(1−cos⁡(θ))+uysin⁡(θ)0 uyux(1−cos⁡(θ))+uzsin⁡(θ)cos⁡(θ)+uy2(1−cos⁡(θ))uyuz(1−cos⁡(θ))−uxsin⁡(θ)0 uzux(1−cos⁡(θ))−uysin⁡(θ)uzuy(1−cos⁡(θ))+uxsin⁡(θ)cos⁡(θ)+uz2(1−cos⁡(θ))0 0001]R = \begin{bmatrix} \cos(\theta) + u_x^2 (1 - \cos(\theta)) &amp;amp; u_xu_y(1 - \cos(\theta)) - u_z\sin(\theta) &amp;amp; u_xu_z(1 - \cos(\theta)) + u_y\sin(\theta) &amp;amp; 0 \ u_yu_x(1 - \cos(\theta)) + u_z\sin(\theta) &amp;amp; \cos(\theta) + u_y^2(1 - \cos(\theta)) &amp;amp; u_yu_z(1 - \cos(\theta)) - u_x\sin(\theta) &amp;amp; 0 \ u_zu_x(1 - \cos(\theta)) - u_y\sin(\theta) &amp;amp; u_zu_y(1 - \cos(\theta)) + u_x\sin(\theta) &amp;amp; \cos(\theta) + u_z^2(1 - \cos(\theta)) &amp;amp; 0 \ 0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1 \end{bmatrix}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size1"&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size1"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;When you plug in everything we've calculated thus far into Matrix &lt;strong&gt;R&lt;/strong&gt; , the resulting matrix will be stored into &lt;code&gt;model&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  View Matrix
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;glm::mat4 view = glm::mat4(1.0f);view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The view matrix is used to transform vertices from world space to camera (view) space. It's analogous to moving and orienting a camera within the scene.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;glm::vec3(0.0f, 0.0f, -3.0f)&lt;/code&gt; indicates that the view is being translated along the z-axis.&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t⃗=&amp;lt;0,0,−3&amp;gt;\vec{t} = \left&amp;lt;0, 0, -3 \right&amp;gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="overlay"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;⟨&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;−&lt;/span&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;⟩&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;glm::translate&lt;/code&gt; function constructs a 4x4 translation matrix. This matrix is an identity matrix with the translation vector added to the fourth column. It shifts the position of all points in the scene relative to the camera.&lt;/p&gt;

&lt;p&gt;For a translation by a vector &lt;strong&gt;t,&lt;/strong&gt; the translation matrix &lt;strong&gt;T&lt;/strong&gt; is:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;T=[100tx 010ty 001tz 0001]T = \begin{bmatrix} 1 &amp;amp; 0 &amp;amp; 0 &amp;amp; t_x \ 0 &amp;amp; 1 &amp;amp; 0 &amp;amp; t_y \ 0 &amp;amp; 0 &amp;amp; 1 &amp;amp; t_z \ 0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1 \end{bmatrix}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size1"&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size1"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;When you plug in vector &lt;code&gt;t&lt;/code&gt; into Matrix &lt;strong&gt;T&lt;/strong&gt; , the resulting matrix will be stored into &lt;code&gt;view&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Projection Matrix
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;glm::mat4 projection = glm::perspective(glm::radians(60.0f), float(screen_width)/(float)screen_height, 0.1f, 100.0f);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The projection matrix maps a 3D world into a 2D view, akin to how a camera lens focuses light onto a film.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;glm::perspective&lt;/code&gt; creates a frustum that defines the visible space. It scales the x and y coordinates of vertices based on their depth (z-value), causing more distant objects to appear smaller and creating a sense of depth.&lt;/p&gt;

&lt;p&gt;The frustum in the context of the &lt;code&gt;glm::perspective&lt;/code&gt; function is a crucial concept in 3D graphics, especially concerning the perspective projection matrix. Let's break down what a frustum is and how it works in the creation of a perspective projection:&lt;/p&gt;
&lt;h3&gt;
  
  
  What is a Frustum?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A frustum in 3D graphics is a geometric shape that resembles a pyramid with the top cut off. In the case of perspective projection, it's more specifically a truncated pyramid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The frustum defines the portion of the 3D space that is visible through the camera. Only objects within this frustum will be rendered on the screen.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Components of the Frustum:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Near Plane&lt;/strong&gt; : This is the closest plane to the viewer (camera). In your code, it's set to 0.1f units from the viewer. Objects closer than this plane are not visible or rendered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Far Plane&lt;/strong&gt; : This is the farthest plane from the viewer, set to 100.0f units in your code. Objects beyond this distance are also not visible or rendered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sides of the Frustum&lt;/strong&gt; : The sides of the frustum are defined by the field of view (FOV). A wider FOV creates a wider frustum, capturing a broader view of the scene but potentially introducing more distortion (similar to a wide-angle lens in photography).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Top and Bottom&lt;/strong&gt; : The aspect ratio (width divided by height) determines the relative heights of the top and bottom planes of the frustum.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Role in Perspective Projection:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The purpose of the frustum in perspective projection is to define how 3D coordinates are projected onto the 2D plane of the screen.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The projection matrix, &lt;strong&gt;P,&lt;/strong&gt; maps coordinates from this 3D frustum to a normalized 2D coordinate system. It scales the x and y coordinates of the vertices based on their z-value (depth), which makes objects appear smaller as they get farther away, creating a realistic depth perception.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;P=[cot⁡(fovy2)aspect000 0cot⁡(fovy2)00 00zfar+znearznear−zfar2×zfar×znearznear−zfar 00−10]P = \begin{bmatrix} \frac{\cot{(\frac{fov_y}{2})}}{aspect} &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \ 0 &amp;amp; \cot{(\frac{fov_y}{2})} &amp;amp; 0 &amp;amp; 0 \ 0 &amp;amp; 0 &amp;amp; \frac{z_{\text{far}} + z_{\text{near}}}{z_{\text{near}} - z_{\text{far}}} &amp;amp; \frac{2 \times z_{\text{far}} \times z_{\text{near}}}{z_{\text{near}} - z_{\text{far}}} \ 0 &amp;amp; 0 &amp;amp; -1 &amp;amp; 0 \end{bmatrix}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size2"&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;p&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;ec&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mop mtight"&gt;&lt;span class="mtight"&gt;c&lt;/span&gt;&lt;span class="mtight"&gt;o&lt;/span&gt;&lt;span class="mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace mtight"&gt;&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mopen nulldelimiter sizing reset-size3 size6"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line mtight"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;f&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;o&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter sizing reset-size3 size6"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;cot&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;f&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;o&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;near&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;far&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;far&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mbin mtight"&gt;+&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;near&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;near&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;far&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;span class="mbin mtight"&gt;×&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;far&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mbin mtight"&gt;×&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;z&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;near&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;−&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size2"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;When you plug in everything we've calculated thus far into Matrix &lt;strong&gt;P&lt;/strong&gt; , the resulting matrix will be stored into &lt;code&gt;projection&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Connecting it to the vertex shader
&lt;/h1&gt;

&lt;p&gt;Now, we need a way to pass these matrices into the vertex shader.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        int modelLoc = glGetUniformLocation(programID, "model"); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); int viewLoc = glGetUniformLocation(programID, "view"); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); int projectionLoc = glGetUniformLocation(programID, "projection"); glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We are going to pass the model, view, and projection matrices to the shaders. The &lt;code&gt;glUniformMatrix4fv&lt;/code&gt; function is an OpenGL function that sets the value of a uniform matrix variable in the shaders. It takes the location of the uniform variable, the number of matrices (1 in this case), a flag for matrix transpose (set to &lt;code&gt;GL_FALSE&lt;/code&gt;), and a pointer to the data.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;vertex.glsl&lt;/code&gt;, we're going to need to grab the variables that we've just defined:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#version 330 corelayout (location = 0) in vec3 aPos;uniform mat4 model;uniform mat4 view;uniform mat4 projection;void main() { gl_Position = projection * view * model * vec4(aPos, 1.0);}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When combining these matrices, the order of multiplication is crucial. The typical order in OpenGL for transforming a vertex &lt;strong&gt;v&lt;/strong&gt; is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Model transformation (rotation in this case)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;View transformation (translation)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Projection transformation&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, the combined transformation matrix &lt;strong&gt;M&lt;/strong&gt; is given by:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;M=P×T×RM = P \times T \times R&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;The final transformed vertex &lt;strong&gt;v&lt;/strong&gt; is obtained by multiplying the vertex's homogeneous coordinate vector &lt;strong&gt;v&lt;/strong&gt; with &lt;strong&gt;M&lt;/strong&gt; :&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;v′=M×vv' = M \times v&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;This process transforms the vertex from its local space (model transformation) to world space (view transformation), and finally to normalized device coordinates (projection transformation), ready for rasterization and rendering on the screen.&lt;/p&gt;

&lt;p&gt;Before we do that, we're going to need to update our &lt;code&gt;vertices&lt;/code&gt; and &lt;code&gt;triangle&lt;/code&gt; arrays in &lt;code&gt;mesh.cpp&lt;/code&gt; to be a 3D cube:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    GLfloat vertices[] = { 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f }; GLint triangles[] = {0, 2, 3, 0, 3, 1, 2, 6, 7, 2, 7, 3, 6, 4, 5, 6, 5, 7, 4, 0, 1, 4, 1, 5, 1, 3, 7, 1, 7, 5, 4, 6, 2, 4, 2, 0};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you forgot how we did this last time, look at &lt;a href="https://hadicya.dev/part-2-make-spinning-3d-shapes-in-sdl2-and-opengl#heading-creating-our-mesh-class"&gt;Part 2&lt;/a&gt; for a more detailed explanation.&lt;/p&gt;

&lt;p&gt;Let's go ahead and run this code! This is what my compilation command looks like now:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clang++ -std=c++20 main.cpp mesh.cpp loadShader.cpp ./glad/src/glad.c -o spinning_shapes -I/Library/Frameworks/SDL2.framework/Headers -I./glad/include -I./glm/ -F/Library/Frameworks -framework SDL2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7wMMtX6y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1702963259239/d55267a8-6e80-4b4b-b199-e6f635f63965.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7wMMtX6y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1702963259239/d55267a8-6e80-4b4b-b199-e6f635f63965.png" alt="" width="800" height="747"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you see a 3D cube, congrats! We are close to making it spin.&lt;/p&gt;

&lt;h1&gt;
  
  
  Making it spin!
&lt;/h1&gt;

&lt;p&gt;To make it spin, all we're going to need to do is update our &lt;code&gt;model&lt;/code&gt; matrix to rotate with time instead of staying at 50 degrees.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;main.cpp&lt;/code&gt; update the code to:&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;Uint32 lastUpdate = SDL_GetTicks();&lt;/code&gt; under the declaration of &lt;code&gt;done&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;Uint32 current = SDL_GetTicks();&lt;/code&gt; as soon as the while loop begins&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;float dT = (current lastUpdate) / 1000.0f;&lt;/code&gt; underneath the &lt;code&gt;glClear()&lt;/code&gt; call&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;*dT&lt;/code&gt; to the rotate matrix in the &lt;code&gt;model&lt;/code&gt; declaration so that it looks like:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;model = glm::rotate(model, glm::radians(50.0f)*dT, glm::vec3(0.5f, 1.0f, 0.0f));&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Simply, this code is going to calculate the difference in time between frames, and then multiply that difference by our rotation, so that it consistently rotates each frame.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O40drRoJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1702964136947/d48c4176-e60d-4681-9518-3c25e3e661a8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O40drRoJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1702964136947/d48c4176-e60d-4681-9518-3c25e3e661a8.gif" alt="" width="800" height="654"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Spinning cube. Speaks for itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  BONUS: Spinning Rhombus
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;mesh.cpp&lt;/code&gt; update the vertices and triangles to make a rhombus:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    GLfloat vertices[] = { 0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, 0.5f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f }; GLint triangles[] = { 0, 4, 1, 1, 4, 2, 2, 4, 3, 3, 4, 0, 0, 5, 1, 1, 5, 2, 2, 5, 3, 3, 5, 0};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when we run our code we get a Rhombus:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TTOoA9ds--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1702964401215/aa5d6968-656a-463a-8bac-bce97b17deea.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TTOoA9ds--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1702964401215/aa5d6968-656a-463a-8bac-bce97b17deea.gif" alt="" width="800" height="654"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I suggest trying to make your mesh to get a better understanding of 3D spaces and how memory management works.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Wrapping Up&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Throughout this series, we have embarked on an exciting journey into the world of 3D graphics programming. Starting from the basics of OpenGL and SDL initialization, we have explored fundamental concepts such as vertices, triangle arrays, and buffer management. Along the way, weve delved into the mathematical principles that make 3D rendering possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Key Takeaways&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Understanding Vertices and Buffers: We understood the role that defining vertices and the order in which to draw them, and how buffers enable efficient storage and manipulation of these vertices on the GPU.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;3D Transformations and Projection: Through matrix mathematics, weve seen how to translate, rotate, and scale objects in a 3D space. While OpenGL GLM handles this math for us, we took the opportunity to see what was happening behind the scenes. We also learned how perspective projection brings depth to our rendering.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating our Spinning Cube! By combining all of the elements we learned, we were able to render a spinning 3D cube, which is the first building block for creating far more complex 3D scenes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Whats Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The door to 3D graphics programming is now wide open. With the foundation laid in this series, you can explore further topics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Texture Mapping: Adding textures to give surfaces realistic appearances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lighting and Shading: Implementing various lighting models to create a more lifelike scene.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;3D Modeling and Animation: Importing and manipulating complex 3D models, and creating intricate animations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether youre looking to build a game, create a simulation, make a movie, or simply experiment with 3D graphics, the skills youve acquired here will be a valuable asset.&lt;/p&gt;

&lt;p&gt;Thank you for joining me on this adventure into 3D graphics programming. Keep experimenting, learning, and most importantly, having fun! Build your castle in the skies, your creativity and intellect will be enough :)&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>opengl</category>
      <category>sdl2</category>
      <category>graphicsprogramming</category>
    </item>
    <item>
      <title>Building Pong with MonoGame: A Step-by-Step Guide</title>
      <dc:creator>Hadi</dc:creator>
      <pubDate>Sun, 08 Oct 2023 19:58:05 +0000</pubDate>
      <link>https://dev.to/hadicya/building-pong-with-monogame-a-step-by-step-guide-1i0k</link>
      <guid>https://dev.to/hadicya/building-pong-with-monogame-a-step-by-step-guide-1i0k</guid>
      <description>&lt;p&gt;In this tutorial, you will create the game Pong in MonoGame using C#. We will be able to play pong with a friend, and more importantly, learn how to build games in MonoGame.&lt;/p&gt;

&lt;p&gt;MonoGame is an open-source, cross-platform game development framework capable of building 2D and 3D games. It is built from the now-expired Microsoft XNA framework, which was popular back in the Xbox 360 days for creating games on the Xbox and PC.&lt;/p&gt;

&lt;p&gt;As a game developer, using MonoGame might seem backward in the world of advanced game engines like Unity and Unreal Engine, which provide many tools and components for you that we'd otherwise have to program ourselves. However, building components of the engine that are specific to your game requires you to understand the code at a far deeper level, which will make you better at identifying programming patterns.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In this tutorial, you will learn how to create a Pong game using MonoGame and C#. This tutorial covers setting up the environment, creating the Paddle and Ball classes, handling collisions, and displaying the score. A basic knowledge of object-oriented programming languages such as C# or C++ is assumed. By the end of this tutorial, you will have a fully functional Pong game to play with a friend and a deeper understanding of MonoGame's framework.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;DISCLAIMER: This walkthrough assumes a basic knowledge of any OOP (Object Oriented Programming) Language, such as C# or C++.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;GitHub Repo: &lt;a href="https://github.com/HadiCya/Pong-MonoGame"&gt;https://github.com/HadiCya/Pong-MonoGame&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;YouTube Version:&lt;/p&gt;

&lt;h1&gt;
  
  
  What you'll need
&lt;/h1&gt;

&lt;p&gt;Let's get set up. We'll need a couple of things to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dotnet.microsoft.com/en-us/download/dotnet/6.0"&gt;.NET 6.0 SDK&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.monogame.net/articles/getting_started/0_getting_started.html"&gt;MonoGame&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First things first, make sure &lt;a href="https://dotnet.microsoft.com/en-us/download/dotnet/6.0"&gt;.NET 6.0 SDK&lt;/a&gt; is installed on your computer matching your operating system (Windows, MacOS, or Linux).&lt;/p&gt;

&lt;p&gt;The recommended way to install MonoGame is by using Visual Studio 2022, because there is already an extension you can use directly in the IDE. Creating a project is a lot more simplified in this way. Follow this guide by &lt;a href="https://docs.monogame.net/articles/getting_started/0_getting_started.html"&gt;MonoGame&lt;/a&gt; to install it for your specific operating system. You will also be able to run it in the command line without an IDE, if you prefer Visual Studio Code, vim, or some other code editor.&lt;/p&gt;

&lt;p&gt;Now that you have it installed, let's create a project.&lt;/p&gt;

&lt;p&gt;If you're using &lt;strong&gt;Visual Studio 2022&lt;/strong&gt; , create a new project, select the &lt;code&gt;MonoGame Cross Platform Desktop Application&lt;/code&gt; option, and name the project Pong.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1OcUJb1D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://docs.monogame.net/images/getting_started/vsmac-mg-new-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1OcUJb1D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://docs.monogame.net/images/getting_started/vsmac-mg-new-2.png" alt="New Template" width="800" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're using the &lt;strong&gt;command line&lt;/strong&gt; , navigate to where you'd like to create a project and type:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dotnet new mgdesktopgl -o Pong&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will create a new dotnet project called Pong.&lt;/p&gt;

&lt;p&gt;Now that you've created a MonoGame project, you'll see that a lot of files have been generated where you created the project. If you're using Visual Studio 2022, go ahead and run the program with the debug button or by pressing &lt;code&gt;F5&lt;/code&gt;. If you're using the command line, type &lt;code&gt;dotnet run&lt;/code&gt;. When you run the project, a blue window should pop up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iWRMIH_A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696712387568/4cd1c7f9-18af-40d5-8388-9ce55ba1d763.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iWRMIH_A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696712387568/4cd1c7f9-18af-40d5-8388-9ce55ba1d763.png" alt="" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you see this, you're ready to get started with MonoGame!&lt;/p&gt;

&lt;h1&gt;
  
  
  Preparing the code
&lt;/h1&gt;

&lt;p&gt;The project that is automatically generated has a lot of files in it, so it may be overwhelming to look at first glance. But, we'll go through the important ones right now and try to understand how the code is structured. This is the general file structure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Bx2vSHP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696713885315/801e1c79-cf5d-4a78-97aa-fb2469a0cf75.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Bx2vSHP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696713885315/801e1c79-cf5d-4a78-97aa-fb2469a0cf75.png" alt="" width="630" height="698"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While there are ways we can reorganize that make sense for a project you'd be working on long term, right now we can use the default structure since we're just making Pong. That being said, the only file we will concern ourselves with (right now) is &lt;code&gt;Game1.cs&lt;/code&gt; which is our game runs.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Game1.cs&lt;/code&gt; we are defining the class &lt;code&gt;Game1&lt;/code&gt;. Let's break it down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Game1()&lt;/code&gt; is the constructor for our class. This is run when we create the instance of our game. The default code is just defining some basic things for the code to run.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Initialize()&lt;/code&gt; is where we will initialize objects inside our game. When we create our paddle class, we will initialize our players here.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;LoadContent()&lt;/code&gt; is where we can load content, such as sprites, fonts, audio, and other content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Update(GameTime gameTime)&lt;/code&gt; is called every frame, and it is where we will update our game logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Draw(GameTime gameTime)&lt;/code&gt; is where we will draw our objects to the screen.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, everything is broken up into clear functions, and we're going to try and keep things clean in this manner while we create our game.&lt;/p&gt;

&lt;p&gt;We're going to try and avoid running too much game logic in the &lt;code&gt;Game1&lt;/code&gt; class, as we want to have clear roles for all the objects in the game. For this project, we can simplify the classes we will make as just &lt;code&gt;Paddle&lt;/code&gt; and &lt;code&gt;Ball&lt;/code&gt;. It may be more intelligent to organize more so there is more separation and more flexibility to change things about the game in the future, but for this tutorial, we're going to just worry about getting a working Pong.&lt;/p&gt;

&lt;p&gt;Before we start coding, let's prepare the existing code for our game.&lt;/p&gt;

&lt;p&gt;Create a file called &lt;code&gt;Globals.cs&lt;/code&gt; so that we can store global variables for our game.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace Pong
{
    class Globals
    {
        public static SpriteBatch spriteBatch;
        public static int WIDTH = 640, HEIGHT = 480;
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our Globals class, we want to store some public global variables, so that we can access them from anywhere in our game. For now, we're going to store the width and height of our screen, as well as &lt;code&gt;SpriteBatch&lt;/code&gt;, which is going to make drawing things to the screen possible.&lt;/p&gt;

&lt;p&gt;Because we've created a global variable &lt;code&gt;spriteBatch&lt;/code&gt;, we can replace all instances of the local private one with the global version. Go into your &lt;code&gt;Game1&lt;/code&gt; class, and delete the &lt;code&gt;_spriteBatch&lt;/code&gt; class variable that was automatically created.&lt;/p&gt;

&lt;p&gt;Replace any mention of &lt;code&gt;_spriteBatch&lt;/code&gt; in &lt;code&gt;Game1&lt;/code&gt; with our newly created &lt;code&gt;Globals.spriteBatch&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let's also update our constructor to use the &lt;code&gt;WIDTH&lt;/code&gt; and &lt;code&gt;HEIGHT&lt;/code&gt; variables we defined earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public Game1() {
    _graphics = new GraphicsDeviceManager(this);
    _graphics.PreferredBackBufferWidth = Globals.WIDTH;
    _graphics.PreferredBackBufferHeight = Globals.HEIGHT;
    Content.RootDirectory = "Content";
    IsMouseVisible = true;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last thing we'll need to do is update our &lt;code&gt;Draw()&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protected override void Draw(GameTime gameTime) {
    GraphicsDevice.Clear(Color.Black);

    Globals.spriteBatch.Begin();
    // TODO: Add your drawing code here            
    Globals.spriteBatch.End();

    base.Draw(gameTime);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to change the Color from &lt;code&gt;Color.CornflowerBlue&lt;/code&gt; to &lt;code&gt;Color.Black&lt;/code&gt; (unless you want your background to be some other color).&lt;/p&gt;

&lt;p&gt;To draw game objects on the screen, start the drawing process by using the &lt;code&gt;Begin()&lt;/code&gt; method on the &lt;code&gt;Globals.spriteBatch&lt;/code&gt; object. This sets up everything needed to show our game elements. After finishing all drawing tasks, end the process by using the &lt;code&gt;End()&lt;/code&gt; method on the &lt;code&gt;Globals.spriteBatch&lt;/code&gt; object. This makes sure all drawing operations are done and the elements show up on the screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UCNIVO9D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696723603318/cc71d14e-32c6-4865-b0f3-57f42f5668aa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UCNIVO9D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696723603318/cc71d14e-32c6-4865-b0f3-57f42f5668aa.png" alt="" width="800" height="632"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not much has changed, but now it will be easier to create objects and draw to the screen. Next, we're going to create the &lt;code&gt;Paddle&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating the Paddle
&lt;/h1&gt;

&lt;p&gt;Let's go ahead and create a file called &lt;code&gt;Paddle.cs&lt;/code&gt; and define our &lt;code&gt;Paddle&lt;/code&gt; class. In this class, create a constructor, a &lt;code&gt;Update()&lt;/code&gt; and a &lt;code&gt;Draw()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;We're also going to want to define a &lt;code&gt;Rectangle&lt;/code&gt; object, which will represent the paddle.&lt;/p&gt;

&lt;p&gt;This is how our class should look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace Pong {
    public class Paddle {
        public Rectangle rect;

        public Paddle() {}
        public void Update(GameTime gameTime) {}
        public void Draw() {}
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we've set up the &lt;code&gt;Paddle&lt;/code&gt; class, let's try just getting a rectangle on the screen.&lt;/p&gt;

&lt;p&gt;In the constructor, let's define what &lt;code&gt;rect&lt;/code&gt; is. The parameters for the MonoGame &lt;code&gt;Rectangle&lt;/code&gt; class is: &lt;code&gt;Rectangle(int x, int y, int width, int height)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we need to fill in the position of the rectangle, x and y, as well as the width and height.&lt;/p&gt;

&lt;p&gt;In computer graphics, we use a different coordinate system than the usual one from math class. The top-left corner of the screen is the starting point &lt;code&gt;(0,0)&lt;/code&gt;. The x-axis shows the horizontal position, and the y-axis shows the vertical position. This system makes it easier to work with graphics on screens and in programming.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WRmZt3fh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696725164891/06d7e30e-c457-4a47-89ff-f366214ae89b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WRmZt3fh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696725164891/06d7e30e-c457-4a47-89ff-f366214ae89b.png" alt="Courtesy of Processing.org" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, let's go to the constructor, and define our &lt;code&gt;rect&lt;/code&gt; variable:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rect = new Rectangle(0, 140, 40, 200)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we're going to want to draw the paddle onto the screen, but before we write anything in the &lt;code&gt;Draw()&lt;/code&gt; function, we need to define a &lt;code&gt;Texture2D&lt;/code&gt; for our rectangle.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Globals.cs&lt;/code&gt;, add &lt;code&gt;public static Texture2D pixel;&lt;/code&gt; to the instance variables.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Game1.cs&lt;/code&gt;, update the &lt;code&gt;LoadContent()&lt;/code&gt; function to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protected override void LoadContent() {
    Globals.spriteBatch = new SpriteBatch(GraphicsDevice);

    Globals.pixel = new Texture2D(GraphicsDevice, 1, 1);
    Globals.pixel.SetData&amp;lt;Color&amp;gt;(new Color[] { Color.White });
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we're doing here is defining the &lt;code&gt;pixel&lt;/code&gt; variable we just created in our &lt;code&gt;Globals&lt;/code&gt; class. Through our code, we're basically just creating a white texture.&lt;/p&gt;

&lt;p&gt;Now, we can go back to our &lt;code&gt;Paddle.cs&lt;/code&gt; class, and update our &lt;code&gt;Draw()&lt;/code&gt; function to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void Draw() {
    Globals.spriteBatch.Draw(Globals.pixel, rect, Color.White);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are accessing the global &lt;code&gt;spriteBatch&lt;/code&gt; variable, and drawing our rectangle to it with our essentially empty texture, with the color white. Because our &lt;code&gt;pixel&lt;/code&gt; variable is white, we can set our &lt;code&gt;Color&lt;/code&gt; to any color we want, but in this case, we'll just keep it white to stay true to the original Pong.&lt;/p&gt;

&lt;p&gt;To get things onto the screen, we need to initialize, update, and draw our &lt;code&gt;Paddle&lt;/code&gt; in the &lt;code&gt;Game1&lt;/code&gt; class. For every matching function, we need to call it in &lt;code&gt;Game1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Game1&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the class variables, add &lt;code&gt;Paddle paddle;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;Initialize()&lt;/code&gt;, add &lt;code&gt;paddle = new Paddle();&lt;/code&gt; right before &lt;code&gt;base.Initialize();&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;Update()&lt;/code&gt;, add &lt;code&gt;paddle.update(gameTime);&lt;/code&gt; right before &lt;code&gt;base.Update(gameTime);&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;Draw()&lt;/code&gt;, add &lt;code&gt;paddle.Draw();&lt;/code&gt; right before &lt;code&gt;Globals.spriteBatch.End();&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go ahead and run the project now&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O8vAxyq_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696794050335/dc84ae68-8330-493f-9d54-0df5c143383b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O8vAxyq_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696794050335/dc84ae68-8330-493f-9d54-0df5c143383b.png" alt="" width="800" height="632"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you did everything correctly, we should be seeing our paddle on the screen! The code is now ready to add movement.&lt;/p&gt;

&lt;p&gt;Back in the &lt;code&gt;Paddle.cs&lt;/code&gt; file, add a new class variable &lt;code&gt;float moveSpeed = 500f;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, let's fill in the &lt;code&gt;Update()&lt;/code&gt; function so we can move the Paddle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void Update(GameTime gameTime) {
    KeyboardState kstate = Keyboard.GetState();
    if (kstate.IsKeyDown(Keys.W) &amp;amp;&amp;amp; rect.Y &amp;gt; 0) {
        rect.Y -= (int)(moveSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
    }
    if (kstate.IsKeyDown(Keys.S) &amp;amp;&amp;amp; rect.Y &amp;lt; Globals.HEIGHT - rect.Height) {
        rect.Y += (int)(moveSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go through this line by line:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;KeyboardState kstate = Keyboard.GetState();&lt;/code&gt; is getting the current state of the Keyboard, which will give us information on what keys are being pressed.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if (kstate.IsKeyDown(Keys.W) &amp;amp;&amp;amp; rect.Y &amp;gt; 0) {&lt;/code&gt; is checking to see if the player is pressing &lt;code&gt;W&lt;/code&gt; to go up and that the paddle is not being clipped off the top of the screen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rect.Y -= (int)(moveSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);&lt;/code&gt; is changing the Y position of the paddle, so that it can go up based on the &lt;code&gt;moveSpeed&lt;/code&gt; multiplied by the time between the last frame and the current frame. We call this delta time (the difference between the previous and current frame).&lt;/p&gt;

&lt;p&gt;Delta time helps make smooth movement and animations in games, no matter the frame rate or device performance.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if (kstate.IsKeyDown(Keys.S) &amp;amp;&amp;amp; rect.Y &amp;lt; Globals.HEIGHT - rect.Height) {&lt;/code&gt; is checking to see if the player is pressing &lt;code&gt;S&lt;/code&gt; to go down and that the paddle is not being clipped off the bottom of the screen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rect.Y += (int)(moveSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);&lt;/code&gt; is changing the Y position of the paddle, so that it can go down, just as we did earlier with up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HLpPD_ei--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696794307951/6640b6d4-91b9-48e4-883c-d2f2959c6021.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HLpPD_ei--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696794307951/6640b6d4-91b9-48e4-883c-d2f2959c6021.gif" alt="" width="800" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've done everything correctly, we should have movement! All we have to do now is add a second player, which should be super easy now that we've made our &lt;code&gt;Paddle&lt;/code&gt; class! We just need to allow the constructor to take in a parameter, if it's the second player or not, and then make modifications accordingly.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Paddle&lt;/code&gt; class, let's add a class variable &lt;code&gt;bool isSecondPlayer;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the constructor, we're going to need to take a boolean parameter so we can make changes based on if the instance of the &lt;code&gt;Paddle&lt;/code&gt; class is the second player or not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public Paddle(bool isSecondPlayer) {
    this.isSecondPlayer = isSecondPlayer;
    rect = new Rectangle((this.isSecondPlayer ? Globals.WIDTH - 40 : 0), 140, 40, 200);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we're telling the computer to change the X variable, so that the paddle is on the right side if there is a second player.&lt;/p&gt;

&lt;p&gt;Now, we need to change the &lt;code&gt;Update()&lt;/code&gt; class to support a second player.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void Update(GameTime gameTime) {
    KeyboardState kstate = Keyboard.GetState();
    if ((this.isSecondPlayer ? kstate.IsKeyDown(Keys.Up) : kstate.IsKeyDown(Keys.W)) &amp;amp;&amp;amp; rect.Y &amp;gt; 0) {
        rect.Y -= (int)(moveSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
    }
    if ((this.isSecondPlayer ? kstate.IsKeyDown(Keys.Down) : kstate.IsKeyDown(Keys.S)) &amp;amp;&amp;amp; rect.Y &amp;lt; Globals.HEIGHT - rect.Height) {
        rect.Y += (int)(moveSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're adding a ternary expression again to change the movement key based on if the paddle is the second player or not.&lt;/p&gt;

&lt;p&gt;Finally, we need to go into &lt;code&gt;Game1&lt;/code&gt; and add a second instance of &lt;code&gt;Paddle&lt;/code&gt;, as well as updating the first &lt;code&gt;Paddle&lt;/code&gt; instance to work with our new constructor.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Game1&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the class variables, add &lt;code&gt;Paddle paddle2;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;Initialize()&lt;/code&gt;, update &lt;code&gt;paddle = new Paddle();&lt;/code&gt; to &lt;code&gt;paddle = new Paddle(false);&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;Initialize()&lt;/code&gt;, add &lt;code&gt;paddle2 = new Paddle(true);&lt;/code&gt; right before &lt;code&gt;base.Initialize();&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;Update()&lt;/code&gt;, add &lt;code&gt;paddle2.update(gameTime);&lt;/code&gt; right before &lt;code&gt;base.Update(gameTime);&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;Draw()&lt;/code&gt;, add &lt;code&gt;paddle2.Draw();&lt;/code&gt; right before &lt;code&gt;Globals.spriteBatch.End();&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, let's run the code!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--myp5u0MZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696794321901/ccfd3459-a29f-4e92-9e85-cb04f5c081c7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--myp5u0MZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696794321901/ccfd3459-a29f-4e92-9e85-cb04f5c081c7.gif" alt="" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wonderful! We now have 2 players on the screen. Now, we need to create the &lt;code&gt;Ball&lt;/code&gt; class and then make the final touches!&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating the Ball
&lt;/h1&gt;

&lt;p&gt;Before we create the &lt;code&gt;Ball&lt;/code&gt; class, we need to create a way to store the score. In the &lt;code&gt;Globals&lt;/code&gt; class, create two new integer variables:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;public static int player1_score, player2_score;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create a file &lt;code&gt;Ball.cs&lt;/code&gt; for the &lt;code&gt;Ball&lt;/code&gt; class&lt;/p&gt;

&lt;p&gt;A lot of the things we are going to do in terms of drawing the rectangle on the screen are extremely similar to how we did it for the Paddle, so we can use this as our starting point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.Xna.Framework;

namespace Pong {
    public class Ball {
        Rectangle rect;
        int right = 1, top = 1, moveSpeed = 200;

        public Ball() {
            rect = new Rectangle(Globals.WIDTH / 2 - 20, Globals.HEIGHT / 2 - 20, 40, 40);
        }
        public void Update(Gametime gameTime, Paddle player1, Paddle player2) {}
        public void Draw() {
            Globals.spriteBatch.Draw(Globals.pixel, rect, Color.White);
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're using the Global &lt;code&gt;WIDTH&lt;/code&gt; and &lt;code&gt;HEIGHT&lt;/code&gt; variables to put the ball at the center of the screen.&lt;/p&gt;

&lt;p&gt;Also, we are going to take in both &lt;code&gt;Paddle&lt;/code&gt; instances, since we want to use the &lt;code&gt;Ball&lt;/code&gt; for all game calculations. This isn't necessarily the best practice, but since it's a simple game like &lt;code&gt;Pong&lt;/code&gt;, it's alright.&lt;/p&gt;

&lt;p&gt;We also created three new integer class variables &lt;code&gt;right = 1&lt;/code&gt;, &lt;code&gt;top = 1&lt;/code&gt;, and &lt;code&gt;moveSpeed = 200&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We will use &lt;code&gt;right&lt;/code&gt; and &lt;code&gt;top&lt;/code&gt; to store either &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;-1&lt;/code&gt; so that we can create conditionals for when the ball collides with something. We're going to want to keep it simple, so the ball will always move at a 45 angle. By adding the same values to the X and the Y of the ball, it will always bounce at the same 45 angle.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Update()&lt;/code&gt; function, we're going to add a bunch of if statements back to back to control the ball:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before any if statements, we're just going to move the ball based on its current trajectory. For every frame, we're multiplying the &lt;code&gt;moveSpeed&lt;/code&gt; with the delta time, and then making it negative or positive based on the modifiers &lt;code&gt;right&lt;/code&gt; and &lt;code&gt;top&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int deltaSpeed = (int)(moveSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
rect.X += right * deltaSpeed;
rect.Y += top * deltaSpeed;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Our first conditional is going to be for the left paddle, the first player. Each value in this if statement is checking each side of the ball and paddle to make sure that if the ball hits the paddle at a valid position, the direction is reversed.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (player1.rect.Right &amp;gt; rect.Left &amp;amp;&amp;amp; rect.Top &amp;gt; player1.rect.Top &amp;amp;&amp;amp; rect.Bottom &amp;lt; player1.rect.Bottom) {
    right = 1;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The same thing is happening for the right paddle, except the right and left values are flipped so collisions make sense for it.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (player2.rect.Left &amp;lt; rect.Right &amp;amp;&amp;amp; rect.Top &amp;gt; player2.rect.Top &amp;amp;&amp;amp; rect.Bottom &amp;lt; player2.rect.Bottom) {
    right = -1;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We check to see if the ball hits the top of the window, and if it does we reverse the top direction so that it can bounce down.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (rect.Y &amp;lt; 0) {
    top *= -1;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Then we check to see if the ball hits the bottom of the screen and reverse the top direction, just like before.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (rect.Y &amp;gt; Globals.HEIGHT - rect.Height) {
    top *= -1;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;For the X values, that means the ball went off the screen. This means we need to award a point to the opposite and reset the game. For this specific if statement, we're checking to see if the ball hits the left side of the screen.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(rect.X &amp;lt; 0) {
    Globals.player2_score += 1;
    resetGame();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;And for this one, we're checking to see if the ball hits the right side of the screen, awarding a point to the first player.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (rect.X &amp;gt; Globals.WIDTH - rect.Width) {
    Globals.player1_score += 1;
    resetGame();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're calling a function &lt;code&gt;resetGame()&lt;/code&gt; that we haven't made yet! We want this to put the ball back at the center of the game, which should be easy for us. Go ahead and create it as part of the &lt;code&gt;Ball&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void resetGame() {
    rect.X = Globals.WIDTH / 2 - 20;
    rect.Y = Globals.HEIGHT / 2 - 20;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, just like we did for the paddles, we need to add an instance of &lt;code&gt;Ball&lt;/code&gt; to the &lt;code&gt;Game1&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Game1&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the class variables, add &lt;code&gt;Ball ball;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;Initialize()&lt;/code&gt;, add &lt;code&gt;ball = new Ball();&lt;/code&gt; right before &lt;code&gt;base.Initialize();&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;Update()&lt;/code&gt;, add &lt;code&gt;ball.update(gameTime, paddle, paddle2);&lt;/code&gt; right before &lt;code&gt;base.Update(gameTime);&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;Draw()&lt;/code&gt;, add &lt;code&gt;ball.Draw();&lt;/code&gt; right before &lt;code&gt;Globals.spriteBatch.End();&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's run it and see our progress!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AKkoCqOq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696740189673/a01ccc6e-0aa5-4481-810c-70d90735e6a5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AKkoCqOq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696740189673/a01ccc6e-0aa5-4481-810c-70d90735e6a5.gif" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now have a working Pong! The only thing missing now is a score.&lt;/p&gt;

&lt;h1&gt;
  
  
  Showing the Score
&lt;/h1&gt;

&lt;p&gt;In MonoGame, displaying text on the screen requires loading a font resource, typically in the form of a &lt;code&gt;SpriteFont&lt;/code&gt;. This allows you to present information such as scores, game instructions, and other textual elements in your MonoGame project.&lt;/p&gt;

&lt;p&gt;For our project, we're going to use it to show the scores on the top.&lt;/p&gt;

&lt;p&gt;If you're using &lt;code&gt;Visual Studio 2022&lt;/code&gt;, go to your files, open the &lt;code&gt;Content&lt;/code&gt; folder, right click the &lt;code&gt;Content.mgcb&lt;/code&gt; file, and open it with the MGCB Editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hkdFMbiN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696741512010/37f7b5e4-26ab-4bed-b73e-f6c0d952d249.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hkdFMbiN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696741512010/37f7b5e4-26ab-4bed-b73e-f6c0d952d249.png" alt="" width="800" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're using the command line, type &lt;code&gt;dotnet mgcb-editor&lt;/code&gt; to open up the editor.&lt;/p&gt;

&lt;p&gt;Whichever way, it should open the MGCB editor, which is the UI interface for content management.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BL0RKZ86--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696741417729/fce7f3cf-92c0-47bb-ad3e-530c2cb38d01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BL0RKZ86--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696741417729/fce7f3cf-92c0-47bb-ad3e-530c2cb38d01.png" alt="" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your Content file isn't already there, go to the top, click &lt;code&gt;File &amp;gt; Open...&lt;/code&gt;, and navigate to your &lt;code&gt;Content.mgcb&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;After you add it, right-click the &lt;code&gt;Content&lt;/code&gt; add click &lt;code&gt;Add &amp;gt; New Item...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UHMhPWbH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696741642471/8fcf002f-9236-406c-a228-bbffc312b293.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UHMhPWbH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696741642471/8fcf002f-9236-406c-a228-bbffc312b293.png" alt="" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;SpriteFont Description&lt;/code&gt; called &lt;code&gt;Score&lt;/code&gt;. This will generate a &lt;code&gt;.spritefont&lt;/code&gt; file that we can use to apply settings for rendering to the screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_VTWRWzk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696741724182/5dfc27d1-b19e-41ac-8cd9-f1b62df163e3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_VTWRWzk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696741724182/5dfc27d1-b19e-41ac-8cd9-f1b62df163e3.png" alt="" width="734" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's save and exit out of the MGCB Editor.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Score.spritefont&lt;/code&gt; file we created is just a standard XML file, that defines properties of the font. By default, the font selected is Arial, which is fine, but you can go in there and make it any font you want, just make sure that you add the &lt;code&gt;.ttf&lt;/code&gt; file to the &lt;code&gt;Content&lt;/code&gt; folder if you don't already have it installed on your machine.&lt;/p&gt;

&lt;p&gt;For me, I downloaded the &lt;a href="https://fonts.google.com/specimen/Press+Start+2P"&gt;Press Start Font&lt;/a&gt; , and put the file in the &lt;code&gt;Content&lt;/code&gt; folder, then opened the &lt;code&gt;Score.sprintefont&lt;/code&gt; file and changed it from Arial to the name of the &lt;code&gt;.ttf&lt;/code&gt; file, in my case &lt;code&gt;prstart.&lt;/code&gt; I chose this font because it has a nice 8-bit style.&lt;/p&gt;

&lt;p&gt;To add our font to the game, open &lt;code&gt;Game1.cs&lt;/code&gt; and:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the class variables, add &lt;code&gt;SpriteFont font;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;LoadContent()&lt;/code&gt;, add &lt;code&gt;font = Content.Load&amp;lt;SpriteFont&amp;gt;("Score");&lt;/code&gt; at the bottom of the function.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add two &lt;code&gt;DrawString&lt;/code&gt; calls to our &lt;code&gt;Draw()&lt;/code&gt; function, underneath &lt;code&gt;Globals.spriteBatch.Begin()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Globals.spriteBatch.DrawString(font, Globals.player1_score.ToString(), new Vector2(100, 50), Color.White);
Globals.spriteBatch.DrawString(font, Globals.player2_score.ToString(), new Vector2(Globals.WIDTH - 112, 50), Color.White);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's save the file and run our project!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6Xl7Kv3G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696749298019/f0ffff2d-f043-4b65-a465-6ece7e32799a.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6Xl7Kv3G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1696749298019/f0ffff2d-f043-4b65-a465-6ece7e32799a.gif" alt="" width="800" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There we go! We now have a fully working version of Pong!&lt;/p&gt;

&lt;p&gt;Great job on completing the Pong game tutorial using MonoGame and C#! This achievement has not only helped you build a classic game but also allowed you to gain hands-on experience in game development concepts. As you continue exploring new projects and honing your skills, you will become more proficient in game development.&lt;/p&gt;

&lt;p&gt;Explore more advanced MonoGame features or other Game Engines/Frameworks, experiment with different game mechanics, learn about game design principles, and create a portfolio of game projects.&lt;/p&gt;

&lt;p&gt;Keep up the good work and happy coding!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>gamedev</category>
      <category>monogame</category>
    </item>
    <item>
      <title>&lt;Part 2&gt; Make spinning 3D shapes in SDL2 and OpenGL</title>
      <dc:creator>Hadi</dc:creator>
      <pubDate>Fri, 25 Aug 2023 03:42:01 +0000</pubDate>
      <link>https://dev.to/hadicya/make-spinning-3d-shapes-in-sdl2-and-opengl-ik2</link>
      <guid>https://dev.to/hadicya/make-spinning-3d-shapes-in-sdl2-and-opengl-ik2</guid>
      <description>&lt;p&gt;Last part, we successfully created a window in SDL2 using OpenGL. Now that we understand how that works, we're going to learn how to render things on the screen by building a mesh class and creating shaders in GLSL, a shader programming language.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;DISCLAIMER: This walkthrough assumes knowledge from Part 1 and a working knowledge of C++ and how to compile it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;GitHub Repo: &lt;a href="https://github.com/HadiCya/spinning_shapes"&gt;https://github.com/HadiCya/spinning_shapes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;YouTube Version:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/ac6mf05O_qw"&gt;https://youtu.be/ac6mf05O_qw&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To start us off, were going to need to create a &lt;code&gt;Mesh&lt;/code&gt; class for us to create &lt;code&gt;Mesh&lt;/code&gt; objects, as eventually were going to make this 3D.&lt;/p&gt;

&lt;p&gt;Go ahead and create a &lt;code&gt;mesh.h&lt;/code&gt; header file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#ifndef MESH_H
#define MESH_H

#include &amp;lt;glad/glad.h&amp;gt;

class Mesh {
    public:
        Mesh();
        void draw();
    private:
        GLuint VertexArrayID, vertexbuffer, elementbuffer, vertex_size;
};

#endif

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will construct a class called &lt;code&gt;Mesh&lt;/code&gt;, which will set us up with the mesh information such as the vertices and what order to draw them in, along with setting up the vertices and triangle points.&lt;/p&gt;

&lt;p&gt;Before we write code, let's take a deep dive into understanding how drawing vertices on the screen works. In computer graphics, a polygon mesh is used to render by drawing triangles. If you see an advanced character in a movie or video game, they are made up of thousands of tiny triangles. Triangles are used because of their ease of manipulation and require less storage, something that becomes important as projects grow in size and complexity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9PQR1OQW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1692917845190/cdaa75bf-fff0-4f69-9b55-1902430fbb67.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9PQR1OQW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1692917845190/cdaa75bf-fff0-4f69-9b55-1902430fbb67.png" alt="" width="658" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo courtesy of &lt;a href="https://realtimerendering.com"&gt;https://realtimerendering.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The way a polygon mesh stores its data is by utilizing a triangle and vertex array. The triangle array is responsible for storing which vertices to access in the vertex array. For example, if we have the triangle array &lt;code&gt;[0, 2, 3, 0, 3, 1]&lt;/code&gt; the first triangle we draw accesses the vertices at positions &lt;code&gt;0, 2, 3&lt;/code&gt; and then connecting them on the screen, creating a triangle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FLGv2QoB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1692927247689/578e3dd6-6748-4b60-89c6-0947c0be9c98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FLGv2QoB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1692927247689/578e3dd6-6748-4b60-89c6-0947c0be9c98.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In OpenGL, we manage this data with buffers, which are responsible for storing triangle and vertex data to be drawn on the screen.&lt;/p&gt;

&lt;p&gt;Let's create our &lt;code&gt;mesh.cpp&lt;/code&gt; file, and we'll see how we can implement this, and how it all works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;vector&amp;gt;
#include "mesh.h"
#include &amp;lt;SDL.h&amp;gt;
#include &amp;lt;iostream&amp;gt;

Mesh::Mesh() {
    glGenVertexArrays(1, &amp;amp;VertexArrayID);
    glBindVertexArray(VertexArrayID);

    GLfloat vertices[] = {
        0.5f, -0.5f, 0.5f,
        -0.5f, -0.5f, 0.5f,
        0.5f, 0.5f, 0.5f,
        -0.5f, 0.5f, 0.5f
    };

    GLint triangles[] = {0, 2, 3, 0, 3, 1};

    glGenBuffers(1, &amp;amp;vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &amp;amp;elementbuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(triangles), triangles, GL_STATIC_DRAW);

    vertex_size = sizeof(triangles) / sizeof(GLint);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;glGenVertexArrays(1, &amp;amp;VertexArrayID)&lt;/code&gt; and &lt;code&gt;glBindVertexArray(VertexArrayID)&lt;/code&gt; creates and binds a vertex array object and its ID so that subsequent vertex buffer operations can be stored in the new object.&lt;/p&gt;

&lt;p&gt;We then define our &lt;code&gt;vertices&lt;/code&gt; and &lt;code&gt;triangles&lt;/code&gt; arrays, like we did earlier in the diagram.&lt;/p&gt;

&lt;p&gt;Now, we have to generate buffers to store our data.&lt;/p&gt;

&lt;p&gt;The vertex buffer is a mechanism that sends the vertex data to the GPU, we are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Generating a unique ID for the buffer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Binding the buffer, setting it as active for OpenGL to operate with.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allocating the appropriate amount of memory, and copying the data to the GPU. &lt;code&gt;GL_STATIC_DRAW&lt;/code&gt; specifies that we are giving it the same unchanging data, that will be drawn many times.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The element buffer, also known as an index buffer, sends the triangle index data to the GPU.&lt;/p&gt;

&lt;p&gt;This series of calls does the same as for the vertex buffer but for the index data. &lt;code&gt;GL_ELEMENT_ARRAY_BUFFER&lt;/code&gt; tells OpenGL that this buffer contains index data.&lt;/p&gt;

&lt;p&gt;Lastly, we'll store vertex_size data for when we call the &lt;code&gt;draw()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Now, we need to make our &lt;code&gt;draw()&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void Mesh::draw(){
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
    glDrawElements(GL_TRIANGLES, vertex_size, GL_UNSIGNED_INT, 0);

    glDisableVertexAttribArray(0);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go through this function line by line:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;glEnableVertexAttribArray(0)&lt;/code&gt;: Enable the first attribute array at position 0. We're simply allowing ourselves to start the drawing process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer)&lt;/code&gt;: Bind the vertex buffer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0)&lt;/code&gt;: Describe how the data for the vertices is stored in the vertex buffer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer)&lt;/code&gt;: Bind the element buffer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;glDrawElements(GL_TRIANGLES, vertex_size, GL_UNSIGNED_INT, 0)&lt;/code&gt;: Draw the triangles using the vertex and element buffers, according to the total size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;glDisableVertexAttribArray(0)&lt;/code&gt;: Disable the first attribute array after drawing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before we can start drawing things on the screen, OpenGL requires us to have at minimum a fragment and vertex shader. We're going to be making these in the Graphics Library Shader Language (GLSL) which is a shader language based on the C programming language. Shaders aren't our primary focus for this series, so we're going to be covering the basics.&lt;/p&gt;

&lt;p&gt;First, well create a file called &lt;code&gt;vertex.glsl&lt;/code&gt; to store our Vertex Shader:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#version 330 core

layout (location = 0) in vec3 aPos;

void main() {
    gl_Position = vec4(aPos, 1.0);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The vertex shader is responsible for telling the GPU where every point is to be drawn, by transforming its position and other attributes using mathematic calculations. In this case, we're not going to be doing much.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;#version 330 core&lt;/code&gt;: This sets the GLSL version to 3.30 and specifies the core profile. (In the last part we talked about using core over compatibility)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;layout (location = 0) in vec3 aPos&lt;/code&gt;: This declares a 3-component vector input variable &lt;code&gt;aPos&lt;/code&gt;, which represents the position of the vertex. The &lt;code&gt;layout (location = 0)&lt;/code&gt; part explicitly sets the location of this attribute to 0.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;void main() { ... }&lt;/code&gt;: The main function of the shader. It's executed once for every vertex.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gl_Position = vec4(aPos, 1.0)&lt;/code&gt;: This converts the input 3D position into a 4D vector by adding a fourth component with a value of 1.0. This is common in graphics to represent homogeneous coordinates.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we want to create a file called &lt;code&gt;fragment.glsl&lt;/code&gt; for our Fragment Shader&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#version 330 core

out vec3 color;

void main() {
    color = vec3(1,1,1);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fragment shader is responsible for telling the GPU what color information needs to be drawn, for every pixel that our geometry covers. This will also be simple, especially since later we will just be using the wireframe setting.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;out vec3 color&lt;/code&gt;: This declares a 3-component vector output variable &lt;code&gt;color&lt;/code&gt;, which will store the output color of the fragment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;void main() { ... }&lt;/code&gt;: The main function of the shader, executed once for every fragment (potential pixel on the screen).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;color = vec3(1,1,1)&lt;/code&gt;: This sets the output color to white (1,1,1), meaning every fragment processed by this shader will have this color.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Were also going to use an existing shader loader and header. This isnt necessary to understand OpenGL completely, go ahead and just copy the code directly.&lt;/p&gt;

&lt;p&gt;Create the file &lt;code&gt;loadShader.h&lt;/code&gt; and populate it with this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#ifndef LOAD_SHADER_H
#define LOAD_SHADER_H

#include &amp;lt;glad/glad.h&amp;gt;

GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_path);

#endif // LOAD_SHADER_H

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the file &lt;code&gt;loadShader.cpp&lt;/code&gt; and populate it with this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include "loadShader.h"
#include &amp;lt;SDL.h&amp;gt;
#include &amp;lt;fstream&amp;gt;
#include &amp;lt;sstream&amp;gt;
#include &amp;lt;iostream&amp;gt;

GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){

 // Create the shaders
 GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
 GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

 // Read the Vertex Shader code from the file
 std::string VertexShaderCode;
 std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
 if(VertexShaderStream.is_open()){
  std::stringstream sstr;
  sstr &amp;lt;&amp;lt; VertexShaderStream.rdbuf();
  VertexShaderCode = sstr.str();
  VertexShaderStream.close();
 }else{
  printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", vertex_file_path);
  getchar();
  return 0;
 }

 // Read the Fragment Shader code from the file
 std::string FragmentShaderCode;
 std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
 if(FragmentShaderStream.is_open()){
  std::stringstream sstr;
  sstr &amp;lt;&amp;lt; FragmentShaderStream.rdbuf();
  FragmentShaderCode = sstr.str();
  FragmentShaderStream.close();
 }

 GLint Result = GL_FALSE;
 int InfoLogLength;

 // Compile Vertex Shader
 printf("Compiling shader : %s\n", vertex_file_path);
 char const * VertexSourcePointer = VertexShaderCode.c_str();
 glShaderSource(VertexShaderID, 1, &amp;amp;VertexSourcePointer , NULL);
 glCompileShader(VertexShaderID);

 // Check Vertex Shader
 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &amp;amp;Result);
 glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &amp;amp;InfoLogLength);
 if ( InfoLogLength &amp;gt; 0 ){
  std::vector&amp;lt;char&amp;gt; VertexShaderErrorMessage(InfoLogLength+1);
  glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &amp;amp;VertexShaderErrorMessage[0]);
  printf("%s\n", &amp;amp;VertexShaderErrorMessage[0]);
 }

 // Compile Fragment Shader
 printf("Compiling shader : %s\n", fragment_file_path);
 char const * FragmentSourcePointer = FragmentShaderCode.c_str();
 glShaderSource(FragmentShaderID, 1, &amp;amp;FragmentSourcePointer , NULL);
 glCompileShader(FragmentShaderID);

 // Check Fragment Shader
 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &amp;amp;Result);
 glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &amp;amp;InfoLogLength);
 if ( InfoLogLength &amp;gt; 0 ){
  std::vector&amp;lt;char&amp;gt; FragmentShaderErrorMessage(InfoLogLength+1);
  glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &amp;amp;FragmentShaderErrorMessage[0]);
  printf("%s\n", &amp;amp;FragmentShaderErrorMessage[0]);
 }

 // Link the program
 printf("Linking program\n");
 GLuint ProgramID = glCreateProgram();
 glAttachShader(ProgramID, VertexShaderID);
 glAttachShader(ProgramID, FragmentShaderID);
 glLinkProgram(ProgramID);

 // Check the program
 glGetProgramiv(ProgramID, GL_LINK_STATUS, &amp;amp;Result);
 glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &amp;amp;InfoLogLength);
 if ( InfoLogLength &amp;gt; 0 ){
  std::vector&amp;lt;char&amp;gt; ProgramErrorMessage(InfoLogLength+1);
  glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &amp;amp;ProgramErrorMessage[0]);
  printf("%s\n", &amp;amp;ProgramErrorMessage[0]);
 }

 glDetachShader(ProgramID, VertexShaderID);
 glDetachShader(ProgramID, FragmentShaderID);

 glDeleteShader(VertexShaderID);
 glDeleteShader(FragmentShaderID);

 return ProgramID;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Credit to: &lt;a href="http://www.opengl-tutorial.org/"&gt;https://www.opengl-tutorial.org/&lt;/a&gt; for creating the shaders loader.&lt;/p&gt;

&lt;p&gt;Now that we have our &lt;code&gt;Mesh&lt;/code&gt; class completed, and our shaders set up, all we have to do now is make it work in our &lt;code&gt;main.cpp&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lets update our includes in &lt;code&gt;main.cpp&lt;/code&gt; to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;SDL.h&amp;gt;
#include "mesh.h"
#include "loadShader.h"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After we call &lt;code&gt;gladLoadGLLoader(SDL_GL_GetProcAddress)&lt;/code&gt; were going to want to initialize our &lt;code&gt;Mesh&lt;/code&gt; and load our shaders:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    SDL_GLContext context;
    context = SDL_GL_CreateContext(window);

    gladLoadGLLoader(SDL_GL_GetProcAddress);

    Mesh cube;

    GLuint programID = LoadShaders("vertex.glsl", "fragment.glsl");

    bool done = false;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, in our while loop, were going to want to actually draw our &lt;code&gt;Mesh&lt;/code&gt; but not before we tell OpenGL to use the shaders we loaded earlier into &lt;code&gt;programID&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Were also going to call &lt;code&gt;glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)&lt;/code&gt; which is going to render everything on the screen in wireframe mode. This is going to show how the triangles are being drawn, as we described earlier. And also, wireframe looks cool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    while(!done) {
        glViewport(0, 0, screen_width, screen_height);

        SDL_Event event;
        while(SDL_PollEvent(&amp;amp;event)){
            if(event.type == SDL_QUIT) {
                done = true;
            }
        }
        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

        glUseProgram(programID);
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

        cube.draw();    

        SDL_GL_SwapWindow(window);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thats all the changes we need! Go ahead and compile your code yet again, this time adding &lt;code&gt;mesh.cpp&lt;/code&gt; and &lt;code&gt;loadShaders.cpp&lt;/code&gt; to your compilation list. This is how my compilation command looks now:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clang++ -std=c++20 main.cpp mesh.cpp loadShader.cpp ./glad/src/glad.c -o spinning_shapes -I/Library/Frameworks/SDL2.framework/Headers -I./glad/include -F/Library/Frameworks -framework SDL2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GwZsSRjB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1692914937898/dbee45f1-fa57-4d5e-8e4f-714abccd58e0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GwZsSRjB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1692914937898/dbee45f1-fa57-4d5e-8e4f-714abccd58e0.png" alt="" width="800" height="664"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you see a slightly stretched-out square, congrats! Youve successfully rendered a square onto the screen.&lt;/p&gt;

&lt;p&gt;You might be asking if our vertices are uniform, why is it stretched like that?&lt;/p&gt;

&lt;p&gt;That, and how we're going to make this a spinning cube, will be answered in our next and final part!&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>opengl</category>
      <category>sdl2</category>
      <category>graphicsprogramming</category>
    </item>
    <item>
      <title>&lt;Part 1&gt; Make spinning 3D shapes in SDL2 and OpenGL</title>
      <dc:creator>Hadi</dc:creator>
      <pubDate>Thu, 17 Aug 2023 09:26:35 +0000</pubDate>
      <link>https://dev.to/hadicya/make-spinning-3d-shapes-in-sdl2-and-opengl-2337</link>
      <guid>https://dev.to/hadicya/make-spinning-3d-shapes-in-sdl2-and-opengl-2337</guid>
      <description>&lt;p&gt;In this miniseries, you will be creating a program in C++ that will be able to render 3D shapes in SDL2 and OpenGL, and more importantly, learn about what is happening in depth while you write your program.&lt;/p&gt;

&lt;p&gt;As a game developer, using SDL2 and OpenGL in a world of advanced game engines such as Unity and Unreal Engine may seem like a waste of time. And youd probably be right. While programming at a low level may have benefits such as program speed, reliability, and smaller sizes, many games youd be able to produce with a low-level framework (in a timely manner) can be made in a game engine much faster, and itd run fine on low-spec machines, and great on average machines.&lt;/p&gt;

&lt;p&gt;So, why bother?&lt;/p&gt;

&lt;p&gt;By learning the components of rendering in a low-level setting, you gain a deeper understanding of how a game engine works under the hood, which in turn will teach you how to optimize your game better, making you a better game developer. And more importantly, because it is cool. Thats why I do it at least. There are many other technical reasons that could be argued, but we neednt dwell, and just begin.&lt;/p&gt;

&lt;p&gt;Lets get started!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;DISCLAIMER: This walkthrough assumes a working knowledge of C++ and how to compile it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;YouTube version:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/ac6mf05O_qw"&gt;https://youtu.be/ac6mf05O_qw&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What you'll need&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First things first, lets get set up. The tools well need for this are (continue reading for more detailed instructions):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.khronos.org/opengl/wiki/Getting_Started#Downloading_OpenGL"&gt;OpenGL&lt;/a&gt; (OpenGL is most likely installed by default on your machine, but you must ensure the latest version is installed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A C++ compiler (I use clang++ and compile C++20)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.libsdl.org/"&gt;SDL 2.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://glad.dav1d.de/"&gt;GLAD&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://glm.g-truc.net/0.9.9/"&gt;GLM&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before we get started, create a directory to store this project in, I named mine &lt;code&gt;spinning_shapes&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;SDL2 is a development library built in C, that provides low-level interfaces to computer graphics hardware (with graphics libraries such as OpenGL), audio, video, peripherals, etc. We will be using it to actually display a window capable of rendering visuals.&lt;/p&gt;

&lt;p&gt;Download SDL2 from the released tab on the &lt;a href="https://www.libsdl.org/"&gt;SDL2 website&lt;/a&gt;. Follow this &lt;a href="https://wiki.libsdl.org/SDL2/Installation"&gt;installation guide&lt;/a&gt; for more specifics about your operating system.&lt;/p&gt;

&lt;p&gt;Whenever you want to access OpenGL, youll need some kind of loading library. Many of them have minor differences and accomplish exceedingly similar things. We will be using GLAD, a multi-language loader-generator for OpenGL. The GLAD web tool we will be using will be able to generate a header file for us.&lt;/p&gt;

&lt;p&gt;Go to the official &lt;a href="https://glad.dav1d.de/"&gt;GLAD loader-generator website&lt;/a&gt;, here you will select &lt;strong&gt;C/C++&lt;/strong&gt; under &lt;strong&gt;Language&lt;/strong&gt; and &lt;strong&gt;OpenGL&lt;/strong&gt; under &lt;strong&gt;Specification.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Under the API tab, were going to be selecting gl &lt;strong&gt;Version 4.1,&lt;/strong&gt; and none for the rest. For &lt;strong&gt;Profile,&lt;/strong&gt; we will be using &lt;strong&gt;Core&lt;/strong&gt; instead of &lt;strong&gt;Compatibility.&lt;/strong&gt; The Extensions column on the left is going to be populated, and were going to go ahead and click &lt;strong&gt;ADD ALL,&lt;/strong&gt; and click the &lt;strong&gt;GENERATE&lt;/strong&gt; button on the bottom.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LUPFLbhK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2AqbOHo3vDMP4RMhkkS3jjAA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LUPFLbhK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2AqbOHo3vDMP4RMhkkS3jjAA.png" alt="GLAD Loader-Generator Web Tool" width="800" height="861"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After you generate your GLAD zip, download it, and extract the glad folder into your project folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xs0yjhLY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A4ISXO6GVoVbqFJbQVF0Mdw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xs0yjhLY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A4ISXO6GVoVbqFJbQVF0Mdw.png" alt="GLAD Generated Files" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Were going to need to be capable of making vector and matrix calculations that we wouldnt otherwise be able to in OpenGL. This is where GLM comes in, a mathematics library for OpenGL and the OpenGL Shading Language (GLSL). Go ahead and download the latest release from the &lt;a href="https://glm.g-truc.net/"&gt;GLM Github&lt;/a&gt;. Extract it and put it in the project directory.&lt;/p&gt;

&lt;p&gt;Thats all the downloads/installations well need!&lt;/p&gt;

&lt;p&gt;As Im sure youve already discovered, installing and configuring these C++ libraries can prove to be difficult from machine to machine, and youre going to probably have to do your own research to get things working especially if youre a beginner. Its all part of the learning. You can see what exactly works for me on my &lt;a href="https://youtu.be/ac6mf05O_qw"&gt;YouTube video&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Let's make a window&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Lets begin by creating a file called &lt;code&gt;main.cpp&lt;/code&gt; &lt;strong&gt;,&lt;/strong&gt; this will be what will run our main C++ code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;glad/glad.h&amp;gt;
#include &amp;lt;SDL.h&amp;gt;

int main(int argc, char* argv[]){
    SDL_Window* window = nullptr;

    int screen_width = 1000;
    int screen_height = 800;

    if (SDL_Init(SDL_INIT_VIDEO) &amp;lt; 0) {
        std::cout &amp;lt;&amp;lt; "SDL failed initialization. " &amp;lt;&amp;lt; SDL_GetError();
        return -1;
    } else {
        std::cout &amp;lt;&amp;lt; "SDL successfully initialized.";
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well need to start the program off by including &lt;code&gt;&amp;lt;iostream&amp;gt;&lt;/code&gt; along with &lt;code&gt;&amp;lt;glad/glad.h&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;SDL.h&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In our &lt;code&gt;main()&lt;/code&gt; function, we want to initialize a &lt;code&gt;SDL_Window&lt;/code&gt; which we will point to an empty pointer. We will be assigning this later, once weve set up some OpenGL attributes.&lt;/p&gt;

&lt;p&gt;We will define our screen height and width, and then check to see if SDL successfully initializes, returning an error if it doesnt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    window = SDL_CreateWindow("C++ SDL2 Window | OpenGL", 
            0, 
            0, 
            screen_width, 
            screen_height, 
            SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
    SDL_GLContext context;
    context = SDL_GL_CreateContext(window);

    gladLoadGLLoader(SDL_GL_GetProcAddress);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a lot of SDL and OpenGL! It is daunting at first glance, but we will be breaking it down to see what exactly is happening, in a digestible way.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SDL_GL_SetAttribute()&lt;/code&gt; is a function in SDL2 for setting window attributes in OpenGL before the window is created. Lets go through this line by line:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;SDL_GL_CONTEXT_MAJOR_VERSION&lt;/code&gt; By setting this attribute to 4, we are telling SDL we intend to use version 4.x.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;SDL_GL_CONTEXT_MINOR_VERSION&lt;/code&gt; This is completed when you set the minor version, and SDL now knows we intend to use version 4.1, when we set this attribute to 1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;SDL_GL_CONTEXT_PROFILE_MASK&lt;/code&gt; is a way to define OpenGL context, which just means which features we want available. When setting up GLAD earlier, we chose Core over Compatibility. Compatibility supports a Legacy and an entirely different format of rendering objects on the screen, which isnt necessary for us. Thats why its important to specify what is available to SDL and set our mask to &lt;code&gt;SDL_GL_CONTEXT_PROFILE_CORE&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;SDL_GL_DOUBLEBUFFER&lt;/code&gt; Double buffer is a rendering technique which stores two separate buffers, hence the name. While one frame is being displayed on the screen, a secondary buffer is generated in the background, so that the render can swap to the other one quickly. This is used to reduce flickering and smoother rendering.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;SDL_GL_DEPTH_SIZE&lt;/code&gt; Depth size stores an integer value representing bits that should be allocated for the depth buffer (or z-buffer). These values are responsible for deciding whether or not a pixel should be rendered, based on its depth to previously rendered pixels. In essence, the depth buffer makes objects clearly behind each other, or far away objects not being rendered directly in front of the camera. &lt;code&gt;24&lt;/code&gt; balances well between precision and memory usage, and is the most common value.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that weve set the attributes for our window, we can create the window!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SDL_CreateWindow()&lt;/code&gt; takes 6 different parameters, a title, the x and y positions of the top left pixel (relative to the computer screen), the window width and height, and &lt;code&gt;FLAGS&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We use two flags: &lt;code&gt;SDL_WINDOW_SHOWN&lt;/code&gt; and &lt;code&gt;SDL_WINDOW_OPENGL&lt;/code&gt; the former indicating that the window should be shown immediately, the latter preparing your window for use with OpenGL. For more info, see &lt;a href="https://wiki.libsdl.org/SDL2/SDL_WindowFlags"&gt;SDL2 Window_Flags values.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you can create an OpenGL context, which is an environment responsible for the state and resources. This manages OpenGLs rendering operations and interactions with the graphics system. In this context, we will be managing the OpenGL state, frame buffer, functions, shaders, textures, buffers, and viewport.&lt;/p&gt;

&lt;p&gt;Last thing in this block of setting up the window, well need to call &lt;code&gt;gladLoadGLLoader()&lt;/code&gt; which will just initialize the GLAD library to load up function pointers with &lt;code&gt;SDL_GL_Get_Proc_Address&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That wasnt so bad, right? There are a lot of abstractions in OpenGL, and its just a matter of taking the time to slowly learn them and try new things. This block of code is crucial to preparing our window for OpenGL rendering. Now, lets finish this window creation by making our main loop!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    bool done = false;

    while(!done) {
        glViewport(0, 0, screen_width, screen_height);

        SDL_Event event;
        while(SDL_PollEvent(&amp;amp;event)){
            if(event.type == SDL_QUIT) {
                done = true;
            }
        }
        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
        SDL_GL_SwapWindow(window);
    }
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Were going to create a boolean &lt;code&gt;done&lt;/code&gt; that will control our while loop, which will handle the updating of our window.&lt;/p&gt;

&lt;p&gt;We will define a &lt;code&gt;glViewport()&lt;/code&gt; which, similar to &lt;code&gt;SDL_CreateWindow()&lt;/code&gt;, takes the x and y pixels of the top left of our window, and how big we want to window width and height.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;SDL_Event&lt;/code&gt; we are checking to see if any events have happened, such as the user quitting out of the application, or clicking the keyboard. After that, we want to call &lt;code&gt;glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;While this function call isnt exactly necessary for us now, it is responsible for clearing the depth and color information in between every call in the while loop, essentially resetting the frame for us to write the next one. Finally, we are swapping the secondary buffer that was being generated in place of the current buffer that is being rendered.&lt;/p&gt;

&lt;p&gt;Go ahead and compile your code, keep in mind youll have to also compile the GLAD file and include the SDL2 and GLAD frameworks. This is the terminal command I used when compiling (I use MacOS):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clang++ -std=c++20 main.cpp ./glad/src/glad.c -o spinning_shapes -I/Library/Frameworks/SDL2.framework/Headers -I./glad/include -F/Library/Frameworks -framework SDL2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Go ahead and run your program, I named mine &lt;code&gt;spinning_shapes&lt;/code&gt; and ran it with the command &lt;code&gt;./spinning_shapes&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6Mhr5995--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A3dYPV30AWSjAcekjkoEptg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6Mhr5995--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2A3dYPV30AWSjAcekjkoEptg.png" alt="An empty window" width="800" height="659"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you did everything right, an empty window is what youll see! How exciting.&lt;/p&gt;

&lt;p&gt;In the next post, we will be integrating shaders into our program so that we are able to start drawing onto the screen, and we will create a square mesh to render.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>opengl</category>
      <category>cpp</category>
      <category>graphics</category>
      <category>sdl2</category>
    </item>
  </channel>
</rss>
