aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-06-02 19:56:25 +0200
committerLoek Le Blansch <loek@pipeframe.xyz>2024-06-02 19:56:25 +0200
commit060e0ae4aa8f71d5a6a6f8c9ed6cf3c60b137e85 (patch)
tree1c4403a88dfa870a4d2242d6bb057ae02a896726
parent52bc19527838f2cac481a89cefd18cfea6e1a2d2 (diff)
what did i do
-rw-r--r--img/desmos-braids.pngbin0 -> 88993 bytes
-rw-r--r--img/goal.pngbin0 -> 236856 bytes
-rw-r--r--img/hello-fragment.pngbin0 -> 769711 bytes
-rw-r--r--img/toy-braids.pngbin0 -> 157464 bytes
-rw-r--r--readme.md110
5 files changed, 94 insertions, 16 deletions
diff --git a/img/desmos-braids.png b/img/desmos-braids.png
new file mode 100644
index 0000000..0776c98
--- /dev/null
+++ b/img/desmos-braids.png
Binary files differ
diff --git a/img/goal.png b/img/goal.png
new file mode 100644
index 0000000..848ef4d
--- /dev/null
+++ b/img/goal.png
Binary files differ
diff --git a/img/hello-fragment.png b/img/hello-fragment.png
new file mode 100644
index 0000000..3dc199c
--- /dev/null
+++ b/img/hello-fragment.png
Binary files differ
diff --git a/img/toy-braids.png b/img/toy-braids.png
new file mode 100644
index 0000000..e1b760f
--- /dev/null
+++ b/img/toy-braids.png
Binary files differ
diff --git a/readme.md b/readme.md
index 899f348..6e0c622 100644
--- a/readme.md
+++ b/readme.md
@@ -1,21 +1,99 @@
-# Voorstel
+# Individueel project
-Een clone van de Windows Media Player "Batterij" visualizer:
+Doel: een clone van de Windows Media Player "Batterij" visualizer:
-![voorbeeld](https://static.wikia.nocookie.net/wmpvis/images/7/74/Battery_%28Randomization%29.jpg/revision/latest?cb=20150219231850)
+![voorbeeld](img/goal.png)
-## Stappenplan
+De batterij visualizer ondersteunt een aantal presets. Op de bovenstaande
+afbeelding is de 'DrowningFlower' preset te zien.
-0. OpenGL tutorial afmaken
- - ook opzoeken of mijn laptop de OpenGL code kan draaien op geïntegreerde
- graphics kaart **-> dit kan, maar er zijn subtiele verschillen tussen de
- implementaties van de OpenGL driver op mijn desktop PC (met nvidia) en
- mijn laptop (intel)** (zoals [SPIR-V
- reflectie](https://stackoverflow.com/a/78500726/5006337))
-1. Video's vinden van de originele visualizer
-2. De visualizer opbreken in een lijst van effecten/beeldgenerators die als
- losse shaders geïmplementeerd kunnen worden
-3. De shaders implementeren
-4. (Als ik tijd over heb) proberen de visualizer live op audio te laten
- reageren
+Alle presets lijken te bestaan uit het volgende:
+- een laag die patronen genereert
+- een filter die (voor of na het patroon) het beeld op een unieke manier
+ vervormt
+
+Voor elk beeld wordt het nieuwe patroon boven op het vorige beeld getekend. Dit
+zorgt voor een soort "visuele galm" die erg lijkt op bijv. een feedbacklus die
+je met een analoge videocamera zou kunnen maken ([voorbeeld][september]).
+
+## Logboek
+
+Eerst heb ik geprobeerd de "[Hello Triangle][hellotriangle]" tutorial te maken
+van <learnopengl.com>. Aan het einde van deze tutorial had ik een simpel
+programma dat reageert op window resize events, en die een fragment shader
+gebruikt om een enkele driehoek te tekenen in een effen kleur. Omdat het effect
+dat ik probeer na te maken geen 3D nodig heeft, was ik van plan alles met
+fragment shaders te implementeren.
+
+Ik had de applicatie hierna nog aangepast om de driehoek schermvullend te
+tekenen. Om dit te doen had ik al snel ondekt dat ik de z-coördinaat van
+`gl_Position` uit mijn vertex shader op 0 kon zetten, omdat de xyz coördinaten
+uiteindelijk door z gedeeld worden. Op mijn NVIDIA kaart zorgde dit zoals ik
+verwachtte voor een schermvullende driehoek (die oneindig groot was omdat er
+gedeeld wordt door 0), maar op Intel zorgde dit voor een leeg scherm. Ik heb
+uiteindelijk de z-coördinaat op 0.001 gezet, en ben hierna direct bewust
+geworden van de verschillen tussen graphics drivers.
+
+Hierna had ik de fragment shader nog wat aangepast om via uniforms de huidige
+tijd en schermgrotte binnen te krijgen. De schermgrotte gebruikte ik om een
+schermvullende kleurovergang te maken (op het groene en blauwe kleurkanaal), en
+de tijd waarde om een ruissignaal te maken (op het rode kleurkanaal):
+
+![](img/hello-fragment.png)
+
+Toen dit allemaal werkte vond ik het een goed moment om mijn tooling wat te
+verbeteren voor het schrijven en compileren van GLSL. Ik heb gekozen om de
+`glslc` 'compiler' te gebruiken, die GLSL omzet naar [SPIR-V][spirv]. Dit heb
+ik gedaan zodat ik GLSL compilatiewaarschuwingen krijg tijdens het bouwen van
+mijn complete applicatie inplaats van tijdens runtime, en zodat ik de C
+preprocessor kan gebruiken tijdens compileertijd, waarmee ik geen broncode hoef
+te bundelen met mijn applicatie. De compiler zelf werkt prima op zowel mijn
+desktop PC als mijn laptop, maar ik liep hier gelijk weer tegen verschillen
+tussen de Intel en NVIDIA graphics drivers aan.
+
+Ik heb er een uitgebereide [vraag op StackOverflow][so-spirv-reflection] over
+gesteld, en ben gewezen op het feit dat de SPIR-V specificatie geen eis stelt
+dat drivers die SPIR-V programma's laden reflectie moeten ondersteunen. Dit zou
+betekenen dat ik de uniform locaties van mijn fragment shader zou moeten
+hard-coden, of toch GLSL gebruiken zodat ik de uniform locaties kan opvragen
+via hun naam als string.
+
+Ik heb ook het build systeem iets uitgebereid om de SPIR-V binaries mee te
+linken met linker scripts en gegenereerde C headers om de data door te geven
+aan OpenGL functies. Dit was niet bijzonder spannend.
+
+Om verder te gaan met het maken van het effect dat in de eerste afbeelding in
+dit document te zien is, heb ik eerst geprobeerd de spiraalvorm in
+[Desmos][desmos-braids] na te maken. Dit was het makkelijkst te doen met een
+parametrische functie, wat een duur wiskunde woord is voor een functie die (in
+dit geval) een 2D punt geeft voor een willekeurige parameter (t). Deze functie
+bestaat uit het dynamische duo, de sinus en cosinus, die samen een cirkel
+maken. Bij deze cirkelvorm tel ik een kleinere 'snellere' cirkel op, en deze
+functie heeft parameters voor het aantal wikkelingen, en de grootte van de
+wikkelingen:
+
+[![](img/desmos-braids.png)][desmos-braids]
+
+Deze functie zou ontzettend snel en eenvoudig zijn om te implementeren op de
+CPU. Omdat de functie periodiek is kun je met alleen een `for`-lus genoeg
+punten uitrekenen om het te laten lijken alsof je een ononderbroken kromme
+tekent. Helaas moet zoveel mogelijk in dit project met OpenGL, dus heb ik deze
+functie als fragment shader geïmplementeerd. Dit is ontzettend inefficiënt,
+omdat je voor elke pixel de parameter t probeert terug te rekenen, inplaats van
+andersom. Hierdoor moet de functie een paar duizend keer uitgerekend worden per
+pixel. Helaas valt mijn visualizer hiermee buiten de duurzaamheidsdoelen van de
+vakbeschrijving.
+
+![](img/toy-braids.png)
+
+TODO:
+- waarom de framebuffer
+- hoe framebuffer
+- hoe kleur??
+
+[september]: https://www.youtube.com/watch?v=Gs069dndIYk
+[hellotriangle]: https://learnopengl.com/Getting-started/Hello-Triangle
+[spirv]: https://www.khronos.org/opengl/wiki/SPIR-V
+[so-spirv-reflection]: https://stackoverflow.com/a/78500726/5006337
+[desmos-braids]: https://www.desmos.com/calculator/yh3tuebwp8