Compare commits

...
Sign in to create a new pull request.

32 commits

Author SHA1 Message Date
e40660c113
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-06-06 07:47:54 +03:30
e19b3fedd3
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-06-05 19:08:53 +03:30
8c4171319b
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-06-04 15:26:25 +03:30
cb1548c0ef
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-06-04 14:39:20 +03:30
77d4184ed1
split the graphics pipeline into 4 articles
Some checks failed
continuous-integration/drone/push Build is failing
2025-06-04 10:38:10 +03:30
9da0ac9d5e
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-06-02 15:49:47 +03:30
96469fa82e
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-06-02 14:28:11 +03:30
8497bd9ccb
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-06-01 18:21:34 +03:30
fc471e5244
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-05-29 16:58:37 +03:30
0fe46fc866
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-05-26 12:04:07 +03:30
1b7185728f
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-05-20 07:10:02 +03:30
d38341c9bc
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-05-18 21:30:29 +03:30
42c9fbe971
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-05-16 08:23:34 +03:30
6697a24c6d
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-05-14 01:31:12 +03:30
be1fcf49bc
some draft for primitive topology and input assembly
Some checks failed
continuous-integration/drone/push Build is failing
2025-05-13 15:37:08 +03:30
85e92a397e
chore: add tip for euclidean geometry
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-12 18:14:39 +03:30
708128d7b7
feat: initial impl of Tip
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-12 17:38:54 +03:30
8dcf3ad973
feat: add note
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-12 15:25:01 +03:30
2d579757b8
wip
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-06 16:49:21 +03:30
95ca3ccf1a
wip
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-06 15:14:19 +03:30
4c6b0983dd
wip
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-05 16:54:00 +03:30
edde7d66cc
wip
All checks were successful
continuous-integration/drone/push Build is passing
2025-04-30 18:15:19 +03:30
9689025934
wip
Some checks reported errors
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build was killed
2025-04-28 18:25:51 +03:30
15547f9926
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-04-28 18:04:53 +03:30
dd435734d3
fix
Some checks failed
continuous-integration/drone/push Build is failing
2025-04-28 18:03:00 +03:30
0bf965e837
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-04-28 18:01:54 +03:30
904f90677a
fuck
Some checks failed
continuous-integration/drone/push Build is failing
2025-04-28 18:00:28 +03:30
6fa8d06da1
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-04-28 17:56:16 +03:30
9a0b503343
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-04-28 17:46:42 +03:30
7722f02ecd
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-04-28 17:42:27 +03:30
7020f69aab
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-04-28 17:23:28 +03:30
e381f028be
wip
Some checks failed
continuous-integration/drone/push Build is failing
2025-04-25 17:13:38 +03:30
38 changed files with 10384 additions and 311 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

@ -1,92 +0,0 @@
# The Graphics Pipeline
Ever wondered how games put all that gore on your display? Well you're about to find out!
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.
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.
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)
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.
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.
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".
"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).
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".
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?
"Always Planar":
Triangles can never be __non-planar__(reside in more than 1 plane)! In Euclidean geometry, any
3
"Normal surface:"
"Algorithm Simplicity:"
"Predictable Winding Order:"
# Primitive Topologies
# Indices
# Input Assembler
# Coordinate System -- Local Space
# Coordinate System -- World Space
# Coordinate system -- View Space
# Coordinate system -- Clip Space
# Coordinate system -- Screen Space
# Vertex Shader
# Tessellation & Geometry Shaders
# Rasterizer
# Pixel Shader
# Output Merger
# The Future
# Conclusion
# Sources
[Tomas Akenine Moller - Real-Time Rendering 4th Edition](https://www.realtimerendering.com/intro.html)
[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)
[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)

45
mdsvex.config.js Normal file
View file

@ -0,0 +1,45 @@
import math from 'remark-math';
import rehype_katex from 'rehype-katex';
import katex from 'katex';
import visit from 'unist-util-visit';
const correct_hast_tree = () => (tree) => {
visit(tree, 'text', (node) => {
if (node.value.trim().startsWith('<')) {
node.type = 'raw';
}
});
};
const katex_blocks = () => (tree) => {
visit(tree, 'code', (node) => {
if (node.lang === 'math') {
const str = katex.renderToString(node.value, {
displayMode: true,
leqno: false,
fleqn: false,
throwOnError: true,
errorColor: '#cc0000',
strict: 'warn',
output: 'htmlAndMathml',
trust: false,
macros: { '\\f': '#1f(#2)' }
});
node.type = 'raw';
node.value = '{@html `' + str + '`}';
}
});
};
export const mdsvex_config = {
extensions: ['.md', '.svx'],
layout: "./src/routes/articles/Layout.svelte",
smartypants: {
dashes: 'oldschool'
},
remarkPlugins: [math, katex_blocks],
rehypePlugins: [correct_hast_tree, rehype_katex]
};

5668
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -16,38 +16,51 @@
"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"
"rehype-mermaid": "^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": [
"esbuild"
]
},
"dependencies": {
"@lucide/svelte": "^0.509.0",
"katex": "^0.16.22",
"lucide": "^0.509.0",
"mermaid": "^11.6.0",
"playwright": "^1.52.0",
"rehype-katex": "^5.0.0",
"rehype-katex-svelte": "^1.2.0",
"remark-math": "2",
"unist-util-visit": "^2.0.3"
}
}

2065
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,12 @@
@import 'tailwindcss';
@plugin '@tailwindcss/forms';
@plugin '@tailwindcss/typography';
body {
margin: 0;
padding: 0;
}
* {
color: #ebdbb2;
font-family: 'Inter';
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
}

View file

@ -3,6 +3,16 @@
<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"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.css"
integrity="sha384-MlJdn/WNKDGXveldHDdyRP1R4CTHr3FeuDNfhsLPYrq2t0UBkUdK2jyTnXPEK1NQ"
crossorigin="anonymous"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>

View file

@ -0,0 +1,31 @@
<script lang="ts">
import './article.css';
import HorizontalBreak from './HorizontalBreak.svelte';
export let title;
export let date;
</script>
<div class="heading">
<h1>{title}</h1>
<p>{date}</p>
</div>
<HorizontalBreak />
<style>
.heading {
width: 100%;
}
.heading > h1 {
display: inline-block;
}
.heading > p {
float: right;
padding-left: auto;
padding-right: auto;
margin-left: auto;
margin-right: auto;
}
</style>

View file

@ -0,0 +1,12 @@
<script lang="ts">
</script>
<div class="horizontal_break"></div>
<style>
.horizontal_break {
margin-top: 1em;
background-color: #928374;
height: 1px;
}
</style>

View file

@ -0,0 +1,21 @@
<script lang="ts">
export let paths: string[] = [];
export let caption: string = '';
</script>
<div class="container">
{#each paths as path (path)}
<img src={path} alt="" />
{/each}
</div>
<style>
.container {
width: fit-content;
margin-right: auto;
padding: 1em;
/* Removed flex properties from here */
gap: 1em;
}
</style>

View file

@ -0,0 +1,46 @@
<script lang="ts">
import './article.css';
import Heading from './Heading.svelte';
export let title;
export let date;
</script>
<div class="container">
<div class="padding"></div>
<div class="body">
<Heading {title} {date} />
<slot></slot>
</div>
<div class="padding"></div>
</div>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
.container {
background-color: #1d2021;
display: flex;
}
.body {
flex: 3;
padding: 1em;
background-color: #282828;
min-width: 80ch;
max-width: 80ch;
text-wrap-mode: wrap;
text-wrap-style: pretty;
text-align: justify;
border-left: 1px solid #92837420;
border-right: 1px solid #92837420;
}
.padding {
flex: 1;
}
</style>

View file

@ -0,0 +1,130 @@
<script lang="ts">
import { Info, BookCopy, Eye, Network, Sigma, Image, Quote } from '@lucide/svelte';
let { title = '', type = 'info' } = $props();
</script>
<div class="note">
<div class="head">
<div class="icon">
{#if type == 'info'}
<Info />
{:else if type == 'image'}
<Image />
{:else if type == 'diagram'}
<Network />
{:else if type == 'quote'}
<Quote />
{:else if type == 'math'}
<Sigma />
{:else if type == 'review'}
<Eye />
{:else if type == 'resource'}
<BookCopy />
{/if}
</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 == 'quote'}
<div class="horiz_line" style:background-color="#d3869b"></div>
{:else if type == 'image'}
<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">
{#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 == 'quote'}
<div class="line" style:background-color="#d3869b"></div>
{:else if type == 'image'}
<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">
{#if title != ''}
<p class="title">{title}</p>
{/if}
<slot />
</div>
</div>
</div>
<style>
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap');
.title {
}
.note {
display: block;
margin: 1em 0 1em 0;
border-radius: 2px;
}
.head {
display: flex;
flex-wrap: wrap;
width: 100%;
text-align: left;
}
.content {
display: flex;
margin-bottom: -1em;
padding: 0;
margin-right: auto;
margin-left: 0;
}
.line {
width: 0.1em;
margin-left: 0.85em;
margin-bottom: 1em;
margin-top: 0.5em;
}
.horiz_line {
height: 0.1em;
margin-left: 0.5em;
margin-top: 0.7em;
display: inline-block;
flex: 1;
}
.slot {
margin-left: 1em;
width: 100%;
}
.slot > p {
flex: 1;
font-family: 'IBM Plex Mono', monospace;
display: inline-block;
margin: 0;
font-weight: bolder;
}
.icon {
}
.icon:first-child {
}
</style>

View file

@ -0,0 +1,53 @@
<script lang="ts">
export let text;
</script>
<div class="tooltip">
{text}
<span class="tooltiptext"><slot /></span>
</div>
<style>
.tooltip {
position: relative;
display: inline-block;
font-weight: 600;
font-style: italic;
color: #fabd2f;
border-bottom: 1px dotted #fe8019;
}
/* Tooltip text */
.tooltip .tooltiptext {
visibility: hidden;
max-width: 60ch;
min-width: 60ch;
margin-left: -30ch; /* Use half of the width (120/2 = 60), to center the tooltip */
margin-top: .5em;
background-color: #282828ea;
text-wrap-mode: wrap;
text-align: justify;
padding: 1em;
border-radius: 6px;
border: 1px solid #fe8019;
top: 100%;
left: 50%;
/* Position the tooltip text - see examples below! */
position: absolute;
z-index: 1;
}
/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover .tooltiptext {
visibility: visible;
}
.tooltip:hover {
color: #fe8019;
}
</style>

View file

@ -0,0 +1,57 @@
* {
color: #ebdbb2;
font-family: 'Inter';
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
}
strong {
font-weight: 600;
font-style: italic;
color: #fabd2f;
}
strong:hover {
color: #fe8019;
}
h1 {
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: 0em;
margin-left: 0;
margin-right: 0;
font-weight: bold;
}
a {
display: inline-block;
text-decoration: none;
color: #83a598;
}
a:hover {
color: #458588;
}
.katex {
width: max-content;
margin-left: 0;
}
.katex-display {
margin-top: 0;
}

View 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>

View file

@ -0,0 +1,846 @@
---
title: The Graphics Pipeline ; Part 1
date: "April 20 - 2025"
---
<script>
import Image from "../../Image.svelte"
import Note from "../../Note.svelte"
import Tip from "../../Tip.svelte"
</script>
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 deeply into the intricate details of this powerful beast.
Don't worry if things don't click right away---well go over all the key terms and restate the important stuff to help it sink in.
And hey, if you still have questions, feel free to reach out :)
Initially, I tried cramming everything in **one article**, which hurt the **brevity** and the **structure**.
The **graphics pipeline** is a beast---incredibly **complex** and constantly **evolving**.
So I split it into a **4-part series**, which lets me go into sufficient depth.
But why exactly **4-parts**?
## Overview
Like any pipeline, the **graphics pipeline** is made up of several **stages**,
each of which can be a mini-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="High level breakdown 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.
all in 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 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---Like executing some
code for each pixel on your screen, there are a ton of pixels but they mostly do their own independent logic. </Tip>.
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 linear algebra.
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**.
In other words, this stage converts a rather abstract and internal presentation (geometry)
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>
(a grid) of pixels.
The **pixel processing** stage then uses the rasterized geometry data (pixel data) to do
**lighting**, **texturing**, **shadow-mapping**, and all the sweet gory details of a scene (like a murder scene).
In short, this stage is responsible for calculating the **final output color** of each pixel.
The pipeline will then serve (present) the output of the **pixel processing** stage, which is a **rendered image**,
to your pretty eyes using your <Tip text="display">Usually a monitor but the technical term for it is
the target **surface**. Which can be anything like a VR headset or some other crazy surface used for displaying purposes.</Tip>.
<Note type="info", title="Chapters of The Graphics Pipeline">
**Geometry Processing**: How geometry is **represented**, **interpreted**, **transformed** and **expanded**.
**Rasterization**: How the final geometric data is converted into **pixels** and what data they hold.
**Pixel Processing**: How we figure out the **final output color** of each pixel.
**Optimizations**: How modern game-engines like Unreal Engine 5 optimize the pipeline.
</Note>
I hope it is now evident why I chose to split the concepts in 4-parts. So... let's jump right into the gory details of the **geometry processing**
stage!
## Surfaces
Ever been jump-scared by this sight in an <Tip text="FPS">First person (shooter) perspective</Tip>? Why are (the inside of) things rendered like that?
<Note title="Boo!", type="image">
<Image
paths={["/images/boo.png"]}
/>
</Note>
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.
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.
But how do we represent surfaces in computer memory?
## Vertices
There are several ways to **represent** the surfaces of 3d objects for a computer to understand.
For instance, <Tip text="NURBS">
**Non-uniform rational basis spline** is a mathematical model using **basis splines** (B-splines) that is commonly used in computer graphics for representing curves and surfaces. It offers great flexibility and precision for handling both analytic (defined by common mathematical formulae) and modeled shapes. ---Wikipedia</Tip> surfaces are great for representing **curves**, and it's all about the
**high precision** needed to do <Tip text="CAD">Computer Assisted Design</Tip>. We could also do **ray-tracing** using fancy equations for
rendering **photo-realistic** images.
These are all great---ignoring the fact that they would take an eternity to process...
But what we need is a **performant** approach that can do this for an entire scene with
hundreds of thousands of objects (like a lot of corpses) in under a small fraction of a second. What we need is **polygonal modeling**.
**Polygonal modeling** enables us to do an exciting thing called **real-time rendering**. The idea is that we only need an
**approximation** of a surface to render it **realistically 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).
<Note title="A sphere made out of triangles", type="image">
<Image
paths={["/images/polygon_sphere.webp"]}
/>
</Note>
A **vertex** is simply a point in space.
Once we get enough of these **points**, we can connect them to form **primitives** such as **triangles**, **lines**, and **dots**.
And once we connect enough of these **primitives** together, they form a **model** or a **mesh** (that we need for our corpse).
With some interesting models put together, we can compose a **scene** (like a murder scene :D).
<Note title="Stanford bunny model in increasing level of detail (LoD)", type="image">
<Image
paths={["/images/bunny.jpg"]}
/>
</Note>
But let's not get ahead of ourselves. The primary type of **primitive** that we care about during **polygonal modeling**
is a **triangle**. But why not squares or polygons with a variable number of edges?
## Why Triangles?
In <Tip text="Euclidean geometry"> Developed by **Euclid** around 300 BCE, is based on five axioms. It describes properties of shapes, angles, and space using deductive reasoning. It remained the standard model of geometry for centuries until non-Euclidean geometries and general relativity showed its limits. It's still widely used in education, engineering, and **computer graphics**. ---Wikipedia </Tip>, triangles are always **planar** (they exist only in one plane),
any polygon composed of more than 3 points may break this rule, but why does polygons residing in one plane so important
to us?
<Note title="Planar vs Non-Planar polygons" type="image">
<Image
paths={["/images/planar.jpg", "/images/non_planar_1.jpg", "/images/non_planar_2.png"]}
/>
</Note>
When a polygon exists only in one plane, we can safely imply that **only one face** of it can be visible
at any one time; this enables us to utilize a huge optimization technique called **back-face culling**.
Which means we avoid wasting a ton of **precious processing time** on the polygons that
we know won't be visible to us. We can safely **cull** the **back-faces** since we won't
be seeing the **back** of a polygon when it's in the context of a closed-off model.
We figure this out by simply using the **winding order** of the triangle to determine whether we're looking at the
back of the triangle or the front of it---I'll go in depth about **culling** in part 4.
Triangles also have a very small **memory footprint**; for instance, when using the **triangle-strip** topology (more on this very soon), for each additional triangle after the first one, only **one extra vertex** is needed.
The most important attribute, in my opinion, is the **algorithmic simplicity**.
Any polygon or shape can be composed from a **set of triangles**; for instance, a rectangle is simply **two coplanar triangles**.
Also, it is a common practice in computer science to break down hard problems into simpler, smaller problems.
Trust me, this will be a lot more convincing when we cover the **rasterization** stage in part 2 :)
<Note title="Evolution", type="info">
As a bonus point to consider; 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.
We literary have a **fixed function** (unprogrammable) stage in the pipeline dedicated for rasterizing
triangles.
</Note>
## Primitive Topology
So, we got our set of vertices, but having a bunch of points floating around wouldn't make a scene very lively
(or gory), we need to form **triangles** out of them to compose **models** (like our beautiful corpse).
The **input assembler** is first the mini-stage in the **geometry processing** stage. And it's responsible for **concatenating** our vertices (the input) to assemble **primitives**.
It is a **fixed function** stage so we can only configure it (it's not programmable).
We can tell the assembler how it should interpret the vertex data by configuring its **primitive** <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>.
Instead of explaining with words, I'm going to show you how each type of topology works with pictures. So buckle up!
When the topology is **point list**, each **consecutive vertex** (v) defines a **single point** primitive (p)
and the number of primitives (n of p) is equals to the number of vertices (n of v).
<Note title="", type="image">
<Image
paths={["/images/primitive_topology_point_list.svg"]}
/>
</Note>
<Note type="math">
```math
\begin{aligned}
&p_i = \{ v_{i} \} \\ &n_p = n_v
\end{aligned}
```
</Note>
When the topology is **line list**, each **consecutive pair of vertices** defines a **single line**:
<Note title="", type="image">
<Image
paths={["/images/primitive_topology_line_list.svg"]}
/>
</Note>
<Note type="math">
```math
\begin{aligned}
&p_i = \{ v_{2i},\ v_{2i+1} \} \\ &n_p = ⌊ n_v / 2 ⌋
\end{aligned}
```
</Note>
When the primitive topology is **line strip**, **one line** is defined by each **vertex and the following vertex**:
<Note title="", type="image">
<Image
paths={["/images/primitive_topology_line_strip.svg"]}
/>
</Note>
<Note type="math">
```math
\begin{aligned}
&p_i = \{ v_i, v_{i+1} \} \\ &n_p = \text{max}(0, n_v - 1)
\end{aligned}
```
</Note>
When the primitive topology is **triangle list**, each **consecutive set of three vertices** defines a **single triangle**:
<Note title="", type="image">
<Image
paths={["/images/primitive_topology_triangle_list.svg"]}
/>
</Note>
<Note type="math">
```math
\begin{aligned}
&p_i = \{ v_{3i}, v_{3i+1}, v_{3i+2} \} \\ &n_p = ⌊n_v / 3⌋
\end{aligned}
```
</Note>
When the primitive topology is **triangle strip**, **one triangle** is defined by each **vertex and the two vertices that follow it**:
<Note title="", type="image">
<Image
paths={["/images/primitive_topology_triangle_strip.svg"]}
/>
</Note>
<Note type="math">
```math
\begin{aligned}
&p_i = \{ v_i,\ v_{i + (1 + i \bmod 2)},\ v_{i + (2 - i \bmod 2)} \} \\ &n_p = \text{max}(0, n_v- 2)
\end{aligned}
```
</Note>
When the primitive topology is **triangle fan**, **triangles** are defined **around a shared common vertex**:
<Note title="", type="image">
<Image
paths={["/images/primitive_topology_triangle_fan.svg"]}
/>
</Note>
<Note type="math">
```math
\begin{aligned}
&p_i = \{ v_{i+1}, v_{i+2}, v_0 \} \\ &n_p = \text{max}(0, n_v - 2)
\end{aligned}
```
</Note>
## Indices
**Indices** are an array of integers that reference the **vertices** in a vertex buffer.
They define the **order** in which vertices should be read (and re-read) by the **input assembler**.
Which allows **vertex reuse** and reduces memory usage by preventing duplicate vertices.
Imagine the following scenario:
```cc
float triangle_vertices[] = {
// x__, y__
0.0, 0.5, // center top
-0.5, -0.5, // bottom left
0.5, -0.5, // bottom right
};
```
Here we have one triangle primitive, cool! Now let's create a rectangle:
```cc
float vertices[] = {
// first triangle
// x__ y__
0.5, 0.5, // top right
0.5, -0.5, // bottom right << DUPLICATE
-0.5, 0.5, // top left << DUPLICATE
// second triangle
// x__ y__
0.5, -0.5, // bottom right << DUPLICATE
-0.5, -0.5, // bottom left
-0.5, 0.5, // top left << DUPLICATE
};
```
As indicated by the comments, we have two **identical** vertices. This situation only gets worse
for each additional **attribute** per vertex (vertices pack a lot more information than positions, we'll get to it later).
And in a large model with hundreds of thousands of triangles, it becomes unacceptable. To remedy this problem, we do
**indexed rendering**:
```cc
float vertices[] = {
// first triangle
// x__ y__
0.5, 0.5, // top right [0]
0.5, -0.5, // bottom right [1]
-0.5, -0.5, // bottom left [2]
-0.5, 0.5, // top left [3]
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
```
And you might be asking, what about **triangle strips** we just talked about? Well, if you try to visualize it,
a **large model** cannot possibly be made from a **single strip** of triangles, but from **many**. And we might not even use
triangle **strips**---we might use triangle **lists**.
Either way, using indices is optional but almost always a good idea to use them!
<Note title="Post-Transform Vertex Cache", type="info">
Indexed rendering also allows the GPU to use a neat optimization trick called **post-transform vertex cache** where
if the same index is used after **transformations** happened, it'll fetch the result that's recently cached and
won't re-run the transformation logic again.
I'll explain how vertices are transformed soon, don't worry (yet).
</Note>
## **Input Assembler**
Alrighty! Do we have everything we need?
We got our surface representation---**vertices**. We set the **primitive topology** to determine
how to concatenate them. And we optionally (but most certainly) provided some **indices** to avoid
duplication.
All this data (and configuration) is then fed to the very first mini-stage of the **graphics pipeline** called
the **input assembler**. Which as stated before, is responsible for **assembling** primitives from our **input** (vertices and indices).
<Note type="diagram", title="Geometry Processing">
[Vertex/Index Data] --> Input Assembler --> ...
</Note>
So what comes next?
## Coordinate System -- Overview
**Assembling primitives** is the **first** essential task in the **geometry processing** stage, and
everything you read so far only went over that part.
Its **second** vital responsibility is the **transformation** of the said primitives. Let me explain.
So far, our examples show the geometry in **normalized device coordinates**; or **NDC** for short.
This is a small space where the x, y and z values are in range of [-1.0 -> 1.0].
Anything outside this range will be **clipped** and won't be visible on screen.
Below is our old triangle again which was specified within **NDC**---ignoring the z for now:
```cc
float triangle_vertices[] = {
// x__, y__
0.0, 0.5, // center top
-0.5, -0.5, // bottom left
0.5, -0.5, // bottom right
};
```
This is because the **rasterizer** expects the **final vertex coordinates** to be in the **NDC** range.
Anything outside of this range is, again, **clipped** and not visible.
Yet, as you might imagine, doing everything in the **NDC** is inconvenient and very limiting.
We'd like to **compose** a scene by <Tip text="transforming">Scale, Rotate, Translate. </Tip> some objects around, **interact**
with the scene by moving and looking around, and express coordinates in arbitrary
units---such as meters.
This is done by transforming these vertices through **5 coordinate systems** before ending up in NDC
(or outside of if they're meant to be clipped). Here's a high-level overview:
**Local Space**: This is where your model begins in, think of it as the data exported from a model
using Blender. If we were to modify a model (the model's vertices itself, not its transformation) it would make most sense to do it here.
**World Space**: All objects will be stuck into each other at coordinates 0, 0, 0 if we don't move them
around the world. This is the transformation that puts your object in the context of the **world**.
**View Space**: Then we transform everything that was relative to the world in such a way that each
vertex is seen from the viewer's point of view.
**Clip Space**: Then we project everything to the clip coordinates, which is in the range of -1.0 and 1.0.
This projection is what makes **perspective** possible (distant objects appearing smaller).
**Screen Space**: This one is out of our control, it simply puts our now normalized coordinates
unto the screen.
As you can see each of these coordinates systems serve a specific purpose and allows **composition** and **interaction** with a scene.
However, doing these **transformations** require a lot of **linear algebra**, specially a ton of **matrix operations**.
So, before we get into more depth about these coordinate systems, let's learn how to do **linear transformations** using **linear algebra**!
<Note title="Mathematics Ahead!">
The concepts in the following sections may be difficult to grasp at first. And **that's okay**, you don't
need to pickup everything the first time you read them (I didn't). If you feel passionate about these topics
and want to have a better grasp, refer to the references at the bottom of this article and **take
your time** :)
</Note>
## Linear Algebra --- Vectors
**Vectors** are the **fundamental** building blocks of the linear algebra. And we're going to get
really familiar with them :) But what is a **vector** anyways? As all things in life, it depends.
For a **physicist**, vectors are **arrows pointing in space**, and what defines them is their **length** (or **magnitude**)
and **direction**---that is, any two vectors moved to different **origins** (starting points) are the **same vectors**,
as long as their **length** and **direction** remain the same:
<Note type="image", title="Physicist">
**Insert Image Here**
</Note>
For a **computer scientist**, vectors are a fancy word for **ordered lists of numbers**. Yep, that's it, it feels good
to be in the simple world of a computer scientist:
<Note type="image", title="Computer Scientist">
**Insert Image Here**
</Note>
But **mathematically** speaking, vectors are a lot more **abstract**.
Virtually **any** representation of **vectors** (which is called a **vector-space**) is valid as long as they follow a set of **axioms**.
It doesn't matter if you think of them as **arrows in space** that happen to have a **numeric representation**,
or as a **list of numbers** that happen to have a cute **geometric interpretation** (or even certain mathmatical **functions**).
As long the [aximos of vector spaces](https://www.math.ucla.edu/~tao/resource/general/121.1.00s/vector_axioms.html) apply to them, they're vectors.
However, we won't go into such axioms as we're not interested in **abstract** thinking here.
We're aiming to do something **concrete** called **linear transformations** of a set of vertices (models).
So it would be ideal for us to think of them like this:
- A vector describes a series of steps to perform a **transformation** in space.
- A vector has the properties: **direction** and **magntitude**.
- If its **magntitude** is exactly **1**, then it describes a **direction** in space and is called a **unit vector**.
Let's go over these points one by one.
**Basis Vector**
**Additions**
**Multiplication**
**Scalar Operations**
**Cross Product**
**Dot Product**
**Length**
**Normalization and the normal vector**
<Note title="The Essence of Linear Algebra">
If you're interested in **mathematics** (bet you are) and **visualization**, then I highly recommend watching the [Essence of Linear Algebra](https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab)
by **3Blue1Brown**. His math series has great intuitive explanations using smooth visuals.
And much of my own understanding comes from this series---and the other sources references at the end.
</Note>
## Linear Algebra --- Matrices
** What is a matrix**
**Addition and Subtraction**
**Scalar Operations**
**Multiplication**
**Division (or lack there of)**
**Identity Matrix**
## Linear Algebra --- Transformations
**Scale**
**Rotation**
<Note type="info", title="Gimbal Lock">
Representing rotations like this makes us prone to a phenomenon called **gimbal lock** where we lose
an axis of control. A way of avoiding this is to rotate around an arbitary axis (makes it a lot harder
to happen but still possible).
The ideal way is to use <Tip text="quaternions" >A quaternion is a four-part hyper-complex number used in three-dimensional rotations and orientations.
A quaternion number is represented in the form a+bi+cj+dk, where a, b, c, and d parts are real numbers, and i, j, and k are the basis elements, satisfying the equation: i2 = j2 = k2 = ijk = 1.</Tip>,
which not only make gimbal lock impossible but are also more computationally friendly.
A full discussion about quaternions is beyond the scope of this article. However, if you're so interested,
I've left links at the end of this article for further study.
</Note>
**Why Translation is not a linear transformation**
**Translation**
<Note type="info", title="Homogeneous coordinates">
Why are we using 4D matrixes for vertices that are three dimensional?
</Note>
**Embedding it all in one matrix**
Great! You've refreshed on lots of cool mathematics today, let's get back to the original discussion.
**Transforming** the freshly generated **primitives** through this **five** mysterious coordinates systems (or spaces),
starting with the **local space**!
## Coordinate System -- Local Space
Alternatively called the **object space**, is the space **relative** to your object's **origin**.
All objects have an origin, and it's probably at coordinates [0, 0, 0] (not guaranteed).
Think of a modelling application like **Blender**. If you create a cube in it and export it, the
**vertices** it outputs is probably something like this:
**insert outputted vertices**.
And the cube looks plain like this:
<Note title="Unit cube", type="image">
</Note>
I hope this one is easy to grasp since **technically** been using it in our initial triangle
and square examples already, the local space just happened to be in NDC though that is not necessary.
Say if we arbitrarily consider each 1 unit is 1cm, then a 10m x 10m cube would have the following
vertices whilst in the local space.
Basically the vertices that are read from a model file is initially in local space.
## Coordinate System -- World Space
This is the where our first transormation happens. If we were constructing a crime scene
without world space transformations then all our corpses would reside somewhere in [0, 0, 0] and
would be inside each other (horrid, or lovely?).
This transformation allows us to **compose** a (game) world, by transforming all the models from
their local space and scattering them around the world. We can **translate** (move) the model to the desired
spot, **rotate** it because why not, and **scale** it if the model needs scaling (capitan obvious here).
This transformation is stored in a matrix called the **model matrix**. This is the first of three primary
**transformation** matrices which gets multiplied by our vertices.
<Note tye="math", title="Model transformation">
```math
\text{model}_M * \text{local}_V
```
</Note>
So one down, two more to go!
## Coordinate system -- View Space
Alternatively names include: **eye space** or the **camera space**.
This is where the crucial element of **interactivity**
comes to life (well depends if you can move the view in your game or not).
Currently, we're looking at the world
through a fixed lens. Since everything that's rendered will be in the [-1.0, 1.0] range, that means
**moving** our selves or our **eyes** or the game's **camera** doesn't have a real meaning.
Now it's you that's stuck! (haha). But don't worry your layz-ass, instead of moving yourself
(which again would not make sense since everything visible ends up in the NDC), you can move the world! (how entitled).
We can achieve this illusion of moving around the world by **reverse transforming** everything based
on our own **location** and **orientation**. So imagine we're in the [+10.0, 0.0, 0.0] coordinates. How we simulate this
movement is to apply this translation matrix:
<Note type="math", title="Simplified movement to the right">
</Note>
** Position **
** Orientation **
We can **rotate** the camera, or more accurately **reverse-rotate** the world, via 3 unit vectors snuggled
inside a matrix, the **up** vector (U), the **target** or **direction** vector (D) and the **right**
vector (R)
<Note type="math", title="LookAt matrix">
```math
\begin{bmatrix} \color{red}{R_x} & \color{red}{R_y} & \color{red}{R_z} & 0 \\ \color{green}{U_x} & \color{green}{U_y} & \color{green}{U_z} & 0 \\ \color{blue}{D_x} & \color{blue}{D_y} & \color{blue}{D_z} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} * \begin{bmatrix} 1 & 0 & 0 & -\color{purple}{P_x} \\ 0 & 1 & 0 & -\color{purple}{P_y} \\ 0 & 0 & 1 & -\color{purple}{P_z} \\ 0 & 0 & 0 & 1 \end{bmatrix}
```
</Note>
">>>>>" explain in depth why such operation makes the view rotate.
Just like the **world space** transformation which is stored in the **model matrix**.
This transformation is stored in anoher matrix called the **view matrix**.
So far we got this equation to apply the **world space** and **view space** transformations
to the **local space** vertices of our model:
<Note tye="math", title="Model_View transformation">
```math
\text{model}_M * \text{view}_M * \text{local}_V
```
</Note>
That's two down, one left to slay!
## Coordinate system -- Clip Space
**Overview***
**Aspect Ratio***
**Field of view***
**Normalization***
**Putting it all together**
<Note tye="math", title="Model_View transformation">
```math
\text{model}_M * \text{view}_M * \text{projection}_M * \text{local}_V
```
</Note>
## Coordinate system -- Screen Space
** Viewport transform **
## Coordinate system -- Putting it All Together
<Note title="Coordinate System", type="diagram">
</Note>
## Vertex Shader
<Note title="Shaders", type="info">
**Why is it called a "shader" when it's not "shading" anything?**
</Note>
## Geometry Shader (optional stage)
**We can generate more geometry here since some geometric details are expressed more efficiently through mathmatical expressions than raw vertex data**
**Different levels of parallelism (why do we still need the vertex shader)**
**Takes as input "a" primitive, outputs any type of (but only one of) primitive(s)**
**Adjecency primitive types**
**Primitive type only indicates number of input vertices since the primitive itself will get cconsumed**
**Geometry shader instancing**
**Geometry shader examples**
**Tessellation/Subdivision**
**Geometry shaders are out of fashion**
**Subdivision**
**Why do we subdivide?**
**Mathmatical presentation more compressed than actual vertex data**
**Geometry shaders are versatile, not performant**
**Data movement bottleneck**
**LoD**
## Tessellation Shader (optional stage)
**Tessellation Control Shader** (or Hull Shader in DirectX terminology)
**Tessllator**
**Quad Primitives**
**Isolines**
**Outer tessellation / Inner tessellation**
**Tessellation Evaluation Shader** (or Domain Shader in DirectX terminology)
**Tessellation examples**
## Geometry Processing --- Conclusion
Let's wrap up!
<Note type="diagram", title="Geometry Processing">
Prepared Vertex Data ->
Input Assembly turns Vertex Data into digestable structures for the Vertex Shader ->
Vertex Shader is invoked per vertex for applying transformations via some clever linear algebra ->
Geometry & Tessellation Shaders expand the geometry on-the-fly and may apply more transformations ->
... Rasterizer
</Note>
The geometric detail that we now have is not **real**. Perfect triangle do not exist in the real world.
Our next challenge in this journey is to turn these mathmatical representations into something
concrete and significant. We're gonna take these primitives and turn them into **pixels** through
a fancy process called **rasterization**.
You can continue on to [part 2](/articles/the-graphics-pipeline/rasterization) of this article series and learn all about how rasterization
works.
## Sources
<Note title="Reviewers", type="review">
MMZ ❤️
Grammarly
Some LLMs
</Note>
<Note title="Books", type="resource">
[Joey De Vriez --- LearnOpenGL](https://learnopengl.com/) <br/>
[Tomas Akenine Moller --- Real-Time Rendering (4th ed)](https://www.realtimerendering.com/intro.html) <br/>
[Gabriel Gambetta --- Computer Graphics from Scratch](https://gabrielgambetta.com/computer-graphics-from-scratch/) <br/>
</Note>
<Note title="Wikipedia", type="resource">
[Polygonal Modeling](https://en.wikipedia.org/wiki/Polygonal_modeling) <br/>
[Non-uniform Rational B-spline Surfaces](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline) <br/>
[Computer Aided Design (CAD)](https://en.wikipedia.org/wiki/Computer-aided_design) <br/>
[Rasterization](https://en.wikipedia.org/wiki/Rasterisation) <br/>
[Euclidean geometry](https://en.wikipedia.org/wiki/Euclidean_geometry) <br/>
[Vector space](https://en.wikipedia.org/wiki/Vector_space) <br/>
</Note>
<Note title="Youtube", type="resource">
[Miolith --- Quick Understanding of Homogeneous Coordinates for Computer Graphics](https://www.youtube.com/watch?v=o-xwmTODTUI) <br/>
[Leios Labs --- What are affine transformations?](https://www.youtube.com/watch?v=E3Phj6J287o) <br/>
[3Blue1Brown --- Essence of linear algebra (highly recommended playlist)](https://www.youtube.com/watch?v=fNk_zzaMoSs&list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab) <br/>
[3Blue1Brown --- Quaternions and 3d rotation, explained interactively](https://www.youtube.com/watch?v=zjMuIxRvygQ) <br/>
[pikuma --- Math for Game Developers (playlist)](https://www.youtube.com/watch?v=Do_vEjd6gF0&list=PLYnrabpSIM-93QtJmGnQcJRdiqMBEwZ7_) <br/>
[pikuma --- 3D Graphics (playlist)](https://www.youtube.com/watch?v=Do_vEjd6gF0&list=PLYnrabpSIM-97qGEeOWnxZBqvR_zwjWoo) <br/>
[Cem Yuksel --- Introduction to Computer Graphics (playlist)](https://www.youtube.com/watch?v=vLSphLtKQ0o&list=PLplnkTzzqsZTfYh4UbhLGpI5kGd5oW_Hh) <br/>
[Cem Yuksel --- Interactive Computer Graphics (playlist)](https://www.youtube.com/watch?v=UVCuWQV_-Es&list=PLplnkTzzqsZS3R5DjmCQsqupu43oS9CFN&pp=0gcJCV8EOCosWNin) <br/>
[javidx9 --- Essential Mathematics For Aspiring Game Developers](https://www.youtube.com/watch?v=DPfxjQ6sqrc) <br/>
</Note>
<Note title="Articles", type="resource">
[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) <br/>
[The ryg blog --- The barycentric conspiracy](https://fgiesen.wordpress.com/2013/02/06/the-barycentric-conspirac/) <br/>
[Juan Pineda --- A Parallel Algorithm for Polygon Rasterization](https://www.cs.drexel.edu/~deb39/Classes/Papers/comp175-06-pineda.pdf) <br/>
[Kristoffer Dyrkorn --- A fast and precise triangle rasterizer](https://kristoffer-dyrkorn.github.io/triangle-rasterizer/) <br/>
[Microsoft --- Rasterization Rules](https://learn.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-rasterizer-stage-rules) <br/>
[Axioms of vector spaces](https://www.math.ucla.edu/~tao/resource/general/121.1.00s/vector_axioms.html)
</Note>
<Note title="Documentations", type="resource">
[Vulkan Docs --- Drawing](https://docs.vulkan.org/spec/latest/chapters/drawing.html) <br/>
[Vulkan Docs --- Pipeline Diagram](https://docs.vulkan.org/spec/latest/_images/pipelinemesh.svg) <br/>
</Note>

View file

@ -0,0 +1,144 @@
---
title: The Graphics Pipeline --- Optimizations
date: "April 20 - 2025"
---
<script>
import Image from "../../Image.svelte"
import Note from "../../Note.svelte"
import Tip from "../../Tip.svelte"
</script>
## Optimizing the Pipeline
<Note type="quote" title="An idiot admires complexity, a genius admires simplicity.">
--- Terry A. Davis
</Note>
Let's get our heads out of the abstract and dizzying mathmatical world now and think like an engineer.
**Out of the mathmatical world, into the engineering world!**
## Deferred Shading
**Deferred Shading**
**Bottleneck in pixel shading**
**The G Buffer**
**Forward pass** or the **Geometry Pass**
**Deferred pass** or the **Lighting pass**
**Anti Aliasing**
## Beyond G-Buffers --- Visibility Buffers
**Pros and Cons of G-Buffers**
**High memory consumption**
**May be slower for simple scenes**
**How we did thing in the traditional graphics pipeline**
**Intro to Visbility Buffers!**
## Meshlet-based Rendering
**Intro to Mesh shaders**
**Issue with Low resolution -> High resolution**
**[Task Shader -> Mesh Generation -> Mesh Shader] -> Rasterization -> Pixel Shader -> Merger**
** ^^^ GEOMETRY PROCESSING -> ^^^ -> Pixel Processing
## Conclusion
Let's---for the final time, have a quick recap and go everything at the speed of **light** :)
**Application** <br/>
The pipeline starts simulating the world on the **CPU** and updates, changes, destroys things
through systems like physics, ecs, events, etc, etc. Here we have full autonomy.
**Geometry Processing** <br/>
The **graphics pipeline** then provides the **scene data** as a set of **vertices** that form
**primitives** to the **input assembler**. We use **triangles** because they're the best! Then this
**input assembler** does what it says and **assembles** some input for the **vertex shader**.
This **vertex shader** transforms the vertices through different **coordinate systems** and figure out where
everything should end up on the screen. Here we can optionally do some work with the **geomtry** and **tessellation**
steps to generate more geometry on the fly---since expressing some geometric detail mathmatically is more efficient than providing the concrete geometry.
This would help us lighten the load on the DRAM -> GPU data lines which are often a bottleneck.
**Rasterization** <br/>
After all that **geometry processing** we pass the final geometry data to the hardcoded hardware **rasterizer**
to do **rasterization** and **interpolation** for us and convert the **abstract geometry** into concrete **pixels**.
All by using triangles because they're the best.
**Pixel Processing** <br/>
The **rasterizer** then hands off the work to the **pixel/fragment shader** and our world will end up
being so sexy and colorful! After processing all the fragments the **output merger** will squeeze these
together and compose the final image.
**Presentation** <br/>
The **presentation engine** will then feed the output of the pipeline to the target display **surface**
for your pretty eyes to digest and enjoy.
You've done it! You read through all this garbage just to learn how the **graphics pipeline** works.
Give yourself a pat on the back and a well deserved reward.
Thanks for reading all the way through! Any feedback, criticism, or question is welcome so contact
me if you'd like. Good luck on your journey, wherever it may take you :)
## Sources
<Note title="Reviewers", type="review">
MMZ ❤️
Grammarly
Some LLMs
</Note>
<Note title="Books", type="resource">
[Joey De Vriez --- LearnOpenGL](https://learnopengl.com/)
[Tomas Akenine Moller --- Real-Time Rendering (4th ed)](https://www.realtimerendering.com/intro.html)
[Gabriel Gambetta --- Computer Graphics from Scratch](https://gabrielgambetta.com/computer-graphics-from-scratch/)
</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">
[Miolith --- Quick Understanding of Homogeneous Coordinates for Computer Graphics](https://www.youtube.com/watch?v=o-xwmTODTUI)
[Leios Labs --- What are affine transformations?](https://www.youtube.com/watch?v=E3Phj6J287o)
[3Blue1Brown --- Essence of linear algebra (highly recommended playlist)](https://www.youtube.com/watch?v=fNk_zzaMoSs&list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab)
[3Blue1Brown --- Quaternions and 3d rotation, explained interactively](https://www.youtube.com/watch?v=zjMuIxRvygQ)
[pikuma --- Math for Game Developers (playlist)](https://www.youtube.com/watch?v=Do_vEjd6gF0&list=PLYnrabpSIM-93QtJmGnQcJRdiqMBEwZ7_)
[pikuma --- 3D Graphics (playlist)](https://www.youtube.com/watch?v=Do_vEjd6gF0&list=PLYnrabpSIM-97qGEeOWnxZBqvR_zwjWoo)
[Cem Yuksel --- Introduction to Computer Graphics (playlist)](https://www.youtube.com/watch?v=vLSphLtKQ0o&list=PLplnkTzzqsZTfYh4UbhLGpI5kGd5oW_Hh)
[Cem Yuksel --- Interactive Computer Graphics (playlist)](https://www.youtube.com/watch?v=UVCuWQV_-Es&list=PLplnkTzzqsZS3R5DjmCQsqupu43oS9CFN&pp=0gcJCV8EOCosWNin)
[javidx9 --- Essential Mathematics For Aspiring Game Developers](https://www.youtube.com/watch?v=DPfxjQ6sqrc)
</Note>
<Note title="Articles", type="resource">
[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)
[The ryg blog --- The barycentric conspiracy](https://fgiesen.wordpress.com/2013/02/06/the-barycentric-conspirac/)
[Juan Pineda --- A Parallel Algorithm for Polygon Rasterization](https://www.cs.drexel.edu/~deb39/Classes/Papers/comp175-06-pineda.pdf)
[Kristoffer Dyrkorn --- A fast and precise triangle rasterizer](https://kristoffer-dyrkorn.github.io/triangle-rasterizer/)
[Microsoft --- Rasterization Rules](https://learn.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-rasterizer-stage-rules)
</Note>
<Note title="Documentations", type="resource">
[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)
</Note>

View file

@ -0,0 +1,115 @@
---
title: The Graphics Pipeline --- Pixel Processing
date: "April 20 - 2025"
---
<script>
import Image from "../../Image.svelte"
import Note from "../../Note.svelte"
import Tip from "../../Tip.svelte"
</script>
## Pixel Processing
**Overview**
## Texturing
**Vertex Data Extension**
**Texture Coordinates**
**Texture Sampling**
**Mipmaps**
**Non-color Data**
## Lighting
**Phong Shading**
// The model was named after its developer B`ui Tóng Phong
**Ambient**
**Diffuse**
**Specular**
**Combined (Phong)**
## Shadows
## Anti-Aliasing
**SSAA**
**MSAA**
## Post-Processing & Screen-Space Effects
## Pixel Shaders
## Presentation
## Depth Testing
## Stencil Testing
## Output Merger
** Transparency**
**Blending**
## Sources
<Note title="Reviewers", type="review">
MMZ ❤️
Grammarly
Some LLMs
</Note>
<Note title="Books", type="resource">
[Joey De Vriez --- LearnOpenGL](https://learnopengl.com/)
[Tomas Akenine Moller --- Real-Time Rendering (4th ed)](https://www.realtimerendering.com/intro.html)
[Gabriel Gambetta --- Computer Graphics from Scratch](https://gabrielgambetta.com/computer-graphics-from-scratch/)
</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">
[Miolith --- Quick Understanding of Homogeneous Coordinates for Computer Graphics](https://www.youtube.com/watch?v=o-xwmTODTUI)
[Leios Labs --- What are affine transformations?](https://www.youtube.com/watch?v=E3Phj6J287o)
[3Blue1Brown --- Essence of linear algebra (highly recommended playlist)](https://www.youtube.com/watch?v=fNk_zzaMoSs&list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab)
[3Blue1Brown --- Quaternions and 3d rotation, explained interactively](https://www.youtube.com/watch?v=zjMuIxRvygQ)
[pikuma --- Math for Game Developers (playlist)](https://www.youtube.com/watch?v=Do_vEjd6gF0&list=PLYnrabpSIM-93QtJmGnQcJRdiqMBEwZ7_)
[pikuma --- 3D Graphics (playlist)](https://www.youtube.com/watch?v=Do_vEjd6gF0&list=PLYnrabpSIM-97qGEeOWnxZBqvR_zwjWoo)
[Cem Yuksel --- Introduction to Computer Graphics (playlist)](https://www.youtube.com/watch?v=vLSphLtKQ0o&list=PLplnkTzzqsZTfYh4UbhLGpI5kGd5oW_Hh)
[Cem Yuksel --- Interactive Computer Graphics (playlist)](https://www.youtube.com/watch?v=UVCuWQV_-Es&list=PLplnkTzzqsZS3R5DjmCQsqupu43oS9CFN&pp=0gcJCV8EOCosWNin)
[javidx9 --- Essential Mathematics For Aspiring Game Developers](https://www.youtube.com/watch?v=DPfxjQ6sqrc)
</Note>
<Note title="Articles", type="resource">
[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)
[The ryg blog --- The barycentric conspiracy](https://fgiesen.wordpress.com/2013/02/06/the-barycentric-conspirac/)
[Juan Pineda --- A Parallel Algorithm for Polygon Rasterization](https://www.cs.drexel.edu/~deb39/Classes/Papers/comp175-06-pineda.pdf)
[Kristoffer Dyrkorn --- A fast and precise triangle rasterizer](https://kristoffer-dyrkorn.github.io/triangle-rasterizer/)
[Microsoft --- Rasterization Rules](https://learn.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-rasterizer-stage-rules)
</Note>
<Note title="Documentations", type="resource">
[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)
</Note>

View file

@ -0,0 +1,99 @@
---
title: The Graphics Pipeline --- Rasterization
date: "April 20 - 2025"
---
<script>
import Image from "../../Image.svelte"
import Note from "../../Note.svelte"
import Tip from "../../Tip.svelte"
</script>
## Rasterization
**Bounding Box**
**Winding order**
**P needs to be on the "RIGHT" side of a->b**
**Cross Product**
**Interpolation**
Remember the god forsaken **input assembler**? Let's expand our understanding of it
since-- for simplicity's sake, we skipped over the fact that **vertices** can hold much, much more data
than only positions.
**Barycentric Interpolation** NOTE NOT linear interpolation
**Some Optimizations**
<Note title="Software Rasterization">
What we've implemented is a simple toy rasterizer written to be run on the CPU for educational
purposes only. It is inefficient, has shit precision (integer precision) thus it is choppy when moving things around, and has many problems.
However, GPUs have dedicated hardwares that run incredibly optimized algorithms to do this
sort of thing; hence what we made is called a **software** rasterizer ---as opposed to the usual
**hardware** rasterizer.
It's nice to be aware of and appreciate the simplicity of triangles. If our polygons had variable
number of edges then it would be really difficult to come up with efficient algorithms for doing this.
</Note>
## Sources
<Note title="Reviewers", type="review">
MMZ ❤️
Grammarly
Some LLMs
</Note>
<Note title="Books", type="resource">
[Joey De Vriez --- LearnOpenGL](https://learnopengl.com/)
[Tomas Akenine Moller --- Real-Time Rendering (4th ed)](https://www.realtimerendering.com/intro.html)
[Gabriel Gambetta --- Computer Graphics from Scratch](https://gabrielgambetta.com/computer-graphics-from-scratch/)
</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">
[Miolith --- Quick Understanding of Homogeneous Coordinates for Computer Graphics](https://www.youtube.com/watch?v=o-xwmTODTUI)
[Leios Labs --- What are affine transformations?](https://www.youtube.com/watch?v=E3Phj6J287o)
[3Blue1Brown --- Essence of linear algebra (highly recommended playlist)](https://www.youtube.com/watch?v=fNk_zzaMoSs&list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab)
[3Blue1Brown --- Quaternions and 3d rotation, explained interactively](https://www.youtube.com/watch?v=zjMuIxRvygQ)
[pikuma --- Math for Game Developers (playlist)](https://www.youtube.com/watch?v=Do_vEjd6gF0&list=PLYnrabpSIM-93QtJmGnQcJRdiqMBEwZ7_)
[pikuma --- 3D Graphics (playlist)](https://www.youtube.com/watch?v=Do_vEjd6gF0&list=PLYnrabpSIM-97qGEeOWnxZBqvR_zwjWoo)
[Cem Yuksel --- Introduction to Computer Graphics (playlist)](https://www.youtube.com/watch?v=vLSphLtKQ0o&list=PLplnkTzzqsZTfYh4UbhLGpI5kGd5oW_Hh)
[Cem Yuksel --- Interactive Computer Graphics (playlist)](https://www.youtube.com/watch?v=UVCuWQV_-Es&list=PLplnkTzzqsZS3R5DjmCQsqupu43oS9CFN&pp=0gcJCV8EOCosWNin)
[javidx9 --- Essential Mathematics For Aspiring Game Developers](https://www.youtube.com/watch?v=DPfxjQ6sqrc)
</Note>
<Note title="Articles", type="resource">
[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)
[The ryg blog --- The barycentric conspiracy](https://fgiesen.wordpress.com/2013/02/06/the-barycentric-conspirac/)
[Juan Pineda --- A Parallel Algorithm for Polygon Rasterization](https://www.cs.drexel.edu/~deb39/Classes/Papers/comp175-06-pineda.pdf)
[Kristoffer Dyrkorn --- A fast and precise triangle rasterizer](https://kristoffer-dyrkorn.github.io/triangle-rasterizer/)
[Microsoft --- Rasterization Rules](https://learn.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-rasterizer-stage-rules)
</Note>
<Note title="Documentations", type="resource">
[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)
</Note>

BIN
static/images/boo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
static/images/bunny.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
static/images/bunny.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
static/images/planar.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="89.898438"
height="107.35807"
viewBox="0 0 89.898439 107.35807"
version="1.1"
id="svg8653"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs8647">
<marker
style="overflow:visible"
id="DartArrow"
refX="0"
refY="0"
orient="auto-start-reverse"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
preserveAspectRatio="xMidYMid">
<path
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
transform="scale(-0.5)"
id="path6" />
</marker>
</defs>
<metadata
id="metadata8650">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="5.0234375"
y="12.867185"
id="text5070-2-2-9-9"><tspan
id="tspan5068-0-3-36-9"
x="5.0234375"
y="12.867185"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">0</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="5.0234375"
y="92.86718"
id="text5070-2-2-9-9-7"><tspan
id="tspan5068-0-3-36-9-6"
x="5.0234375"
y="92.86718"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">2</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="85.023438"
y="12.867185"
id="text5070-2-2-9-9-6"><tspan
id="tspan5068-0-3-36-9-4"
x="85.023438"
y="12.867185"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="85.023438"
y="92.86718"
id="text5070-2-2-9-9-77"><tspan
id="tspan5068-0-3-36-9-5"
x="85.023438"
y="92.86718"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">3</tspan></text>
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-2"
cx="85.023438"
cy="22.86717"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-2-4"
cx="85.023438"
cy="102.86718"
r="3.4908931" />
<path
style="fill:#f9f9f9;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 5.023437,22.86718 H 85.023434"
id="path2033" />
<path
style="fill:#f9f9f9;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 5.023437,102.86718 H 85.023434"
id="path2033-5" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-91-0-3"
cx="5.0234375"
cy="102.86718"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-91-0-3-8"
cx="5.0234375"
cy="22.867186"
r="3.4908931" />
<path
style="fill:#f9f9f9;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#DartArrow)"
d="m 20.023434,17.86718 c 16.66767,0 33.33433,0 50,0"
id="path5581" />
<path
id="path5885"
d="m 20.023434,97.86718 c 16.66767,0 33.33433,0 50,0"
style="fill:#f9f9f9;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#DartArrow)" />
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

View file

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="249.89841"
height="27.365885"
viewBox="0 0 249.89841 27.365885"
version="1.1"
id="svg8653"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs8647">
<marker
style="overflow:visible"
id="DartArrow"
refX="0"
refY="0"
orient="auto-start-reverse"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
preserveAspectRatio="xMidYMid">
<path
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
transform="scale(-0.5)"
id="path6" />
</marker>
</defs>
<metadata
id="metadata8650">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="5.0234332"
y="12.875005"
id="text5070-2-2-9-9-8"><tspan
id="tspan5068-0-3-36-9-9"
x="5.0234332"
y="12.875005"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">0</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="165.02344"
y="12.875005"
id="text5070-2-2-9-9-7-7"><tspan
id="tspan5068-0-3-36-9-6-6"
x="165.02344"
y="12.875005"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">2</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="85.02343"
y="12.875005"
id="text5070-2-2-9-9-6-2"><tspan
id="tspan5068-0-3-36-9-4-8"
x="85.02343"
y="12.875005"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="245.02341"
y="12.875005"
id="text5070-2-2-9-9-77-5"><tspan
id="tspan5068-0-3-36-9-5-1"
x="245.02341"
y="12.875005"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">3</tspan></text>
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-5-0-7"
cx="245.02341"
cy="22.874998"
r="3.4908931" />
<path
style="fill:#f9f9f9;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 5.02343,22.875 240,-5e-6"
id="path2085" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-91-0-3"
cx="5.0234332"
cy="22.874998"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-91-0-3-9"
cx="85.02343"
cy="22.874998"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-91-0-3-1"
cx="165.02344"
cy="22.874998"
r="3.4908931" />
<path
style="fill:#f9f9f9;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#DartArrow)"
d="m 20.02343,17.874995 c 16.66767,0 33.33433,0 50,0"
id="path16307" />
<path
id="path16954"
d="m 100.02343,17.874995 c 16.66767,0 33.33433,0 50,0"
style="fill:#f9f9f9;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#DartArrow)" />
<path
style="fill:#f9f9f9;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#DartArrow)"
d="m 180.02343,17.874995 c 16.66767,0 33.33433,0 50,0"
id="path17316" />
</svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

View file

@ -0,0 +1,334 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200.14062"
height="147.16275"
viewBox="0 0 200.14063 147.16275"
version="1.1"
id="svg8653"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs8647">
<filter
style="color-interpolation-filters:sRGB"
id="filter2"
x="0"
y="0"
width="1"
height="1">
<feColorMatrix
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="fbSourceGraphic"
id="feColorMatrix2" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix14" />
<feColorMatrix
id="feColorMatrix15"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="color2"
in="fbSourceGraphic" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter3"
x="0"
y="0"
width="1"
height="1">
<feColorMatrix
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="fbSourceGraphic"
id="feColorMatrix3" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix16" />
<feColorMatrix
id="feColorMatrix17"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="color2"
in="fbSourceGraphic" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter4"
x="0"
y="0"
width="1"
height="1">
<feColorMatrix
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="fbSourceGraphic"
id="feColorMatrix4" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix18" />
<feColorMatrix
id="feColorMatrix19"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="color2"
in="fbSourceGraphic" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter5"
x="0"
y="0"
width="1"
height="1">
<feColorMatrix
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="fbSourceGraphic"
id="feColorMatrix5" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix20" />
<feColorMatrix
id="feColorMatrix21"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="color2"
in="fbSourceGraphic" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter6"
x="0"
y="0"
width="1"
height="1">
<feColorMatrix
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="fbSourceGraphic"
id="feColorMatrix6" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix22" />
<feColorMatrix
id="feColorMatrix23"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="color2"
in="fbSourceGraphic" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter7"
x="0"
y="0"
width="1"
height="1">
<feColorMatrix
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="fbSourceGraphic"
id="feColorMatrix7" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix24" />
<feColorMatrix
id="feColorMatrix25"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="color2"
in="fbSourceGraphic" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter8"
x="0"
y="0"
width="1"
height="1">
<feColorMatrix
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="fbSourceGraphic"
id="feColorMatrix8" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix26" />
<feColorMatrix
id="feColorMatrix27"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="color2"
in="fbSourceGraphic" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter9"
x="0"
y="0"
width="1"
height="1">
<feColorMatrix
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="fbSourceGraphic"
id="feColorMatrix9" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix28" />
<feColorMatrix
id="feColorMatrix29"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="color2"
in="fbSourceGraphic" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter10"
x="0"
y="0"
width="1"
height="1">
<feColorMatrix
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="fbSourceGraphic"
id="feColorMatrix10" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix30" />
<feColorMatrix
id="feColorMatrix31"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="color2"
in="fbSourceGraphic" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter11"
x="0"
y="0"
width="1"
height="1">
<feColorMatrix
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="fbSourceGraphic"
id="feColorMatrix11" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix32" />
<feColorMatrix
id="feColorMatrix33"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="color2"
in="fbSourceGraphic" />
</filter>
</defs>
<metadata
id="metadata8650">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(52.301544,180.70697)">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427;filter:url(#filter11)"
x="12.534395"
y="-108.03511"
id="text5070-2-2-9-9"><tspan
id="tspan5068-0-3-36-9"
x="12.534395"
y="-108.03511"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke-width:1.16427">0</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427;filter:url(#filter10)"
x="142.53439"
y="-118.03511"
id="text5070-2-2-9-9-1"><tspan
id="tspan5068-0-3-36-9-3"
x="142.53439"
y="-118.03511"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke-width:1.16427">4</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427;filter:url(#filter9)"
x="-47.465607"
y="-148.03511"
id="text5070-2-2-9-9-7"><tspan
id="tspan5068-0-3-36-9-6"
x="-47.465607"
y="-148.03511"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke-width:1.16427">2</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427;filter:url(#filter8)"
x="52.534393"
y="-168.0351"
id="text5070-2-2-9-9-6"><tspan
id="tspan5068-0-3-36-9-4"
x="52.534393"
y="-168.0351"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke-width:1.16427">1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427;filter:url(#filter7)"
x="92.534393"
y="-48.03511"
id="text5070-2-2-9-9-77"><tspan
id="tspan5068-0-3-36-9-5"
x="92.534393"
y="-48.03511"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke-width:1.16427">3</tspan></text>
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter6)"
id="path4517-0-8-5-8"
cx="142.53439"
cy="-108.03511"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5)"
id="path4517-0-8-5-91"
cx="52.534393"
cy="-158.03511"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4)"
id="path4517-0-8-5-2"
cx="92.534393"
cy="-38.03511"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3)"
id="path4517-0-8-5-25"
cx="-47.465607"
cy="-138.03511"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter2)"
id="path4517-0-8-5-5"
cx="12.534393"
cy="-98.03511"
r="3.4908931" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,171 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="169.79558"
height="104.11718"
viewBox="0 0 169.79558 104.11718"
version="1.1"
id="svg8653"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs8647">
<marker
style="overflow:visible"
id="DartArrow"
refX="0"
refY="0"
orient="auto-start-reverse"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
preserveAspectRatio="xMidYMid">
<path
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
transform="scale(-0.5)"
id="path6" />
</marker>
</defs>
<metadata
id="metadata8650">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-248.0435,180.9101)">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="332.53439"
y="-78.035103"
id="text5070-2-2-9-9-75"><tspan
id="tspan5068-0-3-36-9-68"
x="332.53439"
y="-78.035103"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke-width:1.16427">0</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="412.53439"
y="-78.035103"
id="text5070-2-2-9-9-1-4"><tspan
id="tspan5068-0-3-36-9-3-6"
x="412.53439"
y="-78.035103"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke-width:1.16427">4</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="292.53439"
y="-168.0351"
id="text5070-2-2-9-9-7-4"><tspan
id="tspan5068-0-3-36-9-6-3"
x="292.53439"
y="-168.0351"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke-width:1.16427">2</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="252.53439"
y="-78.035103"
id="text5070-2-2-9-9-6-2"><tspan
id="tspan5068-0-3-36-9-4-4"
x="252.53439"
y="-78.035103"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke-width:1.16427">1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="372.53439"
y="-168.0351"
id="text5070-2-2-9-9-77-2"><tspan
id="tspan5068-0-3-36-9-5-2"
x="372.53439"
y="-168.0351"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke-width:1.16427">3</tspan></text>
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-8-0"
cx="412.53439"
cy="-98.035095"
r="3.4908931" />
<path
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 252.53439,-98.0351 40,-59.99999 h 80 l 40,59.99999 z m 40,-59.99999 40,59.99999 40,-59.99999"
id="path875-4" />
<path
id="path1868-1"
d="m 267.53439,-113.0351 20,-30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#DartArrow)" />
<path
id="path1870-2"
d="m 297.53439,-143.0351 20,30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#DartArrow)" />
<path
id="path1872-1"
d="m 317.53439,-103.0351 h -50"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#DartArrow)" />
<path
id="path1868-6-6"
d="m 347.19583,-112.35392 20,-30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#DartArrow)" />
<path
id="path1870-4-3"
d="m 377.19583,-142.35392 20,30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#DartArrow)" />
<path
id="path1872-0-9"
d="m 397.19583,-102.35392 h -50"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#DartArrow)" />
<path
id="path1868-08-3"
d="m 307.53439,-143.03509 20,30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DartArrow)" />
<path
id="path1870-9-9"
d="m 337.53439,-113.03509 20,-30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DartArrow)" />
<path
id="path1872-2-3"
d="m 357.53439,-153.03509 h -50"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DartArrow)" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-91-0-3"
cx="292.53439"
cy="-158.03511"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-2-9"
cx="252.53439"
cy="-98.03511"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-2-9-7"
cx="332.53439"
cy="-98.03511"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-2-9-6"
cx="372.53439"
cy="158.03511"
r="3.4908931"
transform="scale(1,-1)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="210.32816"
height="104.11718"
viewBox="0 0 210.32816 104.11718"
version="1.1"
id="svg8653"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs8647">
<marker
style="overflow:visible"
id="marker3"
refX="0"
refY="0"
orient="auto-start-reverse"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
preserveAspectRatio="xMidYMid">
<path
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
transform="scale(-0.5)"
id="path3" />
</marker>
<marker
style="overflow:visible"
id="marker1"
refX="0"
refY="0"
orient="auto-start-reverse"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
preserveAspectRatio="xMidYMid">
<path
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
transform="scale(-0.5)"
id="path1" />
</marker>
</defs>
<metadata
id="metadata8650">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<path
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 125.02343,22.875 40,59.999997 40,-59.999997 z"
id="path11344" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="85.02346"
y="102.875"
id="text5070-2-2-9-9-75-8"><tspan
id="tspan5068-0-3-36-9-68-4"
x="85.02346"
y="102.875"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">2</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="45.023403"
y="12.87502"
id="text5070-2-2-9-9-7-4-5"><tspan
id="tspan5068-0-3-36-9-6-3-1"
x="45.023403"
y="12.87502"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="5.0234332"
y="102.875"
id="text5070-2-2-9-9-6-2-2"><tspan
id="tspan5068-0-3-36-9-4-4-0"
x="5.0234332"
y="102.875"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">0</tspan></text>
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-91-9-3"
cx="45.023403"
cy="22.875021"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-25-0-0"
cx="85.02346"
cy="82.875"
r="3.4908931" />
<path
id="path1868-1-8"
d="m 20.02343,67.87502 20,-30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker3)" />
<path
id="path1870-2-7"
d="m 50.02343,37.87502 20,30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker3)" />
<path
id="path1872-1-0"
d="m 70.02343,77.87502 h -50"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker3)" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="125.02346"
y="12.875005"
id="text5070-2-2-9-9-75-8-3"><tspan
id="tspan5068-0-3-36-9-68-4-4"
x="125.02346"
y="12.875005"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">3</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="165.02347"
y="102.875"
id="text5070-2-2-9-9-1-4-2"><tspan
id="tspan5068-0-3-36-9-3-6-1"
x="165.02347"
y="102.875"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">5</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="205.02347"
y="12.875005"
id="text5070-2-2-9-9-77-2-4"><tspan
id="tspan5068-0-3-36-9-5-2-0"
x="205.02347"
y="12.875005"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:1.16427">4</tspan></text>
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-8-0-3"
cx="165.02347"
cy="82.875"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-25-0-0-6"
cx="205.02347"
cy="22.875006"
r="3.4908931" />
<path
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 5.02343,82.875005 40,-59.999995 40,59.999995 z"
id="path11342" />
<path
id="path1868-08-3"
d="m 140.02344,37.875 20,30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker1)" />
<path
id="path1870-9-9"
d="m 170.02344,67.875 20,-30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker1)" />
<path
id="path1872-2-3"
d="m 190.02344,27.875 h -50"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker1)" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-91-0-97"
cx="5.0234332"
cy="82.875"
r="3.4908931" />
<circle
style="fill:#f9f9f9;fill-opacity:1;stroke:#f9f9f9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-91-0-3"
cx="125.02346"
cy="22.875006"
r="3.4908931" />
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -0,0 +1,202 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="170.32812"
height="104.11719"
viewBox="0 0 170.32813 104.11719"
version="1.1"
id="svg8653"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs8647">
<marker
style="overflow:visible"
id="marker2"
refX="0"
refY="0"
orient="auto-start-reverse"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
preserveAspectRatio="xMidYMid">
<path
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
transform="scale(-0.5)"
id="path2" />
</marker>
<marker
style="overflow:visible"
id="marker1"
refX="0"
refY="0"
orient="auto-start-reverse"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
preserveAspectRatio="xMidYMid">
<path
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
transform="scale(-0.5)"
id="path1" />
</marker>
<marker
style="overflow:visible"
id="DartArrow"
refX="0"
refY="0"
orient="auto-start-reverse"
markerWidth="1"
markerHeight="1"
viewBox="0 0 1 1"
preserveAspectRatio="xMidYMid">
<path
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
transform="scale(-0.5)"
id="path6" />
</marker>
</defs>
<metadata
id="metadata8650">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-7.5109558,180.91011)">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="12.534393"
y="-78.03511"
id="text5070-2-2-9-9"><tspan
id="tspan5068-0-3-36-9"
x="12.534393"
y="-78.03511"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke-width:1.16427">0</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="172.53439"
y="-78.035103"
id="text5070-2-2-9-9-1"><tspan
id="tspan5068-0-3-36-9-3"
x="172.53439"
y="-78.035103"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke-width:1.16427">4</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="92.534393"
y="-78.035103"
id="text5070-2-2-9-9-7"><tspan
id="tspan5068-0-3-36-9-6"
x="92.534393"
y="-78.035103"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke-width:1.16427">2</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="52.534393"
y="-168.0351"
id="text5070-2-2-9-9-6"><tspan
id="tspan5068-0-3-36-9-4"
x="52.534393"
y="-168.0351"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke-width:1.16427">1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.16427"
x="132.53439"
y="-168.03511"
id="text5070-2-2-9-9-77"><tspan
id="tspan5068-0-3-36-9-5"
x="132.53439"
y="-168.03511"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke-width:1.16427">3</tspan></text>
<circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-8"
cx="172.53439"
cy="-98.035103"
r="3.4908931" />
<circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-2"
cx="132.53439"
cy="-158.03511"
r="3.4908931" />
<path
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 12.534393,-98.035106 40,-59.999994 h 79.999997 l 40,59.999994 z m 40,-59.999994 39.999997,59.999994 40,-59.999994"
id="path875" />
<path
id="path1868"
d="m 27.534393,-113.0351 20,-30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker2)" />
<path
id="path1870"
d="m 57.534393,-143.0351 19.999997,30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker2)" />
<path
id="path1872"
d="M 77.53439,-103.0351 H 27.534393"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker2)" />
<path
id="path1868-6"
d="m 107.19584,-112.35393 20,-30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker2)" />
<path
id="path1870-4"
d="m 137.19584,-142.35393 19.99999,30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker2)" />
<path
id="path1872-0"
d="M 157.19583,-102.35393 H 107.19584"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker2)" />
<path
id="path1868-08-3-3"
d="m 67.53439,-143.0351 20,30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker1)" />
<path
id="path1870-9-9-3"
d="m 97.53439,-113.0351 20,-30"
style="fill:none;stroke:#f9f9f9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker1)" />
<path
id="path1872-2-3-1"
d="M 111.73438,-153.0351 H 67.53439"
style="fill:none;stroke:#f9f9f9;stroke-width:0.940213px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DartArrow)" />
<circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-91-0-97"
cx="12.872943"
cy="-98.716286"
r="3.4908931" />
<circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-91-0-97-3"
cx="92.534393"
cy="-98.035103"
r="3.4908931" />
<circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4517-0-8-5-91-0-3"
cx="52.534393"
cy="-158.0351"
r="3.4908931" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -1,13 +1,11 @@
import { mdsvex } from 'mdsvex';
import { mdsvex_config } from './mdsvex.config.js';
import adapter from '@sveltejs/adapter-static';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://svelte.dev/docs/kit/integrations
// for more information about preprocessors
preprocess: [vitePreprocess(), mdsvex()],
kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
@ -15,8 +13,14 @@ const config = {
adapter: adapter()
},
extensions: ['.svelte', '.svx']
extensions: ['.svelte', '.svx', '.md'],
// Consult https://svelte.dev/docs/kit/integrations
// for more information about preprocessors
preprocess: [
vitePreprocess(),
mdsvex(mdsvex_config)
],
};
export default config;