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.
|
||||
|
@ -145,16 +160,22 @@ basically defines the way we connect our vertices together, it would be more cle
|
|||
As stated previously, we got 3 main types of primitives, **triangles**, **lines**, and **dots**.
|
||||
(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