articles/graphics-pipeline (#1)
All checks were successful
continuous-integration/drone/push Build is passing

Reviewed-on: #1
Co-authored-by: light7734 <light7734@tuta.io>
Co-committed-by: light7734 <light7734@tuta.io>
This commit is contained in:
light7734 2025-04-28 15:00:11 +00:00 committed by light7734
parent 903d7358b0
commit 0cf1ecbb76
9 changed files with 127 additions and 3608 deletions

View file

@ -7,6 +7,7 @@ steps:
privileged: true
image: node:latest
commands:
- rm -rf ./node_modules
- npm install
- npm run build
- cp -r ./build/* /dazzle/

View file

@ -16,34 +16,35 @@
"test": "npm run test:unit -- --run"
},
"devDependencies": {
"@eslint/compat": "^1.2.5",
"@eslint/js": "^9.18.0",
"@eslint/compat": "^1.2.8",
"@eslint/js": "^9.25.1",
"@sveltejs/adapter-auto": "^6.0.0",
"@sveltejs/adapter-node": "^5.2.12",
"@sveltejs/adapter-static": "^3.0.8",
"@sveltejs/kit": "^2.16.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@tailwindcss/forms": "^0.5.9",
"@tailwindcss/typography": "^0.5.15",
"@tailwindcss/vite": "^4.0.0",
"@sveltejs/kit": "^2.20.7",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/typography": "^0.5.16",
"@tailwindcss/vite": "^4.1.4",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/svelte": "^5.2.4",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-svelte": "^3.0.0",
"@testing-library/svelte": "^5.2.7",
"eslint": "^9.25.1",
"eslint-config-prettier": "^10.1.2",
"eslint-plugin-prettier": "^5.2.6",
"eslint-plugin-svelte": "^3.5.1",
"globals": "^16.0.0",
"jsdom": "^26.0.0",
"mdsvex": "^0.12.3",
"prettier": "^3.4.2",
"jsdom": "^26.1.0",
"mdsvex": "^0.11.2",
"prettier": "^3.5.3",
"prettier-plugin-svelte": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.11",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"tailwindcss": "^4.0.0",
"typescript": "^5.0.0",
"typescript-eslint": "^8.20.0",
"vite": "^6.2.5",
"vitest": "^3.0.0"
"svelte": "^5.28.2",
"svelte-check": "^4.1.6",
"tailwindcss": "^4.1.4",
"typescript": "^5.8.3",
"typescript-eslint": "^8.31.0",
"vite": "^6.3.3",
"vitest": "^3.1.2"
},
"pnpm": {
"onlyBuiltDependencies": [

3562
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,3 @@
@import 'tailwindcss';
@plugin '@tailwindcss/forms';
@plugin '@tailwindcss/typography';
@tailwind base;
@tailwind components;
@tailwind utilities;

View file

@ -3,6 +3,10 @@
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap"
rel="stylesheet"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>

View file

@ -0,0 +1,14 @@
<script lang="ts">
import './article.css';
let { children } = $props();
</script>
<div class="body">
<div class="article_padding"></div>
<div class="article_body">
{@render children()}
</div>
<div class="article_padding"></div>
</div>

View file

@ -0,0 +1,47 @@
@import "tailwindcss";
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
* {
color: #ebdbb2;
font-family: "Inter", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
}
br {
margin-bottom: 1em;
}
h1 {
font-size: 2em;
margin-bottom: .3em;
}
h2 {
font-size: 1.7em;
margin-bottom: .3em;
margin-top: .6em;
}
.body {
background-color: #1d2021;
display: flex;
}
.article_body {
flex: 3;
margin-left: 10em;
margin-right: 10em;
padding: 1em;
background-color: #282828;
text-align: justify;
max-width: 80ch;
border-left: 1px solid #7c6f64;
border-right: 1px solid #7c6f64;
}
.article_padding {
flex: 1;
}

View file

@ -1,49 +1,56 @@
# The Graphics Pipeline
Ever wondered how games put all that gore on your display? Well you're about to find out!
<br/>
At the heart of rendering, is the "Graphics Pipeline". And like any pipeline, it's 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 for the next stage.
<br/>
We can coarsely divide the entire pipeline into 4 stages:
Application -> [Geometry Processing] -> Rasterization -> Pixel Processing
The pipeline will then serve a "rendered image" to your pretty eyes using your display.
<br/>
But to avoid drowning you in overviews, let's jump right into the details of the "Geometry Processing"
stage and have a recap afterwards to demystify our 4-stage division!
# Vertices (points in space)
## Vertices (points in space)
In order to render a murder scene, we need to have a way of representing the deceased in computer memory.
We only care about the "surface" since we won't be seeing the insides anyways--We don\'t want to either.
At this stage, we only care about the "shape" or the "geometry" of the "surface",
texturing, lighting and all the sweet gory details comes at a much later stage once all the "geometry" has been processed.
<br/>
There are several ways to "represent 3d objects" for a computer to understand.
For instance, _NURB_(Non-uniform rational B-spline) surfaces are great for representing "curves"
and it's all about the "high-precision" needed to do _CAD_(computer assisted design).
We could also do "ray-tracing" using fancy equations for rendering photo-realistic images.
<br/>
These are all great--ignoring the fact that they would take "an eternity" to process.
But what we need is a hardware-friendly approach that can do this for an entire scene with
hundereds of thousands of objects for at least 60 times undr a second. What we need is "polygonal modeling".
<br/>
"Polygonal modeling" allows us to do "real-time rendering". The idea is that we only need an
"approximation" of a surface to render it "realisticly-enough" for us to have some fun killing time!
We can achieve this approximation using a collection of "triangles", "lines" and "dots" (primitives),
which themselves are composed of a series of "vertices" (points in space).
<br/>
A "vertex" is simply a point in space.
Once we get enough of these "points", we can conncet them to form "primitives" such as "triangles", "lines" and "dots".
And once we have enough "primitives" together, they form a "model" or a "mesh" (that we need for our corpse).
With some interesting models, we can compose a "scene".
<br/>
But let's not get ahead of ourselves. The primary type of "primitive" we care about during "polygonal modeling"
is a "triangle". But why not squares or polygons with variable number of edges?
# Why Triangles?
## Why Triangles?
"Always Planar":
Triangles can never be __non-planar__(reside in more than 1 plane)! In Euclidean geometry, any
3
"Normal surface:"
@ -52,38 +59,41 @@ Triangles can never be __non-planar__(reside in more than 1 plane)! In Euclidean
"Predictable Winding Order:"
# Primitive Topologies
## Primitive Topologies
# Indices
## Indices
# Input Assembler
## Input Assembler
# Coordinate System -- Local Space
## Coordinate System -- Local Space
# Coordinate System -- World Space
## Coordinate System -- World Space
# Coordinate system -- View Space
## Coordinate system -- View Space
# Coordinate system -- Clip Space
## Coordinate system -- Clip Space
# Coordinate system -- Screen Space
## Coordinate system -- Screen Space
# Vertex Shader
## Vertex Shader
# Tessellation & Geometry Shaders
## Tessellation & Geometry Shaders
# Rasterizer
## Rasterizer
# Pixel Shader
## Pixel Shader
# Output Merger
## Output Merger
# The Future
## The Future
# Conclusion
## Conclusion
# Sources
## Sources
[Tomas Akenine Moller - Real-Time Rendering 4th Edition](https://www.realtimerendering.com/intro.html)
<br/>
[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)

View file

@ -6,7 +6,12 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
const config = {
// Consult https://svelte.dev/docs/kit/integrations
// for more information about preprocessors
preprocess: [vitePreprocess(), mdsvex()],
preprocess: [
vitePreprocess(),
mdsvex({
extensions: ['.md', '.svx'],
})
],
kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
@ -15,8 +20,7 @@ const config = {
adapter: adapter()
},
extensions: ['.svelte', '.svx']
extensions: ['.svelte', '.svx', '.md']
};
export default config;