This commit is contained in:
		
							parent
							
								
									be1fcf49bc
								
							
						
					
					
						commit
						6697a24c6d
					
				
					 5 changed files with 181 additions and 64 deletions
				
			
		| 
						 | 
				
			
			@ -1,19 +1,50 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import { Info } from '@lucide/svelte';
 | 
			
		||||
	export let title;
 | 
			
		||||
	import { Info, BookCopy, Eye, Network, Sigma } from '@lucide/svelte';
 | 
			
		||||
	let { title, type = 'info' } = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div class="note">
 | 
			
		||||
	<div class="head">
 | 
			
		||||
		<div class="icon">
 | 
			
		||||
			<Info />
 | 
			
		||||
			{#if type == 'info'}
 | 
			
		||||
				<Info />
 | 
			
		||||
			{:else if type == 'diagram'}
 | 
			
		||||
				<Network />
 | 
			
		||||
			{:else if type == 'math'}
 | 
			
		||||
				<Sigma />
 | 
			
		||||
			{:else if type == 'review'}
 | 
			
		||||
				<Eye />
 | 
			
		||||
			{:else if type == 'resource'}
 | 
			
		||||
				<BookCopy />
 | 
			
		||||
			{/if}
 | 
			
		||||
		</div>
 | 
			
		||||
 | 
			
		||||
		<div class="horiz_line"></div>
 | 
			
		||||
		{#if type == 'info'}
 | 
			
		||||
			<div class="horiz_line" style:background-color="#8ec07c"></div>
 | 
			
		||||
		{:else if type == 'diagram'}
 | 
			
		||||
			<div class="horiz_line" style:background-color="#d3869b"></div>
 | 
			
		||||
		{:else if type == 'math'}
 | 
			
		||||
			<div class="horiz_line" style:background-color="#fe8019"></div>
 | 
			
		||||
		{:else if type == 'review'}
 | 
			
		||||
			<div class="horiz_line" style:background-color="#cc241d"></div>
 | 
			
		||||
		{:else if type == 'resource'}
 | 
			
		||||
			<div class="horiz_line" style:background-color="#458588"></div>
 | 
			
		||||
		{/if}
 | 
			
		||||
	</div>
 | 
			
		||||
 | 
			
		||||
	<div class="content">
 | 
			
		||||
		<div class="line"></div>
 | 
			
		||||
		{#if type == 'info'}
 | 
			
		||||
			<div class="line" style:background-color="#8ec07c"></div>
 | 
			
		||||
		{:else if type == 'diagram'}
 | 
			
		||||
			<div class="line" style:background-color="#d3869b"></div>
 | 
			
		||||
		{:else if type == 'math'}
 | 
			
		||||
			<div class="line" style:background-color="#fe8019"></div>
 | 
			
		||||
		{:else if type == 'review'}
 | 
			
		||||
			<div class="line" style:background-color="#cc241d"></div>
 | 
			
		||||
		{:else if type == 'resource'}
 | 
			
		||||
			<div class="line" style:background-color="#458588"></div>
 | 
			
		||||
		{/if}
 | 
			
		||||
 | 
			
		||||
		<div class="slot">
 | 
			
		||||
			<p>{title}</p>
 | 
			
		||||
			<slot />
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +77,6 @@
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	.line {
 | 
			
		||||
		background-color: #8ec07c;
 | 
			
		||||
		width: 0.1em;
 | 
			
		||||
		margin-left: 0.85em;
 | 
			
		||||
		margin-bottom: 1em;
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +84,6 @@
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	.horiz_line {
 | 
			
		||||
		background-color: #8ec07c;
 | 
			
		||||
		height: 0.1em;
 | 
			
		||||
		margin-left: 0.5em;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +102,7 @@
 | 
			
		|||
		font-family: 'IBM Plex Mono', monospace;
 | 
			
		||||
		display: inline-block;
 | 
			
		||||
		margin: 0;
 | 
			
		||||
        font-weight: bolder;
 | 
			
		||||
		font-weight: bolder;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.icon {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@
 | 
			
		|||
        font-weight: 600;
 | 
			
		||||
        font-style: italic;
 | 
			
		||||
        color: #fabd2f;
 | 
			
		||||
        border-bottom: .5px solid #d79921;
 | 
			
		||||
        border-bottom: 1px solid #fe8019;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Tooltip text */
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +32,7 @@
 | 
			
		|||
		text-align: justify;
 | 
			
		||||
        padding: 1em;
 | 
			
		||||
		border-radius: 6px;
 | 
			
		||||
        border: 1px solid #928374;
 | 
			
		||||
        border: 1px dotted #fe8019;
 | 
			
		||||
 | 
			
		||||
		top: 100%;
 | 
			
		||||
		left: 50%;
 | 
			
		||||
| 
						 | 
				
			
			@ -46,4 +46,8 @@
 | 
			
		|||
	.tooltip:hover .tooltiptext {
 | 
			
		||||
		visibility: visible;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    .tooltip:hover {
 | 
			
		||||
        color: #fe8019;
 | 
			
		||||
    }
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,38 +1,52 @@
 | 
			
		|||
* {
 | 
			
		||||
    color: #ebdbb2;
 | 
			
		||||
    font-family: 'Inter';
 | 
			
		||||
    font-optical-sizing: auto;
 | 
			
		||||
    font-weight: 400;
 | 
			
		||||
    font-style: normal;
 | 
			
		||||
	color: #ebdbb2;
 | 
			
		||||
	font-family: 'Inter';
 | 
			
		||||
	font-optical-sizing: auto;
 | 
			
		||||
	font-weight: 400;
 | 
			
		||||
	font-style: normal;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
strong {
 | 
			
		||||
    font-weight: 600;
 | 
			
		||||
    font-style: italic;
 | 
			
		||||
    color: #fabd2f;
 | 
			
		||||
	font-weight: 600;
 | 
			
		||||
	font-style: italic;
 | 
			
		||||
	color: #fabd2f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
strong:hover {
 | 
			
		||||
	color: #fe8019;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h1 {
 | 
			
		||||
    display: block;
 | 
			
		||||
    font-size: 2em;
 | 
			
		||||
    margin-top: 0.0em;
 | 
			
		||||
    margin-bottom: 0.0em;
 | 
			
		||||
    margin-left: 0;
 | 
			
		||||
    margin-right: 0;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
	display: block;
 | 
			
		||||
	font-size: 2em;
 | 
			
		||||
	margin-top: 0em;
 | 
			
		||||
	margin-bottom: 0em;
 | 
			
		||||
	margin-left: 0;
 | 
			
		||||
	margin-right: 0;
 | 
			
		||||
	font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h2 {
 | 
			
		||||
    display: block;
 | 
			
		||||
    font-size: 1.5em;
 | 
			
		||||
    margin-top: 0.83em;
 | 
			
		||||
    margin-bottom: 0.0em;
 | 
			
		||||
    margin-left: 0;
 | 
			
		||||
    margin-right: 0;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
	display: block;
 | 
			
		||||
	font-size: 1.5em;
 | 
			
		||||
	margin-top: 0.83em;
 | 
			
		||||
	margin-bottom: 0em;
 | 
			
		||||
	margin-left: 0;
 | 
			
		||||
	margin-right: 0;
 | 
			
		||||
	font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a {
 | 
			
		||||
	display: block;
 | 
			
		||||
	text-decoration: none;
 | 
			
		||||
	color: #83a598;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a:hover {
 | 
			
		||||
	color: #458588;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.katex {
 | 
			
		||||
    width: max-content;
 | 
			
		||||
    margin-left: 0;
 | 
			
		||||
	width: max-content;
 | 
			
		||||
	margin-left: 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										25
									
								
								src/routes/articles/technical-debt/+page.svx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/routes/articles/technical-debt/+page.svx
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
---
 | 
			
		||||
title: C++ Technical Debt
 | 
			
		||||
date: "April 20 - 2025"
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import Paragraph from '../Paragraph.svelte';
 | 
			
		||||
import HorizontalBreak from '../HorizontalBreak.svelte';
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<HorizontalBreak/>
 | 
			
		||||
 | 
			
		||||
<Paragraph>
 | 
			
		||||
 | 
			
		||||
Have you ever had your project grow too messy that the idea of **total-rewrite** started haunting your
 | 
			
		||||
dreams? In this article I'll teach you how to avoid that state forever :)
 | 
			
		||||
</Paragraph>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Technical Debt
 | 
			
		||||
 | 
			
		||||
<Paragraph>
 | 
			
		||||
 | 
			
		||||
What causes such a state?
 | 
			
		||||
</Paragraph>
 | 
			
		||||
| 
						 | 
				
			
			@ -11,28 +11,39 @@ import Tip from "../Tip.svelte"
 | 
			
		|||
 | 
			
		||||
Ever wondered how games put all that gore on your display? All that beauty is brought into life by
 | 
			
		||||
a process called **rendering**, and at the heart of it, is the **graphics pipeline**.
 | 
			
		||||
In this article we'll dive deep into  the intricate details of this beast.
 | 
			
		||||
In this article we'll dive deep into the intricate details of this powerful beast.
 | 
			
		||||
 | 
			
		||||
We'll cover all the terminologies needed to understand each stage and have many restatements so don't
 | 
			
		||||
worry if you don't fully grasp something at first. I'll make sure you understand everything at the
 | 
			
		||||
end of our journey. If you still had questions, feel free to contact me :)
 | 
			
		||||
 | 
			
		||||
So without further ado---
 | 
			
		||||
 | 
			
		||||
## Overview
 | 
			
		||||
 | 
			
		||||
Like any pipeline, the **graphics pipeline** is comprised 
 | 
			
		||||
of several **stages**, each of which can be a pipeline in itself or even parallelized.
 | 
			
		||||
Each stage takes some input (data and configuration) to generate some output data for the next stage.
 | 
			
		||||
 | 
			
		||||
<Note title="A coarse division of the graphics pipeline">
 | 
			
		||||
<Note title="A coarse division of the graphics pipeline", type="diagram">
 | 
			
		||||
 | 
			
		||||
Application --> Geometry Processing --> Rasterization --> Pixel Processing --> Presentation
 | 
			
		||||
</Note>
 | 
			
		||||
 | 
			
		||||
Before the heavy rendering work starts on the <Tip text="GPU">Graphics Processing Unit</Tip>,
 | 
			
		||||
we simulate and update the world through systems such as physics engine, game logic, networking, etc.
 | 
			
		||||
we simulate and update the world through **systems** such as physics engine, game logic, networking, etc.
 | 
			
		||||
during the **application** stage.
 | 
			
		||||
This stage is mostly ran on the <Tip text="CPU">Central Processing Unit</Tip>, 
 | 
			
		||||
therefore it is extremely efficient on executing <Tip text="sequentially dependendent logic">
 | 
			
		||||
therefore it is extremely efficient on executing <Tip text="sequentially dependent logic">
 | 
			
		||||
A type of execution flow where the operations depend on the results of previous steps, limiting parallel execution.
 | 
			
		||||
In other words, **CPUs** are great at executing **branch-heavy** code, and **GPUs** are geared
 | 
			
		||||
towards executing a TON of **branch-less** or **branch-light** code in parallel. </Tip>.
 | 
			
		||||
 | 
			
		||||
The updated scene data is then prepped and fed to the **GPU** for **geometry processing**; which is 
 | 
			
		||||
where we figure out where everything ends up on our screen. We'll cover this stage in depth very soon so don't panic (yet).
 | 
			
		||||
// NOTE: twice  "where..."
 | 
			
		||||
 | 
			
		||||
The updated scene data is then prepped and fed to the **GPU** for **geometry processing**. Here 
 | 
			
		||||
we figure out where everything ends up on our screen by doing lots of fancy matrix math.
 | 
			
		||||
We'll cover this stage in depth very soon so don't panic (yet).
 | 
			
		||||
 | 
			
		||||
Afterwards, the final geometric data are converted into <Tip text="pixels"> Pixel is the shorthand for **picture-element**, Voxel is the shorthand for **volumetric-element**. </Tip>
 | 
			
		||||
and prepped for the **pixel processing** stage via a process called **rasterization**.
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +51,7 @@ In other words, this stage converts a rather abstract and internal presentation
 | 
			
		|||
into something more concrete (pixels). It's called rasterization because end the product is a <Tip text="raster">Noun. A rectangular pattern of parallel scanning lines followed by the electron beam on a television screen or computer monitor. -- 1930s: from German Raster, literally ‘screen’, from Latin rastrum ‘rake’, from ras- ‘scraped’, from the verb radere. ---Oxford Languages</Tip> of pixels.
 | 
			
		||||
 | 
			
		||||
The **pixel processing** stage then uses the rasterized geometry data (pixel data) to do **lighting**, **texturing**, 
 | 
			
		||||
and all the sweet gory details of a murder scene. 
 | 
			
		||||
and all the sweet gory details of a scene (like a murder scene). 
 | 
			
		||||
This stage is often, but not always, the most computationally expensive. 
 | 
			
		||||
A huge problem that a good rendering engine needs to solve is how to be **performant**. And a great deal
 | 
			
		||||
of **optimization** can be done through **culling** the work that we can deem unnecessary/redundant in each
 | 
			
		||||
| 
						 | 
				
			
			@ -61,9 +72,9 @@ Ever been jump-scared by this sight in an <Tip text="FPS">First Person (Shooter)
 | 
			
		|||
/> 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
In order to display a scene (like a murder scene), 
 | 
			
		||||
In order to display a (murder) scene, 
 | 
			
		||||
we need to have a way of **representing** the **surface** of its composing objects (like corpses) in computer memory.
 | 
			
		||||
We only care about the **surface** since we won't be seeing the insides anyway---Not that we want to.
 | 
			
		||||
We only care about the **surface** since we won't be seeing the insides anyway---Not with that attitude.
 | 
			
		||||
At this stage, we only care about the **shape** or the **geometry** of the **surface**.
 | 
			
		||||
Texturing, lighting, and all the sweet gory details come at a much later stage once all the **geometry** has been processed.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -128,16 +139,20 @@ Also, it is a common practice in computer science to break down hard problems in
 | 
			
		|||
This will be a lot more convincing when we cover the **rasterization** stage :)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Bonus point: present-day **hardware** and **algorithms** have become **extremely efficient** at processing 
 | 
			
		||||
triangles (sorting, rendering, etc) after eons of evolving around them.
 | 
			
		||||
<Note title="Bonus point: evolution", type="info">
 | 
			
		||||
 | 
			
		||||
present-day **hardware** and **algorithms** have become **extremely efficient** at processing 
 | 
			
		||||
triangles by doing operations such as sorting, rasterizing, etc, after eons of evolving around them.
 | 
			
		||||
 | 
			
		||||
</Note>
 | 
			
		||||
 | 
			
		||||
## Primitive Topology
 | 
			
		||||
So, we got our set of vertices, but having a bunch of points floating around wouldn't be so
 | 
			
		||||
interesting, we need to form **triangles** out of them, or more specifically, **triangle strips**.
 | 
			
		||||
So, we got our set of vertices, but having a bunch of points floating around wouldn't make a scene very lively
 | 
			
		||||
(or even deadly), we need to form **triangles** out of them to compose **models**.
 | 
			
		||||
 | 
			
		||||
We communicate to the computer what type of primitives we want to generate from our vertices by
 | 
			
		||||
configuring the **primitive topology** of the **input assembler**.
 | 
			
		||||
We'll get into the **input assembler** in a second, but what is a **primitive toplogy**?
 | 
			
		||||
We'll get into the **input assembler** bit in a second, but what is a **primitive toplogy**?
 | 
			
		||||
 | 
			
		||||
<Tip text="Toplogy">The way in which constituent parts are interrelated or arranged.--mid 19th century: via German from Greek topos ‘place’ + -logy.---Oxford Languages</Tip>
 | 
			
		||||
basically defines the way we connect our vertices together, it would be more clear to provide examples than drown you in theory.
 | 
			
		||||
| 
						 | 
				
			
			@ -146,15 +161,21 @@ As stated previously, we got 3 main types of primitives, **triangles**, **lines*
 | 
			
		|||
(There's also a **patch primitive** which we won't get into for now). Let's quickly run through all
 | 
			
		||||
the possible ways we can make these 3 types of primitives alongside some visual cues.
 | 
			
		||||
 | 
			
		||||
In the following equations, **p** stands for **primitive** and **v** stands for **vertex**.
 | 
			
		||||
	
 | 
			
		||||
**Point list**:
 | 
			
		||||
 | 
			
		||||
When the topology is **point list**, each consecutive vertex defines a single point primitive, according to the equation:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<Note title="Point list equation", type="math">
 | 
			
		||||
 | 
			
		||||
```math
 | 
			
		||||
    p_i = \{ v_i \}
 | 
			
		||||
p_i = \{ v_{2i},\ v_{2i+1} \} \\
 | 
			
		||||
n_p = \left\lfloor \frac{n_v}{2} \right\rfloor
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
As there is only one vertex, that vertex is the provoking vertex. The number of primitives generated is equal to vertexCount.
 | 
			
		||||
</Note>
 | 
			
		||||
 | 
			
		||||
**Line list**:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -223,10 +244,10 @@ which processes the data we feed to it based on the configurations we set on it.
 | 
			
		|||
The **vertices** and **indices** are provided to this stage via something we call buffers.
 | 
			
		||||
So technically we have to provide  **two** buffers here, a **vertex buffer** and a **index buffer**.
 | 
			
		||||
 | 
			
		||||
To give you yet-another ovreview, this is the diagram of the "Geometry Processing" section of 
 | 
			
		||||
To give you yet-another ovreview, this is the diagram of the **geometry processing** section of 
 | 
			
		||||
our pipeline:
 | 
			
		||||
 | 
			
		||||
<Note title="Geometry Processing Pipeline">
 | 
			
		||||
<Note title="Geometry Processing Pipeline", type="diagram">
 | 
			
		||||
 | 
			
		||||
Draw --> Input Assembler -> Vertex Shader -> Tessellation Control Shader -> Tessellation Primitive Generator -> Tessellation Evaluation Shader -> Geometry Shader -> Vertex Post-Processing -> ... Rasterization ...
 | 
			
		||||
</Note>
 | 
			
		||||
| 
						 | 
				
			
			@ -259,17 +280,41 @@ Draw --> Input Assembler -> Vertex Shader -> Tessellation Control Shader -> Tess
 | 
			
		|||
## Conclusion
 | 
			
		||||
 | 
			
		||||
## Sources
 | 
			
		||||
[Tomas Akenine Moller - Real-Time Rendering 4th Edition](https://www.realtimerendering.com/intro.html)
 | 
			
		||||
 | 
			
		||||
<br/>
 | 
			
		||||
<Note title="Reviewers", type="review">
 | 
			
		||||
 | 
			
		||||
[LearnOpenGL - Hello Triangle](https://learnopengl.com/Getting-started/Hello-Triangle)
 | 
			
		||||
[LearnOpenGL - Face Culling](https://learnopengl.com/Advanced-OpenGL/Face-culling)
 | 
			
		||||
[Wikipedia - Polygonal Modeling](https://en.wikipedia.org/wiki/Polygonal_modeling)
 | 
			
		||||
[Wikipedia - Non-uniform Rational B-spline Surfaces](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline)
 | 
			
		||||
[Wikipedia - Computer Aided Design (CAD)](https://en.wikipedia.org/wiki/Computer-aided_design)
 | 
			
		||||
[Wikipedia - Rasterization](https://en.wikipedia.org/wiki/Rasterisation)
 | 
			
		||||
[Wikipedia - Euclidean geometry](https://en.wikipedia.org/wiki/Euclidean_geometry)
 | 
			
		||||
[Stackoverflow - Why do 3D engines primarily use triangles to draw surfaces?](https://stackoverflow.com/questions/6100528/why-do-3d-engines-primarily-use-triangles-to-draw-surfaces)
 | 
			
		||||
[Vulkan Docs - Drawing](https://docs.vulkan.org/spec/latest/chapters/drawing.html)
 | 
			
		||||
[Vulkan Docs - Pipeline Diagram](https://docs.vulkan.org/spec/latest/_images/pipelinemesh.svg)
 | 
			
		||||
Mohammad Reza Nemati
 | 
			
		||||
</Note>
 | 
			
		||||
 | 
			
		||||
<Note title="Books", type="resource">
 | 
			
		||||
 | 
			
		||||
[Tomas Akenine Moller --- Real-Time Rendering 4th Edition](https://www.realtimerendering.com/intro.html)
 | 
			
		||||
[JoeyDeVriez --- LearnOpenGL - Hello Triangle](https://learnopengl.com/Getting-started/Hello-Triangle)
 | 
			
		||||
[JoeyDeVriez --- LearnOpenGL - Face Culling](https://learnopengl.com/Advanced-OpenGL/Face-culling)
 | 
			
		||||
</Note>
 | 
			
		||||
 | 
			
		||||
<Note title="Wikipedia", type="resource">
 | 
			
		||||
 | 
			
		||||
[Polygonal Modeling](https://en.wikipedia.org/wiki/Polygonal_modeling)
 | 
			
		||||
[Non-uniform Rational B-spline Surfaces](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline)
 | 
			
		||||
[Computer Aided Design (CAD)](https://en.wikipedia.org/wiki/Computer-aided_design)
 | 
			
		||||
[Rasterization](https://en.wikipedia.org/wiki/Rasterisation)
 | 
			
		||||
[Euclidean geometry](https://en.wikipedia.org/wiki/Euclidean_geometry)
 | 
			
		||||
</Note>
 | 
			
		||||
 | 
			
		||||
<Note title="Youtube", type="resource">
 | 
			
		||||
 | 
			
		||||
...
 | 
			
		||||
 | 
			
		||||
</Note>
 | 
			
		||||
 | 
			
		||||
<Note title="Stackoverflow", type="resource">
 | 
			
		||||
 | 
			
		||||
[Why do 3D engines primarily use triangles to draw surfaces?](https://stackoverflow.com/questions/6100528/why-do-3d-engines-primarily-use-triangles-to-draw-surfaces)
 | 
			
		||||
</Note>
 | 
			
		||||
 | 
			
		||||
<Note title="Vulakn Docs", type="resource">
 | 
			
		||||
 | 
			
		||||
[Drawing](https://docs.vulkan.org/spec/latest/chapters/drawing.html)
 | 
			
		||||
[Pipeline Diagram](https://docs.vulkan.org/spec/latest/_images/pipelinemesh.svg)
 | 
			
		||||
</Note>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue