<?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: NoticeableSmeh</title>
    <description>The latest articles on DEV Community by NoticeableSmeh (@noticeablesmeh).</description>
    <link>https://dev.to/noticeablesmeh</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%2F3535029%2Fc1833d53-7670-4889-aa71-59c4f588397d.jpg</url>
      <title>DEV Community: NoticeableSmeh</title>
      <link>https://dev.to/noticeablesmeh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/noticeablesmeh"/>
    <language>en</language>
    <item>
      <title>Rasterizer Project - The end? is published</title>
      <dc:creator>NoticeableSmeh</dc:creator>
      <pubDate>Fri, 07 Nov 2025 22:11:43 +0000</pubDate>
      <link>https://dev.to/noticeablesmeh/rasterizer-project-the-end-is-published-222k</link>
      <guid>https://dev.to/noticeablesmeh/rasterizer-project-the-end-is-published-222k</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-basicend-d4i" class="crayons-story__hidden-navigation-link"&gt;Rasterizer Project - Part: BASIC_END&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/noticeablesmeh" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535029%2Fc1833d53-7670-4889-aa71-59c4f588397d.jpg" alt="noticeablesmeh profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/noticeablesmeh" class="crayons-story__secondary fw-medium m:hidden"&gt;
              NoticeableSmeh
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                NoticeableSmeh
                
              
              &lt;div id="story-author-preview-content-3001501" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/noticeablesmeh" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535029%2Fc1833d53-7670-4889-aa71-59c4f588397d.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;NoticeableSmeh&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-basicend-d4i" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Nov 7 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-basicend-d4i" id="article-link-3001501"&gt;
          Rasterizer Project - Part: BASIC_END
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cpp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cpp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/graphics"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;graphics&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/learning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;learning&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gamedev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gamedev&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-basicend-d4i#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>cpp</category>
      <category>graphics</category>
      <category>learning</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Rasterizer Project - Part: BASIC_END</title>
      <dc:creator>NoticeableSmeh</dc:creator>
      <pubDate>Fri, 07 Nov 2025 22:11:30 +0000</pubDate>
      <link>https://dev.to/noticeablesmeh/rasterizer-project-part-basicend-d4i</link>
      <guid>https://dev.to/noticeablesmeh/rasterizer-project-part-basicend-d4i</guid>
      <description>&lt;p&gt;Hello folks lets continue working on this rasterizer, lets get the rasterization going and then were putting this project on hold for a while. I will be making the DoingOpenGL series after this part were I will get a graphics demo going for OpenGL stay tuned for that but heres what were doing today. &lt;/p&gt;

&lt;p&gt;So to avoid going too into detail and just making this just completely unreadable I will be trying to keep my explanations more concise and quicker with fewer images just so we can get through this stuff together folks &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkiijy5211kam2b6xpdq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkiijy5211kam2b6xpdq.png" alt=" " width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is our triangle fill function, this essentially takes coordinates for 3 different points and fills the area between them. This is finally were barycentric coordinates finally get more useful but more on that in just a second.&lt;/p&gt;

&lt;p&gt;Anyways we stard by defining our max and minimum on our 2D plain view for both the X and Y coordinate, this is simply just to ensure that we never paint outside the actually triangle. &lt;/p&gt;

&lt;p&gt;So to figure out if a pixel should be painted or not (in other words if its inside the triangle) You use barycentric weights. These are essentially three numbers that symbolize how close that pixel is to each vertex of the triangle hence why we have three numbers. Inside the triangle those numbers always stay between 0 and 1 so we are essentially just making sure that none one of them are negative and all of them added together sum up to 1. &lt;br&gt;
That is what this if statement checks here&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbjngymzqhntvjkxxw15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbjngymzqhntvjkxxw15.png" alt=" " width="523" height="57"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the more meaty math lets take a  look more here &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbroag2pa17my8ai881eq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbroag2pa17my8ai881eq.png" alt=" " width="800" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;denom here is jus tone big number that represents the triangles size and if its zero that means the points are all on one line, nothing to fill essentially. The way to calculate it is from the differences between the triangles points, how far apart they are on each respective axis. Were counting the area here folks essentially we just dont care about dividing it with 2 because it doesnt really serve a purpose in knowing the exact area size, we care about ratios.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zu9tht3veq2rrtivj9l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zu9tht3veq2rrtivj9l.png" alt=" " width="800" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So in our code we define our direction of calculating the side that is inside (good side) or outside (bad side) from clockwise direction, which is different from how a lot of other program use it. This however is still fine but this means that if we were to orient our Edges upright it would mean the right side is the side that is inside the triangle and the left side is the one that is outside. &lt;/p&gt;

&lt;p&gt;Phew, I am not very good at math but thats my best attempt at explaining this for you as simple as I could.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf5o5dqi09xwxemzh2ya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf5o5dqi09xwxemzh2ya.png" alt=" " width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Time to break down this function. This function has my favorite type of for loop (yay) and it loops through our face count (our amount of triangles inside of our model. &lt;/p&gt;

&lt;p&gt;Each face in our model has three vertices, of course, and we then project those vertices into a 2D view, since we’re currently rendering in 2D space. Although the model itself exists in 3D, we’re essentially flattening it onto the screen, turning it into a 2D representation we can draw.&lt;/p&gt;

&lt;p&gt;We retrieve each vertex based on the current face index in our loop (since faceCount gives us how many total faces we have). From that index, we can access the first vertex (our A coordinate), then the second (B), and finally the third (C).&lt;/p&gt;

&lt;p&gt;Note: Remember that in programming, we start counting at 0, not 1!&lt;/p&gt;

&lt;p&gt;Then that backface culled skips triangles that are facing away from the triangle, more on that in a second. And the color of the triangle each gets a random RGB value so via a modulo variation that makes it always unique thanks to our facecount index. I say random in the sense that I have no clue what colour it will be when you run it but really it will always be the same colour on compile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F450jrkw3tt5e78tmzzde.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F450jrkw3tt5e78tmzzde.png" alt=" " width="658" height="139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright so this function essentially checks if the triangle is facing toward or away from the camerea. So the first part abx and acx we make towo edge vertex, vertex from a to b and a vertex from a to c. These vectors describe the direction of the triangle in 2d space. Then we are computing the 2D cross product via area2. If the tirangle area is zero or facing the wrong direction dont draw it! Simple. Anyways lets load this cow! That I found on the internet. &lt;br&gt;
&lt;a href="https://www.cs.cmu.edu/%7Ekmcrane/Projects/ModelRepository/" rel="noopener noreferrer"&gt;https://www.cs.cmu.edu/~kmcrane/Projects/ModelRepository/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiqo5wq6ytsvg0bdfwowj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiqo5wq6ytsvg0bdfwowj.png" alt=" " width="658" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So we declare the model and the name of the file as we did in the previous part and then we call our function drwa model filled and pass in the model and our framebuffer and voila &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmoz7fmp5hzbukouwz22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmoz7fmp5hzbukouwz22.png" alt=" " width="502" height="715"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There we go folks, &lt;/p&gt;

&lt;p&gt;Thank you for reading and here are some useful links aswell as sources&lt;/p&gt;

&lt;p&gt;&lt;a href="https://haqr.eu/tinyrenderer/" rel="noopener noreferrer"&gt;https://haqr.eu/tinyrenderer/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.cs.cmu.edu/%7Ekmcrane/Projects/ModelRepository/" rel="noopener noreferrer"&gt;https://www.cs.cmu.edu/~kmcrane/Projects/ModelRepository/&lt;/a&gt;&lt;br&gt;
@article{crane2013robust,&lt;br&gt;
  title={Robust fairing via conformal curvature flow},&lt;br&gt;
  author={Crane, Keenan and Pinkall, Ulrich and Schr{\"o}der, Peter},&lt;br&gt;
  journal={ACM Transactions on Graphics (TOG)},&lt;br&gt;
  volume={32},&lt;br&gt;
  number={4},&lt;br&gt;
  pages={1--10},&lt;br&gt;
  year={2013},&lt;br&gt;
  publisher={ACM New York, NY, USA}&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;&lt;a href="https://3d.si.edu/object/3d/triceratops-horridus-marsh-1889:d8c623be-4ebc-11ea-b77f-2e728ce88125" rel="noopener noreferrer"&gt;https://3d.si.edu/object/3d/triceratops-horridus-marsh-1889:d8c623be-4ebc-11ea-b77f-2e728ce88125&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nothings/stb" rel="noopener noreferrer"&gt;https://github.com/nothings/stb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The git repository for this project is also avalible at: &lt;a href="https://github.com/NoticeableSmeh/Rasterizer_Project" rel="noopener noreferrer"&gt;https://github.com/NoticeableSmeh/Rasterizer_Project&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>graphics</category>
      <category>learning</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Rasterizer Project - Part 4: Its out featuring Dinosaurs (rawr)</title>
      <dc:creator>NoticeableSmeh</dc:creator>
      <pubDate>Wed, 05 Nov 2025 13:49:59 +0000</pubDate>
      <link>https://dev.to/noticeablesmeh/rasterizer-project-part-4-its-out-featuring-dinosaurs-rawr-1dlk</link>
      <guid>https://dev.to/noticeablesmeh/rasterizer-project-part-4-its-out-featuring-dinosaurs-rawr-1dlk</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/noticeablesmeh" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535029%2Fc1833d53-7670-4889-aa71-59c4f588397d.jpg" alt="noticeablesmeh"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-4-triceratops-wireframe-26d1" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Rasterizer Project - Part 4: Triceratops Wireframe&lt;/h2&gt;
      &lt;h3&gt;NoticeableSmeh ・ Nov 5&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#gamedev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cpp&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#graphics&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#learning&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>gamedev</category>
      <category>cpp</category>
      <category>graphics</category>
      <category>learning</category>
    </item>
    <item>
      <title>Rasterizer Project - Part 4: Triceratops Wireframe</title>
      <dc:creator>NoticeableSmeh</dc:creator>
      <pubDate>Wed, 05 Nov 2025 00:15:36 +0000</pubDate>
      <link>https://dev.to/noticeablesmeh/rasterizer-project-part-4-triceratops-wireframe-26d1</link>
      <guid>https://dev.to/noticeablesmeh/rasterizer-project-part-4-triceratops-wireframe-26d1</guid>
      <description>&lt;p&gt;Okay so its time to define our model class both its .h file and cpp file. Lets start with the .h file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrkw8zuy4y3kt3xv0lu3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrkw8zuy4y3kt3xv0lu3.png" alt=" " width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First lets define a vector list made of of different vec3 that our model consists of and then lets. &lt;/p&gt;

&lt;p&gt;Then we store each face inside the int list. What is a face? Well every 3 vertexpositions we can draw a triangle, that triangle is the face. &lt;/p&gt;

&lt;p&gt;Then for our public class stuff. Our constructor takes a string path (constant so we dont fuzz about with it accidentally later on). Then our functions, quite simple. Constant get functions because we dont intend to change models after they have loaded in right now so our vertex count and face count will not change. Lets take a look at the cpp file now&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fqsgjyq5dmvzr96yhlx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fqsgjyq5dmvzr96yhlx.png" alt=" " width="800" height="159"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets start simple with this little helper function that takes a reference to str and the reference we have to check if equivalence. Our .obj files for models are essentially text files with data stored in rows, each row starts with v or f and if the program sees those it knows what type of data the numbers after are. Heres an example: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6j5s04hfhmxsjq9gkg5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6j5s04hfhmxsjq9gkg5.png" alt=" " width="429" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;those are the vertex positions for example that we have to read. &lt;/p&gt;

&lt;p&gt;Anyways the helper function checks if the str size is larger or equal to the reference, then we actually check if our firstletter is correct with the compare function.&lt;/p&gt;

&lt;p&gt;The compare function works like this, takes this string we have and start from this position in the string (0) and continue until the end of this index (firstLetter.size(), then if its equal to this string (firstLetter) then its correct and therefor == 0. 0 Means they are equal. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fonomh0xrtiu56kxchsgk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fonomh0xrtiu56kxchsgk.png" alt=" " width="736" height="808"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So lets go through this constructor.&lt;br&gt;
We create a ifstream that takes our filepath and tries to find it, if it cant fidn it it throws an error.&lt;/p&gt;

&lt;p&gt;Then we go line by line and read the line and if the line starts with the letter v we use a istringsteam to be able to manipulate the string, essentially we skip the first two positions in the string with substr(2) (More acurately we start at 2. &lt;br&gt;
Then we feed in our coordinates with istringstream dynamically because istringstream are super usefull and we place them in our vector list but we use emplace_back to create a new vec3 in our vector list.&lt;/p&gt;

&lt;p&gt;We do the same thing if the line starts with "f", which means it defines a face.&lt;br&gt;
Each face line in an .obj file contains multiple vertex references separated by spaces — for example:&lt;/p&gt;

&lt;p&gt;f 1/2/3 2/3/4 3/4/5&lt;/p&gt;

&lt;p&gt;We split the line into separate sections (like "1/2/3", "2/3/4", etc.).&lt;br&gt;
Each section contains vertex information, where the first number before the slash refers to the vertex index.&lt;/p&gt;

&lt;p&gt;To extract that, we look for the first / in the section using find('/').&lt;br&gt;
Then we take everything before that slash thats the vertex index we care about using substr(0, slashPos).&lt;br&gt;
We convert it to an integer with stoi() and subtract 1, because .obj files use 1-based indexing, but us programmers like to start at 0.&lt;/p&gt;

&lt;p&gt;Then we just store that int in our int list. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysfnydr65xrmkfgpblah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysfnydr65xrmkfgpblah.png" alt=" " width="750" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;getVertexCount we return the size of our vertexPositions list.&lt;br&gt;
Facecount we return how many faces our object has, its the amount of faceVertexIndices / 3 because 3 vertices make up a triangle duh.&lt;br&gt;
getVertex gets you the vertex from the index you send in. &lt;br&gt;
getVertexFromFace() This method takes a face index (yknow triangle) and a corner number which represents a vertex of that triangle then looks up which vertex that corner refers to and returns its 3D position. So for this to make sense we have to remember that our faces are defined in our .obj file as "f 1/2/3/" etc etc, so were essentially saying, gimme the second vertex (in plain english)! It would return the number 2 in that.&lt;/p&gt;

&lt;p&gt;Next lets head back into our main c++ file. So our models are in 3d right but we are presenting our models on a 2D plain, we have to have a function that converts 3d space into 2d space projection. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F50sjooo2203tyh289mkk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F50sjooo2203tyh289mkk.png" alt=" " width="800" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright so what this function does is take our 3D vertex coordinates that go from -1 to +1 (you know, model space) and remap them to 0 to screen size. We basically stretch our model to fill the whole screen.&lt;br&gt;
Then we just return those two values (x and y) so we can use them as pixel coordinates when drawing lines between points.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63uv9yofwwoikvki3cud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63uv9yofwwoikvki3cud.png" alt=" " width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we see were we instantiate our model and declare its file path but also how we draw it out! &lt;/p&gt;

&lt;p&gt;So once our model has loaded we create my favorite type of for loop which i use for like everything lol. But we declare a starting int variable and then we add + everytime we complete the loop and it finished when the model runs out of faces. So we retrieve the vertexes from their face respectively, this is where we get to use our getVertexFromFace function finally and here we also confusingnly get to use programming language with our index "Start at 0 for the 1 position this time!". We assign those vertices and then we project those vertices via our project function in order to figure out where they should be on our screen.&lt;/p&gt;

&lt;p&gt;Then finally we draw our beautiful lines, and by the end we will have this beautiful triceratops that totally does not look like a big blob.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fql3q8t6yl5bhcdhb9iin.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fql3q8t6yl5bhcdhb9iin.png" alt=" " width="786" height="791"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>cpp</category>
      <category>graphics</category>
      <category>learning</category>
    </item>
    <item>
      <title>Rasterizer project - Part 3 is up! Its all about 3D math. It was actually quite a fun thing to write about.</title>
      <dc:creator>NoticeableSmeh</dc:creator>
      <pubDate>Sat, 01 Nov 2025 23:16:07 +0000</pubDate>
      <link>https://dev.to/noticeablesmeh/rasterizer-project-part-3-is-up-its-all-about-3d-math-it-was-actually-quite-a-fun-thing-to-66b</link>
      <guid>https://dev.to/noticeablesmeh/rasterizer-project-part-3-is-up-its-all-about-3d-math-it-was-actually-quite-a-fun-thing-to-66b</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-3-geometry-3ek3" class="crayons-story__hidden-navigation-link"&gt;Rasterizer Project - Part 3: Geometry&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/noticeablesmeh" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535029%2Fc1833d53-7670-4889-aa71-59c4f588397d.jpg" alt="noticeablesmeh profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/noticeablesmeh" class="crayons-story__secondary fw-medium m:hidden"&gt;
              NoticeableSmeh
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                NoticeableSmeh
                
              
              &lt;div id="story-author-preview-content-2979176" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/noticeablesmeh" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535029%2Fc1833d53-7670-4889-aa71-59c4f588397d.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;NoticeableSmeh&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-3-geometry-3ek3" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Nov 1 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-3-geometry-3ek3" id="article-link-2979176"&gt;
          Rasterizer Project - Part 3: Geometry
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cpp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cpp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/learning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;learning&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/graphics"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;graphics&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gamedev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gamedev&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-3-geometry-3ek3#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>cpp</category>
      <category>learning</category>
      <category>graphics</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Rasterizer Project - Part 3: Geometry</title>
      <dc:creator>NoticeableSmeh</dc:creator>
      <pubDate>Sat, 01 Nov 2025 23:15:16 +0000</pubDate>
      <link>https://dev.to/noticeablesmeh/rasterizer-project-part-3-geometry-3ek3</link>
      <guid>https://dev.to/noticeablesmeh/rasterizer-project-part-3-geometry-3ek3</guid>
      <description>&lt;p&gt;So lets create a geomtry.h so we can actually calculate the 3d math we need for our rasterizer to work. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd925rk5z5z8a3cb54eb2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd925rk5z5z8a3cb54eb2.png" alt=" " width="571" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets start with this struct. This is ofcourse a vector 2, 2 coordinates. Default constructor is asserting 0, 0 on them, otherwise you can declare them. &lt;/p&gt;

&lt;p&gt;The operator functions return asign so you can return a value of either the x of y via an integer. What helped me understand this is to think of like OpenGl VertexAttrib, or assigned textures in Opengl. You assign them to an int and via that reference you can access that component in the array. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgwcorx2v05yp50nw83kp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgwcorx2v05yp50nw83kp.png" alt=" " width="800" height="646"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The vec3 struct works the same but with 3 components instead of 2! Excitng. What is assert? Well it checks wether or not a condition is true and if it isnt lets crash the program and display a problem so we can see what went wrong.&lt;/p&gt;

&lt;p&gt;Now lets do math magic, this is math guys this is all math.&lt;/p&gt;

&lt;p&gt;Except this one here this is just an overrided function that allows us to write out a vec2 as a string with our cout, its like &lt;a class="mentioned-user" href="https://dev.to/override"&gt;@override&lt;/a&gt; in java for toString(). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdd4wxgseu1yp87wge6c5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdd4wxgseu1yp87wge6c5.png" alt=" " width="800" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frlcty5kqvfqb8u60twej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frlcty5kqvfqb8u60twej.png" alt=" " width="663" height="122"&gt;&lt;/a&gt;&lt;br&gt;
heres our + operator, adding two vectors together is essentially just adding together each x and y with the coresponding x, y of the other vector. So 1, 2 + 2, 1 = 3, 3. Its quite simple really. if we just want to add to like for example the X coordinate, we just make do 0 on the Y like 1, 0.&lt;/p&gt;

&lt;p&gt;Now were done with establishing the basic math of vec2. Lets start doing the vector 3 stuff!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw06zxv92m7t1sflm1g0y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw06zxv92m7t1sflm1g0y.png" alt=" " width="733" height="113"&gt;&lt;/a&gt;&lt;br&gt;
minus - works the exact same way as + just with -. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j389w51zhdyl04tddj0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j389w51zhdyl04tddj0.png" alt=" " width="690" height="246"&gt;&lt;/a&gt;&lt;br&gt;
heres how the * functions if we multiply a vector by a scalar. Pretty simple I mean you know this. I dont really know how to explain it honestly we take it each coordinate times the scalar, and if we reverse the order we take the scalar first times the vec- you get it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7oltzl4pwb9r8rw80429.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7oltzl4pwb9r8rw80429.png" alt=" " width="724" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Division works just the same as the first multiplication method we defined but with /. You might be thinking, huh how come we need 2 different methods for * but only 1 for /? Well its simple dummy, You cant divide like this Scalar / Vector. Like what are you trying to accomplish here? &lt;/p&gt;

&lt;p&gt;Now its time for some slightly harder math&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5ci1cikkbaz1q7tvcj8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5ci1cikkbaz1q7tvcj8.png" alt=" " width="663" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is how we calculate our beautiful dot product. The dot proct lets us calculate how aligned two vectors are. The closer to 1 they are the more aligned and the closer to 0 the closer they are to being perpendicular. So if its 0 its completely perpendicular as in 90 degrees. However the dot product can also be negative, if this is the case it goes past those 90 degrees and faces away from the other vector. So the closer to -1 the closer the lines are to being opposite. The way to calculate a dot product is by multiplying each component of the vectors by one another and then + the x and y results of that. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmdmku6muss3gdrg8n5a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmdmku6muss3gdrg8n5a.png" alt=" " width="618" height="147"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So to calculate the length of a vector we use pythagoras theorem, that classic square root of (a^2 + b^2), I knew I had a reason to learn that in school!&lt;/p&gt;

&lt;p&gt;Now this is a helper function to our normalized function which looks like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fniqb5c3mmcrp98gr9i1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fniqb5c3mmcrp98gr9i1n.png" alt=" " width="492" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Normalizing means keeping a vectors direction in accordance to the origin point but making the it length of 1. We figure out the length of the vector via pythagoras theorem. We then divide the X and Y coordinate by that length. Now we get 1 length of the vector! Worth to note that if a vector is 0, 0 we return that vector but otherwise run that calculation of dividing. &lt;/p&gt;

&lt;p&gt;Now the vec2 math stuff is done and we can move onto the vec3 stuff. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxvj2pdc80xhye4bwd8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxvj2pdc80xhye4bwd8c.png" alt=" " width="605" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz9and90e9p4bul1tprv2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz9and90e9p4bul1tprv2.png" alt=" " width="680" height="142"&gt;&lt;/a&gt;&lt;br&gt;
Addition with vectors is still pretty easy and its the same for minus on the vectors aswell. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs80bo6o307twjo9ww5ua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs80bo6o307twjo9ww5ua.png" alt=" " width="552" height="106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Multiplication works the same as vector2 you just add another coordinate to multiply. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F295r5junbk34uraf49qe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F295r5junbk34uraf49qe.png" alt=" " width="538" height="106"&gt;&lt;/a&gt;&lt;br&gt;
division works the same essentially just with an added z.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63yju0y115q6128f5pow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63yju0y115q6128f5pow.png" alt=" " width="599" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Heres our dot product, it is also the same as before essentially we just need to add each vectors z value and multiply those together and add them to our total. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fca9eskzey43gu7fgl0t2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fca9eskzey43gu7fgl0t2.png" alt=" " width="626" height="127"&gt;&lt;/a&gt;&lt;br&gt;
Calculating length is the same principle we just gotta add the z value, this is getting quite repetetive right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgv36xjhupxji6v75gms5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgv36xjhupxji6v75gms5.png" alt=" " width="580" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And our normalize function is exactly the same we just take a vec3 instead of a vec 2!.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwtx2bqr3rpkbho9fv2wm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwtx2bqr3rpkbho9fv2wm.png" alt=" " width="800" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally we have this juicer of the cross product. &lt;br&gt;
We are using a right handed cross product system which means that our perpendicular vector created by comparing two vectors will be positive facing us and negative going away from us. I like to think of cross products as you are taking two lines and adding them ontop of eachother, where they both intersect you stick a needle through and thats where your new vector is. This new needle is perpendicular to both our other vectors, and depending on if its a right handed system or not were sticking the needle through the front (if left handed) or through the back so the needle is facing us (right handed).&lt;/p&gt;

&lt;p&gt;The way to calculate the cross product in math is i like to picture it as you have to multiply all different combinations of each vectors x, y and z values and then subtract it by another. Excluding if they have the same coordinate designation, like you wouldnt multiply A.y and B.y together. It is honeslty though probably the hardest formula to remember of the top of your head, so I always google it but hey it works.&lt;/p&gt;

&lt;p&gt;That does it for this part, really excited to actually dive deeper and draw some wirefram models but this has been very rewarding on the math aspect as that is were I am definitely lacking the most.&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>learning</category>
      <category>graphics</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Part 2 is up on the Rasterizer Project, were actually drawing a triangle now! Exciting!</title>
      <dc:creator>NoticeableSmeh</dc:creator>
      <pubDate>Fri, 31 Oct 2025 14:23:23 +0000</pubDate>
      <link>https://dev.to/noticeablesmeh/part-2-is-up-on-the-rasterizer-project-were-actually-drawing-a-triangle-now-exciting-318j</link>
      <guid>https://dev.to/noticeablesmeh/part-2-is-up-on-the-rasterizer-project-were-actually-drawing-a-triangle-now-exciting-318j</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-2-lines-and-optimization-excited-reaction-423j" class="crayons-story__hidden-navigation-link"&gt;Rasterizer Project - Part 2: Lines and Optimization (Excited reaction)&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/noticeablesmeh" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535029%2Fc1833d53-7670-4889-aa71-59c4f588397d.jpg" alt="noticeablesmeh profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/noticeablesmeh" class="crayons-story__secondary fw-medium m:hidden"&gt;
              NoticeableSmeh
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                NoticeableSmeh
                
              
              &lt;div id="story-author-preview-content-2976503" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/noticeablesmeh" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535029%2Fc1833d53-7670-4889-aa71-59c4f588397d.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;NoticeableSmeh&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-2-lines-and-optimization-excited-reaction-423j" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 31 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-2-lines-and-optimization-excited-reaction-423j" id="article-link-2976503"&gt;
          Rasterizer Project - Part 2: Lines and Optimization (Excited reaction)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/learning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;learning&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/graphics"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;graphics&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cpp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cpp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gamedev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gamedev&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-2-lines-and-optimization-excited-reaction-423j" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-2-lines-and-optimization-excited-reaction-423j#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>learning</category>
      <category>graphics</category>
      <category>cpp</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Rasterizer Project - Part 2: Lines and Optimization (Excited reaction)</title>
      <dc:creator>NoticeableSmeh</dc:creator>
      <pubDate>Fri, 31 Oct 2025 14:20:39 +0000</pubDate>
      <link>https://dev.to/noticeablesmeh/rasterizer-project-part-2-lines-and-optimization-excited-reaction-423j</link>
      <guid>https://dev.to/noticeablesmeh/rasterizer-project-part-2-lines-and-optimization-excited-reaction-423j</guid>
      <description>&lt;p&gt;Hello there beautiful people, lets continue on this rasterizer.&lt;/p&gt;

&lt;p&gt;So now we want to draw lines between points inside of our image. How do we do this? Well firstly lets talk about linear interpolation. It works like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F39tgf6pq92smvfjhypft.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F39tgf6pq92smvfjhypft.png" alt=" " width="800" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You take point A (origin point) and your point B (goal point), whats a point? well in 2D that comprises of a X and a Y coordinate. &lt;/p&gt;

&lt;p&gt;You calculate the X and Y cooridnate seperately in functions. What you do is you take A's x coordinate + (Bx - Ax) and * it by a scalar between 0 and 1. So in our example we use 0.02f which is 2% of the total lines length. So what this formula does is that we essentially calculate, what is 2% of the X value in the distance between our two Points (A and B). Then we store that and apply the same logic for our Y calculation. Its important to note that we round to nearest our result for each X and Y value we achieve. Then we paint that pixel, then we move on until that scalar gets fully to 100%.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F179bohm8nnwy73c5m2h6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F179bohm8nnwy73c5m2h6.png" alt=" " width="64" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the result, it has faults. Because just declaring a 0.02f scalar will not accurately paint out pixels perfectly, I mean that makes sense right you can't just decide that a random number will work perfectly for every instance of drawing a line. So lets try and fix this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxl1hesgkxeyzh0xod2az.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxl1hesgkxeyzh0xod2az.png" alt=" " width="800" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;here we are changing the code to loop over the X values instead of the scalar we were using before. This ensures us that were going from the x coordinate of point A to the x coordinate of point B. &lt;/p&gt;

&lt;p&gt;so the t float represents how far along the line we are, same as before 0.02 is 2% of the length of the line, were casting our A point and B points x valeus to floats because that's we don't want to lose any data on our calculations. Then were just doing the LERP calculation of Ax + (bx - Ax) * t);&lt;/p&gt;

&lt;p&gt;However you might have noticed that we will get a bug here? I managed to evade the bug by the nature of which i decided to draw my triangle in my code as you can see here &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqdrfkex9um7rry2bwwa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqdrfkex9um7rry2bwwa.png" alt=" " width="423" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So the green Line actually draws but lets say that bx is not bigger or equal to ax, then the condition for this loop would be false and that line wouldn't be drawn, we can fix this with a simple swap function before checkign with the loop. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6odj4q1r1usirn4rixk2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6odj4q1r1usirn4rixk2.png" alt=" " width="293" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;with this we should get this image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2h0c0muycc5is3wm5vg0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2h0c0muycc5is3wm5vg0.png" alt=" " width="64" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;well that blue line doesn't look good, were missing a lot there. Sometimes a line is more vertical than it is horizontal and this could cause problems with our code, the way to fix this is by transposing the y value to an x value and then doing the calculation essentially treating our y value as our x value in our set function. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cgsqbof5ucdbufjc506.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cgsqbof5ucdbufjc506.png" alt=" " width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and with that we get our very nice loooking triangle here. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvjoixrnls84xwpyq35b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvjoixrnls84xwpyq35b.png" alt=" " width="83" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I changed our image files to bmp files instead because it was easier to get those uncompressed but the code is basically the same. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9dl9f8tebal6x7rnbyd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9dl9f8tebal6x7rnbyd.png" alt=" " width="582" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw43sme5lc2smcuav14ek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw43sme5lc2smcuav14ek.png" alt=" " width="387" height="43"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;now it is time to do some otpimization, why you might ask? Because I want to learn. &lt;/p&gt;

&lt;p&gt;so lets define some random lines in our code that set a random x and y paint and paints lines between them. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcee9sbmjnww522vfq87a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcee9sbmjnww522vfq87a.png" alt=" " width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our first optimization is to just statically add 1 to the y axis and or subtract 1 on the y axis depending on if the direction is up and down, since thats how th y line is always calculated, there is no reason to manually calculate the y position everytime with our scalar. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqbolify8yebptz7v0lmn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqbolify8yebptz7v0lmn.png" alt=" " width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That divide part at the very end of y += is what gives us that either positive or negative number. &lt;/p&gt;

&lt;p&gt;Time for our second optimization. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn94n5sqd3g4bmsv8idu0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn94n5sqd3g4bmsv8idu0.png" alt=" " width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So before we declared a float for our y, this is however a little bit of wasted memory. This should make it so that we only use an int to store our y value but we correct it via a float that keeps our y aligned to the ration in which its increasing on the y. It does this by checking if the error is bigger than 0.5, this essentially means should it move up one more pixel and it does so accordingly.&lt;/p&gt;

&lt;p&gt;were still however using a float for this so lets ditch that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flk3rern17utzskqf9wx3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flk3rern17utzskqf9wx3.png" alt=" " width="647" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;were essentialy doing the same thing here but instead of dividing were multiplying because thats easier to do with integers right. So were performing the same mathematical calculation but just arriving their via integer instead. &lt;/p&gt;

&lt;p&gt;So this code is actually slower on paper than what we began with beacause were using an if statement. Since this is coded on the CPU if statements with a conditional like &amp;gt; essentially slows down and boggs down the pipleline. Since the CPU has to check wether or not this statement is correct and does so repeatedly for every loop it guesses everytime it is run, however if it guesses wrong it has to flush its pipeline and reset from 0, this ofcourse takes a little bit mor time, this is unlike the GPU which can run multiple paths but masks the incorrect one. So lets do this code without any if statements. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fil2q2ojt56abtdzr5cvs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fil2q2ojt56abtdzr5cvs.png" alt=" " width="722" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That does it for this part, in the next part we will implement our own geometry.h file. The one tinyrenderer uses I find confusing and not very c++ beginner friendly so I will make my own one that still works the same (essentially hopefully), then maybe if we have time we will finish the wireframe loading aswell. &lt;/p&gt;

</description>
      <category>learning</category>
      <category>graphics</category>
      <category>cpp</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Rasterizer project - Lets get this ball loading</title>
      <dc:creator>NoticeableSmeh</dc:creator>
      <pubDate>Mon, 27 Oct 2025 16:47:17 +0000</pubDate>
      <link>https://dev.to/noticeablesmeh/rasterizer-project-lets-get-this-ball-loading-1n93</link>
      <guid>https://dev.to/noticeablesmeh/rasterizer-project-lets-get-this-ball-loading-1n93</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-1-getting-started-jph" class="crayons-story__hidden-navigation-link"&gt;Rasterizer Project - Part 1: Getting started&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/noticeablesmeh" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535029%2Fc1833d53-7670-4889-aa71-59c4f588397d.jpg" alt="noticeablesmeh profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/noticeablesmeh" class="crayons-story__secondary fw-medium m:hidden"&gt;
              NoticeableSmeh
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                NoticeableSmeh
                
              
              &lt;div id="story-author-preview-content-2965499" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/noticeablesmeh" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535029%2Fc1833d53-7670-4889-aa71-59c4f588397d.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;NoticeableSmeh&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-1-getting-started-jph" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 27 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-1-getting-started-jph" id="article-link-2965499"&gt;
          Rasterizer Project - Part 1: Getting started
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/graphics"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;graphics&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cpp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cpp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gamedev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gamedev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/learning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;learning&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-1-getting-started-jph" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/noticeablesmeh/rasterizer-project-part-1-getting-started-jph#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>graphics</category>
      <category>cpp</category>
      <category>gamedev</category>
      <category>learning</category>
    </item>
    <item>
      <title>Rasterizer Project - Part 1: Getting started</title>
      <dc:creator>NoticeableSmeh</dc:creator>
      <pubDate>Mon, 27 Oct 2025 16:47:00 +0000</pubDate>
      <link>https://dev.to/noticeablesmeh/rasterizer-project-part-1-getting-started-jph</link>
      <guid>https://dev.to/noticeablesmeh/rasterizer-project-part-1-getting-started-jph</guid>
      <description>&lt;p&gt;Were making a Rasterizer folks, exciting really. I would like to credit: I will be using these resources in my journey in making this rasterizer. &lt;a href="https://lazyfoo.net/tutorials/SDL/" rel="noopener noreferrer"&gt;https://lazyfoo.net/tutorials/SDL/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://haqr.eu/tinyrenderer/bresenham/" rel="noopener noreferrer"&gt;https://haqr.eu/tinyrenderer/bresenham/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is a Rasterizer?&lt;br&gt;
Its a part of the graphics pipeline that turns all that magical mathematical geometry, points lines and tirangles into colored pixels on a 2D image. &lt;/p&gt;

&lt;p&gt;Everything you see in a rendered game or 3D scene comes down to rasteriztion. The program has to decide which pixels on the screen correspond to which parts of what triangles, what colour they should be (how bright etc etc). &lt;/p&gt;

&lt;p&gt;So the basic idea is that you start with triangles defined by vertices in 3D space, you transform those into 2D coordinates on your screen, after you have applied your perspective and projection and once they are in 2D the rasterizer does three things.&lt;/p&gt;

&lt;p&gt;Determines which pixels fall inside each triangle&lt;/p&gt;

&lt;p&gt;Interpolates values (Color, depth, texture coordinates, normals) across the pixels&lt;/p&gt;

&lt;p&gt;Writes the results into a framebuffer, which is the image in our memory that eventually gets display.&lt;/p&gt;

&lt;p&gt;It is like a coloring book for children although were talking to a computer which is even stupider than a child. Essentially we have to tell the program "Draw inside of this triangle shape, and do it with this color". &lt;/p&gt;

&lt;p&gt;So why am I building one by myself?&lt;br&gt;
It's fun, and it will look great on a CV. Unironically though it is really something you should learn a lot from and that is (mostly) why I am doing it. It is really helpful to do before you delve deeper into 3D graphics as we will see behind the curtains of the graphics API and really get down there in the mud and shape things up. It is important to note that were doing this all on the CPU because... Why not. Anyways lets delve deeper. &lt;/p&gt;

&lt;p&gt;I will be Using SDL 2.0 and STB_Image as I have worked with these before and I find them convenient. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44163bb9jkon57r0e4be.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44163bb9jkon57r0e4be.png" alt=" " width="64" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So this is what we want to make to start with, an image printed out into a file that we can open and displays three vertices so we can draw lines between them, lets take a look at the code. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sm2udtvr2kisg8x5m8t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sm2udtvr2kisg8x5m8t.png" alt=" " width="367" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;lets begin with this little struct here. Here we are essentially defining a pixel. A pixel has a RGBA value. What is RGBA? well it stands for Red, Green, Blue, Alpha silly. Each channel is stored in as an 8-bit unsigned integer. So each channel holds a value between 0 and 255, that is 256 total intensity levels per color channel. uint8_t stands for unsigned 8-bit integer (also known as a byte) and is imported via the  include. So essentially this struct represents a pixel. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh8qb7kr4pfjwrloo774q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh8qb7kr4pfjwrloo774q.png" alt=" " width="800" height="806"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;WOooo heres our Framebuffer struct. What is a framebuffer? well its a tiny CPU "canvas": holdsa width and heigh t plus a flat byte buffer holding the RGBA pixels. &lt;/p&gt;

&lt;p&gt;Now our constructor for our Framebuffer struct takes the width and height, we fill the entire thing with our data vector with a black color.&lt;/p&gt;

&lt;p&gt;That little for loop  in our clear walks through pixel by pixel and paints all pixels one colour. &lt;/p&gt;

&lt;p&gt;Alright now lets walk through the set function.&lt;br&gt;
First we check the bounds, this is just a safety thing so we dont accidentally write out of the bounds of the screen. &lt;/p&gt;

&lt;p&gt;the int i = (y * w + x) * 4; is translating our 2d space into a 1D byte index inside of our data vector. Each row has W pixels, each pixel takes up 4 bytes so y*w jumps down y rows, the +x moves x pixels across that row and the * 4 converts the pixel inedx into a byte offset (because we have RGBA values).&lt;/p&gt;

&lt;p&gt;Then we have this little section &lt;br&gt;
data[i + 0] = c.r;&lt;br&gt;
data[i + 1] = c.g;&lt;br&gt;
data[i + 2] = c.b;&lt;br&gt;
data[i + 3] = c.a;&lt;br&gt;
This copies the 4 color components of our Color struct into the right spot of our data vector. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fppq658putv7k5e8sjtwx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fppq658putv7k5e8sjtwx.png" alt=" " width="795" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now heres the function for actually writing out or data into a file. First things first we flip the image since were writing from the top left (unlike tinyrenderer who counts from bottom left) and then we yknow write it out. We provide the path directly to where our code is at yknow, provide the width and height. The number of channels, a pointer to our raw pixel data and the number of bytes per row. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqia7wx0b3ydbtt7jbqko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqia7wx0b3ydbtt7jbqko.png" alt=" " width="593" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;heres where we actually define our program. So we create the 64x64 framebuffer, fill it with black and paint three white pixels.&lt;/p&gt;

&lt;p&gt;Thats it for this part, we have now set up this program and we will continue with drawing lines in the next part&lt;/p&gt;

</description>
      <category>graphics</category>
      <category>cpp</category>
      <category>gamedev</category>
      <category>learning</category>
    </item>
    <item>
      <title>learning OpenGl - My journey through LearnOpenGL website is done, now its time to make something.</title>
      <dc:creator>NoticeableSmeh</dc:creator>
      <pubDate>Sun, 26 Oct 2025 21:25:34 +0000</pubDate>
      <link>https://dev.to/noticeablesmeh/learning-opengl-my-journey-through-learnopengl-website-is-done-now-its-time-to-make-something-4m99</link>
      <guid>https://dev.to/noticeablesmeh/learning-opengl-my-journey-through-learnopengl-website-is-done-now-its-time-to-make-something-4m99</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/noticeablesmeh/learning-opengl-part-the-end-model-loading-3ck5" class="crayons-story__hidden-navigation-link"&gt;Learning OpenGL Part: The End - Model loading&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/noticeablesmeh" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535029%2Fc1833d53-7670-4889-aa71-59c4f588397d.jpg" alt="noticeablesmeh profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/noticeablesmeh" class="crayons-story__secondary fw-medium m:hidden"&gt;
              NoticeableSmeh
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                NoticeableSmeh
                
              
              &lt;div id="story-author-preview-content-2950178" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/noticeablesmeh" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535029%2Fc1833d53-7670-4889-aa71-59c4f588397d.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;NoticeableSmeh&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/noticeablesmeh/learning-opengl-part-the-end-model-loading-3ck5" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 26 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/noticeablesmeh/learning-opengl-part-the-end-model-loading-3ck5" id="article-link-2950178"&gt;
          Learning OpenGL Part: The End - Model loading
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/learning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;learning&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/graphics"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;graphics&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cpp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cpp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gamedev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gamedev&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/noticeablesmeh/learning-opengl-part-the-end-model-loading-3ck5" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/noticeablesmeh/learning-opengl-part-the-end-model-loading-3ck5#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>learning</category>
      <category>graphics</category>
      <category>cpp</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Learning OpenGL Part: The End - Model loading</title>
      <dc:creator>NoticeableSmeh</dc:creator>
      <pubDate>Sun, 26 Oct 2025 21:23:57 +0000</pubDate>
      <link>https://dev.to/noticeablesmeh/learning-opengl-part-the-end-model-loading-3ck5</link>
      <guid>https://dev.to/noticeablesmeh/learning-opengl-part-the-end-model-loading-3ck5</guid>
      <description>&lt;p&gt;So far weve only been using a cube and thats not very exciting is it. We probably want to expand beyond this cube if we want to make more impressive 3d graphics. We want to be able to import .fbx files that store the vertices data without us having to declare it everytime, just fetch the file and display that information accordingly. So lets do this.&lt;/p&gt;

&lt;p&gt;Assimp:&lt;br&gt;
Assimp is an open sourcce library that loads a model files data, once Assimp has loaded the file we can retrieve the data we need from Assimp. When you import the model it creates a scene object that contains the data of that model. If you want to read more about how Assimp exactly functions you can read more here. &lt;br&gt;
&lt;a href="https://learnopengl.com/Model-Loading/Assimp" rel="noopener noreferrer"&gt;https://learnopengl.com/Model-Loading/Assimp&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Mesh Class:&lt;br&gt;
LearnOpenGL introduces the mesh class at this point so lets explain that class and how it works exactly. Lets take this step by step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkby57je3dh1l6oxbdr4m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkby57je3dh1l6oxbdr4m.png" alt=" " width="561" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Position: where the models position is.&lt;/p&gt;

&lt;p&gt;Normal: The directions for each surface&lt;/p&gt;

&lt;p&gt;TexCoords: the texture coordinates&lt;/p&gt;

&lt;p&gt;Tangent &amp;amp; Bitangent: These are honestly a little bit confusing but the way i understand it is that they both along with the normal contribute to making the UV mapping make sense accordingly. An object is only really textured on its outside and is hollow inside so we have to both orient the textures accordingly to how the model should look and make sure they are properly displayed in which the normal points. Tangent tells the X(U) direciton and Bitangent tells the Y (V)direction. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F71jqpvyuy9bk2z3kl72j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F71jqpvyuy9bk2z3kl72j.png" alt=" " width="330" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The standard unsigned int id, this ofcourse stores the texture ID that will be created with glGenTextures, and the string ofcourse stores its type, our Mesh::Draw() function will look at the type to decide which uniform name to use when binding the texture.&lt;/p&gt;

&lt;p&gt;now lets actually look at the mesh class instead of the file. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu9zuej8yjh00gpqhwkwa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu9zuej8yjh00gpqhwkwa.png" alt=" " width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So the class has three global variables that are lists (vectors).&lt;br&gt;
Vertices, indices and textures, now these should seem familiar to you by now but here we go again&lt;br&gt;
Vertices = all the vertex data (positions, normals, uvs etc etc), Its convenient that we made that struct before right? Because now we get to use it!&lt;/p&gt;

&lt;p&gt;indices: lets tell our program which vertices to connect and in what order!&lt;/p&gt;

&lt;p&gt;textures = textures. But more interesting now because we have diffuse, normalmap and specular textures etc etc. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzrqtsh4liax9fzapo78l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzrqtsh4liax9fzapo78l.png" alt=" " width="800" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we have this very boring constructor that takes arguments and asigns its arguments to the class variables, boring boo! But we do call a function in it that is setupMesh(), neato.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsrqvfgawp0213z2l62eb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsrqvfgawp0213z2l62eb.png" alt=" " width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets take a look at this draw function.&lt;/p&gt;

&lt;p&gt;The function takes a reference to the shader object yknow so we can acess it and everything.&lt;/p&gt;

&lt;p&gt;each texture type can have mutliple textures so we can refer to them properly we need a numbering system with ints. Just add 1!, texture1, texture2 etc etc.&lt;/p&gt;

&lt;p&gt;Then we loop through all the textures and actiavte each texture accordingly and bind it. &lt;/p&gt;

&lt;p&gt;Then we figure out the names of the uniform name and in that figure out what kind of texture it is, specular, diffuse etc etc. Then we bind that accordingly. &lt;/p&gt;

&lt;p&gt;Then finally we draw the mesh yknow with drawElements etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggn5qftflew27jrmfefs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggn5qftflew27jrmfefs.png" alt=" " width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So lets go through this one more time&lt;/p&gt;

&lt;p&gt;VAO remembers how to read our vertex data and which EBO is attached.&lt;/p&gt;

&lt;p&gt;VBO = this is like a chunk of memory that stores vertex data, its positions, normals, texture coords, tangents, bitangents etc etc. &lt;/p&gt;

&lt;p&gt;EBO carries the indices (which vertices make which triangles)&lt;/p&gt;

&lt;p&gt;Then we bind the VAO accordingly to openGL.&lt;/p&gt;

&lt;p&gt;Proceeding to upload the vertex data into the VBO and doing the same with the EBO. &lt;/p&gt;

&lt;p&gt;Then we do the classic song and dance of the vertexAttribgame with the offsets and making sure things are bound accordingly to our vertices and indices array. &lt;/p&gt;

&lt;p&gt;Then finally we unbind the VAO with glBindVertexArrray(0);.&lt;/p&gt;

&lt;p&gt;Model Class:&lt;br&gt;
Now lets implement a model class, the model class will essentially create an object that includes a bunch of different meshes. A house for example is built out of multiple different meshes, so storing them all inside a "model" would be ideal. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2do0mvyap0y6akk3bfk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2do0mvyap0y6akk3bfk.png" alt=" " width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So we have a few public class variables here so lets talk about those. &lt;br&gt;
textures_loaded stores all the loaded texture, it would be expensive and stupid to load all the textures time and time again in order to draw a model. What if a model reuses a texture a lot? Should we load it everytime? Ofcourse not thats not a good idea.&lt;/p&gt;

&lt;p&gt;meshes, this is the list of our meshes that the model consists of.&lt;/p&gt;

&lt;p&gt;directory, this stores the path to the folder where the model file came from, so if textures are stored with relative paths we can find the properly.&lt;/p&gt;

&lt;p&gt;gammacorrection, this is just a boolean flag for handling gamma correction when loading textures, not really used right now.&lt;/p&gt;

&lt;p&gt;Then we have our constructor, So in order to create a model we have to give a filepath, and as soon as the object is constructed it loads its model, immediately upon creation all the models meshes, data and textures are ready!&lt;/p&gt;

&lt;p&gt;Then we have our wildly simple render function, It just loops over all our meshes inside the model and calls the draw function passing in a reference to the shader. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5tgsxofa6coqanq8b4b2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5tgsxofa6coqanq8b4b2.png" alt=" " width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that our Model class is set up, we need a way to actually load the data from a model file. That’s where loadModel() comes in.&lt;br&gt;
This function takes a file path, gives it to Assimp, and builds a scene out of it.&lt;/p&gt;

&lt;p&gt;So we create an Assimp::importer objectm this class reads the files and returns a scene, whats a scene? well its a container for essentially everything inside the models file. Assimp handles its meshes, materials. textures etc etc with hierarchies. A part of our model can have a child. I like to think of this like how it is in Unity, lets say you have a Wall with a cutout of a door, then you have the door. You attach the door to the wall (so now the door is a child of the wall) so you can just rotate the door without rotating the whole wall. &lt;/p&gt;

&lt;p&gt;Anyway then we read the file through our path variable which is provided within our argument. &lt;br&gt;
aiProcess_Triangulate makes sure that every face of the model is converted into triangles cuz triangles are awesome.&lt;/p&gt;

&lt;p&gt;aiProcess_triangulate apparently flips the Y coordinate of the texture coordinates, OpenGL treats the top of a texture as 0, other programs do differently i guess.&lt;/p&gt;

&lt;p&gt;aiProcess_genSmoothNormals So if the model doesnt have normals this will automatically generate them.&lt;/p&gt;

&lt;p&gt;Then were onto a quick sanity check code, that our code is actually working, no errors.&lt;/p&gt;

&lt;p&gt;If everything works out we continue and we extract the directory path and then finally we process the root node, process node then goes through all its children, extracts those meshes and stores it in our Model object.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpyqp806paoxcx9sgv05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpyqp806paoxcx9sgv05.png" alt=" " width="800" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we loop through all meshes that the node references, we stores the indices of each mesh if there are any in our global scene-&amp;gt;mMeshes array.&lt;br&gt;
Then for each index we call processMesh, thats what converts our Assimp mesh into the Mesh class. Then we push back the processed mesh into our meshes vector which our Model object has. &lt;br&gt;
After handling the meshes in the current node we Go to its children. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxfsr6uj7av6xbhn6eqc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxfsr6uj7av6xbhn6eqc.png" alt=" " width="800" height="631"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now here we have a doozy, took me a long time to make this function actually work and this seems to work so lets go through this massive function here.&lt;/p&gt;

&lt;p&gt;Local containers for vertices, indices and textures, this the stuff that make up a mesh right so we need to define and extract that. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46939i2661ppva4gn4sa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46939i2661ppva4gn4sa.png" alt=" " width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets build the vertex list.&lt;br&gt;
aiMesh stores positions in mVertices, mNormals and up to 8 UV sets in mTextureCoords. This is pretty standard right you loop through each vertex insid the mesh and retrieve these and add to the vector list. Push_back ofcourse adds the element to the end of the vector list. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysb7sxa4kvj2hrr1t64w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysb7sxa4kvj2hrr1t64w.png" alt=" " width="599" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We build the index list, Assimp gives faces and we flatten their indices into one indices array to be used by our EBO. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5g9tgyxlgpjnt21tl2ia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5g9tgyxlgpjnt21tl2ia.png" alt=" " width="798" height="52"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we snatch that material for this particulary mesh, we will read the textures from this material right heeeeere&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq0uhv7xtscn59hd9qrbk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq0uhv7xtscn59hd9qrbk.png" alt=" " width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oh wee a lambda exciting. A little local helper function (addTex) inside our procesMesh function, So it can access textures and mat because of [&amp;amp;] you know it has its refrences. When its called it loads all the textures ofa certain type from the material and then appends them all into the main texture list. SO eachcall just loads a new category of textures and adds them to the list. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmraaq70fl1mlk910v72t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmraaq70fl1mlk910v72t.png" alt=" " width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I mean ye lets add all the different textures, not that complicated just looks like right old mess. Small little algorithm function find_if and none_of with a cute little lambda. Diffuse and base_color are different names for the same thing so its worth it to check both and if we dont have those check ambient and all that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqey2q2m127ltrn3b065.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqey2q2m127ltrn3b065.png" alt=" " width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;lets load a materials textures! Basic arguments, what material are we loading? What type of material? Whats the name we want to assign to it in our shader, and the gamma thing. Whether to load textures in sRGB or linear color space.  Returns the textures vector list that we will append to the meshs texture list. &lt;/p&gt;

&lt;p&gt;We loop over all the textures of that type, GetTextureCount() is a helper function that asks how many textures of a type it has. Then we fetch that texture. &lt;/p&gt;

&lt;p&gt;bool skip, we check if we have already loaded it, if we have skip that stuff. If not load it now.&lt;/p&gt;

&lt;p&gt;TextureFromFile reads the actual image and creates an opengl texture and returns its id. Then we fill in the rest, Type of texture and its path.&lt;/p&gt;

&lt;p&gt;Add it to our local list with push back and then we add it to the global cache with textures_loaded.push_back(t) so other meshes can reuse it. &lt;/p&gt;

&lt;p&gt;Okay now lets take a look at how we implement the model class inside our main c++ file&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxlflb5mern50hf8yvt3v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxlflb5mern50hf8yvt3v.png" alt=" " width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We build the shader and hook up the sampler uniforms. We immediately set the sampler uniforms to the texture units, GL_Texture_0, Gl_Texture_1 etcetc. This must match what Mesh::Draw does though when it binds textures, but eh. &lt;/p&gt;

&lt;p&gt;We load the model asset via our constructor. &lt;br&gt;
Then the render loop is as usual but its very satisfying. Anyways, heres the result&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzny5wf7ythps91y22ev1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzny5wf7ythps91y22ev1.png" alt=" " width="800" height="732"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oh and heres the link to the model &lt;a href="https://sketchfab.com/3d-models/survival-guitar-backpack-799f8c4511f84fab8c3f12887f7e6b36" rel="noopener noreferrer"&gt;https://sketchfab.com/3d-models/survival-guitar-backpack-799f8c4511f84fab8c3f12887f7e6b36&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;and shoutout to &lt;a href="https://learnopengl.com" rel="noopener noreferrer"&gt;https://learnopengl.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So like I'm sort of done. I feel like I have gotten the basics of openGL sort of under my hands. I do not think it would be very beneficial to go through every section of LearnOpenGL, specificly the advanced stuff. I think learning opengl has reached a pretty natural conclusion. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://learnopengl.com" rel="noopener noreferrer"&gt;https://learnopengl.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sketchfab.com/3d-models/survival-guitar-backpack-799f8c4511f84fab8c3f12887f7e6b36" rel="noopener noreferrer"&gt;https://sketchfab.com/3d-models/survival-guitar-backpack-799f8c4511f84fab8c3f12887f7e6b36&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/assimp/assimp" rel="noopener noreferrer"&gt;https://github.com/assimp/assimp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nothings/stb" rel="noopener noreferrer"&gt;https://github.com/nothings/stb&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.glfw.org/download.html" rel="noopener noreferrer"&gt;https://www.glfw.org/download.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/g-truc/glm" rel="noopener noreferrer"&gt;https://github.com/g-truc/glm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://glad.dav1d.de/" rel="noopener noreferrer"&gt;https://glad.dav1d.de/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Dav1dde/glad" rel="noopener noreferrer"&gt;https://github.com/Dav1dde/glad&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and you&lt;/p&gt;

</description>
      <category>learning</category>
      <category>graphics</category>
      <category>cpp</category>
      <category>gamedev</category>
    </item>
  </channel>
</rss>
