Repository navigation
Expand file tree
/
Copy pathde.html
More file actions
287 lines (287 loc) · 25.2 KB
/
Copy pathde.html
File metadata and controls
287 lines (287 loc) · 25.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Moritz Falk — Grafik- und Systemprogrammierer in Stuttgart. Renderer, Immediate-Mode-UI, Engine-Entwicklung und Performance-Optimierung. Offen für Stellen und freiberufliche Projekte.">
<meta name="theme-color" content="#f5f4ef">
<title>Moritz Falk — Grafik- & Systemprogrammierer</title>
<link rel="canonical" href="https://moritzfalk.com/de.html">
<link rel="alternate" hreflang="en" href="https://moritzfalk.com/">
<link rel="alternate" hreflang="de" href="https://moritzfalk.com/de.html">
<link rel="alternate" hreflang="ja" href="https://moritzfalk.com/ja.html">
<link rel="alternate" hreflang="x-default" href="https://moritzfalk.com/">
<style>
:root { color-scheme: light; --paper: #f5f4ef; --ink: #222b26; --muted: #5b655e; --line: #cdd2c8; --accent: #285d43; --mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace; }
* { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: 30px; }
body { margin: 0; background: var(--paper); color: var(--ink); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 17px; line-height: 1.65; -webkit-font-smoothing: antialiased; }
a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 5px; }
a:hover { color: var(--accent); }
a:focus-visible, summary:focus-visible, button:focus-visible { outline: 2px solid var(--accent); outline-offset: 7px; }
::selection { background: #ccdccb; }
.wrap { width: min(1000px, calc(100% - 64px)); margin-inline: auto; }
.skip-link { position: absolute; top: -100px; left: 24px; padding: 10px 20px; background: var(--ink); color: white; z-index: 2; }
.skip-link:focus { top: 16px; }
.site-header { display: flex; flex-wrap: wrap; align-items: center; gap: 24px; padding-block: 22px; }
.identity { display: grid; grid-template-columns: 72px minmax(0, 1fr); align-items: center; gap: 16px; margin-right: auto; min-width: 0; }
.wordmark { text-decoration: none; }
nav { display: flex; flex-wrap: wrap; gap: 28px; font-size: 14px; }
nav a { text-decoration: none; }
nav a:hover { text-decoration: underline; }
.language-switcher { gap: 16px; font-size: 13px; }
.language-switcher [aria-current="page"] { color: var(--accent); text-decoration: underline; font-weight: 600; }
.language-note { margin: 6px 0 0; color: var(--muted); font-size: 14px; line-height: 1.6; }
html[lang="ja"] body { font-family: "Helvetica Neue", Helvetica, Arial, "Hiragino Kaku Gothic ProN", "Yu Gothic", Meiryo, sans-serif; line-height: 1.85; }
html[lang="ja"] .profile-facts dt::after { content: ":"; }
html[lang="ja"] h2, html[lang="ja"] h3, html[lang="ja"] .lead { letter-spacing: 0; }
.eyebrow { font-size: 13px; color: var(--muted); }
h1 { font-size: 20px; line-height: 1.3; font-weight: 650; margin: 0 0 2px; }
.role { margin: 0; font-size: 14px; line-height: 1.5; color: var(--muted); }
.portrait { display: block; width: 72px; height: 72px; max-width: 100%; object-fit: cover; object-position: 50% 32%; }
.profile-facts { margin: 0; font-size: 14px; line-height: 1.6; }
.profile-facts > div + div { margin-top: 2px; }
.profile-facts dt { display: inline; color: var(--muted); }
.profile-facts dt::after { content: ": "; }
.profile-facts dd { display: inline; margin: 0; }
.company-affiliation { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin: 10px 0 6px; font-size: 14px; line-height: 1.5; }
.company-card { display: inline-flex; align-items: center; gap: 6px; padding: 3px 6px; border: 1px solid var(--line); color: var(--ink); text-decoration: none; }
.company-card:hover { border-color: var(--accent); color: var(--ink); }
.company-card img { width: 22px; height: 22px; flex-shrink: 0; padding: 2px; background: #151a17; }
.section-heading { border-top: 1px solid var(--line); padding-top: 22px; }
.section-heading h2 { margin: 0; font-size: 23px; font-weight: 550; letter-spacing: -.7px; }
.project { display: grid; grid-template-columns: 190px minmax(0, 1fr); gap: 40px; padding: 32px 0 40px; border-bottom: 1px solid var(--line); }
.project-meta h3 { margin: 0 0 8px; font-size: 24px; line-height: 1.2; font-weight: 550; letter-spacing: -.7px; }
.project-meta p { font-size: 13px; line-height: 1.65; color: var(--muted); margin: 6px 0; }
.project-meta .period { font-size: 13px; margin-top: 12px; }
.project-body > p:first-child { margin-top: 0; }
.project-body p { max-width: 730px; margin: 0 0 19px; }
.project-body .lead { font-size: 22px; line-height: 1.45; letter-spacing: -.4px; color: var(--ink); }
.project-body ul { margin: 22px 0 0; padding-left: 19px; }
.project-body li { padding-left: 5px; margin: 10px 0; }
.project-body li::marker { color: var(--accent); }
.project-body li:last-child { margin-bottom: 0; }
figure { margin: 30px 0 0; }
figcaption { margin-top: 10px; display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 20px; color: var(--muted); font-size: 13px; }
.media { width: 100%; display: block; height: auto; background: #151a17; }
.blick-logo { display: inline-block; text-decoration: none; }
.blick-logo img { display: block; width: 180px; max-width: 100%; height: auto; }
.blick-logo span { display: block; margin-top: 8px; color: var(--muted); font-size: 13px; }
.blick-logo:hover span { color: var(--accent); }
.article-card { display: grid; grid-template-columns: 125px minmax(0, 1fr); gap: 24px; align-items: center; margin-top: 28px; padding: 20px; border: 1px solid var(--line); text-decoration: none; color: var(--ink); }
.article-card:hover { color: var(--ink); border-color: var(--accent); }
.article-card > img { width: 100%; height: auto; display: block; }
.article-card h4 { font-size: 22px; line-height: 1.35; letter-spacing: -.4px; margin: 10px 0 12px; font-weight: 500; }
.article-card p { font-size: 14px; line-height: 1.65; margin: 0 0 16px; color: var(--muted); }
.article-link { font-size: 13px; color: var(--accent); }
.project-links { display: flex; flex-wrap: wrap; gap: 12px 24px; margin-top: 22px; font-size: 14px; color: var(--accent); }
.youtube-preview { position: relative; display: block; width: 100%; aspect-ratio: 16 / 9; padding: 0; border: 1px solid var(--line); background: #151a17; color: white; text-decoration: none; overflow: hidden; }
.youtube-preview:hover { color: white; }
.arc-preview { aspect-ratio: 12 / 5; }
.youtube-preview.arc-preview img { position: absolute; width: 116.364%; height: auto; max-width: none; left: -3.182%; top: -5.018%; }
.youtube-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }
.youtube-preview::after { content: ""; position: absolute; inset: 35% 0 0; background: linear-gradient(transparent, rgba(0,0,0,.85)); pointer-events: none; }
.engine-preview::after { inset: 0; background: linear-gradient(25deg, rgba(0,0,0,.8), transparent 60%); }
.play-label { position: absolute; inset: auto 24px 22px; display: block; text-align: left; font: 15px/1.4 "Helvetica Neue", Helvetica, Arial, sans-serif; z-index: 1; }
.square-demo { max-width: 520px; }
.media-note { margin-top: 16px !important; font-size: 13px; color: var(--muted); }
.experiments { padding: 32px 0 40px; }
.experiments .section-heading { border-top: 0; padding-top: 0; margin-bottom: 12px; }
details { border-bottom: 1px solid var(--line); }
summary { list-style: none; display: grid; grid-template-columns: 144px minmax(0, 1fr) 24px; gap: 24px; align-items: center; padding: 22px 0; cursor: pointer; }
.experiment-preview { display: block; width: 144px; height: 96px; object-fit: contain; background: #151a17; }
summary::-webkit-details-marker { display: none; }
summary .year { display: block; color: var(--muted); font-size: 13px; margin-top: 5px; }
summary h3 { font-size: 19px; font-weight: 550; line-height: 1.4; letter-spacing: -.4px; margin: 0 0 4px; }
summary p { color: var(--muted); font-size: 14px; line-height: 1.55; margin: 0; }
summary .toggle { font: 22px/1.3 var(--mono); color: var(--accent); text-align: right; }
summary .toggle::before { content: "+"; }
details[open] .toggle::before { content: "−"; }
summary:hover h3 { color: var(--accent); }
.experiment-body { max-width: 900px; padding: 0 0 26px 168px; font-size: 16px; }
.experiment-body p { margin: 0 0 14px; }
.experiment-body p:last-child { margin-bottom: 0; }
.contact { padding: 26px 0; display: grid; grid-template-columns: 190px minmax(0, 1fr); gap: 40px; border-top: 1px solid var(--line); }
.contact h2 { font-size: 23px; line-height: 1.35; font-weight: 550; margin: 0; }
.profile-copy { margin: 0; font-size: 16px; line-height: 1.6; }
.availability { margin: 12px 0 0; color: var(--muted); font-size: 16px; }
.contact-links { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 12px; font-size: 14px; }
.contact-links a { color: var(--accent); }
@media (max-width: 760px) {
.site-header { gap: 12px 24px; }
.identity { flex-basis: 100%; }
.language-switcher { margin-left: auto; }
.project { grid-template-columns: 160px minmax(0, 1fr); gap: 28px; }
.contact { grid-template-columns: 160px minmax(0, 1fr); gap: 28px; }
}
@media (max-width: 620px) {
.wrap { width: calc(100% - 40px); }
.site-header { padding-block: 16px; }
nav { gap: 16px; font-size: 13px; }
.contact { display: block; }
.contact h2 { margin-bottom: 16px; }
.project { display: block; padding: 26px 0 32px; }
.project-meta { margin-bottom: 20px; }
.project-body .lead { font-size: 21px; }
.project-body { font-size: 16px; }
.article-card { grid-template-columns: 85px minmax(0, 1fr); gap: 16px; padding: 16px; align-items: start; }
.article-card h4 { font-size: 18px; }
.article-card p { display: none; }
.article-card .eyebrow { font-size: 12px; }
.play-label { inset: auto 14px 14px; font-size: 14px; }
summary { grid-template-columns: 88px minmax(0, 1fr) 16px; gap: 14px; }
.experiment-preview { width: 88px; height: 66px; }
summary h3 { font-size: 17px; }
.experiment-body { padding-left: 0; }
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
@media print {
body { background: white; font-size: 11pt; }
.wrap { width: 100%; }
.skip-link, nav, .toggle { display: none; }
h1 { font-size: 20pt; }
.project { padding-block: 25px; }
.project-meta, h2, h3, summary { break-after: avoid; }
figure, .contact { break-inside: avoid; }
.contact { background: none; padding: 25px 0; }
a { text-decoration: none; }
}
</style>
</head>
<body>
<a class="skip-link" href="#main">Zum Inhalt</a>
<div class="wrap">
<header class="site-header">
<div class="identity">
<img class="portrait" src="assets/previews/moritz-falk-144.jpg" srcset="assets/previews/moritz-falk-144.jpg 144w, assets/previews/moritz-falk-216.jpg 216w, assets/previews/moritz-falk-288.jpg 288w, assets/previews/moritz-falk-432.jpg 432w, assets/previews/moritz-falk-576.jpg 576w" sizes="72px" width="72" height="72" alt="Moritz Falk" decoding="async">
<div><h1><a class="wordmark" href="#" aria-label="Moritz Falk, zurück nach oben">Moritz Falk</a></h1><p class="role">Grafik- & System­programmierer</p></div>
</div>
<nav aria-label="Hauptnavigation">
<a href="#contact">Kontakt</a>
</nav>
<nav class="language-switcher" aria-label="Sprache">
<a href="index.html" lang="en" hreflang="en">English</a>
<a href="de.html" lang="de" hreflang="de" aria-current="page">Deutsch</a>
<a href="ja.html" lang="ja" hreflang="ja">日本語</a>
</nav>
</header>
<main id="main">
<section id="projects" aria-labelledby="projects-title">
<div class="section-heading"><h2 id="projects-title">Projekte</h2></div>
<article class="project" id="blick" aria-labelledby="blick-title">
<div class="project-meta">
<h3 id="blick-title"><a class="blick-logo" href="https://blickeditor.com/" aria-label="Zur Blick-Website"><img src="assets/blick-logo.svg" width="230" height="40" alt="Blick"><span>Video Editor</span></a></h3>
<p>Dihedron Software GmbH<br>Mitgründer · UI & Rendering</p>
<p class="period">2026 — heute</p>
</div>
<div class="project-body">
<p class="lead">Ein plattformübergreifender Videoeditor mit Immediate-Mode-UI.</p>
<a class="article-card" href="https://blickeditor.com/blog/caching-an-immediate-mode-ui">
<img src="assets/previews/ui-painter-cover-125.png" srcset="assets/previews/ui-painter-cover-85.png 85w, assets/previews/ui-painter-cover-125.png 125w, assets/previews/ui-painter-cover-170.png 170w, assets/previews/ui-painter-cover-250.png 250w, assets/previews/ui-painter-cover-255.png 255w, assets/previews/ui-painter-cover-375.png 375w" sizes="(max-width: 620px) 85px, 125px" width="1470" height="1936" alt="" loading="lazy">
<div><span class="eyebrow">Aus dem Blick-Blog · Englisch</span><h4>Don’t throw it all away.<br>Caching an immediate-mode UI</h4><p>Wie der UI Painter gerenderte Pixel in einer Immediate-Mode-UI wiederverwendet und was das für den Stromverbrauch bedeutet.</p><span class="article-link">Artikel lesen</span></div>
</a>
<ul>
<li>Ein Tile-basierter Renderer mit Compute-Shadern, der Signed Distance Fields (SDFs) auf der GPU auswertet.</li>
<li>Eine kleine Rendering-Sprache, die im Shader interpretiert wird und die Rendering-Logik auf der CPU auf ein Minimum beschränkt.</li>
<li>Rendering-Caches, die unveränderte Ergebnisse wiederverwenden, um Arbeit und Energie zu sparen.</li>
</ul>
</div>
</article>
<article class="project" id="arc" aria-labelledby="arc-title">
<div class="project-meta">
<h3 id="arc-title">ARC</h3>
<p>AnyDesk Software GmbH<br>Software Developer</p>
<p>Renderer & Plattformcode<br>Teamleitung in den letzten vier Monaten</p>
<p class="period">2024 — 2026</p>
</div>
<div class="project-body">
<p class="lead">Eine Immediate-Mode-UI-Library, entwickelt von einem vierköpfigen Team.</p>
<figure>
<a class="youtube-preview arc-preview" href="https://www.youtube.com/watch?v=UULQyRKc6sM" target="_blank" rel="noopener noreferrer">
<img src="assets/arc-typography-1440.jpg" alt="Text- und Typografiebeispiele aus der ARC-Demo." width="2560" height="1440" loading="lazy">
<span class="play-label"><span>ARC-Vortrag auf YouTube ansehen</span></span>
</a>
<figcaption><span>ARC · Better Software Conference 2025</span></figcaption>
</figure>
<p class="media-note">Eine Demo mit Q&A von einem ehemaligen ARC-Teamkollegen.</p>
<ul>
<li>Ein Hash Grid zur Erkennung veränderter Bereiche in einem der Renderer.</li>
<li>Stencil Buffer und Early Depth/Stencil Tests, um Pixel-Shader-Aufrufe in unveränderten Bereichen zu vermeiden – auch wenn die Anwendung die UI jedes Mal neu beschreibt.</li>
</ul>
</div>
</article>
<article class="project" id="custom-engine" aria-labelledby="engine-title">
<div class="project-meta">
<h3 id="engine-title">Ein Spiel in einer eigenen Engine</h3>
<p>Eigenes Projekt<br>Grafik- & Engine-Entwicklung</p>
<p class="period">2020 — heute</p>
</div>
<div class="project-body">
<p class="lead">Eine eigene 3D-Engine für dynamische Beleuchtung und einen malerischen Look.</p>
<figure>
<a class="youtube-preview engine-preview" href="https://www.youtube.com/watch?v=VtJMUp938f8" target="_blank" rel="noopener noreferrer">
<img src="assets/engine-demo-1080.jpg" alt="Die eigene Engine mit einer beleuchteten 3D-Szene und Developer-Tools." width="1920" height="1080" loading="lazy">
<span class="play-label"><span>Engine-Demo auf YouTube ansehen</span></span>
</a>
<figcaption><span>It's voxel o'clock · Engine-Demo</span></figcaption>
</figure>
<ul>
<li>Mehrere Iterationen von voxelbasierter, dynamischer Global Illumination: Mesh-Voxelisierung auf der GPU, ein cachefreundliches Acceleration Grid sowie Spatial und Temporal Denoising.</li>
<li>Stochastic Alpha mit Interleaved Gradient Noise, um Deferred Decals und Volumetric Billboards in die Deferred-Shading-Pipeline einzubinden.</li>
<li>Ein separates Tool, das per MSAA-basierter Voxelisierung Daten für Volumetric Billboards in einem eigenen Format erzeugt.</li>
<li>Eine Developer-UI mit microui für Timing-Messungen, zum Untersuchen von Entities und für Debug-Views.</li>
</ul>
</div>
</article>
</section>
<section class="experiments" aria-labelledby="experiments-title">
<div class="section-heading"><h2 id="experiments-title">Weitere Projekte & Experimente</h2></div>
<details id="retro-racer">
<summary><picture><source media="(max-width: 620px)" srcset="assets/previews/synthforce-88.jpg 1x, assets/previews/synthforce-176.jpg 2x, assets/previews/synthforce-264.jpg 3x"><img class="experiment-preview" src="assets/previews/synthforce-144.jpg" srcset="assets/previews/synthforce-288.jpg 2x, assets/previews/synthforce-432.jpg 3x" width="144" height="96" alt="" loading="lazy" decoding="async"></picture><div class="experiment-title"><h3>SynthForce 2099</h3><p>Ein Pseudo-3D-Arcade-Racer, den wir zu viert in einem zehntägigen Game Jam entwickelt haben.</p><span class="year">2023</span></div><span class="toggle" aria-hidden="true"></span></summary>
<div class="experiment-body">
<p>Wir haben in einem kleinen Team unter Zeitdruck zusammengearbeitet. Der Renderer skaliert und verschiebt Sprites, um einen 3D-Eindruck wie in OutRun zu erzeugen.</p><p>Für die Platzierung und das Tuning habe ich ein kleines Runtime-Tweak-System gebaut. Es liest den Sourcecode des Spiels und lädt ausgewählte Variablenwerte über eine Hash Table und ein Makro im laufenden Spiel neu.</p>
<figure><a href="https://deltaofpie.itch.io/synthforce-2099"><img class="media" src="assets/synthforce-2099.png" width="797" height="447" alt="Screenshot von SynthForce 2099 aus dem itch.io-Beitrag des Teams." loading="lazy"></a><figcaption><span>SynthForce 2099 · Game-Jam-Beitrag</span></figcaption></figure>
<div class="project-links"><a href="https://deltaofpie.itch.io/synthforce-2099">Auf itch.io spielen</a></div>
</div>
</details>
<details id="ddgi">
<summary><picture><source media="(max-width: 620px)" srcset="assets/previews/ddgi-88.jpg 1x, assets/previews/ddgi-176.jpg 2x, assets/previews/ddgi-264.jpg 3x"><img class="experiment-preview" src="assets/previews/ddgi-144.jpg" srcset="assets/previews/ddgi-288.jpg 2x, assets/previews/ddgi-432.jpg 3x" width="144" height="96" alt="" loading="lazy" decoding="async"></picture><div class="experiment-title"><h3>Dynamic Diffuse Global Illumination</h3><p>Eine D3D11-Implementierung nach einem Paper von NVIDIA.</p><span class="year">2022–23</span></div><span class="toggle" aria-hidden="true"></span></summary>
<div class="experiment-body">
<p>Mein erstes größeres Projekt mit einer Grafik-API und Shadern. Ich wollte verstehen, wie Probe-basiertes Lighting funktioniert und welche Trade-offs es mit sich bringt, etwa bei der Platzierung der Probes und beim Umgang mit dynamischen Objekten.</p><p>Die Implementierung funktioniert, hat aber keine Acceleration Structure und verwendet einfache, unoptimierte Shader. Darauf konnte ich bei meinen späteren voxelbasierten Projekten aufbauen.</p>
<figure><video class="media" controls playsinline preload="none" poster="assets/ddgi-poster.jpg" width="1280" height="720" aria-label="Dynamic-Diffuse-Global-Illumination-Demo, aufgenommen am 10. Februar 2023"><source src="assets/ddgi-demo.mp4" type="video/mp4"><a href="assets/ddgi-demo.mp4">GI-Demo herunterladen</a></video><figcaption><span>Aufnahme aus der Entwicklung · 10. Februar 2023</span><a href="assets/ddgi-demo.mp4">Video öffnen</a></figcaption></figure>
</div>
</details>
<details id="rasterizer">
<summary><picture><source media="(max-width: 620px)" srcset="assets/previews/rasterizer-88.jpg 1x, assets/previews/rasterizer-176.jpg 2x, assets/previews/rasterizer-264.jpg 3x"><img class="experiment-preview" src="assets/previews/rasterizer-144.jpg" srcset="assets/previews/rasterizer-288.jpg 2x, assets/previews/rasterizer-432.jpg 3x" width="144" height="96" alt="" loading="lazy" decoding="async"></picture><div class="experiment-title"><h3>Software-Rasterizer</h3><p>Transformationen und Rasterisierung auf der CPU selbst implementieren.</p><span class="year">2022</span></div><span class="toggle" aria-hidden="true"></span></summary>
<div class="experiment-body">
<p>Auf Basis von <a href="https://github.com/ssloy/tinyrenderer">tinyrenderer</a> habe ich Echtzeit-Rendering, eine frei bewegliche Kamera und einfaches Clipping ergänzt. Dabei habe ich die Transformation Pipeline besser verstanden, besonders Clip Space und das Canonical View Volume.</p>
<figure class="square-demo"><video class="media" controls playsinline muted loop preload="none" poster="assets/software-rasterizer-poster.jpg" width="800" height="800" aria-label="Software-Rasterizer-Demo"><source src="assets/software-rasterizer.mp4" type="video/mp4"><a href="assets/software-rasterizer.mp4">Software-Rasterizer-Demo herunterladen</a></video><figcaption><span>Software-Rasterizer · Demo</span></figcaption></figure>
</div>
</details>
<details id="ray-tracer">
<summary><picture><source media="(max-width: 620px)" srcset="assets/previews/miniray-88.jpg 1x, assets/previews/miniray-176.jpg 2x, assets/previews/miniray-264.jpg 3x"><img class="experiment-preview" src="assets/previews/miniray-144.jpg" srcset="assets/previews/miniray-288.jpg 2x, assets/previews/miniray-432.jpg 3x" width="144" height="96" alt="" loading="lazy" decoding="async"></picture><div class="experiment-title"><h3>MiniRay · CPU-Raytracer</h3><p>BVH-Traversal, Multithreading und schnelleres Laden von Modellen.</p><span class="year">2022</span></div><span class="toggle" aria-hidden="true"></span></summary>
<div class="experiment-body">
<p>Um interaktives Rendering zu ermöglichen, habe ich eine Bounding Volume Hierarchy und ein Threading-Modell mit einem Producer und mehreren Consumern implementiert.</p><p>Mein OBJ-Loader speichert geparste Modelle in einem eigenen Cache-Format, damit große Dateien nicht jedes Mal neu geparst werden müssen. Außerdem habe ich die C-Runtime entfernt, um die Abhängigkeiten besser zu verstehen und zu reduzieren.</p>
<figure><a href="assets/miniray.png" aria-label="MiniRay-Rendering in voller Größe ansehen"><img class="media" src="assets/miniray.png" width="1274" height="718" alt="MiniRay-Rendering einer Statue mit Schwert und Schild sowie einer spiegelnden Kugel darüber." loading="lazy"></a><figcaption><span>MiniRay · Whitted-Style CPU-Raytracing</span></figcaption></figure>
<div class="project-links"><a href="https://github.com/moritzfalk/MiniRay">Sourcecode auf GitHub</a></div>
</div>
</details>
</section>
<section class="contact" id="contact" aria-labelledby="contact-title">
<h2 id="contact-title">Über mich & Kontakt</h2>
<div>
<p class="profile-copy">Ich entwickle Renderer, Immediate-Mode-UIs und eigene Engines. Ich lebe in Stuttgart.</p>
<p class="company-affiliation"><span>Mitgründer bei</span> <a class="company-card" href="https://dihedron.net"><img src="assets/previews/dihedron-36.png" srcset="assets/previews/dihedron-36.png 36w, assets/previews/dihedron-54.png 54w, assets/previews/dihedron-72.png 72w, assets/previews/dihedron-108.png 108w, assets/dihedron-logo.png 128w" sizes="18px" width="18" height="18" alt=""><span>Dihedron Software</span></a></p>
<dl class="profile-facts">
<div><dt>Programmiersprachen</dt><dd>C / C++ · Odin · HLSL · MSL</dd></div>
<div><dt>Sprachen</dt><dd>Englisch · Deutsch · Japanisch (Grundkenntnisse)</dd></div>
</dl>
<p class="availability">Ich bin offen für Jobs in der Grafik- und Systemprogrammierung sowie für freiberufliche Projekte.</p>
<div class="contact-links"><a href="mailto:Moritz@falkhf.de">Moritz@falkhf.de</a><a href="https://x.com/falk_moritz" rel="me">X · @falk_moritz</a><a href="assets/moritz-falk-cv.pdf" download>CV (Englisch)</a></div>
</div>
</section>
</main>
</div>
<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js" data-cf-beacon='{"token":"37d3513c0c1e4e1fae831c56cad0a641"}'></script>
</body>
</html>