Merge branch 'master' into gallery

pull/118/head
kynd 8 years ago
commit 94820c5d40

@ -0,0 +1,50 @@
# Einleitung
<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas>
Die oben abgebildeten Grafiken wurden auf ganz unterschiedliche Weise erstellt. Die linke Abbildung stammt aus den Händen des Malers Van Gogh, der die Farben in stundenlanger Arbeit Schicht für Schicht mit einem Pinsel aufgetragen hat. Die rechte Abbildung wurde dagegen innerhalb von Sekundenbruchteilen mit Hilfe von vier Punktmatrizen erzeugt: eine für Cyan, eine für Magenta, eine für Gelb und eine für Schwarz. Der entscheidende Unterschied: Das zweite Bild wurde nicht seriell erstellt, d.h. Strich für Strich, sondern parallel, alle Punkte zur gleichen Zeit.
Dieses Buch handelt von einer Computertechnik mit Namen *Fragment Shader*, die die digitale Erzeugung von Bildern revolutioniert und zu neuen Höhen geführt hat. Man kann ihre Erfindung ein wenig vergleichen mit dem Schritt von der manuellen Vervielfältigung einzelner Grafiken und Dokumente hin zur massenhaften Replikation durch Gutenbergs Druckerpresse.
![Gutenbergs Druckerpresse](gutenpress.jpg)
Fragment-Shader ermöglichen die vollständige Kontrolle über alle Bildpunkte, die als Grafik auf dem Bildschirm erscheinen. Und das mit ungeheurer Geschwindigkeit. Deshalb wird diese Technik mittlerweile in vielen Bereichen der Computergrafik angewandt, von Videofiltern auf Smartphones bis hin zu den neuesten fotorealistisch wirkenden 3D-Videospielen.
![Grafik aus dem Spiel „Journey“ von That Game Company](journey.jpg)
Die folgenden Kapitel wollen Dir zeigen, wie unglaublich schnell und leistungsfähig diese Technik ist, und wie Du sie im Rahmen von privaten und beruflichen Projekten einsetzen kannst.
## Für wen ist dieses Buch geeignet?
Dieses Buch wendet sich an kreative Programmierer, Spieleentwickler und Ingenieure, die bereits über eine gewisse Programmiererfahrung, sowie grundlegende Kenntnisse aus den Bereichen der linearen Algebra und der Trigonometrie verfügen. (Falls Du erst noch Programmieren lernen möchtest, empfehle ich Dir, mit [Processing](https://processing.org/) zu beginnen und anschließend mit diesem Buch fortzufahren.)
Die folgenden Kapitel werden Dir zeigen, wie Du Shader in Deinen Projekten einsetzen kannst, um die Qualität und die Geschwindigkeit bei der Erzeugung von Grafiken zu verbessern. GLSL-Shader (GLSL steht für „OpenGL Shading Language“) lassen sich auf einer Vielzahl von Hardwareplattformen und Betriebssystemen kompilieren und ausführen. Dadurch kannst Du das erlernte Wissen in jeder Umgebung einsetzen, die OpenGL, OpenGL ES oder WebGL unterstützt.
In anderen Worten, Du kannst Dein Know-how u.a. beim Malen mit [Processing](https://processing.org/), bei Anwendungen für [openFrameworks](http://openframeworks.cc/), interaktiven Installationen mit [Cinder](http://libcinder.org/), Webseiten mit [Three.js](http://threejs.org/) oder bei Spielen für iOS/Android nutzen.
## Welchen Aspekten widmet sich dieses Buch?
Dieses Buch konzentriert sich auf den Einsatz von GLSL-Pixel-Shadern. Zunächst erklären wir, was Shader sind, dann wenden wir uns der algorithmischen Erzeugung von Formen, Mustern, Texturen und Animationen zu. Du lernst die Grundlagen der Programmiersprache für OpenGL-Shader kennen und erfährst, wie man sie für konkrete Zwecke nutzt. Dazu zählt die Bildbearbeitung (Bildmanipulationen, Matrizenoperationen, Farbfilter und weitere Effekte), sowie Simulationen (Conways Game of Life, Reaktion und Diffusion von Chemikalien nach Gray-Scott, Erzeugung von Wasserwellen, die Nachbildung des Malens mit Wasserfarben, Erzeugung von Voronoi-Zellen und mehr). Zum Ende des Buches hin lernst Du fortschrittliche Techniken kennen, bei denen etwa mit Hilfe des sogenannten „Ray Marchings“ beeindruckende 2D-Grafiken aus 3D-Daten generiert werden.
*In jedem Kapitel gibt es interaktive Beispiele, mit denen Du vieles ausprobieren kannst.* Sobald du etwas am Programmcode änderst, erscheinen die daraus resultierenden Veränderungen an der erzeugten Grafik sofort auf dem Bildschirm. Die vorgestellten Konzepte sind teilweise abstrakt und auf den ersten Blick vielleicht ein wenig verwirrend. Aber mit Hilfe der interaktiven Beispiele kannst Du den Lernstoff leicht nachvollziehen. Je mehr Du ausprobierst, desto einfacher wird Dir das Lernen fallen.
Was dieses Buch nicht behandelt:
* Dies *ist kein * Buch über openGL oder webGL. OpenGL/webGL ist ein umfassenderes Thema als GLSL- oder Fragment-Shader. Wenn Du mehr über openGL/webGL lernen möchtest, empfehle ich Dir die folgenden Materialien: [OpenGL Einführung (Englisch)](https://open.gl/introduction), [Die achte Ausgabe des „OpenGL Programming Guide“ (Englisch)](http://www.amazon.com/OpenGL-Programming-Guide-Official-Learning/dp/0321773039/ref=sr_1_1?s=books&ie=UTF8&qid=1424007417&sr=1-1&keywords=open+gl+programming+guide) (auch bekannt als das „Red Book“) oder [„WebGL: Up and Running“ (Englisch)](http://www.amazon.com/WebGL-Up-Running-Tony-Parisi/dp/144932357X/ref=sr_1_4?s=books&ie=UTF8&qid=1425147254&sr=1-4&keywords=webgl)
* Das vorliegende Werk *ist außerdem kein* Mathematik-Buch. Obwohl wir bei vielen Techniken und Algorithmen auf Algebra und Trigonometrie zurückgreifen, werden die mathematischen Grundlagen nicht an jeder Stelle vollständig in allen Details erklärt. Bei Fragen dazu empfehle ich Dir eines der folgenden Bücher: [Dritte Ausgabe von „Mathematics for 3D Game Programming and Computer Graphics“ (Englisch)](http://www.amazon.com/Mathematics-Programming-Computer-Graphics-Third/dp/1435458869/ref=sr_1_1?ie=UTF8&qid=1424007839&sr=8-1&keywords=mathematics+for+games) oder [Zweite Ausgabe von „Essential Mathematics for Games and Interactive Applications“ (Englisch)](http://www.amazon.com/Essential-Mathematics-Games-Interactive-Applications/dp/0123742978/ref=sr_1_1?ie=UTF8&qid=1424007889&sr=8-1&keywords=essentials+mathematics+for+developers).
## Was benötigst Du, um loszulegen?
Nicht viel! Wenn Du auf Deinem Rechner, Smartphone oder Tablet einen modernen Webbrowser hast, der WebGL unterstützt (etwa Chrome, Firefox oder Safari), und eine Internetverbindung besteht, dann drücke einfach auf die Schaltfläche für das nächste Kapitel am Ende dieser Seite.
Alternativ kannst Du auch:
- [Eine Offline-Fassung dieses Buches erstellen](https://thebookofshaders.com/appendix/?lan=de)
- [Die Beispielprogramme aus diesem Buch direkt auf einem RaspberryPi ausführen (ohne Internet-Browser)](https://thebookofshaders.com/appendix/?lan=de)
- [Eine PDF-Datei mit diesem Buch erzeugen, um es auszudrucken](https://thebookofshaders.com/appendix/?lan=de)
- Die [Online-Ablage dieses Buches](https://github.com/patriciogonzalezvivo/thebookofshaders) bei GitHub nutzen, um Fehler zu melden und Programmcode mit anderen Lesern zu teilen.

@ -0,0 +1,48 @@
# Einstieg
## Was ist ein Fragment-Shader?
Im vorangegangenen Kapitel haben wir Fragment-Shader als eine Art Gutenbergsche Druckerpresse für Grafiken beschrieben. Nun, wie kommen wir darauf? Und vor allem: Was genau soll das sein, ein „Shader“?
![Von Brief-für-Brief zu Seite-für-Seite. Rechts: William Blades (1891), links Rolt-Wheeler (1920).](print.png)
Falls Du schon Erfahrung mit der Erstellung von Computergrafiken gesammelt hast, kennst Du bestimmt die folgende Vorgehensweise: Man malt per Programmbefehl Kreise, Rechtecke, Dreiecke und Linien, damit auf dem Bildschirm nach und nach die gewünschte Grafik entsteht. Dieser Prozess erinnert stark an das Verfassen eines Dokuments per Hand, indem man einzelne Zeichen-Operationen Schritt für Schritt abarbeitet.
Auch Shader verkörpern eine Abfolge von Operationen, doch hier werden diese Operationen gleichzeitig für jeden Bildpunkt (Pixel) auf der Zeichenfläche ausgeführt. Das hat zur Folge, dass der Programmcode des Shaders in Abhängigkeit von der Lage des jeweils bearbeiteten Bildpunktes unterschiedlich agieren muss. Der Shader arbeitet dabei als eine Funktion, die die Koordinaten des jeweiligen Bildpunktes erhält und als Ergebnis die Farbe für diesen Bildpunkt zurückliefert. Ist der Shader einmal kompiliert, läuft dieser Prozess unglaublich schnell und für sehr viele Bildpunkte gleichzeitig ab.
![Verschiebbare Lettern mit Chinesischen Symbolen](typepress.jpg)
## Warum arbeiten Shader schnell?
Diese Frage beantwortet sich, wenn wir uns das Prinzip der *parallelen Verarbeitung* anschauen.
Stelle Dir den Prozessor in Deinem Computer als eine große Pipeline vor und jede zu bearbeitende Aufgabe als etwas, das durch die Pipeline fließt - wie an einem Fließband innerhalb einer Fabrik. Einige Aufgaben sind größer als andere, weshalb ihre Abarbeitung mehr Zeit und mehr Energie in Anspruch nimmt. Wir sagen dann, diese Aufgaben benötigen mehr „Prozessorleistung“. Der Aufbau des Computers zwingt die verschiedenen Aufgaben dazu, eine nach der anderen durch die Pipeline zu strömen. Die nächste Aufgabe ist an der Reihe, sobald die vorangehende Aufgabe erfolgreich abgearbeitet wurde. Moderne Prozessoren verfügen in der Regel über mehrere Kerne (typischerweise zwei, vier oder acht), von denen jeder wie eine Pipeline arbeitet, so dass mehrere Ströme von Aufgaben (engl. „Threads“) gleichzeitig abgearbeitet werden können.
![CPU](00.jpeg)
Videospiele und leistungsstarke Grafikanwendungen benötigen in der Regel wesentlich mehr Prozessorleistung als andere Computerprogramme. Weil sie grafikorientiert arbeiten, müssen diese Programme eine enorme Anzahl an Pixel-Operationen ausführen. Jeder einzelne Bildpunkt muss individuell berechnet werden, und bei 3D-Anwendungen kommen noch perspektivische Verzerrungen sowie das Spiel von Licht und Schatten hinzu.
Kommen wir noch einmal auf das Bild einer Pipeline zurück. Jeder einzelne Bildpunkt verkörpert eine Rechenaufgabe, die durch die Pipeline abgearbeitet werden muss. Einzeln genommen macht das nicht viel Arbeit - der enorme Aufwand entsteht erst durch die schiere Masse an Pixeln auf dem Bildschirm. Schon bei einer Auflösung von 800 x 600 Bildpunkten müssen pro Bild 480.000 Pixels berechnet werden. Für eine flüssige Darstellung mit 30 Bildern pro Sekunde ergeben sich also bereits 14.400.000 Berechnungen pro Sekunde. Das ist eine Dimension, bei der auch moderne Prozessoren an ihre Grenzen stoßen. Und bei einem hochauflösenden Retina-Display mit 2880 x 1800 Bildpunkten und einer Wiederholrate von 60 Bildern pro Sekunde kommen sogar 311.040.000 Berechnungen pro Sekunde zusammen. Fragt sich also, wie ein Computersystem dies bewältigen kann?
![](03.jpeg)
Hier kommt die gleichzeitige - parallele - Berechnung möglichst vieler Bildpunkte ins Spiel. An die Stelle weniger großer und immens leistungsfähiger Pipelines (sprich: Mikroprozessoren) treten viele kleine, einfachere Prozessoren, die parallel arbeiten. Sie bilden den Kern einer sogenannten „Graphic Processing Unit“, kurz GPU.
![GPU](04.jpeg)
Stelle Dir eine solche GPU wie ein Feld aus lauter Pipelines vor - eine neben der anderen. Jeder Bildpunkt entspricht einem Tischtennisball, der durch eine solche Pipeline hindurchmuss. 14.400.000 Bälle pro Sekunde sind wahrscheinlich zu viel für jede einzelne noch so dicke Pipeline. Hat man aber ein Feld aus 800 x 600 kleinen Pipelines, muss jede nur 30 Bälle pro Sekunde verarbeiten, damit man eine flüssige Darstellung auf dem Bildschirm erhält. Und das ist durchaus machbar. Gleiches gilt für höhere Auflösungen und größere Bildwiederholraten: Je mehr Pipelines parallel arbeiten, desto mehr Bildpunkte können sie pro Zeiteinheit bewältigen.
Die enorme Leistung einer solchen GPU rührt aber auch aus einer anderen Quelle: Viele für die Grafikberechnung unverzichtbare mathematische Operationen lassen sich direkt in der Hardware, in jeder einzelnen Pipeline, parallel ausführen. Es wird also keine zusätzliche Software benötigt, um diese Berechnungen in mehreren Schritten aus einfachen Grundoperationen zusammenzusetzen. Das gilt beispielsweise für die wichtigen trigonometrischen Funktionen und für Matrizenoperationen. Das bringt die Darstellung zusätzlich auf Trab.
## Was ist GLSL?
GLSL ist die Abkürzung für „OpenGL Shading Language“, einem weit verbreiteten Standard für Shader-Programme, mit dem sich die folgenden Kapitel beschäftigen. Es gibt auch andere Arten von Shadern, je nach Grafikhardware und Betriebssystem. Wir orientieren uns hier an der wichtigen OpenGL-Spezifikation, die von der [Khronos Gruppe](https://www.khronos.org/opengl/) erarbeitet wurde. Wenn man die Geschichte von OpenGL kennt, kann man einige der teilweise etwas merkwürdigen Konstrukte und Konventionen besser verstehen. Allen Interessierten empfehle ich deshalb einen Blick auf [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html).
## Warum sind Shader so anspruchsvoll?
Mein reicher Onkel Willi aus Amerika sagte früher immer zu mir: „Denk dran, Junge, unglaublich viel Power bedeutet immer auch unglaublich viel Verantwortung“. Dies gilt in gewisser Weise auch für das Feld des „Parallel Computings“. Die enorme Leistungsfähigkeit moderner GPUs erzeugt ihre eigenen Regeln und Abhängigkeiten. Und die wollen beachtet werden, damit wir nicht über das Ziel hinausschießen.
Damit jede Pipeline innerhalb der GPU parallel an ihrer Aufgabe arbeiten kann, muss sie unabhängig von den anderen Pipelines sein. Sie ist quasi blind dafür, was die anderen gerade tun. Dies bringt u.a. die Einschränkung mit sich, dass alle Daten nur in eine Richtung fließen können. Es ist praktisch unmöglich, auf die Ergebnisse einer anderen Pipeline einzugehen, deren Ergebnis abzurufen und damit eine dritte Pipeline zu füttern.
Außerdem hält die GPU ihre zahlreichen Mikroprozessoren (Pipelines) ständig beschäftigt. Sobald eine Pipeline mit der Berechnung der Farbe für einen Bildpunkt fertig ist, wird sie auch schon mit dem nächsten Bildpunkt „gefüttert“. Aus Sicht des Shader-Programms gibt es quasi kein Vorher und Nachher, sondern immer nur den aktuell zu berechnenden Bildpunkt. Das Shader-Programm in jeder Pipeline ist also nicht nur blind für alle anderen, sondern auch ohne Erinnerung für das Gewesene. Das ist ein Teil der Herausforderung, die die Entwicklung von Shadern bei Programmieranfängern nicht unbedingt beliebt macht.
Aber keine Angst! In den folgenden Kapiteln werden wir uns Schritt für Schritt von einfachen Shadern hin zu komplexen Shadern voran arbeiten. Sofern Du diesen Text mit einem modernen Browser liest, wirst Du ganz einfach mit den zahlreichen interaktiven Beispielprogrammen experimentieren können. Also, lass uns gleich anfangen, indem Du auf die „*Next*“-Schaltfläche unten auf der Seite klickst.

@ -15,7 +15,7 @@ Shaders are also a set of instructions, but the instructions are excecuted all a
To answer this, I present the wonders of *parallel processing*.
Imagine the CPU of your computer as a big industrial pipe, and every task as something that passes through it - like a factory line. Some tasks are bigger than others, which means they require more time and energy to deal with. We say they require more processing power. Because of the architecture of computers the jobs are forced to run in a series; each job has to be finished one at a time. Modern computers usually have groups of four processors that work like these pipes, completing tasks one after another to keeping things running smoothly. Each pipe is also known as *thread*.
Imagine the CPU of your computer as a big industrial pipe, and every task as something that passes through it - like a factory line. Some tasks are bigger than others, which means they require more time and energy to deal with. We say they require more processing power. Because of the architecture of computers the jobs are forced to run in a series; each job has to be finished one at a time. Modern computers usually have groups of four processors that work like these pipes, completing tasks one after another to keeping things running smoothly. Each pipe is also known as a *thread*.
![CPU](00.jpeg)
@ -45,4 +45,4 @@ In order to run in parallel every pipe, or thread, has to be independent from ev
Also the GPU keeps the parallel micro-processor (the pipes) constantly busy; as soon as they get free they receive new information to process. It's impossible for a thread to know what it was doing in the previous moment. It could be drawing a button from the UI of the operating system, then rendering a portion of sky in a game, then displaying the text of an email. Each thread is not just **blind** but also **memoryless**. Besides the abstraction required to code a general function that changes the result pixel by pixel depending on its position, the blind and memoryless constraints make shaders not very popular among beginning programmers.
Don't worry! In the following chapters, we will learn step-by-step how to go from simple to advanced shading computations. If you are reading this with a modern browser, you will appreciate playing with the interactive examples. So let's not delay the fun any longer and press *Next >>* to jump into the code!
Don't worry! In the following chapters, we will learn step-by-step how to go from simple to advanced shading computations. If you are reading this with a modern browser, you will appreciate playing with the interactive examples. So let's not delay the fun any longer and press *Next >>* to jump into the code!

@ -0,0 +1,53 @@
## Hallo Welt
Beim Erlernen einer neuen Programmiersprache beginnt man häufig mit dem berühmten „Hello world!“-Beispiel. Dabei handelt es sich um einen simplen Einzeiler, der die Meldung „Hello world!“ auf den Bildschirm bringt - als Gruß an die Welt und als Ausdruck der Vorfreude auf die kommenden Möglichkeiten.
In der Welt der Shader-Programmierung ist die Textausgabe eine zu komplizierte Angelegenheit, um gleich damit zu beginnen. Stattdessen wollen wir eine leuchtende Farbe als Willkommensgruß auf den Bildschirm zaubern.
<div class="codeAndCanvas" data="hello_world.frag"></div>
Falls Du dieses Buch in einem Internet-Browser liest, ist der obige Programmcode interaktiv. Du kannst in das Listing hineinklicken und jeden Teil des Programmcodes ändern. Deine Änderungen werden sofort innerhalb der Zeichenfläche sichtbar, weil der Shader-Code automatisch kompiliert und ausgeführt wird. Versuche es doch einfach einmal, indem Du die Zahlenwerte in der *Programmzeile 6* änderst.
Obwohl diese wenigen, einfachen Programmzeilen noch nicht nach viel aussehen, können wir daraus bereits einige Erkenntnisse gewinnen:
1. Shader-Programme verfügen über genau eine ```main```-Funktion, die an ihrem Ende einen Farbcode zurückliefert. Das erinnert stark an die Programmiersprache C, nur dass es dort nicht immer um Farbcodes geht.
2. Der berechnete Farbwert wird für die Rückgabe in die reservierte globale Variable ```gl_FragColor``` eingetragen.
3. Die stark von C beeinflusste Programmiersprache für Shader verfügt über eingebaute *Variablen* (so wie ```gl_FragColor```), *Funktionen* und *Datentypen*. Im obigen Beispiel sehen wir bereits den Datentyp ```vec4```, der einen vierdimensionalen Vektor aus Fließkommazahlen repräsentiert. Im weiteren Verlauf des Buches werden wir noch die Typen ```vec3``` und ```vec2``` kennen lernen, ebenso die wichtigen Typen ```float```, ```int``` und ```bool```.
4. Wenn wir uns den ```vec4``` Datentyp im obigen Beispiel genau anschauen, können wir bereits erahnen, dass die vier Zahlenwerte für die Farbkanäle Rot, Grün, Blau und Alpha (ein Maß für die Deckkraft) stehen. Außerdem erkennen wir, dass diese Werte offensichtlich normalisiert sind, sich also zwischen ```0.0``` und ```1.0``` bewegen. Später werden wir noch sehen, dass es uns diese Normalisierung vereinfacht, die Inhalte von Variablen auf Farbwerte *abzubilden*.
5. Eine weiteres aus C bekanntes Element sind die Präprozessor-Makros, die auch in unserem obigen Beispiel auftauchen. Mit ihrer Hilfe lassen sich Konstanten definieren (```#define```) und konditionale Festlegungen treffen (mit ```#ifdef``` und ```#endif```). Alle diese Makrobefehle beginnen mit einer Raute (```#```). Ihre Auswertung erfolgt als erster Schritt noch vor der eigentlichen Kompilierung des Shaders. Das Ergebnis dieser Auswertung bestimmt jeweils, welche Zeilen und Ausdrücke tatsächlich in den Programmcode einfließen, der anschließend kompiliert wird. In unserem obigen Beispiel wird die *Programmzeile 2* beispielsweise nur dann übernommen, wenn das Symbol ```GL_ES``` definiert ist. Dies ist in der Regel nur in Umgebungen auf mobilen Geräten der Fall, d.h. wenn das obige Programm beispielsweise auf einem Smartphone kompiliert wird, ist die Zeile 2 darin vorhanden und wirkt sich entsprechend aus. Beim Kompilieren auf einem Laptop oder PC taucht die Zeile 2 aber gar nicht auf, weil dort auch das Symbol ```GL_ES``` nicht definiert ist.
6. Fließkomma-Datentypen sind ganz entscheidend für die Berechnungen innerhalb von Shadern. Deshalb spielt die *Genauigkeit* dieser Operationen eine wichtige Rolle. Eine geringere Genauigkeit bedeutet weniger Aufwand und geht deshalb mit einer schnelleren Berechnung einher. Der Preis dafür sind allerdings Einbußen bei der Qualität der Berechnungen. Wenn man will, kann man die Genauigkeit jeder einzelnen Fließkommavariablen genau festlegen. Meist unterscheidet man jedoch grundsätzlich, je nach den Möglichkeiten der Plattform, auf der ein Shader zur Ausführung kommen soll. So setzen wir hier in der zweiten Programmzeile die Genauigkeit auf Medium (```precision mediump float;```), wenn der Shader auf einem Mobilgerät kompiliert wird. Darüber hinaus gibt es noch die Genauigkeitsstufen „niedrig“ (```precision lowp float;```) und „hoch“ (```precision highp float;```). Letzteres ist auf vielen Plattformen die Vorgabe, sofern wir nichts Anderes festlegen.
7. Die letzte und für die Praxis vielleicht wichtigste Erkenntnis aus dem obigen Programmcode ist, dass wir Fließkommawerte immer mit einem Punkt („.“) versehen sollten, auch wenn der Nachkommateil leer bleibt (Null ist). Denn sonst macht der Compiler möglicherweise Integer-Werte (Ganzzahlen) daraus, und das kann während der Ausführung des Shaders zu hässlichen Programmfehlern führen. Die Zeichenfläche bleibt dann einfach weiß, weil es nicht weitergeht. Wenn du guten und auf vielen Shader-Plattformen ausführbaren Code entwickeln möchtest, gewöhne Dir die Kennzeichnung als Fließkommazahl durch den Punkt am besten gleich an. Denn der folgende Programmcode wird beispielsweise auf einigen Shader-Plattformen funktionieren, auf anderen hingegen nicht:
```glsl
void main() {
gl_FragColor = vec4(1,0,0,1); // potenzielle Fehlerquelle!
}
```
So, wo wir nun die wichtigen Elemente unseres kleinen „Hello world!“-Programms beschrieben haben, ist es an der Zeit, mit Veränderungen am Programmcode zu experimentieren. Du wirst feststellen, dass sich das Programm bei Syntaxfehlern oder unbekannten Befehlen weigert, zu kompilieren, und die Zeichenfläche deshalb weiß bleibt. Es gibt einige interessante Dinge, die Du direkt einmal ausprobieren kannst, beispielsweise:
* Versuche, die Fließkommazahlen durch Ganzzahlen zu ersetzen. Dann wirst Du unmittelbar feststellen, ob Deine aktuelle Umgebung/Grafikkarte damit umgehen kann.
* Versuche, die *Programmzeile 6* auszukommentieren, und schau was passiert, wenn der Code dadurch keinen Farbwert zurückliefert.
* Versuche, eine zusätzliche Funktion in den Programmcode einzufügen, die eine von Dir gewählte Farbe zurückliefert und rufe diese Funktion innerhalb von ```main()``` auf. Dazu ein Tipp: Hier folgt der Programmcode für eine Funktion, die Rot zurückliefert:
```glsl
vec4 red(){
return vec4(1.0,0.0,0.0,1.0);
}
```
* Es gibt verschiedene Wege, um einen Wert vom Typ ```vec4``` zu konstruieren. Versuche, weitere Wege zu entdecken. So geht es zum Beispiel auch:
```glsl
vec4 color = vec4(vec3(1.0,0.0,1.0),1.0);
```
Obwohl dieses „Hello world!“-Programm noch nicht so wahnsinnig aufregend daherkommt, ist es doch das simpelste Beispiel aus der Welt der Shader. Wir beeinflussen damit die Farbe aller Bildpunkte innerhalb unserer Zeichenfläche. In den nun folgenden Kapiteln werden wir die Farbe der einzelnen Bildpunkte aufgrund von zwei unterschiedlichen Arten von Eingabewerten steuern: Ihrer Position (d.h. die Lage des zu bearbeitenden Pixels innerhalb der Zeichenfläche) und der Zeit (d.h. der Zeitspanne, die seit dem Laden einer Seite vergangen ist).

@ -22,7 +22,7 @@ Although these simple lines of code don't look like a lot, we can infer substant
6. Float types are vital in shaders, so the level of *precision* is crucial. Lower precision means faster rendering, but at the cost of quality. You can be picky and specify the precision of each variable that uses floating point. In the first line (```precision mediump float;```) we are setting all floats to medium precision. But we can choose to set them to low (```precision lowp float;```) or high (```precision highp float;```).
7. The last, and maybe most important, detail is that GLSL specs dont guarantee that variables will be automatically casted. What does that mean? Manufacturers have different approaches to accelerate graphic card processes but they are forced to guarantee minimum specs. Automatic casting is not one of them. In our “hello world!” example ```vec4``` has floating point precision and for that it expects to be assigned with ```floats```. If you want to make good consistent code and not spend hours debugging white screens, get used to putting the point ( ```.``` ) in your floats. This kind of code will not always work:
7. The last, and maybe most important, detail is that GLSL specs dont guarantee that variables will be automatically casted. What does that mean? Manufacturers have different approaches to accelerate graphics card processes but they are forced to guarantee minimum specs. Automatic casting is not one of them. In our “hello world!” example ```vec4``` has floating point precision and for that it expects to be assigned with ```floats```. If you want to make good consistent code and not spend hours debugging white screens, get used to putting the point ( ```.``` ) in your floats. This kind of code will not always work:
```glsl
void main() {

@ -0,0 +1,61 @@
## Uniforms
Wir haben bereits gesehen, wie die GPU eine große Anzahl von parallelen Aufgaben (engl. *Threads*) verwaltet. Jeder Thread übernimmt die Berechnung des Farbwerts für einen Pixel, also für einen kleinen Teil der gesamten Grafik. Obwohl er dabei blind für die anderen Threads ist, muss es einen Weg geben, wie die CPU bestimmte Daten an alle Threads übermitteln kann. Aufgrund der Architektur einer Grafikkarte müssen diese Daten für alle ausgeführten Threads einheitlich (engl. *uniform*) und nur lesbar (engl. *read-only*) sein. Jeder Thread erhält also die gleichen Daten, die er nicht verändern kann.
Man bezeichnet diese Daten deshalb als ```uniform```. Es gibt sie in den wichtigsten Datentypen, die GLSL unterstützt: ```float```, ```vec2```, ```vec3```, ```vec4```, ```mat2```, ```mat3```, ```mat4```, ```sampler2D``` und ```samplerCube```. Uniforms werden gemeinsam mit ihrem jeweiligen Datentyp am Anfang eines Shader-Programms definiert, sofern man darauf Bezug nehmen möchte. Dies geschieht in der Regel gleich nachdem man die gewünschte Genauigkeit für alle Fließkommaoperationen in dem Programm festgelegt hat.
```glsl
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution; // Groesse der Malfläche (canvas) in Pixeln (Breite, Hoehe)
uniform vec2 u_mouse; // Mausposition über der Malfleache in Pixeln (X, Y)
uniform float u_time; // Zeit in Sekunden seit dem Start des Bildaufbaus
```
Man kann sich Uniforms als eine Brücke zwischen der CPU und der GPU vorstellen. Ihre Bezeichnung hängt von der jeweiligen Implementation der GLSL-Umgebung ab. Im Rahmen dieses Buches verwenden wir die folgenden Namen: ```u_time``` , ```u_resolution``` und ```u_mouse```. Wir folgen damit der Konvention, die Variablennamen jeweils mit dem Präfix ```u_``` beginnen zu lassen, damit sie im Programmcode deutlich als Uniforms erkennbar sind. In anderen Umgebungen für die Entwicklung von Shadern tragen sie andere Namen, wie beispielsweise bei [ShaderToy.com](https://www.shadertoy.com/). Dort heißt es:
```glsl
uniform vec3 iResolution; // Groesse der Malflaeche
uniform vec4 iMouse; // Mausposition
uniform float iGlobalTime; // Zeit seit dem Start
```
Aber nun genug geredet. Lass uns die Uniforms in Aktion betrachten. Der folgende Programmcode nutzt ```u_time``` - die Anzahl der Sekunden, seitdem der Shader gestartet wurde - in Verbindung mit einer Sinus-Funktion, um die Intensität der Rotfärbung der Malfläche pulsieren zu lassen.
<div class="codeAndCanvas" data="time.frag"></div>
Wie Du siehst, hält GLSL noch einige Überraschungen bereit. Die GPU unterstützt in der Hardware realisierte Winkel-, Trigonometrie- und Exponential-Funktionen. Hier einige dieser Funktionen in der Übersicht: [```sin()```](../glossary/?search=sin), [```cos()```](../glossary/?search=cos), [```tan()```](../glossary/?search=tan), [```asin()```](../glossary/?search=asin), [```acos()```](../glossary/?search=acos), [```atan()```](../glossary/?search=atan), [```pow()```](../glossary/?search=pow), [```exp()```](../glossary/?search=exp), [```log()```](../glossary/?search=log), [```sqrt()```](../glossary/?search=sqrt), [```abs()```](../glossary/?search=abs), [```sign()```](../glossary/?search=sign), [```floor()```](../glossary/?search=floor), [```ceil()```](../glossary/?search=ceil), [```fract()```](../glossary/?search=fract), [```mod()```](../glossary/?search=mod), [```min()```](../glossary/?search=min), [```max()```](../glossary/?search=max) sowie [```clamp()```](../glossary/?search=clamp).
Nun ist es an der Zeit, mit dem obigen Shader zu experimentieren.
* Versuche, die Frequenz zu verlangsamen, mit der sich die Rotfärbung ändert, bis dieser Prozess kaum noch wahrnehmbar ist.
* Beschleunige die Frequenz, bis man fast nur noch eine Farbe sieht.
* Experimentiere mit periodischen Änderungen auch in den anderen Farbkanälen (Grün und Blau), so dass sich interessante Farbspiele und Muster ergeben.
## gl_FragCoord
So, wie GLSL das Resultat eines Shader-Durchlaufs standardmäßig in der Variable ```vec4 gl_FragColor``` erwartet, liefert es uns auch standardmäßig einen Eingabewert: Die Koordinate des jeweils zu bearbeitenden Bildpunkts in der Variable ```vec4 gl_FragCoord```. Im Englischen spricht man in diesem Zusammenhang auch von einem *screen fragment*, weil es sich nur um einen kleinen Teil der Zeichenfläche handelt, eben ein „Fragment“. Diese Variable kann man nicht als ```uniform``` bezeichnen, weil ihr Inhalt bzw. ihr Wert mit jedem Shader-Durchlauf variiert. Man spricht deshalb auch von einem *varying*.
<div class="codeAndCanvas" data="space.frag"></div>
Im obigen Programmcode *normalisieren* wir zunächst die Koordinate des zu bearbeitenden Fragments, indem wir sie durch die Auflösung der Zeichenfläche teilen. Auf diese Weise bilden wir die *X-* und *Y-Ordinate* jeweils auf den Wertebereich zwischen ```0.0``` und ```1.0``` ab. Das erleichtert es uns, diese Ordinaten auf Farbwerte für den Rot- und den Grün-Kanal zu übertragen. Schließlich müssen sich diese Farbwerte in GLSL auch immer jeweils zwischen ```0.0``` und ```1.0``` bewegen.
In der Welt der Shader-Programmierung haben wir nicht so viele Möglichkeiten zum Debugging, abgesehen davon, dass wir dem gerade berechneten Bildpunkt intensive Farbtöne zuweisen können. Das entstehende Bild lässt dann Rückschlüsse auf die Abläufe innerhalb des Shaders zu. Du wirst im Laufe dieses Buches entdecken, dass die Shader-Programmierung manchmal dem Versuch gleicht, ein Modellschiff in eine Flasche zu pressen. Denn das ist gleichermaßen schwierig, aber auch schön anzusehen und in jedem Fall lohnend.
![](08.png)
Jetzt ist es an der Zeit für eine kleine Herausforderung in Bezug auf das Verständnis des obigen Programmcodes.
* Kannst du ausmachen, wo sich die Koordinate ```(0.0,0.0)``` innerhalb unserer Zeichenfläche befindet?
* Und wo liegen wohl die Koordinaten ```(1.0,0.0)```, ```(0.0,1.0)```, ```(0.5,0.5)``` und ```(1.0,1.0)```? Die Farben der jeweiligen Bildpunkte verraten es Dir!
* Gelingt es Dir, die aktuelle Mausposition aus dem Uniform ```u_mouse``` einzubeziehen? Denke daran, dass sich die Angaben in diesem Uniform auf Pixel beziehen und zunächst nicht normalisiert sind. Kannst Du den Programmcode so gestalten, dass die erzeugten Farben auf die Mausbewegung reagieren?
* Fällt Dir ein Weg ein, wie man die Farbgestaltung auf interessante Weise durch die Einbeziehung von ```u_time``` und ```u_mouse``` dynamisieren kann?
Nach all diesen Übungen fragst Du Dich vielleicht, wo Du Deine neuen Shader-Kenntnisse sonst noch ausprobieren kannst. Im folgenden Kapitel zeigen wir, wie man Shader in *three.js*, *Processing* und *openFrameworks* zum Laufen bringt.

@ -0,0 +1,190 @@
## Ausführung Deiner Shader
Beim Schreiben dieses Buches und im Rahmen meiner künstlerischen Tätigkeit habe ich eine Sammlung von Tools entwickelt, mit deren Hilfe man Shader programmieren, anzeigen, teilen und kuratieren kann. Dieses Tools laufen auf Linux Desktops, Rechnern mit MacOS, dem [Raspberry Pi](https://www.raspberrypi.org/) und auf Internet-Browsern. Sie sorgen dafür, dass Du Deine Shader dort nutzen kannst, ohne etwas an deren Programmcode verändern zu müssen.
**Anzeige**: Alle Live-Beispiele in diesem Buch werden mit [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas) angezeigt. Dieses Tool macht es unglaublich einfach, Shader ohne weitere Umstände im Internet-Browser auszuführen.
```html
<canvas class="glslCanvas" data-fragment-url="yourShader.frag" data-textures="yourInputImage.png" width="500" height="500"></canvas>
```
Wie Du oben siehst, benötigt man lediglich ein ```canvas``` HTML-Element mit der Klassenzuweisung ```class="glslCanvas"``` und eine URL als Verweis auf Deine Shader-Datei im Attribut ```data-fragment-url```. Mehr darüber kannst Du [hier](https://github.com/patriciogonzalezvivo/glslCanvas) erfahren.
Vielleicht geht es Dir wie mir, und Du möchtest Deine Shader direkt aus der Kommandozeile starten. In diesem Fall solltest Du Dir einmal den [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) anschauen. Diese Anwendung ermöglicht es Dir, Shader aus ```bash```-Skripten oder aus der Unix-Pipeline heraus zu starten, ganz ähnlich wie dies mit [ImageMagick](http://www.imagemagick.org/script/index.php) möglich ist. Außerdem bietet der [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) eine großartige Möglichkeit, Shader auf Deinem [Raspberry Pi](https://www.raspberrypi.org/) zu kompilieren. Das ist auch der Grund, warum das Projekt [openFrame.io](http://openframe.io/) dieses Tool für die Präsentation von Computerkunst nutzt. Mehr über diese Anwendung kannst Du [hier](https://github.com/patriciogonzalezvivo/glslViewer) erfahren.
```bash
glslViewer deinShader.frag deineEingabeGrafik.png -w 500 -h 500 -s 1 -o deineAusgabeGrafik.png
```
**Entwickeln**: Um die Entwicklung von Shadern im Internet-Browser zu ermöglichen, habe ich einen Online-Editor mit dem Namen [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor) entwickelt. Dieser Editor kommt bei den Live-Beispielen in diesem Buch zum Einsatz. Er bringt eine Reihe praktischer Widgets mit, die Dich beim Experimentieren mit dem Shader-Code unterstützen. Du kannst diesen Editor auch als eigenständige Web-Anwendung über die URL [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/) ausführen lassen. Mehr über diesen Editor erfährst Du [hier](https://github.com/patriciogonzalezvivo/glslEditor).
![](glslEditor-01.gif)
Wenn Du lieber offline statt online mit [SublimeText](https://www.sublimetext.com/) arbeitest, kannst Du dieses [Paket für den glslViewer](https://packagecontrol.io/packages/glslViewer) installieren. Mehr darüber erfährst Du [hier](https://github.com/patriciogonzalezvivo/sublime-glslViewer).
![](glslViewer.gif)
**Teilen**: Du kannst Deine Shader direkt aus dem Online-Editor ([editor.thebookofshaders.com/](http://editor.thebookofshaders.com/)) heraus mit anderen teilen. Sowohl die eingebettete als auch die eigenständige Variante des Editors verfügen über eine *Export*-Schaltfläche. Sie liefert Dir eine einzigartige URL als Referenz auf Deinen Shader. Diese URL kannst Du dann an andere weitergeben. Außerdem bietet der Editor die Möglichkeit, Deine Shader zur Veröffentlichung direkt an das Projekt [openFrame.io](http://openframe.io/) zu senden.
![](glslEditor-00.gif)
**Kuratieren**: Deinen Shader-Code mit anderen zu teilen ist nur der Anfang. Du kannst Deine Shader auch als Werke der Computerkunst veröffentlichen. Jenseits der Weitergabe an das Projekt [openFrame.io](http://openframe.io/), habe ich ein Tool entwickelt, mit dem man Shader-Programme in eine Galerie innerhalb einer Webseite einbetten kann. Der Name dieses Tools lautet passenderweise [glslGallery](https://github.com/patriciogonzalezvivo/glslGallery). Mehr darüber erfährst Du [hier](https://github.com/patriciogonzalezvivo/glslGallery).
![](glslGallery.gif)
## Ausführen von Shadern in Deiner bevorzugten Umgebung
Falls Du bereits Erfahrung mit der Programmierung in einer Umgebung wie [Processing](https://processing.org/), [three.js](http://threejs.org/) oder [OpenFrameworks](http://openframeworks.cc/) gesammelt hast, möchtest Du Deine Shader vielleicht in dieser Umgebung ausführen lassen. Die folgenden Codebeispiele zeigen Dir, wie man Shader unter Verwendung der gleichen Uniforms, die wir in diesem Buch verwenden, in diesen Umgebungen ausführen kann. (In der [GitHub-Ablage dieses Kapitels](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04) findest Du den gesamten Sourcecode für die Einbindung von Shadern unter den drei genannten Umgebungen.)
### Ausführung unter **three.js**
Der brillante und äußerst bescheidene Ricardo Cabello (aka [MrDoob](https://twitter.com/mrdoob) ) hat zusammen mit [Gleichgesinnten](https://github.com/mrdoob/three.js/graphs/contributors) eines der wahrscheinlich populärsten Frameworks für WebGL mit dem Namen [three.js](http://threejs.org/) entwickelt. Du findest dort viele Beispiele, Tutorials und Bücher, die Dir zeigen, wie Du diese JavaScript-Bibliothek zur Erstellung cooler 3D-Grafiken nutzen kannst.
Hier folgt ein Beispiel für den HTML- und JS-Code, den Du für Deine ersten Experimente mit Shadern unter *three.js* benötigst. Bitte beachte das Script unter dem HTML-Tag ```id="fragmentShader"```. Dort kannst Du Deine Shader aus dem vorliegenden Buch einfügen.
```html
<body>
<div id="container"></div>
<script src="js/three.min.js"></script>
<script id="vertexShader" type="x-shader/x-vertex">
void main() {
gl_Position = vec4( position, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec2 u_resolution;
uniform float u_time;
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
gl_FragColor=vec4(st.x,st.y,0.0,1.0);
}
</script>
<script>
var container;
var camera, scene, renderer;
var uniforms;
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.Camera();
camera.position.z = 1;
scene = new THREE.Scene();
var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
uniforms = {
u_time: { type: "f", value: 1.0 },
u_resolution: { type: "v2", value: new THREE.Vector2() },
u_mouse: { type: "v2", value: new THREE.Vector2() }
};
var material = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
} );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
container.appendChild( renderer.domElement );
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
document.onmousemove = function(e){
uniforms.u_mouse.value.x = e.pageX
uniforms.u_mouse.value.y = e.pageY
}
}
function onWindowResize( event ) {
renderer.setSize( window.innerWidth, window.innerHeight );
uniforms.u_resolution.value.x = renderer.domElement.width;
uniforms.u_resolution.value.y = renderer.domElement.height;
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
uniforms.u_time.value += 0.05;
renderer.render( scene, camera );
}
</script>
</body>
```
### In **Processing**
Ursprünglich im Jahre 2001 von [Ben Fry](http://benfry.com/) und [Casey Reas](http://reas.com/) entwickelt, verkörpert [Processing](https://processing.org/) eine unglaublich einfache und gleichzeitig leistungsfähige Umgebung für Deinen Einstieg in das Thema „Programmierung“. (Auch ich habe so angefangen.) [Andres Colubri](https://codeanticode.wordpress.com/) hat wichtige Erweiterungen für die Einbeziehung von openGL und Videofunktionen in Processing entwickelt. Sie machen es ganz einfach, in dieser Umgebung mit GLSL-Shadern zu arbeiten. Processing sucht dazu einfach nach einem Shader mit dem Namen ```shader.frag``` in dem Unterverzeichnis ```data``` Deines Zeichenblocks („sketch“). Stelle einfach sicher, dass Du die Beispiele aus dem vorliegenden Buch unter diesem Dateinamen in dem genannten Verzeichnis ablegst.
```cpp
PShader shader;
void setup() {
size(640, 360, P2D);
noStroke();
shader = loadShader("shader.frag");
}
void draw() {
shader.set("u_resolution", float(width), float(height));
shader.set("u_mouse", float(mouseX), float(mouseY));
shader.set("u_time", millis() / 1000.0);
shader(shader);
rect(0,0,width,height);
}
```
Damit Dein Shader auch unter Versionen von Processing kleiner 2.1 läuft, musst Du lediglich die folgende Programmzeile an den Anfang Deines Shaders stellen: ```#define PROCESSING_COLOR_SHADER```. Das sieht dann so aus:
```glsl
#ifdef GL_ES
precision mediump float;
#endif
#define PROCESSING_COLOR_SHADER
uniform vec2 u_resolution;
uniform vec3 u_mouse;
uniform float u_time;
void main() {
vec2 st = gl_FragCoord.st/u_resolution;
gl_FragColor = vec4(st.x,st.y,0.0,1.0);
}
```
Mehr Informationen über den Einsatz von Shadern in Processing findest Du auch in diesem [Tutorial](https://processing.org/tutorials/pshader/).
### In **openFrameworks**
Jeder hat einen Platz, an dem er oder sie sich besonders wohl fühlt. Bei mir ist das die [openFrameworks Gemeinschaft](http://openframeworks.cc/). Diese C++-Umgebung ermöglicht die bequeme Einbindung von OpenGL und weiteren Open Source C++-Bibliotheken. In vielerlei Hinsicht ähnelt sie der Arbeit mit Processing, nur dass man es hier mit C++ und C++-Compilern zu tun hat. Genau wie Processing sucht *openFrameworks* nach Deinen Shader-Dateien im ```DATA```-Unterverzeichnis. Deshalb vergiss nicht, Deine ```.frag```-Dateien dorthin zu kopieren und den Dateinamen entsprechend anzupassen, wenn Du diese Dateien ausführen willst.
```cpp
void ofApp::draw(){
ofShader shader;
shader.load("","shader.frag");
shader.begin();
shader.setUniform1f("u_time", ofGetElapsedTimef());
shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight());
ofRect(0,0,ofGetWidth(), ofGetHeight());
shader.end();
}
```
Weitere Informationen über die Verwendung von Shadern in *openFrameworks* findest Du in diesem [exzellenten Tutorial](http://openframeworks.cc/ofBook/chapters/shaders.html), das von [Joshua Noble](http://thefactoryfactory.com/) verfasst wurde.

@ -0,0 +1,152 @@
# Algorithmisches Zeichnen
## Modellierungsfunktionen
Dieses Kapitel könnte auch die Überschrift „Mr. Miyagi's Zaun- Lektion“ tragen, in Anspielung auf den Film „Karate Kid“ aus dem Jahre 1984. Bislang haben wir die normalisierte Position von *x* und *y* auf den *roten* und *grünen* Farbkanal des jeweiligen Punktes abgebildet. Wir haben dazu eine Funktion gebaut, die im Wesentlichen einen zweidimensionalen Vektor (*X* und *Y*) entgegennimmt und einen vierdimensionalen Vektor (*Rot*, *Grün*, *Blau* und *Alpha*) zurückliefert. Aber bevor wir damit fortfahren, Daten zwischen verschiedenen Dimensionen zu transformieren, müssen wir mit einfacheren Aufgaben beginnen. Und zwar mit viel einfacheren Aufgaben. Ich meine damit das Verständnis eindimensionaler Funktionen. Desto mehr Zeit und Energie Du darauf verwendest, desto stärker wird Dein Shader-Karate sein.
![Ausschnitt aus dem Film "Karate Kid" (1984)](mr_miyagi.jpg)
Die folgende Codestruktur ist unser Zaun, an dem wir in Anlehnung an die Geschichte von „Karate Kid“ üben werden. Wir visualisieren damit den normalisierten Wert der *X-Ordinate* (```st.x```) auf zweierlei Weise: einmal in Form der Helligkeit (beachte den weichen, schrittweisen Übergang von Schwarz zu Weiß) und außerdem indem wir die Werte in Form einer grünen (Funktions-) Linie darstellen (der jeweilige *X-Wert* wird dabei eins-zu-eins auf den *Y-Wert* abgebildet). Halte Dich dabei bitte nicht zu lange mit der *plot()*-Funktion auf, denn darauf werden wir gleich noch im Detail eingehen.
<div class="codeAndCanvas" data="linear.frag"></div>
**Ein kurzer Hinweis**: Der Konstruktor des ```vec3```-Datentyps „versteht“, wenn Du allen drei Farbkanälen durch die Angabe eines einzigen Parameters diesen einen gleichen Wert zuweisen willst. In diesem Fall erhält man immer einen Grauton zwischen Schwarz ```(0.0, 0.0, 0.0)``` und Weiß ```(1.0, 1.0, 1.0)```.
Ebenso versteht der Konstruktor des ```vec4```-Datentyps, wenn Du einen vierdimensionalen Vektor aus einem dreidimensionalen Vektor erzeugen willst. Der dreidimensionale Vektor verkörpert in diesem Fall den *RGB-Farbwert*, der zusätzliche Parameter den Wert für den *Alpha-Kanal*, also die Deckkraft. Dies geschieht hier in den *Programmzeilen 20 und 26*.
Dieser Programmcode ist Dein Zaun, an dem Du das Streichen bzw. Malen üben kannst. Es ist wichtig, dass Du Dir den Code genau anschaust und ihn verstehst. Denn die darin enthaltenen Konzepte, wie etwa die Normalisierung von *x* und *y* auf Werte zwischen *0.0* und *1.0*, werden uns weiterhin begleiten.
Die hier genutzte Eins-zu-Eins-Abbildung zwischen *x* und *y* (in diesem Fall als Helligkeit genutzt) wird als *lineare Interpolation* bezeichnet. Davon abweichend können wir auch unterschiedliche mathematische Funktionen nutzen, um der Linie eine andere Form zu geben. So können wir zum Beispiel *x hoch 5* einsetzen, um eine geschwungene, steil ansteigende Kurve zu erzeugen.
<div class="codeAndCanvas" data="expo.frag"></div>
Interessant, nicht wahr? Versuche einfach einmal, in der *Zeile 22* andere Exponenten wie beispielsweise ```20.0```, ```2.0```, ```1.0```, ```0.0```, ```0.2``` und ```0.02``` einzusetzen. Das Verständnis zwischen dem Exponenten und den daraus resultierenden Werten wird Dir sicher weiterhelfen. Schließlich ist es der geschickte Einsatz dieser und anderer mathematischer Funktionen, die Dir bei der Shader-Programmierung unglaubliche Möglichkeiten eröffnen.
[```pow()```](../glossary/?search=pow) ist eine eingebaute mathematische Funktion von GLSL. Daneben gibt es noch viele weitere. Die meisten davon können sehr schnell in der Hardware der Grafikkarte ausgeführt werden. Ihr geschickter Einsatz beschleunigt deshalb die Ausführung Deiner Shader.
Ersetze die Funktion *pow* in der *Zeile 22* durch eine andere Funktion und beobachte das Resultat. Probiere zum Beispiel die folgenden Funktionen aus: [```exp()```](../glossary/?search=exp), [```log()```](../glossary/?search=log) und [```sqrt()```](../glossary/?search=sqrt). Einige dieser Funktionen erzeugen interessantere Ergebnisse, wenn man sie in Verbindung mit einem Vielfachen oder einem Bruchteil der Kreiszahl *pi* nutzt. In der *Programmzeile 8* findest Du deshalb ein Makro, dass das Symbol ```PI``` innerhalb des Programmcodes durch den zugehörigen Wert ```3.14159265359``` ersetzt.
### Step und Smoothstep
GLSL bringt auch einige einzigartige Interpolationsfunktionen mit, die durch die Hardware beschleunigt werden.
Die Interpolationsfunktion [```step()```](../glossary/?search=step) nimmt zwei Argumente entgegen: Das erste verkörpert den Schwellenwert, während das zweite Argument den Wert darstellt, der mit diesem Schwellenwert verglichen werden soll. Liegt dieser Wert unterhalb des Schwellenwerts, liefert die Funktion ```0.0``` zurück, bei jedem Wert größer oder gleich dem Schwellenwert hingegen ```1.0```.
Ändere im folgenden Programmcode doch einfach einmal den Schwellenwert in *Zeile 20* und beobachte, was dann passiert.
<div class="codeAndCanvas" data="step.frag"></div>
Die zweite eingebaute Interpolationsfunktion trägt den Namen [```smoothstep()```](../glossary/?search=smoothstep). Sie interpoliert einen Wert, sofern sich dieser innerhalb eines angegebenen Wertbereichs befindet. Die ersten zwei Argumente stellen dabei die untere und die obere Schwelle dieses Wertebereichs dar, während das dritte Argument den zu interpolierenden Wert verkörpert.
Die Funktion liefert ```0.0``` zurück, wenn der zu interpolierende Wert unterhalb des genannten Schwellenwerts liegt, also kleiner als das erste Argument ist. Analog dazu liefert sie ```1.0``` zurück, wenn der zu interpolierende Wert größer als der obere Schwellenwert
ist. Befindet sich der zu interpolierende Wert jedoch innerhalb der gegebenen Spanne, wird ein Wert zwischen ```0.0``` und ```1.0``` zurückgeliefert, je nachdem wie nahe sich der Wert am oberen oder unteren Ende der Spanne befindet. Genau in der Mitte lautet das Ergebnis ```0.5```.
Wie das folgende Programm zeigt, ist das Ergebnis jedoch nicht vollständig linear, sondern am oberen und unteren Ende des Wertebereichs etwas „abgerundet“. Dadurch wird in den Randbereichen bewusst ein etwas weicherer Übergang erzielt, falls sich weitere interpolierte Werte anschließen.
<div class="codeAndCanvas" data="smoothstep.frag"></div>
Im obigen Beispiel nutzen wir die ```smoothstep()```-Funktion innerhalb der ```plot()```-Funktion, um die grüne Linie zu erzeugen, die die Ergebnisse aus der Y-Berechnung in *Zeile 20* darstellt. Siehst Du, wie diese grüne Linie nach oben und unten jeweils ein wenig ausfedert und sanft in den Hintergrund übergeht? Das erreichen wir, indem wir in *Zeile 12 und 13* zwei Aufrufe von [```smoothstep()```](../glossary/?search=smoothstep) miteinander verbinden. Schau Dir die folgende Berechnung an und setze sie in die *Zeile 20* ein.
```glsl
float y = smoothstep(0.2,0.5,st.x) - smoothstep(0.5,0.8,st.x);
```
Die Formel entspricht dem Vorgehen innerhalb der ```plot()```-Funktion. Sie symbolisiert, wie ```plot()``` genau in der Mitte (auf dem gegebenen Y-Wert) ein volles Grün erzeugt (Rückgabewert ```1.0```), während bei Werten darunter und darüber ein weicher Übergang zur Hintergrundfarbe erfolgt (Rückgabewerte von ```1.0``` langsam absteigend zu ```0.0```).
### Sinus und Cosinus
Wenn man mathematische Funktionen nutzen möchte, um Grafiken zu animieren, in eine geschwungene Form zu bringen oder sanft ein- und auszublenden, gibt es nichts Besseres, als sich mit Sinus und Cosinus anzufreunden.
Diese beiden trigonometrischen Funktionen sind so praktisch wie ein Schweizer Offiziersmesser, wenn es darum geht, Kreise zu konstruieren. Es ist wichtig zu verstehen, wie sich die beiden Funktionen einzeln verhalten und wie man sie gemeinsam nutzen kann. Kurz gesagt, bei einem gegebenen Winkel (in Form eines Bogenmaßes) liefern sie die korrekte *x*- ([*Cosinus*](../glossary/?search=cos)) und *y*- ([*Sinus*](../glossary/?search=sin)) Ordinate für die Position des zugehörigen Punktes auf einem Einheitskreis mit dem Radius ```1```. Weil die zurückgelieferten Funktionsergebnisse dabei immer dynamisch zwischen ```-1.0``` und ```1.0``` oszillieren, sind diese Funktionen ein ungeheuer praktisches Werkzeug für vielerlei Aufgaben.
![](sincos.gif)
Es ist nicht ganz leicht, alle Zusammenhänge zwischen trigonometrischen Funktionen auf der einen Seite und Kreisen auf der anderen Seite zu beschreiben. Die obige Animation zeigt jedoch sehr schön die oben zitierte Rolle von *Sinus* und *Cosinus* bei der Erzeugung eines Einheitskreises.
<div class="simpleFunction" data="y = sin(x);"></div>
Schau Dir die Sinuswelle genau an und beobachte, wie der daraus abgeleitete Wert für die Y-Ordinate auf dem Einheitskreis sanft zwischen ```+1``` und ```-1``` oszilliert. Und mit der Cosinuswelle erzeugen wir die zugehörige X-Ordinate.
Wie wir in dem zeitbasierten Beispiel im vorangegangenen Kapitel gesehen haben, lässt sich dieses rhythmische Verhalten von [```sin()```](../glossary/?search=sin) gut nutzen, um bestimmte Werte und Eigenschaften zu animieren. Wenn Du diesen Text in einem Internet-Browser liest, wirst du feststellen, dass Du die obige Formel *y=sin(x);* editieren kannst, um zu sehen, wie sich die Funktionskurve dadurch ändert. (Hinweis: Bitte nicht das Semikolon am Ende der Zeile vergessen, sonst gibt es einen Syntaxfehler.)
Probiere die folgenden Übungen aus und beobachte, was daraufhin geschieht:
* Addiere die Zeit (```u_time```) zu *x* hinzu, bevor Du aus der Summe den ```sin``` berechnest. Verinnerliche die daraus entstehende **Bewegung** entlang der *x-Achse*.
* Multipliziere *x* mit ```PI```, bevor Du den ```sin``` berechnest. Beobachte, wie sich die Phasenlänge auf jeweils 2 Einheiten entlang der X-Achse verkürzt und sich die Schwingung dann wiederholt. Dadurch verdoppelt sich also die Frequenz.
* Multipliziere die Zeit (```u_time```) mit *x*, bevor Du daraus den ```sin``` berechnest. Du wirst sehen, wie die einzelnen Wellen so weit zusammengedrückt werden, dass das Ergebnis wie ein unidentifizierbares Rauschen wirkt.
* Addiere den Wert ```1.0``` zum Ergebnis von [```sin(x)```](../glossary/?search=sin) hinzu und beobachte, wie sich die Welle dadurch nach oben verschiebt und jeweils zwischen den Werten von ```0.0``` und ```2.0``` oszilliert.
* Multipliziere [```sin(x)```](../glossary/?search=sin) mit ```2.0```. Du wirst feststellen, dass sich die Amplitude der Schwingung (die Minimal- und Maximalwerte) verdoppelt.
* Lass den absoluten Wert ([```abs()```](../glossary/?search=abs)) von ```sin(x)``` berechnen. Der entstehende Graph erinnert an die Spur eines hüpfenden Balls, nicht wahr?
* Lass nur den Nachkommateil ([```fract()```](../glossary/?search=fract)) des Resultats von [```sin(x)```](../glossary/?search=sin) berechnen.
* Addiere jeweils den höheren Integer-Wert ([```ceil()```](../glossary/?search=ceil)) von [```sin(x)```](../glossary/?search=sin) und den kleineren Integer-Wert ([```floor()```](../glossary/?search=floor)) von [```sin(x)```](../glossary/?search=sin), um eine digitale Welle zwischen ```1``` und ```-1``` zu erhalten.
### Einige besonders nützliche Funktionen
Am Ende der letzten Übung haben wir einige neue Funktionen eingeführt. Jetzt ist es an der Zeit, mit diesen Funktionen zu experimentieren, indem Du Schritt für Schritt die Kommentarzeichen aus den folgenden Programmzeilen entfernst. Lerne diese Funktionen kennen und beobachte, wie sie funktionieren. Du wirst Dich vielleicht fragen, warum? Eine Google-Suche nach „generativer Kunst“ bzw. „generative art“ wird Dir diese Frage schnell beantworten. Denke daran, dass diese Funktionen wie der Zaun aus „Karate Kid“ sind. Noch bewegen wir uns nur in einer Dimension, aufwärts und abwärts. Aber bald schon geht es damit in zwei, drei und vier Dimensionen!
![Anthony Mattox (2009)](anthony-mattox-ribbon.jpg)
<div class="simpleFunction" data="y = mod(x,0.5); // liefert den Modulo von x mit 0.5
//y = fract(x); // liefert den Nachkommateil einer Zahl
//y = ceil(x); // die kleinste Ganzzahl, groesser oder gleich x
//y = floor(x); // die naechste Ganzzahl, kleiner oder gleich x
//y = sign(x); // das Vorzeichen von x
//y = abs(x); // der absolute Wert von x
//y = clamp(x,0.0,1.0); // x auf den Bereich zwischen 0.0 und 1.0 abbilden
//y = min(0.0,x); // die kleinere Zahl von x und 0.0 zurueckliefern
//y = max(0.0,x); // die groessere Zahl von x und 0.0 zurueckliefern"></div>
### Fortgeschrittene formgebende Funktionen
[Golan Levin](http://www.flong.com/) hat eine großartige Dokumentation über komplexe formgebende Funktionen verfasst, die für unsere Zwecke extrem hilfreich ist. Indem Du einen Teil dieser Funktionen nach GLSL portierst, schaffst Du Dir eine wertvolle Sammlung an Codeschnipseln.
* [Polynomische formgebende Funktionen: www.flong.com/texts/code/shapers_poly](http://www.flong.com/texts/code/shapers_poly/)
* [Exponentielle formgebende Funktionen: www.flong.com/texts/code/shapers_exp](http://www.flong.com/texts/code/shapers_exp/)
* [Kreisförmige & elliptische formgebende Funktionen: www.flong.com/texts/code/shapers_circ](http://www.flong.com/texts/code/shapers_circ/)
* [Bezier und andere parametrische formgebende Funktionen: www.flong.com/texts/code/shapers_bez](http://www.flong.com/texts/code/shapers_bez/)
<div class="glslGallery" data="160414041542,160414041933,160414041756" data-properties="clickRun:editor,hoverPreview:false"></div>
Genau wie Küchenchefs Gewürze und exotische Zutaten sammeln, entwickeln Digitalkünstler und kreative Entwickler häufig eine Liebe für bestimmte formgebenden Funktionen.
[Inigo Quiles](http://www.iquilezles.org/) stellt eine großartige Auswahl an [nützlichen Funktionen](http://www.iquilezles.org/www/articles/functions/functions.htm) vor. Wenn Du [diesen Artikel](http://www.iquilezles.org/www/articles/functions/functions.htm) gelesen hast, dann werfe einen Blick auf die folgenden Übertragungen dieser Funktionen nach GLSL. Beobachte aufmerksam die kleinen, aber erforderlichen Anpassungen wie etwa den Punkt (".") bei Fließkommazahlen und die Umsetzung der Funktionsnamen von C auf GLSL; so heißt es in GLSL beispielsweise ```pow()``` statt ```powf()``` wie in C:
<div class="glslGallery" data="05/impulse,05/cubicpulse,05/expo,05/expstep,05/parabola,05/pcurve" data-properties="clickRun:editor,hoverPreview:false"></div>
Um Deine Motivation zu erhalten, hier ein elegantes Beispiel (entwickelt von [Danguafer](https://www.shadertoy.com/user/Danguafer)) für die Meisterschaft im Karate der formgebenden Funktionen.
<iframe width="800" height="450" frameborder="0" src="https://www.shadertoy.com/embed/XsXXDn?gui=true&t=10&paused=true" allowfullscreen></iframe>
Im nächsten Kapitel werden wir neue Schrittfolgen für unser „Karate“ lernen. Zunächst beim Mischen von Farben, dann beim Malen von Formen.
####Übung
Wirf einen Blick auf die folgende Tabelle mit Gleichungen, die von [Kynd](http://www.kynd.info/log/) erstellt wurde. Schau Dir an, wie er Funktionen und ihre Eigenschaften kombiniert, um Werte zwischen ```0.0``` und ```1.0``` zu erhalten. Jetzt ist ein guter Moment, um mit diesen Funktionen ein wenig zu experimentieren. Denn je mehr Du in dieses Denken hineinwächst, desto besser wird Dein Karate sein.
![Kynd - www.flickr.com/photos/kynd/9546075099/ (2013)](kynd.png)
####Für Deine Werkzeugsammlung
Hier kommen einige Tools, die es Dir erleichtern werden, diese Art von Funktionen grafisch zu visualisieren.
* Grapher: Wenn Du einen Computer mit MacOS hast, gib bei der Suche mit Spotlight ```grapher``` ein, und Du wirst dieses superpraktische Tool finden.
![OS X Grapher (2004)](grapher.png)
* [GraphToy](http://www.iquilezles.org/apps/graphtoy/): Einmal mehr ein Werkzeug von [Inigo Quilez](http://www.iquilezles.org), mit dem man GLSL-Funktionen in WebGL darstellen kann.
![Inigo Quilez - GraphToy (2010)](graphtoy.png)
* [Shadershop](http://tobyschachman.com/Shadershop/): Dieses großartige Werkzeug von [Toby Schachman](http://tobyschachman.com/) zeigt Dir auf intuitive und grafisch faszinierende Weise, wie Du komplexe Funktionen entwickeln kannst.
![Toby Schachman - Shadershop (2014)](shadershop.png)

@ -0,0 +1,147 @@
![Paul Klee Farbkarte (1931)](klee.jpg)
## Farben
Wir hatten bislang noch wenig Gelegenheit, um über die Vektortypen von GLSL zu sprechen. Bevor es mit anderen Inhalten weitergeht, ist es wichtig, mehr über diese Variablentypen zu erfahren. Das Thema „Farben“ bietet sich dafür an.
Falls Du mit den Konzepten der objektorientierten Programmierung vertraut bist, ist Dir vielleicht schon aufgefallen, dass wir die verschiedenen Elemente innerhalb eines Vektors wie eine gewöhnliche ```struct``` in C ansprechen.
```glsl
vec3 red = vec3(1.0,0.0,0.0);
red.x = 1.0;
red.y = 0.0;
red.z = 0.0;
```
Die Festlegung von Farben über die Komponenten *x*, *y* und *z* wirkt auf den ersten Blick etwas merkwürdig, nicht wahr? Aus diesem Grund gibt es weitere Möglichkeiten, um auf diese Elemente zuzugreifen. Die Inhalte von ```.x```, ```.y``` und ```.z``` können auch als ```.r```, ```.g``` und ```.b```, sowie als ```.s```, ```.t``` und ```.p``` angesprochen werden (```.s```, ```.t``` und ```.p``` werden typischerweise für die Raumkoordinaten von Texturen genutzt, wie wir in späteren Kapiteln noch sehen werden). Darüber hinaus lassen sich die Elemente eines Vektors auch über ihre Index-Position als ```[0]```, ```[1]``` und ```[2]``` ansprechen.
Die folgenden Programmzeilen zeigen die unterschiedlichen Ansätze, um jeweils auf die gleichen Vektorinhalte zuzugreifen:
```glsl
vec4 vector;
vector[0] = vector.r = vector.x = vector.s;
vector[1] = vector.g = vector.y = vector.t;
vector[2] = vector.b = vector.z = vector.p;
vector[3] = vector.a = vector.w = vector.q;
```
Tatsächlich handelt es sich bei den unterschiedlichen Namen nur um verschiedene Bezeichner für jeweils ein und dieselbe Sache. Die Namen sollen Dir helfen, verständlichen Code zu schreiben, je nachdem, wofür ein Vektor gerade zum Einsatz kommt (Farben, Koordinaten, Raumpunkte etc.)
Ein weiteres praktisches Merkmal der Vektortypen in GLSL ist die Möglichkeit, ihre Eigenschaften in beliebiger Weise zu kombinieren. Das macht es besonders einfach, Werte zu tauschen und in andere Datentypen zu konvertieren. Diese Fähigkeit wird im Englischen als *swizzle* bezeichnet, was so viel wie „umrühren“ oder „mischen“ bedeutet.
```glsl
vec3 yellow, magenta, green;
// Zusammenruehren von Gelb
yellow.rg = vec2(1.0); // Zuweisung von 1. an den Rot- und den Gruen-Kanal von yellow
yellow[2] = 0.0; // Zuweisung von 0. an den Blau-Kanal von yellow
// Zusammenruehren von Magenta
magenta = yellow.rbg; // Zuweisung von yellow an magenta bei gleichzeitigem Tausch der Kanaele fuer Blau und Gruen
// Zusammenruehren von Gruen
green.rgb = yellow.bgb; // Zuweisung des Blau-Kanals von yellow an den Rot- und Blau-Kanal von green
```
#### Für Deine Werkzeugkiste
Vielleicht bist Du es nicht gewohnt, Farben über Zahlenwerte zu definieren. Und mal ganz ehrlich, das ist ja auch nicht sonderlich intuitiv. Glücklicherweise gibt es eine Menge intelligenter Programme und Webseiten, mit denen man Farben am Bildschirm auswählen kann und dann die zugehörigen Werte für Rot, Grün und Blau erhält. Am besten, man bekommt sie gleich als Definition für einen ```vec3``` oder ```vec4``` im GLSL-Format geliefert. Hier sind zum Beispiel die Vorlagen, die ich auf [Spectrum](http://www.eigenlogik.com/spectrum/mac) nutze, um einen passenden Ausdruck für GLSL zu erhalten:
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### Mischen von Farben
Jetzt, wo Du weißt, wie man Farben definiert, wird es Zeit, dies mit unserem bisher gesammelten Wissen zu verknüpfen. In GLSL gibt es eine äußerst praktische Funktion mit dem Namen [```mix()```](../glossary/?search=mix), über die man zwei Werte in Form von Prozentangaben mischen kann. Vielleicht kannst Du Dir bereits denken, wie diese Prozentangaben auszusehen haben? Genau, als Werte zwischen ```0.0``` und ```1.0```! Das passt doch perfekt, nachdem Du schon so viel Zahlen-Karate am Zaun geübt hast. Es ist an der Zeit, Dein Wissen umzusetzen.
![](mix-f.jpg)
Lenke Dein Augenmerk im folgenden Programm besonders auf die *Zeile 18*. Schau Dir genau an, wie hier die absoluten Werte aus einer *Sinusfunktion* genutzt werden, um zeitabhängig und mit unterschiedlichen Verhältnissen die Farben aus den Variablen ```colorA``` und ```colorB``` zu mischen.
<div class="codeAndCanvas" data="mix.frag"></div>
Jetzt zeige Deine Fähigkeiten, indem Du:
* Einen ausdrucksstarken Übergang zwischen den Farben konstruierst. Denke an ein bestimmtes Gefühl, eine impulsive menschliche Regung. Welche Farbe vermag dieses Gefühl wohl am besten auszudrücken? Und wie soll sich diese Farbe entwickeln, um anschließend wieder zu verschwinden? Animiere den Übergang mit Hilfe formgebender Funktionen. Robert Penner hat eine Reihe populärer Übergangsfunktionen für Computeranimationen entwickelt, die als [easing functions](http://easings.net/) bekannt sind. Du kannst für Deine Nachforschungen und als Inspiration auf [dieses Beispiel](../edit.php#06/easing.frag) zurückgreifen. Aber die besten Ergebnisse erzielst Du natürlich, wenn Du Deine ganz eigenen Übergänge kreierst.
### Das Spiel mit Farbverläufen
Die [```mix()```](../glossary/?search=mix)-Funktion hat noch mehr zu bieten. Anstelle eines einzelnen Werts vom Typ ```float```, können wir auch einen Datentyp übergeben, der zu den ersten beiden Argumenten passt. In unserem Fall ist das ein ```vec3```. Dadurch gewinnen wir die Kontrolle über das Mischen in allen drei Farbkanälen *Rot*, *Grün* und *Blau* (```r```, ```g``` und ```b```).
![](mix-vec.jpg)
Wirf nun einen Blick auf das folgende Beispiel. Wie schon bei den Beispielen im letzten Kapitel verbinden wir den Übergang auch hier mit dem normalisierten Wert der *X-Ordinate* und visualisieren ihn als eine Linie. Im ersten Schritt folgen die Übergänge in allen drei Farbkanälen derselben Linie.
Lösche jetzt die Kommentarzeichen aus der *Programmzeile 25*, damit diese ebenfalls ausgeführt wird. Dann schau, was daraufhin geschieht. Entferne anschließend auch die Kommentarzeichen vor den *Zeilen 26 und 27*. Achte darauf, dass diese drei Zeilen jeweils das Mischverhältnis für die *Rot-*, *Grün*, und *Blau-Kanäle* zwischen den Farben aus den Variablen ```colorA``` und ```colorB``` festlegen.
<div class="codeAndCanvas" data="gradient.frag"></div>
Vielleicht erkennst Du die drei formgebenden Funktionen in den *Zeilen 25 bis 27* wieder. Experimentiere mit ihnen. Es ist an der Zeit, dass Du die erlernten Fähigkeiten aus dem letzten Kapitel nutzt, um interessante Farbverläufe zu produzieren. Probiere die folgenden Übungen aus:
![William Turner - The Fighting Temeraire (1838)](turner.jpg)
* Erzeuge einen Farbverlauf, der an den Sonnenuntergang bei William Turner erinnert.
* Animiere einen Übergang zwischen Sonnenaufgang und Sonnenuntergang mit Hilfe von ```u_time```.
* Kannst Du mit Hilfe des bislang Erlernten einen Regenbogen entstehen lassen?
* Nutze die ```step()```-Funktion, um eine farbenfrohe Flagge zu erzeugen.
### HSB
Beim Thema „Farben“ kommen wir nicht an dem Konzept der „Farbräume“ vorbei. Wie Du vielleicht weißt, gibt es unterschiedliche Möglichkeiten, Farben zu beschreiben, jenseits ihrer Auftrennung in *Rot-*, *Grün-* und *Blau-Anteile* (sprich: Kanäle).
[HSB](https://de.wikipedia.org/wiki/HSV-Farbraum) steht für *Hue* (dt. Farbwert), *Saturation* (dt. Farbsättigung) und *Brightness* (dt. absolute Helligkeit). Dieses Farbsystem ist intuitiver und in vielen Fällen auch praktischer, wenn es um die Festlegung von Farben geht. Nimm Dir einen Moment Zeit, um die Konvertierungsfunktionen ```rgb2hsv()``` und ```hsv2rgb()``` im folgenden Programmcode zu studieren.
Indem wir die Position auf der *X-Achse* auf den Farbwert und die Position auf der *Y-Achse* auf die Helligkeit abbilden, erhalten wir ein hübsches Spektralbild. Diese räumliche Verteilung der Farben kann sehr praktisch sei, wenn es um die Auswahl einer Farbe für einen bestimmten Zweck geht.
<div class="codeAndCanvas" data="hsb.frag"></div>
### HSB in Polarkoordinaten
Das *HSB-Farbmodell* wurde ursprünglich entwickelt, um Farben in Polarkoordinaten (bestehend aus einem *Winkel* und einem *Radius*) auszudrücken und nicht als kartesische Koordinaten (bestehend aus einer *X-* und einer *Y-Ordinate*). Um unsere ```HSB```-Funktion mit Polarkoordinaten arbeiten zu lassen, müssen wir den Winkel und die Entfernung des jeweiligen Bildpunktes von der Mitte der Zeichenfläche berechnen. Dafür nutzen wir die [```length()```](../glossary/?search=length)-Funktion, sowie die Funktion [```atan(y,x)```](../glossary/?search=atan) (das ist die GLSL-Variante der in vielen Programmiersprachen verfügbaren Funktion ```atan2(y,x)``` zur Berechnung des Arkustangens).
Bei der Nutzung von Vektor- und Trigonometrie-Funktionen werden Variablen der Datentypen ```vec2```, ```vec3``` und ```vec4``` wie Vektoren behandelt, auch wenn sie tatsächlich Farben verkörpern. Wir beginnen hier also, Farben und Vektoren gleichermaßen zu bearbeiten - eine Flexibilität, die sich noch als äußerst praktisch und weitreichend erweisen wird.
**Hinweis:** Nur, falls Du Dich fragst: Abgesehen von [```length```](../glossary/?search=length) gibt es noch viele weitere geometrische Funktionen. Dazu gehören beisielsweise: [```distance()```](../glossary/?search=distance), [```dot()```](../glossary/?search=dot), [```cross```](../glossary/?search=cross), [```normalize()```](../glossary/?search=normalize), [```faceforward()```](../glossary/?search=fraceforward), [```reflect()```](../glossary/?search=reflect) und [```refract()```](../glossary/?search=refract).
Außerdem bietet GLSL vergleichende Funktionen für Vektoren wie [```lessThan()```](../glossary/?search=lessThan), [```lessThanEqual()```](../glossary/?search=lessThanEqual), [```greaterThan()```](../glossary/?search=greaterThan), [```greaterThanEqual()```](../glossary/?search=greaterThanEqual), [```equal()```](../glossary/?search=equal) und [```notEqual()```](../glossary/?search=notEqual).
Nachdem wir den Winkel und die Entfernung (Länge) berechnet haben, müssen wir diese Werte normalisieren, indem wir sie auf den Wertebereich zwischen ```0.0``` und ```1.0``` abbilden. In der *Programmzeile 27* liefert der Aufruf von [```atan(y,x)```](../glossary/?search=atan) den Winkel als Bogenmaß zwischen *-PI* und *PI* (```-3.14``` bis ```3.14```) zurück. Deshalb müssen wir dieses Ergebnis durch ```TWO_PI``` (Zweimal *PI*, als Konstante oben im Programm definiert) teilen. Wir erhalten dadurch Werte zwischen ```-0.5``` und ```0.5```, die wir durch einfache Addition von ```0.5``` auf den benötigten Wertebereich zwischen ```0.0``` und ```1.0``` abbilden. Allerdings werden wir hier als Ergebnis immer maximal ```0.5``` erhalten, weil wir ja die Entfernung von der Mitte der Zeichenfläche berechnen. Deshalb müssen wir dieses Ergebnis noch mit ```2``` multiplizieren, damit wir maximal auf den Wert von ```1.0``` kommen.
Wie Du siehst, dreht sich also auch hier das ganze Spiel darum, Werte zwischen ```0.0``` und ```1.0``` zu erzielen, mit denen wir so gerne arbeiten.
<div class="codeAndCanvas" data="hsb-colorwheel.frag"></div>
Probiere die folgenden Übungen aus:
* Verändere das obige Programmbeispiel so, dass sich das Farbrad dreht, wie der Mauszeiger bei einer länger währenden Operation.
* Nutze eine formgebende Funktion in Verbindung mit der Konvertierungsfunktion von *HSB* nach *RGB*, um einen bestimmten Farbwert in den Vordergrund zu rücken und die anderen Farben „klein“ zu halten.
![William Home Lizars - Das Rot-, Gelb- und Blau-Spektrum in Relation zum Spektrum des Sonnenlichts (1834)](spectrums.jpg)
* Wenn Du Dir das Farbrad auf Farbauswahlfeldern (wie in der folgenden Abbildung) genau anschaust, erkennst Du, dass diese einen *RYB-Farbraum* repräsentieren. Die gegenüberliegende Farbe von Rot sollte z.B. Grün sein, doch in unserem obigen Beispielprogramm erscheint dort Zyan. Gelingt es Dir, einen Weg zu finden, damit unser Beispielprogramm das gleiche Farbbild liefert, wie auf der Abbildung unten? (Ein Tipp: Das ist der perfekte Moment, um eine passende formgebende Funktion zum Einsatz zu bringen.)
![](colorwheel.png)
* Lies [Josep's Alvers Buch: „Interaction of Color“](http://www.goodreads.com/book/show/111113.Interaction_of_Color) und klicke die folgenden Shader an, um aus deren Programmcode zu lernen.
<div class="glslGallery" data="160505191155,160505193939,160505200330,160509131554,160509131509,160509131420,160509131240" data-properties="clickRun:editor,openFrameIcon:false,showAuthor:false"></div>
#### Ein Hinweis zu Funktionen und ihren Argumenten
Bevor wir zum nächsten Kapitel springen, lass und kurz innehalten und einen Schritt zurückgehen. Schau Dir noch einmal die Funktionen aus den letzten Beispielprogrammen an. Vielleicht fällt Dir das Schüsselwort ```in``` im Kopf einer Funktion vor dem jeweiligen Argument auf. Es handelt sich dabei um einen sogenannten [*qualifier*](http://www.shaderific.com/glsl-qualifiers/#inputqualifier), der in diesem Fall festlegt, dass der jeweilige Parameter von der Funktion nur ausgelesen und nicht überschrieben werden kann. In kommenden Programmbeispielen werden wir sehen, dass Parameter auch als ```out``` oder ```inout``` gekennzeichnet werden können. ```inout``` entspricht dabei der Übergabe eines Arguments „by reference“, so dass Änderungen an diesem Parameter auch an den Aufrufer und in die von ihm eingesetzte Variable zurückfließen.
```glsl
int newFunction(in vec4 aVec4, // nur auslesbar
out vec3 aVec3, // nicht initalisiert, nur beschreibbar
inout int aInt); // lesen und schreiben, Aenderungen fliessen zum Aufrufer zurueck
```
Du hast vielleicht nicht damit gerechnet, aber jetzt haben wir bereits alle Elemente beisammen, um aufregende Grafiken zu erstellen. Im nächsten Kapitel werden wir lernen, wie man alle unsere kleinen Tricks nutzen kann, um den Raum richtig in Wallung zu bringen. Ja, du hast richtig gehört. Genau darum geht's.

@ -0,0 +1,234 @@
![Alice Hubbard, Providence, USA, ca. 1892. Foto: Zindman/Freemont.](froebel.jpg)
## Formen
Endlich! Auf diesen Moment haben wir in den vorangegangenen Kapiteln hingearbeitet! Du hast die wichtigsten Grundlagen von GLSL, seine Datentypen und Funktionen kennengelernt. Und du hast mit formgebenden Funktionen gearbeitet. Jetzt ist es an der Zeit, all dieses Wissen zusammenzuführen. Bist Du bereit? In diesem Kapitel wirst Du lernen, wie man grundlegende geometrische Formen auf parallele, prozedurale Weise erstellt.
### Rechtecke
Stell dir vor, Du hast ein Millimeterpapier vor Dir, wie man es zuweilen im Mathematikunterricht nutzt. Und Deine Aufgabe ist es, darauf ein ausgefülltes Quadrat zu zeichnen. Die Größe des Papieres beträgt *10 x 10* und das Quadrat soll *8 x 8* sein. Wie gehst Du vor?
![](grid_paper.jpg)
Vielleicht würdest Du einfach die gesamte Fläche ausfüllen und dabei nur die erste und die letzte Zeile auslassen, ebenso wie die erste und die letzte Spalte. So käme das gewünschte Quadrat sehr einfach zustande.
Wie hängt das nun mit Shadern zusammen? Jedes kleine Quadrat auf unserem Millimeterpapier können wir uns als ein Pixel, d.h. einen parallel ausgeführten *Thread*, vorstellen. Und jedes dieser Quadrate (*jeder Thread*) kennt seine Koordinate, wie bei einem Schachbrett. In den vorangegangenen Kapiteln haben wir die *x-* und die *y-Ordinate* jeweils auf den *roten* und *grünen* Farbkanal des Punktes abgebildet. Wir haben gelernt, wie wir den schmalen zweidimensionalen Bereich zwischen ```0.0``` und ```1.0``` bearbeiten. Wie können wir dieses Wissen nun anwenden, um in der Mitte unserer Zeichenfläche ein zentriertes weißes Quadrat zu malen?
Lass uns mit etwas Pseudocode beginnen, der mit ```if```-Befehlen auf die Lage des zu bearbeitenden Pixels innerhalb der Zeichenfläche eingeht. Das Vorgehen ähnelt dabei in bemerkenswerte Weise dem oben skizzierten beim Malen auf Millimeterpapier.
```glsl
if ( (X GROESSER ALS 1) UND (Y GROESSER ALS 1) )
male weiss
else
male schwarz
```
Jetzt, wo wir eine Idee haben, wie die Lösung aussehen könnte, lass uns den ```if```-Befehl durch einen Aufruf der [```step()```](../glossary/?search=step)-Funktion ersetzen, und anstelle der Maße *10 x 10* normalisierte Werte zwischen ```0.0``` und ```1.0``` bearbeiten:
```glsl
uniform vec2 u_resolution;
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
// diese Berechnungen liefern jeweils 1.0 (weiss) oder 0.0 (schwarz).
float left = step(0.1,st.x); // entspricht X groesser als 0.1
float bottom = step(0.1,st.y); // entspricht Y groesser als 0.1
// die Multiplikation von left*bottom entspricht der logischen Verknüpfung durch UND
color = vec3( left * bottom );
gl_FragColor = vec4(color,1.0);
}
```
Die [```step()```](../glossary/?search=step)-Funktion setzt jedes Pixel unterhalb von ```0.1``` auf Schwarz (```vec3(0.0)```) und alle anderen auf Weiß (```vec3(1.0)```). Die Multiplikation von ```left``` und ```bottom``` arbeitet wie eine logische *UND-Verknüpfung*, weil nur dann nicht ```0.0```, sondern ```1.0``` herauskommt, wenn beide Variablen auf ```1.0``` stehen. So entstehen zwei schwarze Linien, eine am linken und eine am unteren Rand der Zeichenfläche. Der Rest wird weiß.
![](rect-01.jpg)
Im obigen Programmcode wiederholen wir die gleiche Vorgehensweise für beide Ränder (links und unten). Wir können das noch etwas kompakter formulieren, indem wir in einem Aufruf zwei Testwerte in Form eines zweidimensionalen Vektors an [```step()```](../glossary/?search=step) übergeben. Das sieht dann so aus:
```glsl
vec2 borders = step(vec2(0.1),st);
float pct = borders.x * borders.y;
```
Bis jetzt haben wir nur zwei Kanten unseres Rechtecks bearbeitet. Jetzt kommen auch die beiden anderen Kanten die rechte und die obere an die Reihe. Schau Dir den folgenden Programmcode an:
<div class="codeAndCanvas" data="rect-making.frag"></div>
Entferne die Kommentarzeichen aus den *Zeilen 21-22* und beobachte, wie wir die Koordinaten auf den linken und unteren Rand abbilden (```1-st```), damit wir sie wieder mit der [```step()```](../glossary/?search=step) Funktion und dem Wert von ```0.1``` vergleichen können. Aus der oberen rechten Ecke (```vec2(1.0,1.0)```) wird so für unsere Berechnungen quasi die untere linke Ecke ```vec2(0.0,0.0)```. Das ist so, als würden wir die Zeichenfläche einfach um 180 Grad drehen und den Test dann wie zuvor wiederholen.
![](rect-02.jpg)
Beachte außerdem, dass in den *Zeilen 18 und 22* die Ergebnisse von ```step()``` in Bezug auf alle vier Seiten miteinander multipliziert werden. Dies entspricht wiederum eine logischen *UND*-Verknüpfung, denn wir erhalten nur dann *Weiß* (```1.0```), wenn keines der Ergebnisse *Schwarz* (```0.0```) ist. Wir könnten auch schreiben:
```glsl
vec2 bl = step(vec2(0.1),st); // linke und untere Kante
vec2 tr = step(vec2(0.1),1.0-st); // rechte und obere Kante
color = vec3(bl.x * bl.y * tr.x * tr.y); //UND-Verknuepfung
```
Interessant, nicht wahr? Wir nutzen für diese Technik also [```step()```](../glossary/?search=step) zum Vergleichen, eine Subtraktion für die Drehung der Koordinaten und die Multiplikation als logische *UND*-Verknüpfung.
Bevor wir weitermachen, probiere bitte die folgenden Übungen aus:
* Ändere die Größe und die Proportionen des Rechtecks.
* Experimentiere mit dem Ersetzen von [```step()```](../glossary/?search=step) durch [```smoothstep()```](../glossary/?search=smoothstep). Versuche, dadurch von harten Kanten zu weichen Kanten mit eleganten Übergängen zu gelangen.
* Baue den Code so um, dass er [```floor()```](../glossary/?search=floor) verwendet.
* Nimm die Implementierung, die Dir am besten gefällt, und baue daraus eine Funktion, die Du in Zukunft zum Zeichnen von Rechtecken und Quadraten verwenden kannst. Gestalte diese Funktion möglichst effizient.
* Entwickle eine andere Funktion, die kein ausgefülltes Rechteck zeichnet, sondern nur die Umrisse, d.h. die vier Kanten.
* Überlege Dir, wie Du die Rechtecke verschieben und mehrere davon auf der Zeichenfläche platzieren kannst. Falls Dir das gelingt, unterstreiche Deine Fähigkeiten, indem Du eine Komposition in der Art von [Piet Mondrian](http://de.wikipedia.org/wiki/Piet_Mondrian) erstellst.
![Piet Mondrian - Tableau (1921)](mondrian.jpg)
### Kreise
Es ist nicht schwer, Quadrate auf Millimeterpapier zu zeichnen und Rechtecke mit Hilfe kartesischer Koordinaten zu konstruieren. Kreise verlangen jedoch einen anderen Ansatz, zumal wie hier einen Pixel-orientierten Algorithmus benötigen. Eine Lösung besteht darin, die Koordinaten zu transformieren, damit wir beim Zeichnen die [```step()```](../glossary/?search=step)-Funktion nutzen können.
Doch wie soll das funktionieren? Lasse uns noch einmal zum Mathematikunterricht und dem Millimeterpapier zurückkehren. In der Schule haben die meisten von uns vermutlich gelernt, wie man mit dem Zirkel einen Kreis malt: Über das Drehrad stellt man zunächst den gewünschten Radius ein, platziert den Zirkel im Mittelpunkt des zu zeichnenden Kreises und schwingt das Zeichengerät anschließend mit einer eleganten Drehung über das Papier.
![](compass.jpg)
Will man diese Vorgehensweise auf ein Shader-Programm übertragen, bei dem jedes kleine Feld auf dem Millimeterpapier einem Pixel entspricht, muss man jedes Pixel (bzw. Thread) *fragen*, ob es zum Kreis gehört. Das machen wir, indem wir die Entfernung des Pixels zum Mittelpunkt des gewünschten Kreises berechnen.
![](circle.jpg)
Tatsächlich gibt es in GLSL mehrere Wege, diese Entfernung zu bestimmen. Die einfachste Möglichkeit greift auf die [```distance()```](../glossary/?search=distance)-Funktion zurück, die intern den Abstand (die Länge) [```length()```](../glossary/?search=length) zwischen zwei Punkten berechnet. In unserem Fall werden diese beiden Punkte durch die aktuelle Pixel-Koordinate sowie die Mitte der Zeichenfläche verkörpert, die hier den Kreismittelpunkt bilden soll. Die ```length()```-Funktion ist nichts anderes als eine Umsetzung der [Hypothenuse-Formel](http://de.wikipedia.org/wiki/Rechtwinkliges_Dreieck), die intern die Quadratwurzel ([```sqrt()```](../glossary/?search=sqrt)) berechnet.
![](hypotenuse.png)
Man kann wahlweise die [```distance()```](../glossary/?search=distance)-Funktion, die [```length()```](../glossary/?search=length)-Funktion oder die [```sqrt()```](../glossary/?search=sqrt)-Funktion nutzen, um die Entfernung zur Mitte der Zeichenfläche zu berechnen. Der folgende Programmcode enthält alle drei Möglichkeiten und liefert erwartungsgemäß jeweils das gleiche Ergebnis zurück.
* Kommentiere die einzelnen Zeilen aus bzw. ein, um Dir die verschiedenen Wege anzuschauen.
<div class="codeAndCanvas" data="circle-making.frag"></div>
In dem obigen Beispiel bilden wir die Entfernung zum Mittelpunkt der Zeichenfläche auf die Helligkeit der Pixel ab. Je näher sich ein Pixel beim Mittelpunkt befindet, desto geringer (dunkler) ist sein Farbwert. Beachte bitte, dass die Pixel auch zum Rand hin nicht allzu hell werden, weil die Entfernung vom Mittelpunkt ( ```vec2(0.5, 0.5)``` ) zu den Rändern maximal ```0.5``` beträgt. Denke ein wenig über die Abbildung nach und überlege Dir:
* Was kannst Du daraus ableiten?
* Wie kannst Du all dies nutzen, um einen Kreis zu malen?
* Verändere des obige Beispiel, damit der Farbverlauf ausschließlich innerhalb der Grenzen des Kreises stattfindet.
### Distanzfelder
Man kann sich das obige Beispiel auch als eine Art Höhenprofil vorstellen, bei dem dunklere Stellen für größere Höhen stehen. Der Farbverlauf repräsentiert dann so etwas wie einen Kegel. Stell Dir vor, Du stehst auf der Spitze des Kegels. Die horizontale Entfernung zum Kegelrand beträgt in alle Richtungen jeweils ```0.5```. Indem Du den Kegel an einer gewählten Stelle abschneidest, erhältst Du je nachdem eine größere oder eine kleinere Kreisfläche.
![](distance-field.jpg)
Im Prinzip nutzen wir also eine Neuinterpretation des Raumes (ausgehend vom Abstand zur Mitte), um eine bestimmte Form zu kreieren. Diese Technik ist als „Distanzfeld“ bekannt und wird bei der Erstellung von 3D-Grafiken auf vielfältige Weise genutzt.
Versuche Dich doch einmal an folgenden Übungen:
* Nutze die [```step()```](../glossary/?search=step)-Funktion, um alle Punkte größer als ```0.5``` weiß zu malen und alles darunter schwarz.
* Invertiere die Farben von Vordergrund und Hintergrund.
* Setze [```smoothstep()```](../glossary/?search=smoothstep) ein und experimentiere mit verschiedenen Grenzwerten, um angenehm sanfte Übergänge am Rand Deines Kreises zu erzeugen.
* Sobald Dir die Implementierung gefällt, baue daraus eine Funktion, die Du in zukünftigen Projekten einsetzen kannst.
* Fülle den Kreis mit einer Farbe.
* Kannst Du den Kreis animieren, so dass sein Umfang rhythmisch ansteigt und abschwillt, so wie bei einem schlagenden Herz? (Du kannst Dich dabei von der Animation aus dem letzten Kapitel anleiten lassen.)
* Wie sieht es mit der Bewegung des Kreises aus? Gelingt es Dir, den Kreis zu verschieben und mehrere Kreise innerhalb der Zeichenfläche erscheinen zu lassen?
* Was passiert, wenn Du mehrere Distanzfelder durch unterschiedliche Funktionen und Operationen kombinierst?
```glsl
pct = distance(st,vec2(0.4)) + distance(st,vec2(0.6));
pct = distance(st,vec2(0.4)) * distance(st,vec2(0.6));
pct = min(distance(st,vec2(0.4)),distance(st,vec2(0.6)));
pct = max(distance(st,vec2(0.4)),distance(st,vec2(0.6)));
pct = pow(distance(st,vec2(0.4)),distance(st,vec2(0.6)));
```
* Entwickle drei Kompositionen auf Basis dieser Technik. Wenn Du sie animieren kannst, umso besser!
####Für Deine Werkzeugsammlung
Im Hinblick auf die erforderliche Rechenleistung kann die [```sqrt()```](../glossary/?search=sqrt)-Funktion und alle Funktionen, die darauf basieren sehr kostspielig sein. Deshalb hier nun ein anderer Weg, wie man kreisförmige Distanzfelder mit Hilfe der [```dot()```](../glossary/?search=dot)-Funktion über das Skalarprodukt erzeugen kann.
<div class="codeAndCanvas" data="circle.frag"></div>
### Nützliche Eigenschaften von Distanzfeldern
![Zen garden](zen-garden.jpg)
Distanzfelder lassen sich nutzen, um beinahe jede Art von Form zu zeichnen. Je komplexer die gewünschte Form, desto komplexer fällt in der Regel auch die dafür benötigte Distanzformel aus. Doch sobald Du die benötigte Distanzformel beisammenhast, wird es sehr einfach, gewünschte Effekte darauf anzuwenden, beispielweise weiche Kanten oder mehrfache Umrisse. Aus diesem Grund sind Distanzfelder u.a. bei der Schriftenerzeugung sehr populär, nachzulesen etwa bei [Mapbox GL Labels](https://www.mapbox.com/blog/text-signed-distance-fields/), bei [Matt DesLauriers](https://twitter.com/mattdesl) und bei [Material Design Fonts](http://mattdesl.svbtle.com/material-design-on-the-gpu).
Schau Dir den folgenden Programmcode an.
<div class="codeAndCanvas" data="rect-df.frag"></div>
Wir beginnen, indem wir den Wertebereich unserer *x*- und *y*-Ordinate auf die Spanne zwischen ```-1``` und ```1``` skalieren und damit gleichzeitig die Basis des Koordinatensystems *(0/0)* in die Mitte der Zeichenfläche verschieben. In der *Zeile 24* visualisieren wir die Werte unseres Distanzfeldes, indem wir sie mit zehn multiplizieren und die [```fract()```](../glossary/?search=fract)-Funktion auf das Ergebnis anwenden. *fract()* liefert immer nur den Nachkommateil des Ergebnisses, also eine Zahl zwischen ```0.0``` und ```0.99999...```, so dass bei den wiederholten Aufrufe für die verschiedenen Pixel ein Farbverlauf von Schwarz nach Weiß entsteht. Durch die Multiplikation mit zehn wiederholt sich dieser Verlauf genau zehn Mal. So entsteht ein repetitives Kreismuster, wie bei einem Zen-Garten.
Lass uns einen Blick auf die Formel zur Berechnung des Distanzfeldes in der *Programmzeile 19* werfen. Dort berechnen wir den Abstand zur Position ```(.3,.3)```. Damit dies in allen vier Quadranten gleichermaßen geschieht, wird der zu bearbeitende Punkt jeweils auf den ersten Quadranten abgebildet. Dafür sorgt hier die [```abs()```](../glossary/?search=abs)-Funktion.
Wenn Du die Kommentarzeichen in *Programmzeile 20* entfernst, kannst Du beobachten, wie wir die Entfernung bei allen Punkten um ```0.3``` reduzieren. Anschließend setzen wir den Abstand mit Hilfe der [```min()```](../glossary/?search=min)-Funktion für alle Punkte, deren Abstand dann noch größer als ```0.0``` ist (also vorher größer als ```0.3``` war), auf ```0.0```. Das erzeugt ein neues interessantes Muster.
Sobald Du anschließend die Kommentarzeichen aus der *Programmzeile 21* entfernst, geschieht etwas ähnliches, nur quasi umgekehrt und mit Hilfe der Funktion [```max()```](../glossary/?search=max). Wieder wird der Abstand um ```0.3``` verringert, anschließend aber für alle Punkte auf ```0.0``` gesetzt, deren Abstand nun kleiner als ```0.0``` ist (vorher also zwischen ```0.0``` und ```0.3``` lag). Wir erhalten auf diese Weise mehrere geschachtelte Quadrate mit abgerundeten Ecken.
Entferne nun nach und nach die Kommentarzeichen aus den *Programmzeilen 27 bis 29*, um deren Auswirkung auf das Zeichnen mit dem Distanzfeld zu verstehen.
### Polarformen
![Robert Mangold Ohne Titel (2008)](mangold.jpg)
Im Kapitel über die Verwendung von Farben haben wir kartesische Koordinaten auf Polarkoordinaten abgebildet. Wir berechneten dazu den *Radius* und den *Winkel* jeder Koordinate mit Hilfe der folgenden Formel:
```glsl
vec2 pos = vec2(0.5)-st;
float r = length(pos)*2.0;
float a = atan(pos.y,pos.x);
```
Einige dieser Formeln haben wir auch am Anfang dieses Kapitels genutzt, als es darum ging, Kreise zu zeichnen. Wir berechneten die Entfernung zum Kreismittelpunkt mit Hilfe der [```length()```](../glossary/?search=length)-Funktion. Jetzt, wo wir Distanzfelder kennengelernt haben, öffnet sich uns ein weiterer Weg zum Zeichnen komplexer Formen mithilfe von Polarkoordinaten.
Diese Technik unterliegt gewissen Beschränkungen, ist dafür aber sehr simpel und leistungsfähig. Sie beruht darauf, den Radius eines Kreises in Abhängigkeit des jeweiligen Winkels zu verändern, um unterschiedliche Formen zu erschaffen. Wie genau läuft diese Modulierung ab? Nun, Du hast es vielleicht schon erraten: Mit formgebenden Funktionen.
Unten findest Du verschiedene Funktionen jeweils zwei Mal: einmal als Verlaufskurve in einem kartesischen Koordinatensystem und dann als Shader-Programmcode in einem polaren Koordinatensystem. Dort stehen die verschiedenen formgebenden Funktionen in den *Programmzeilen 21 bis 25*. Entferne nun Schritt für Schritt die Kommentarzeilen und vergleiche den jeweiligen Funktionsgraphen im kartesischen Koordinatensystem mit seinem Äquivalent beim Zeichnen innerhalb eines Polarkoordinatensystem mit GLSL.
<div class="simpleFunction" data="y = cos(x*3.);
//y = abs(cos(x*3.));
//y = abs(cos(x*2.5))*0.5+0.3;
//y = abs(cos(x*12.)*sin(x*3.))*.8+.1;
//y = smoothstep(-.5,1., cos(x*10.))*0.2+0.5;"></div>
<div class="codeAndCanvas" data="polar.frag"></div>
Versuche doch einmal:
* Diese Formen zu animieren.
* Verschiedene formgebende Funktionen zu kombinieren, um Löcher in die Formen zu „stanzen“ und dadurch Blumen, Schneeflocken oder Zahnräder entstehen zu lassen.
* Nutze die ```plot()```-Funktion aus dem Kapitel über formgebende Funktionen, um nur die Kontur der jeweiligen Form zeichnen zu lassen.
### Und nun alles zusammen
Wir haben gelernt, den Radius einer Kreisform mit Hilfe der [```atan()```](../glossary/?search=atan)-Funktion in Abhängigkeit des Winkels für das Zeichnen unterschiedlicher Formen zu nutzen. Nun können wir ```atan()``` auch mit Distanzfeldern einsetzen, um ganz unterschiedliche Effekte zu erzielen.
Unser Trick nutzt die gegebene Anzahl der Seiten eines Polygons, um das benötigte Distanzfeld mit Hilfe von Polarkoordinaten zu erzeugen. Schau Dir dazu auch den [folgenden Programmcode](http://thndl.com/square-shaped-shaders.html) von [Andrew Baldwin](https://twitter.com/baldand) an.
<div class="codeAndCanvas" data="shapes.frag"></div>
* Nutze das obige Programmbeispiel, um eine Funktion zu programmieren, die als Eingabe die Anzahl und Position der Ecken einer gewünschten Form erhält und als Ergebnis den Wert für das Distanzfeld liefert.
* Mische verschiedene Distanzfelder miteinander, indem Du die Funktionen [```min()```](../glossary/?search=min) und [```max()```](../glossary/?search=max) nutzt.
* Wähle ein geometrisches Logo, das Du mit Hilfe von Distanzfeldern replizierst.
Herzlichen Glückwunsch! Du hast Dich durch schwieriges Fahrwasser gekämpft. Nimm eine kleine Pause, damit sich das Erlernte setzen kann. Das Zeichnen komplexer Formen im Land der Shader ist wahrlich nicht ganz trivial, das kann durchaus ein wenig erschöpfen.
Da Du nun weißt, wie man unterschiedliche Formen zeichnet, kommen Dir bestimmt viele interessante Ideen in den Sinn. In den folgenden Kapiteln lernen wir, wie man Formen verschieben, skalieren und rotieren kann. Das wird Dir ermöglichen, komplexe Kompositionen zu erstellen.

@ -0,0 +1,101 @@
## 2D-Matrizen
<canvas id="custom" class="canvas" data-fragment-url="matrix.frag" width="700px" height="200px"></canvas>
### Verschieben
Im letzten Kapitel haben wir gesehen, wie man unterschiedliche Formen zeichnet. Der Trick, um diese Formen auf der Zeichenfläche beliebig zu positionieren, besteht nun darin, das Koordinatensystem „unterhalb“ dieser Formen zu verschieben. Wir erreichen dies, indem wir einfach einen Vektor zu der ```st```-Variable addieren, die die Lage des jeweiligen Objekts beim Zeichnen bestimmt. Dadurch verschiebt sich das gesamte Koordinatensystem.
![](translate.jpg)
Es ist vermutlich einfacher, das Verfahren in der Praxis nachzuvollziehen, als es in der Theorie zu studieren. Schau einfach selbst:
* Entferne die Kommentarzeichen in der *Programmzeile 35*, und Du wirst sehen, wie sich das Zeichenobjekt gemeinsam mit dem darunterliegenden Koordinatenraum bewegt.
<div class="codeAndCanvas" data="cross-translate.frag"></div>
Jetzt versuche Dich an der folgenden Aufgabe:
* Nutze ```u_time``` in Verbindung mit einer formgebenden Funktion, um das kleine Kreuz auf interessante Weise über die Zeichenfläche zu bewegen. Das Vorbild dafür kann durchaus aus der realen Welt stammen, beispielsweise eine Wellenbewegung, das Schwingen eines Pendels, ein springender Ball, ein beschleunigendes Auto oder ein stoppendes Fahrrad.
### Rotationen
Um Objekte rotieren zu lassen, müssen wir ebenfalls nur das zugrundeliegende Koordinatensystem transformieren. Wir verwenden dafür eine [Rotationsmatrix](http://de.wikipedia.org/wiki/Matrix_(Mathematik)). Eine Matrix ist eine geordnete Anordnung von Zahlen in Form von Zeilen und Spalten. Vektoren werden mit Matrizen nach einem festen vorgegebenen Verfahren multipliziert, um den Vektor auf eine bestimmte Art und Weise zu verändern.
[![Aus dem Wikipedia-Eintrag zur Matrizenmultiplikation](matrixes.png)](http://de.wikipedia.org/wiki/Matrizenmultiplikation)
GLSL verfügt über eingebaute Unterstützung für zwei-, drei- und vierdimensionale Matrizen: [```mat2```](../glossary/?search=mat2) (2x2), [```mat3```](../glossary/?search=mat3) (3x3) und [```mat4```](../glossary/?search=mat4) (4x4). Außerdem unterstützt GLSL die Matrizenmultiplikation (```*```) mit einem Vektor sowie die Multiplikation zweier Matrizen mit der speziellen Funktion ([```matrixCompMult()```](../glossary/?search=matrixCompMult)).
Darauf basierend, wie Matrizen funktionieren, kann man Matrizen mit einem bestimmten „Verhalten“ konstruieren. Beispielsweise können wir eine Matrix zum Verschieben eines Vektors nutzen:
![](3dtransmat.png)
Noch interessanter wird es, wenn wir eine Matrix zur Drehung des Koordinatensystems verwenden:
![](rotmat.png)
Schau Dir den folgenden Programmcode an, der die benötigte Matrix für eine Rotation des Koordinatensystems um einen vorgegebenen Winkel produziert. Diese Funktion folgt der obigen Formel für zweidimensionale Vektoren, um die Koordinaten um einen ```vec2(0.0)```-Punkt rotieren zu lassen.
```glsl
mat2 rotate2d(float _angle){
return mat2(cos(_angle),-sin(_angle),
sin(_angle),cos(_angle));
}
```
In Bezug auf die Art und Weise, wie wir Formen bislang gezeichnet haben, ist das noch nicht ganz das, was wir benötigen. Unser Kreuz wird auf der Mitte der Zeichenfläche generiert, ausgehend vom Punkt ```vec2(0.5)```. Vor der Rotation müssen wir die Form deshalb von der Mitte des Koordinatensystem zum ```vec2(0.0)``` verschieben, anschließend die Drehung ausführen und das Objekt dann wieder an seinen ursprünglichen Platz bringen.
![](rotate.jpg)
In Programmcode „gegossen“, sieht das dann wie folgt aus:
<div class="codeAndCanvas" data="cross-rotate.frag"></div>
Probiere die folgenden Übungen aus:
* Entferne die Kommentarzeichnen aus der *Programmzeile 45* und beobachte, was dann passiert.
* Kommentiere das Verschieben vor und nach der Rotation in den *Zeilen 37 und 39* aus und beobachte die Konsequenzen.
* Nutze Rotationen, um die Animation zu verbessern, die Du beim Beispiel zum Verschieben erstellt hast.
### Skalieren
Wir haben gesehen, wie man die Verschiebung und die Rotation von Objekten realisiert, indem man mit Matrizen auf den Koordinatenraum einwirkt. Falls Du bereits mit 3D-Modellierungssoftware oder den Matrizenfunktionen in Procesing gearbeitet hast, weißt Du wahrscheinlich, dass man Matrizen auch für die Skalierung von Objekten verwenden kann.
![](scale.png)
Indem wir uns an der obigen Formel orientieren, können wir eine 2D-Saklierungsmatrix für das gewünschte Vergrößern oder Verkleinern erstellen:
```glsl
mat2 scale(vec2 _scale){
return mat2(_scale.x,0.0,
0.0,_scale.y);
}
```
<div class="codeAndCanvas" data="cross-scale.frag"></div>
Probiere die folgenden Übungen aus, um noch besser zu verstehen, wie das Ganze funktioniert.
* Entferne die Kommentare in der *Programmzeile 42*, um zu sehen, wie der Koordinatenraum skaliert wird.
* Schau Dir an, was geschieht, wenn Du die Verschiebung vor und nach der Skalierung in den *Programmzeilen 37 und 39* entfernst.
* Probiere eine Rotationsmatrix in Verbindung mit einer Skalierungsmatrix aus. Sei Dir bewusst, dass die Reihenfolge der Matrixoperationen dabei eine entscheidende Rolle spielt.
* Jetzt, wo Du weißt, wie man unterschiedliche Formen malt, verschiebt, rotiert und skaliert, ist es an der Zeit, eine etwas komplexere Komposition zu erstellen. Designe und entwickle die Simulation einer [futuristischen Benutzeroberfläche bzw. eines Head-up-Displays](https://www.pinterest.com/patriciogonzv/huds/). Nutze das folgende Beispiel aus den Shadertoys von [Ndel](https://www.shadertoy.com/user/ndel) als Inspirationsquelle und als Referenz.
<iframe width="800" height="450" frameborder="0" src="https://www.shadertoy.com/embed/4s2SRt?gui=true&t=10&paused=true" allowfullscreen></iframe>
### Ein anderes Einsatzgebiet für Matrizen: YUV-Farben
[*YUV*](https://de.wikipedia.org/wiki/YUV-Farbmodell) ist ein Farbmodell, das für die analoge Kodierung von Fotos und Videos verwendet wird. Das Modell berücksichtigt die Grenzen der menschlichen Farbwahrnehmung und nutzt dies für die Beschränkung der Bandbreite (der benötigten Bits) bei der Kodierung der Farbigkeit (Chrominanz).
Der folgende Programmcode zeigt eine interessante Einsatzmöglichkeit für den Einsatz von Matrizenfunktionen zur Konvertierung von Farben zwischen zwei Farbräumen bzw. Farbsystemen.
<div class="codeAndCanvas" data="yuv.frag"></div>
Wie Du siehst, behandeln wir Farben hier als Vektoren, indem wir sie mit Matrizen multiplizieren. Auf diese Weise können wir die Farben über ihre Farbwerte hin und her bewegen.
In diesem Kapitel haben wir gelernt, wie man Matrixtransformationen für das Verschieben, Rotieren und Skalieren von Vektoren nutzt. Für die Erstellung von Kompositionen aus mehreren grafischen Formen und Objekten sind diese Transformationen essenziell. Im nächsten Kapitel werden wir all das Erlernte anwenden, um bezaubernde prozedurale Muster zu erstellen. Du wirst sehen, dass die Wiederholung und Variation von Programmcode höchst interessante Resultate liefern kann.

@ -0,0 +1,116 @@
## Muster
Weil Shader-Programme Bildpunkt für Bildpunkt ausgeführt werden, spielt es keine große Rolle, wie oft man ein bestimmtes Muster innerhalb der Zeichenfläche wiederholt die Anzahl der Berechnungen bleibt gleich. Aus diesem Grund eignen sich Fragment-Shader ganz hervorragend für die Erzeugung sich wiederholender Kachelmuster.
[ ![Nina Warmerdam Das IMPRINT Projekt (2013)](warmerdam.jpg) ](../edit.php#09/dots5.frag)
In diesem Kapitel werden wir anwenden, was wir bislang gelernt haben, und es über den gesamten Raum unserer Zeichenfläche wiederholen. Wie schon in den vorhergehenden Kapiteln wird unsere Strategie darin bestehen, die Koordinaten zu vervielfältigen. Dadurch werden sich Formen, die wir innerhalb des Koordinatenraumes zwischen ```0.0``` und ```1.0``` zeichnen, vervielfältigen lassen, so dass ein kontinuierliches Muster entlang eines Rasters entsteht.
*"Das Gitternetz eröffnet einen Rahmen, innerhalb dessen sich die menschliche Intuition und Schöpfungskraft entfalten kann. Inmitten des Chaos der Natur stellen Muster einen Kontrastpunkt dar, indem sie eine vorhersehbare, sich wiederholende Ordnung realisieren. Schon seit frühen Mustern auf Keramikflächen in antiken Bädern haben die Menschen Gitternetze genutzt, um ihr Leben durch repetitive Dekorationen zu verschönen.“* [*10 PRINT*, Mit Press, (2013)](http://10print.org/)
Lasst uns zunächst noch einmal die [```fract()```](../glossary/?search=fract)-Funktion ins Gedächtnis rufen. Sie liefert den Nachkommateil einer Zahl zurück, wodurch ```fract()``` effektiv den Modulo (Rest) einer Division durch 1 ergibt ([```mod(x,1.0)```](../glossary/?search=mod)). Unsere normalisierte Variable für das Koordinatensystem (```st```) bewegt sich ohnehin zwischen ```0.0``` und ```1.0```. Deshalb macht es wenig Sinn, Berechnungen wie die folgende anzustellen:
```glsl
void main(){
vec2 st = gl_FragCoord.xy/u_resolution;
vec3 color = vec3(0.0);
st = fract(st);
color = vec3(st,0.0);
gl_FragColor = vec4(color,1.0);
}
```
Wenn wir aber das Koordinatensystem hochskalieren sagen wir einmal um den Faktor drei erhalten wir drei interpolierende Sequenzen: die Erste mit Fließkommawerten von ```0``` bis ```1```, die Zweite mit Werten von ```1``` bis ```2``` und die Dritte mit Werten zwischen ```2``` und ```3```.
<div class="codeAndCanvas" data="grid-making.frag"></div>
Jetzt ist es an der Zeit, in jedem dieser Drei mal Drei „Unterräume“ zu zeichnen, indem Du die Kommentarzeichen in *Programmzeile 27* entfernst. (Weil wir die *x*- und *y*-Ordinate gleichermaßen skalieren, bleibt das Seitenverhältnis erhalten.)
Probiere einige der folgenden Übungen aus, um Dein Verständnis zu vertiefen:
* Multipliziere die Koordinaten (den Raum) mit anderen Faktoren. Probiere auch einmal nicht ganzzahlige Werte, sowie unterschiedliche Faktoren für *x* und *y* aus.
* Verwandle diesen „Muster-Trick“ in eine wiederverwendbare Funktion.
* Teile den Raum in drei Spalten und drei Zeilen auf. Finde einen Weg, wie Dein Programmcode erkennen kann, an welcher Zeile und Spalte er gerade arbeitet und nutze dies, um die gezeichneten Formen zu variieren. Versuche, ein Tick-Tack-Toe-Spielfeld nachzuempfinden.
### Anwendung von Matrizen innerhalb von Mustern
Weil jeder „Unterraum“ und jede Gitterzelle eine verkleinerte Fassung des normalisierten Koordinatensystems darstellt, mit dem wir bereits gearbeitet haben, können wir auch Matrizenoperationen darauf anwenden. So lässt sich der Koordinatenraum innerhalb einer Gitterzelle verschieben, rotieren und auch skalieren.
<div class="codeAndCanvas" data="checks.frag"></div>
* Überlege Dir interessante Wege, um dieses Muster zu animieren. Denke z.B. an die Animation von Farbe, Form oder Bewegung. Erstelle drei unterschiedliche Animationen.
* Erzeuge komplexere Muster durch das Zusammenfügen unterschiedlicher Formen.
[![](diamondtiles-long.png)](../edit.php#09/diamondtiles.frag)
* Vereine unterschiedliche Schichten von Mustern, um Dein eigenes Karomuster entstehen zu lassen, wie es [für schottische Tartans typisch ist](http://de.wikipedia.org/wiki/Tartan_(Muster)).
[ ![Vektormuster eines schottischen Tartans von Kavalenkava](tartan.jpg) ](http://graphicriver.net/item/vector-pattern-scottish-tartan/6590076)
### Versetzte Muster
Sagen wir einmal, wir wollen ein Mauerwerk zeichnen. Beim Blick auf eine solche Wand fällt sofort auf, dass die Steine in jeder Reihe jeweils um eine halbe Steinlänge versetzt sind. Stellt sich natürlich die Frage, wie wir so etwas per Programmcode umsetzen können?
![](brick.jpg)
Im ersten Schritt müssen wir zunächst einmal wissen, ob die Zeile, an der unser Thread gerade arbeitet, gerade oder ungerade ist. Denn darüber können wir den Versatz der Muster entlang der *x-Achse* bestimmen. Dafür können wir [```mod()```](../glossary/?search=mod) mit ```2.0``` verwenden und schauen, ob das Ergebnis weniger als ```1.0``` beträgt oder nicht. Wirf einen Blick auf die folgende Formel und entferne nacheinander die Kommentarzeichen in den letzten beiden Zeilen.
<div class="simpleFunction" data="y = mod(x,2.0);
// y = mod(x,2.0) < 1.0 ? 0. : 1. ;
// y = step(1.0,mod(x,2.0));"></div>
Wie Du siehst, können wir den [ternären Operator](http://de.wikipedia.org/wiki/Bedingte_Anweisung_und_Verzweigung#Auswahloperator) nutzen, um zu prüfen, ob das Ergebnis von [```mod()```](../glossary/?search=mod) mit ```2.0``` unter dem Wert von ```1.0``` liegt. Oder wir können die [```step()```](../glossary/?search=step)-Funktion nutzen, um das gleiche Ergebnis zu erzielen. Und ```step()``` ist in der konkreten Ausführung sogar noch etwas schneller. Doch wie kommt das? Obwohl es schwer vorhersehbar ist, wie eine bestimmte Grafikkarte Shader-Code kompiliert und optimiert, können wir davon ausgehen, dass eingebaute Funktionen schneller ausgeführt werden, also solche, die erst in mehrere Einzelschritte aufgelöst werden müssen. Wann immer Du eine eingebaute Funktion für Deine Zwecke nutzen kannst, tue dies deshalb auch!
Nun haben wir also unsere „Ungerade-Funktion“ beisammen, sodass wir den ungeraden Reihen unseres Mauerwerks einen Versatz geben können. In der *Programmzeile 14* des folgenden Listings befindet sich der entsprechende Programmcode. Beachte, dass das Ergebnis unserer Berechnung für gerade Reihen ```0.0``` lautet und die Multiplikation mit dem Versatz von ```0.5``` dann eben auch ```0.0``` ergibt. Bei ungeraden Reihen multiplizieren wir den Versatz von ```0.5``` hingegen mit ```1.0```, so dass daraus eine entsprechende Verschiebung der *x-Achse* des Koordinatensystems folgt.
Entferne jetzt die Kommentarzeichen in der *Programmzeile 32*, wodurch das Seitenverhältnis unseres Koordinatensystems gestreckt wird und wir die Anmutung eines modernen Mauerwerks erhalten. Wenn Du die Kommentarzeichen in *Programmzeile 40* entfernst, erkennst Du die Anordnung und Wiederholung des Koordinatensystems anhand der Farben Rot und Grün.
<div class="codeAndCanvas" data="bricks.frag"></div>
* Versuche diese Grafik zu animieren, indem Du den Versatz auf Basis der Zeit veränderst.
* Baue eine weitere Animation, bei der sich die geraden Reihen nach links und die ungeraden Reihen nach rechts bewegen.
* Gelingt es Dir, diesen Effekt auch in Bezug auf die Spalten zu wiederholen?
* Versuche einen Versatz entlang der *x-Achse* mit einem entlang der *y-Achse* zu kombinieren, um so etwas wie die folgende Animation zu erhalten:
<a href="../edit.php#09/marching_dots.frag"><canvas id="custom" class="canvas" data-fragment-url="marching_dots.frag" width="520px" height="200px"></canvas></a>
## Truchet-Kacheln
Wir haben nun gelernt, wie man feststellt, ob sich die zu zeichnende Gitterzelle in einer geraden oder ungeraden Zeile bzw. Spalte befindet, Auf Basis dieser Information können wir ein einzelnes Designelement in Abhängigkeit seiner Position wiederverwenden. Wirf einen Blick auf die sogenannten [Truchet-Kacheln](http://en.wikipedia.org/wiki/Truchet_tiles), bei denen eine einzelne Form in vier unterschiedlichen Anordnungen dargestellt wird:
![](truchet-00.png)
Indem wir die Anordnung des Musters von Kachel zu Kachel variieren, können wir eine unendliche Menge von Designs erzeugen.
![](truchet-01.png)
Schaue Die die Funktion ```rotateTilePattern()``` genau an. Sie unterteilt den Raum jeweils in vier Zellen und dreht jede davon in eine unterschiedliche Richtung.
<div class="codeAndCanvas" data="truchet.frag"></div>
* Kommentiere die *Programmzeilen 69 bis 72*, entferne die Kommentare wieder und vervielfältige diese Zeilen, um neue Designs entstehen zu lassen.
* Ersetze das Schwarzweiß-Dreieck durch andere Formen, beispielsweise Halbkreise, gedrehte Quadrate oder Linien.
* Kodiere andere Muster, bei denen die Elemente in Abhängigkeit ihrer Position unterschiedlich gedreht werden.
* Entwickle ein Muster, das weitere Merkmale in Abhängigkeit der Elementposition verändert.
* Denke an andere Darstellungen, die nicht notwendigerweise Muster verkörpern müssen, aber die Konzepte aus diesem Abschnitt aufgreifen, beispielsweise an das [chinesische I-Ging](http://de.wikipedia.org/wiki/I_Ging).
<a href="../edit.php#09/iching-01.frag"><canvas id="custom" class="canvas" data-fragment-url="iching-01.frag" width="520px" height="200px"></canvas></a>
## Erschaffe Deine eigenen Regeln
Prozedurale, sich wiederholende Muster zu kreieren, ist eine interessante Übung für den Geist. Es geht darum, den minimalen Satz an Elementen zu finden, die sich wiederholen müssen, um ein größeres komplexes Ganzes zu erschaffen. Diese Vorgehensweise ist sehr alt. Die Menschheit benutzt Muster und Gitternetze schon seit tausenden von Jahren, um Wände und Böden, Textilien und andere Objekte zu verzieren. Angefangen von mäandernden Mustern im alten Griechenland bis hin zu chinesischen Gitterfenstern, ist es immer wieder das Spiel aus Wiederholung bei gleichzeitiger Variation, die unsere Fantasie anregt. Nimm Dir ein wenig Zeit, um diese Art von [Dekorationen](https://archive.org/stream/traditionalmetho00chririch#page/130/mode/2up) und [Mustern](https://www.pinterest.com/patriciogonzv/paterns/) zu studieren. Von geometrischen Mustern aus Arabien bis hin zu prachtvollen Stoffmustern aus dem afrikanischem Kulturkreis eröffnet sich Dir ein ganzes Universum an Mustern, von denen Du lernen kannst.
![Franz Sales Meyer Handbuch der Ornamentik (1920)](geometricpatters.png)
Mit diesem Kapitel enden die Abschnitte zum algorithmischen Zeichnen. In den folgenden Kapiteln werden wir sehen, wie man ein wenig mehr Zufall in unsere Shader bringt, um die Natur nachzuempfinden.

@ -0,0 +1,93 @@
# Generative Designs
Nachdem wir in den vorangegangenen Kapiteln so viel über Wiederholungen und wohlgeformte Ordnungen gelernt haben, ist es nur konsequent, nun eine kleine Exkursion in das Reich des Chaotischen zu unternehmen.
## Zufall
[![Ryoji Ikeda Testmuster (2008) ](ryoji-ikeda.jpg) ](http://www.ryojiikeda.com/project/testpattern/#testpattern_live_set)
Zufälligkeit ist der konsequenteste Ausdruck von Entropie. Doch wie können wir Zufälle innerhalb einer so vorhersehbaren Umgebung wie die der Programmiersprache GLSL erzeugen?
Lass uns damit beginnen, die folgende Funktion zu analysieren:
<div class="simpleFunction" data="y = fract(sin(x)*1.0);"></div>
Oben sehen wir das Ergebnis, wenn man nur den Nachkommateil der Werte einer *Standardsinuskurve* betrachtet. Die Funktionswerte von [```sin()```](../glossary/?search=sin) oszillieren zwischen ```-1.0``` und ```1.0```. Hier wurde der Vorkommateil abgeschnitten, so dass wir es nur noch mit positiven Werten zwischen ```0.0``` und ```0.99999999...``` zu tun haben. Wir können diesen Effekt nutzen, um „pseudo-zufällige“ Zahlen zu generieren, indem wir die Sinuswelle in kleine Teilstücke „aufbrechen“. Wie das geht? Indem wir das Resultat von [```sin(x)```](../glossary/?search=sin) mit großen Zahlen multiplizieren. Füge dem Faktor ```1.0``` in der obigen Formel einfach ein paar Nullen vor dem Komma hinzu eine nach der anderen und beobachte die Auswirkungen auf den Funktionsgraphen.
Spätestens, wenn Du bei ```100000.0``` angekommen bist (und die Formel so aussieht ```y = fract(sin(x)*100000.0)``` ), wirst Du die zugrundeliegende Sinuswelle nicht mehr erkennen können. Die Granularität des Nachkommaergebnisses hat den stetigen Fluss der Sinuswelle in ein pseudo-zufälliges Chaos verwandelt.
## Wir steuern das
Zufälligkeit für die Shader-Programmierung nutzbar zu machen, kann ganz schön kompliziert sein. Manchmal ist der Zufall zu chaotisch, dann wieder nicht zufällig genug. Schau Dir den folgenden Funktionsgraphen an. Wir haben ihn mit Hilfe der ```rand()```-Funktion konstruiert, die nach eben jenem Prinzip aufgebaut ist, das wir eben beschrieben haben.
Bei einem genauen Blick erkennst Du, dass die [```sin()```](../glossary/?search=sin)-Funktion ihren Scheitel bei ```-1.5707``` und ```1.5707``` hat. Ich wette, Du ahnst bereits warum weil dort das Maximum und Minimum einer Sinuswelle liegt, nämlich bei *PI /2.0*.
Außerdem wirst Du im Hinblick auf die Zufallsverteilung feststellen, dass es eine gewisse Häufung im mittleren Bereich im Vergleich zu den äußeren Bereichen gibt.
<div class="simpleFunction" data="y = rand(x);
//y = rand(x)*rand(x);
//y = sqrt(rand(x));
//y = pow(rand(x),5.);"></div>
Vor einiger Zeit hat der Autor mit dem Pseudonym [Pixelero](https://pixelero.wordpress.com) einen interessanten [Artikel über Zufallsverteilungen](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/) veröffentlicht. Ich habe einige der Funktionen, die er dort anspricht, in dem obigen Graphen aufgeführt. Du kannst die Kommentare in den einzelnen Zeilen entfernen, um Dir diese Funktionen und ihre Zufallsverteilung anzuschauen.
Wenn Du den bereits zitierten Artikel von [Pixelero](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/) liest, darfst Du nicht vergessen, das unsere ```rand()```-Funktionen deterministische Zufallswerte erzeugt, die als „pseudo-zufällig“ bezeichnet werden. Damit ist unter anderem gemeint, das beispielsweise ```rand(1.)``` immer den gleichen Wert zurückliefern wird. Pixelero geht in seinem Artikel auch auf die Funktion ```Math.random()```unter *ActionScript* ein, die beispielsweise nicht-deterministisch ist. Jeder Aufruf mit einem gegebenen Wert als Funktionsargument liefert bei ihr andere Werte zurück.
## 2D-Zufall
Mit diesem vertieften Verständnis von Zufall im Gepäck ist es an der Zeit, den Zufall in zwei Dimensionen wirken zu lassen entlang der *x-Achse* und der *y-Achse*. Dafür müssen wir einen zweidimensionalen Vektor in einen eindimensionalen Fließkommawert verwandeln. Man kann dies auf verschiedenen Wegen erreichen, aber die Nutzung der [```dot()```](../glossary/?search=dot)-Funktion ist in diesem Fall besonders hilfreich. Sie liefert einen Fließkommawert zwischen ```0.0``` und ```1.0``` zurück, je nachdem wie die beiden Vektoren, deren Skalarprodukt sie bildet, zueinander stehen.
<div class="codeAndCanvas" data="2d-random.frag"></div>
Bitte schaue Dir die *Programmzeilen 13 bis 15* an und beobachte, wie wir den ```vec2 st``` mit einem anderen (konstanten) Vektor (```vec2(12.9898,78.233)```) verknüpfen.
* Verändere die konstanten Werte in den *Programmzeilen 14 und 15*. Beobachte, wie sich das Zufallsmuster dadurch ändert und überlege, was wir daraus lernen können.
* Verknüpfe die Zufallsfunktion mit der Mausposition (```u_mouse```) und der Zeit (```u_time```), damit der Zufall noch weniger vorhersehbar wird.
## Das Chaos nutzen
Zufallswerte in zwei Dimensionen erinnern stark an das Rauschen im analogen TV, wenn das Antennensignal fehlt, nicht wahr? Als Ausgangsmaterial für die Erzeugung von Grafiken scheint es nur wenig geeignet. Aber lass uns einmal schauen, ob wir nicht doch etwas Sinnvolles damit anfangen können.
Unser erster Schritt besteht darin, ein Gitternetz zu unterlegen. Mit Hilfe der [```floor()```](../glossary/?search=floor)-Funktion werden wir eine Integer-Tabelle der Zellen erzeugen. Schau Dir den folgenden Programmcode an, insbesondere die *Programmzeilen 22 und 23*.
<div class="codeAndCanvas" data="2d-random-mosaic.frag"></div>
Nachdem wir den Koordinatenraum in ein Gitternetz mit 10 x 10 Feldern unterteilt haben (in *Programmzeile 21*), separieren wir den Vorkommateil der jeweiligen Koordinate von ihrem Nachkommateil. Wir kennen das bereits aus der Unterteilung des Koordinatenraums in kleinere Zellen, die sich jeweils von ```0.0``` bis ```1.0``` erstrecken. Indem wir den ganzzahligen Teil der Koordinate isolieren, erhalten wir einen gemeinsamen Wert für alle Pixel innerhalb eines Feldes des Gitternetzes. Diesen Wert nutzen wir dann, um einen Zufallswert für diese Region zu generieren. Weil unsere Zufallsfunktion deterministisch ist, wird der Zufallswert für alle Bildpunkte innerhalb dieser Zelle gleich sein.
Entferne die Kommentierung von *Programmzeile 29*, um zu beobachten, wie wir den Nachkommateil der Koordinate behalten. Dadurch können wir diesen Wert weiterhin nutzen, um innerhalb der Zellen zu zeichnen.
Indem wir diese beiden Werte kombinieren den Vorkomma- und den Nachkommateil der Koordinate können wir Ordnung und Chaos zusammenbringen.
Schau Dir einmal die GLSL-Portierung des berühmten Labyrinth-Generators in BASIC an, der dort nur aus einer einzigen Programmierzeile besteht: ```10 PRINT CHR$(205.5+RND(1)); : GOTO 10```
<div class="codeAndCanvas" data="2d-random-truchet.frag"></div>
Hier nutze ich die Zufallswerte der Zellen, um innerhalb der Zellen eine Linie mal in die eine, mal in die andere Richtung zu zeichnen. Ich setze dafür die ```truchetPattern()```-Funktion aus dem vorangehenden Kapitel ein (es geht um die *Programmzeilen 41 bis 47*).
Du erhältst ein sehenswertes animiertes Muster, wenn Du die Kommentarzeichen aus den *Programmzeilen 35 und 36* entfernst.
## Meister des Zufalls
[Ryoji Ikeda](http://www.ryojiikeda.com/), ein japanischer Komponist elektronischer Musik und Grafikkünstler, ist ein Meister des Zufälligen. Es fällt schwer, von seinen Arbeiten nicht berührt zu werden. Der Einsatz des Zufalls in seinen Werken ist so gestaltet, dass nicht verwirrendes Chaos, sondern ein Abbild der Komplexität unserer technischen Kultur entsteht.
<iframe src="https://player.vimeo.com/video/76813693?title=0&byline=0&portrait=0" width="800" height="450" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
Schau Dir die Arbeiten von [Ikeda](http://www.ryojiikeda.com/) an und versuche Dich an den folgenden Aufgaben:
* Erzeuge Zeilen sich gegenläufig bewegender Zellen mit Farben aus Zufallswerten. Stelle nur die Zellen mit helleren Werten dar. Lasse sich die Geschwindigkeit der Bewegung im Laufe der Zeit verändern.
<a href="../edit.php#10/ikeda-00.frag"><canvas id="custom" class="canvas" data-fragment-url="ikeda-00.frag" width="520px" height="200px"></canvas></a>
* Erzeuge auf ganz ähnliche Weise mehrere Zeilen, von denen sich jede mit unterschiedlicher Geschwindigkeit und Richtung seitwärts bewegt. Verknüpfe die Mausposition mit dem Schwellenwert für die Anzeige der Zellen aufgrund ihrer Helligkeit.
<a href="../edit.php#10/ikeda-03.frag"><canvas id="custom" class="canvas" data-fragment-url="ikeda-03.frag" width="520px" height="200px"></canvas></a>
* Erzeuge weitere interessante Effekte, bei denen der Zufall eine Rolle spielt.
<a href="../edit.php#10/ikeda-04.frag"><canvas id="custom" class="canvas" data-fragment-url="ikeda-04.frag" width="520px" height="200px"></canvas></a>
Zufallswerte auf ästhetische Art und Weise einzusetzen, kann schwierig sein, besonders wenn man Simulationen erstellen möchten, die die Natur nachahmen. Zufall ist einfach zu chaotisch und nur sehr wenige Dinge ums uns herum entstehen wirklich komplett zufällig. Wenn Du Dir beispielsweise das Muster von Regentropfen oder den Verlauf eines Aktienkurses anschaust zwei Vorgänge, die Beide sicherlich eine Menge mit Zufall zu tun haben wirst Du eben doch kein Chaos, sondern komplexe Strukturen und Abhängigkeiten erkennen. Schließlich sind hier jenseits des Zufälligen immer auch systemabhängige Korrelationen und ein Bezug auf vorherige Systemzustände am Werk.
Das nächste Kapitel beschäftigt sich deshalb mit Rauschen, dem sanften und der Natur nachempfunden Weg, um Dinge dynamisch und innerhalb des Chaotischen auch ein wenig strukturiert wirken zu lassen.

@ -0,0 +1,230 @@
![NASA / WMAP Wissenschaftsteam](mcb.jpg)
## Rauschen
Im letzten Kapitel haben wir mit Zufallsfunktionen gearbeitet, die wie weißes Rauschen auf dem Fernsehbildschirm wirken. Nach so vielen Shader-Funktionen auf einmal dreht sich Dir bestimmt der Kopf und vielleicht sind auch Deine Augen etwas müde. Jetzt ist ein guter Moment, um einen kleinen Spaziergang zu unternehmen und ein wenig nach Luft zu schnappen.
Draußen im Freien spüren wir den Luftzug auf unserer Haut und die Sonne in unserem Gesicht. Die Erde ist ein so lebendiger und vielgestaltiger Ort voller Farben, Texturen und Klängen. Während wir uns in der Natur bewegen, können wir gar nicht anders, als die unterschiedlichen Oberflächen von Straßen, Gestein, Bäumen und Wolken wahrzunehmen.
![](texture-00.jpg)
![](texture-01.jpg)
![](texture-02.jpg)
![](texture-03.jpg)
![](texture-04.jpg)
![](texture-05.jpg)
![](texture-06.jpg)
Die Unvorhersehbarkeit dieser Texturen könnte man als „zufällig“ auffassen. Dabei wirken sie so gar nicht wie die Zufallsstrukturen, mit denen wir uns im letzten Kapitel befasst haben. Die Wirklichkeit ist ein so komplexer Ort! Wir kann es uns gelingen, ihr Antlitz mit Hilfe von Algorithmen nachzuahmen?
Diese Frage beschäftigte [Ken Perlin](https://mrl.nyu.edu/~perlin/) in den frühen 1980er Jahren, als er den Auftrag erhielt, realistische Texturen für den Hollywood-Film „Tron“ zu erschaffen. Er entwickelte damals eine elegante Vorgehensweise, die als „Noise Algorithmus“ bekannt und sogar mit einem Oskar prämiert wurde (kein Witz).
![Disney - Tron (1982)](tron.jpg)
Die folgende Funktion entspricht nicht dem klassischen Noise-Algorithmus von Perlin, aber sie ist ein guter Ausgangspunkt, um die Erzeugung „verrauschter“-Strukturen zu begreifen.
<div class="simpleFunction" data="
float i = floor(x); // ganzzahliger Teil
float f = fract(x); // Nachkommateil
y = rand(i); //rand() wurde im vorangegangenen Kapitel beschrieben
//y = mix(rand(i), rand(i + 1.0), f);
//y = mix(rand(i), rand(i + 1.0), smoothstep(0.,1.,f));
"></div>
In diesen Zeilen gehen wir ähnlich vor, wie im vorangegangenen Kapitel. Wir teilen eine fortlaufende Fließkommazahl (```x```) in ihren ganzzahligen Vorkommateil (```i```) und ihren Nachkommateil (```f```) auf. Wir nutzen dabei [```floor()```](.../glossary/?search=floor), um ```i``` zu erhalten, sowie [```fract()```](.../glossary/?search=fract) für die Berechnung von ```f```. Dann wenden wir ```rand()``` auf den ganzzahligen Teil von ```x``` an, wodurch wir für jede Ganzzahl eine einzigartige Zufallszahl erhalten.
Dahinter folgen zwei Programmzeilen, die zunächst auskommentiert sind. Die Erste davon interpoliert zwischen dem Zufallswert (```rand(i)```) und dem Zufallswert von (```rand(i+1)```) (also zwischen zwei ganz unterschiedlichen Zahlen) auf lineare Weise, wobei der Abstand für die Interpolation jeweils durch (```f```) bestimmt wird.
```glsl
y = mix(rand(i), rand(i + 1.0), f);
```
Fahre fort, indem Du die Kommentarzeichen für diese Zeile entfernst und Dir das Ergebnis anschaust.
An diesem Punkt unseres kleinen GLSL-Kurses wissen wir bereits, dass es noch etwas besseres als eine simple lineare Interpolation gibt, nicht wahr? Entferne deshalb die Kommentarzeichen aus der nächsten Zeile, die [```smoothstep()```](.../glossary/?search=smoothstep) nutzt, um bei der Interpolation weichere Verläufe und Übergänge zu erzielen.
```glsl
y = mix(rand(i), rand(i + 1.0), smoothstep(0.,1.,f));
```
Sobald Du die Kommentarzeichen aus dieser Zeile entfernt hast, erscheint ein anderes Ergebnis. In einigen Implementationen für Rausch-Funktionen verwenden die Autoren lieber ihre eigenen kubischen Kurven an Stelle von [```smoothstep()```](.../glossary/?search=smoothstep), wie etwa im folgenden Beispiel.
```glsl
float u = f * f * (3.0 - 2.0 * f ); // kubische Verlaufskurve
y = mix(rand(i), rand(i + 1.0), u); // angewandt auf die Interpolation
```
Diese *sanfte Zufälligkeit* ist das entscheidende Merkmal, auf das es vielen Grafikkünstlern ankommt. Erst dadurch wird es möglich, geometrische Formen und Bilder zu erstellen, die so organisch wirken, als kämen sie direkt aus der Natur. Perlins Noise-Algorithmus wurde seit seiner Veröffentlichung immer wieder in ganz unterschiedlichen Programmiersprachen und für verschiedene Dimensionen implementiert. Er hat Grafiker und Grafikkünstler auf der ganzen Welt bei ihren Arbeiten unterstützt.
![Robert Hodgin - Written Images (2010)](robert_hodgin.jpg)
Und nun bist Du dran:
* Entwickle Deine eigene ```float noise(float x)```-Funktion.
* Nutze Deine Noise-Funktion, um Formen zu animieren, indem Du sie bewegst, rotierst oder skalierst.
* Erstelle eine animierte Komposition aus mehreren Formen, die „miteinander“ tanzen, indem Du auf Noise-Funktionen zurückgreifst.
* Baue organisch wirkende Formen mit Hilfe der Noise-Funktion.
* Sobald Du auf diese Weise eine eigene „Kreatur“ erschaffen hast, versuche ihr Lebendigkeit einzuhauchen, indem Du sie auf ganz charakteristische Weise bewegst.
## 2D-Rauschen
![](02.png)
Jetzt, wo wir wissen, wie man Rauschen in einer Dimension erzeugt, können wir uns dem zweidimensionalen Rauschen zuwenden. Während wir im eindimensionalen Raum entlang einer Linie zwischen zwei Punkten (```fract(x)``` und ```fract(x)+1.0```) interpolieren, geschieht dies im zweidimensionalen Raum zwischen den vier Eckpunkten eines Vierecks innerhalb einer Ebene (```fract(st)```, ```fract(st)+vec2(1.,0.)```, ```fract(st)+vec2(0.,1.)``` und ```fract(st)+vec2(1.,1.)```).
![](01.png)
In ähnlicher Weise müssen wir im dreidimensionalen Raum vorgehen. Hier sind es die acht Ecken eines Kubus, zwischen denen es zu interpolieren gilt. Dabei dreht sich alles um die Interpolation von Zufallswerten (engl. random values), weshalb man in diesem Zusammenhang auch von **Value Noise** spricht.
![](04.jpg)
Wie schon bei unserem Beispiel für den eindimensionalen Raum, erfolgt die Interpolation auch hier nicht linear, sondern kubisch, damit ein sanfter Verlauf zwischen allen Punkten des viereckigen Rasters entsteht.
![](05.jpg)
Schau Dir die folgende Noise-Funktion an.
<div class="codeAndCanvas" data="2d-noise.frag"></div>
Wir „blasen“ den Raum zunächst auf das Fünffache auf (*Programmzeile 45*), damit wir die Interpolation zwischen den einzelnen Elementen unseres Rasters besser erkennen können. Innerhalb der Noise-Funktion erfolgt dann die Einteilung des Raumes in einzelne Zellen. Wir speichern die Integer-Position der Zelle, ebenso den Nachkommateil für die Position innerhalb der Zelle. Die Integer-Position nutzen wir, um einen Zufallswert für alle vier Eckpunkte der Zelle zu erhalten (*Programmzeilen 23-26*). Schließlich interpolieren wir in der *Programmzeile 35* zwischen den vier zufällig gewählten Eckpunkten auf Basis des Nachkommateils, den wir zuvor gespeichert haben.
Jetzt bist Du wieder dran. Versuche Dich an den folgenden Aufgaben:
* Ändere den Multiplikationsfaktor in *Programmzeile 45*. Versuche ihn zu animieren.
* Versuche herauszufinden, ab welcher Vergrößerungsstufe das Rauschen wieder vollkommen zufällig und unzusammenhängend (chaotisch) wirkt.
* Ab welcher Vergrößerungsstufe ist das Rauschen nicht mehr wahrnehmbar?
* Versuche die Noise-Funktion sinnvoll mit den Mauskoordinaten in Verbindung zu bringen.
* Was wäre, wenn wir den Farbverlauf des Rauschens als Distanzfeld behandeln? Versuche etwas Interessantes damit anzufangen.
* Nun, da wir ein gewisses Maß an Kontrolle über Ordnung und Chaos erzielt haben, ist es an der Zeit, dieses Wissen umzusetzen. Erstelle eine Komposition aus Rechtecken, Farben und Rauschen, die an die Struktur eines Kunstwerks von [Mark Rothko](http://de.wikipedia.org/wiki/Mark_Rothko) erinnert.
![Mark Rothko - Three (1950)](rothko.jpg)
## Rauschen und seine Verwendung für generative Designs
Noise-Algorithmen wurden ursprünglich entwickelt, um digitalen Texturen ein natürliches Aussehen zu verleihen. Die ein- und zweidimensionale Implementation, die wir bislang betrachtet haben, verwendet dafür Interpolationen zwischen Zufallswerten (engl. *random values*), weshalb sie als **Value Noise** bezeichnet wird. Doch es gibt noch andere Verfahren, um Rauschen zu erzeugen.
[ ![Inigo Quilez - Value Noise](value-noise.png) ](../edit.php#11/2d-vnoise.frag)
Wie die vorangegangenen Abschnitte gezeigt haben, tendiert *Value Noise* zur Erzeugung blockartiger Strukturen. Um diesen Blockeffekt zu reduzieren, hat [Ken Perlin](https://mrl.nyu.edu/~perlin/) im Jahre 1985 einen weiteren Algorithmus mit Namen **Gradient Noise** entwickelt. Ken hatte herausgefunden, wie man zwischen zufälligen Gradienten (Verläufen) interpoliert, anstatt zwischen einfachen Zufallszahlen. Diese Gradienten waren das Ergebnis einer 2D-Zufallsfunktion, die Richtungsvektoren (bei GLSL in Form eines ```vec2```) anstelle einfacher Fließkommazahlen (```float```) zurückliefert. Klicke auf das folgende Bild, um einen Blick auf den dahinterstehenden Programmcode zu werfen und zu verstehen, wie das Ganze funktioniert.
[ ![Inigo Quilez - Gradient Noise](gradient-noise.png) ](../edit.php#11/2d-gnoise.frag)
Nimm Dir einen Moment Zeit, um die beiden folgenden Beispiele von [Inigo Quilez](http://www.iquilezles.org/) zu studieren und richte Deine Aufmerksamkeit dabei besonders auf die Unterschiede zwischen [*Value Noise*](https://www.shadertoy.com/view/lsf3WH) und [*Gradient Noise*](https://www.shadertoy.com/view/XdXGW8).
Wie ein Maler, der genau weiß, wie die Farben auf seiner Staffelei miteinander harmonieren, werden auch wir die Noise-Funktionen umso besser nutzen können, je mehr wir deren Vorgehensweise verstehen. Wenn wir beispielsweise eine zweidimensionale Noise-Funktion nutzen, um den Raum zu drehen, während wir gerade Linien zeichnen, entsteht der folgende Dreheffekt, der stark an die Maserung von Holz erinnert. Auch hier kannst Du wieder auf die Grafik klicken, um der den Shader-Code dahinter anzuschauen.
[ ![Holzmaserung](wood-long.png) ](../edit.php#11/wood.frag)
```glsl
pos = rotate2d( noise(pos) ) * pos; // drehe den Raum
pattern = lines(pos,.5); // zeichne Linien
```
Ein anderer Weg zur Erzeugung interessanter Muster mit Hilfe von Noise-Funktionen besteht in ihrer Behandlung als Distanzfeld und der Anwendung einiger Tricks, die wir im [Kapitel über Formen](../07/) kennengelernt haben.
[ ![Farbspritzer-Textur](splatter-long.png) ](../edit.php#11/splatter.frag)
```glsl
color += smoothstep(.15,.2,noise(st*10.)); // schwarze Spritzer
color -= smoothstep(.35,.4,noise(st*10.)); // Löcher in den Spritzern
```
Ein dritter Weg basiert auf der Modulation einer Form mit Hilfe einer Noise-Funktion. Auch dabei kommen einige der Techniken zum Einsatz, die wir im [Kapitel über Formen](../07/) kennengelernt haben.
<a href="../edit.php#11/circleWave-noise.frag"><canvas id="custom" class="canvas" data-fragment-url="circleWave-noise.frag" width="300px" height="300"></canvas></a>
Empfohlene Übungen:
* Welche anderen generativen Designs fallen Dir ein? Was ist mit Granitgestein? Marmor? Magma? Wasser? Suche Dir drei Fotos entsprechender Materialien und entwickle die zugehörigen Algorithmen unter Einbeziehung von Noise-Funktionen.
* Nutze Noise-Funktionen, um eine Form zu modulieren.
* Wie steht es um die Nutzung von Noise-Funktionen für Bewegungsabläufe? Schlage noch einmal im [Kapitel über Matrizenoperationen](../08/) nach. Nutze das dortige Beispiel, in welchem das Kreuz über die Zeichenfläche bewegt wird, und füge dem Ganzen etwas Zufall und Noise hinzu.
* Erzeuge ein generatives Design wie bei Jackson Pollocks Bildern.
![Jackson Pollock - Number 14 gray (1948)](pollock.jpg)
## Verbesserte Noise-Funktionen
Eine Verbesserung von Perlin an seinem ursprünglichen **Non-Simplex Noise**-Algorithmus hin zu einem **Simplex Noise** ist der Ersatz der kubischen Hermite-Funktionn ( _f(x) = 3x^2-2x^3_, die der [```smoothstep()```](.../glossary/?search=smoothstep)-Funktion in GLSL entspricht) durch eine quintische Interpolationsfunktion ( _f(x) = 6x^5-15x^4+10x^3_ ).
Diese lässt die Interpolationskurve an ihren Enden flacher werden, so dass sie nahtloser in die nächste Interpolationskurve übergeht. Man erhält dadurch kontinuierlichere Übergänge zwischen den einzelnen Zellen. Du kannst Dir ein Bild davon machen, indem Du die Kommentare an der zweiten Formel in dem folgenden Graphen entfernst. ([Beide Graphen in einem Bild siehst Du auch hier](https://www.desmos.com/calculator/2xvlk5xp8b)). Entscheidend ist wie immer der Bereich zwischen ```0.0``` und ```1.0``` auf der *x-Achse*.
<div class="simpleFunction" data="
// Kubische Hermite-Funktion wie bei SmoothStep()
y = x*x*(3.0-2.0*x);
// Quintische Interpolationskurve
//y = x*x*x*(x*(x*6.-15.)+10.);
"></div>
Beachte, wie die beiden unterschiedlichen Kurven an ihren Endbereichen voneinander abweichen. Mehr dazu erfährst du in [Ken s eigenen Worten hier](http://mrl.nyu.edu/~perlin/paper445.pdf).
## Simplex Noise
Für Ken Perlin war der Erfolg seines ersten Noise-Algorithmus noch nicht genug. Er suchte weiter nach Verbesserungen. Auf der berühmten Grafik-Konferenz *Siggraph* präsentierte er im Jahre 2001 den „Simplex Noise“-Algorithmus, mit dem er die folgenden Optimierungen gegenüber dem Vorgänger erzielte:
* Geringerer Rechenaufwand und weniger Multiplikationen.
* Ein Rauschen, das sich auch für höhere Dimensionen berechnen lässt, ohne dass der Aufwand ins Astronomische steigt.
* Ein Rauschen ohne sichtbare Richtungsartefakte.
* Ein Rauschen mit sauber definierten und nahtlosen Übergangen, das sich einfach berechnen lässt.
* Ein Algorithmus, der auch in der Hardware einfach zu implementieren ist.
Ich weiß, was Du jetzt denkst... „Wow, wer ist dieser Mann?“ Ja, seine Leistungen sind wirklich großartig. Aber mal ganz im Ernst, wie ist es ihm gelungen, seinen Algorithmus zu verbessern? Nun, wir haben gesehen, dass er zur Berechnung des Rauschens in zwei Dimensionen zwischen den vier Eckpunkten eines Vierecks interpoliert. Man darf deshalb zurecht davon ausgehen, dass er für die Berechnung in drei Dimensionen ([eine Implementierung in GLSL findest Du hier](../edit.php#11/3d-noise.frag)) und vier Dimensionen zwischen 8 bzw. 16 einzelnen Eckpunkten interpolieren muss. Korrekt?
In anderen Worten: Für die Berechnung des Rauschens in N Dimensionen muss man zwischen *2 hoch N* (_2^N_) verschiedenen Punkten interpolieren. Ken war jedoch aufgefallen, dass die offensichtliche „Bauweise“ für eine flächenfüllende Form zwar fraglos ein Viereck darstellt, die einfachste Form der Abdeckung jedoch mit gleichseitigen Dreiecken erzielt wird. Deshalb ersetzte er das rechtwinklige Gitternetz durch ein Netz aus gleichseitigen Dreiecken.
![](simplex-grid-00.png)
Mit gleichseitigen Dreiecken besteht die einfachste Form für *N Dimensionen* aus einer Konstruktion mit *N+1 Eckpunkten*. Das bedeutet einen Eckpunkt weniger für zweidimensionales Rauschen, vier Eckpunkte weniger für dreidimensionales Rauschen und elf Eckpunkte weniger für vierdimensionales Rauschen. Diese „Ersparnis“ bringt einen enorm reduzierten Rechenaufwand und dadurch einen großen Geschwindigkeitszuwachs mit sich!
In zwei Dimensionen erfolgt die Interpolation genau wie bei der Standard Noise-Funktion. Weil wir aber ein gleichseitiges Dreieck nutzen, müssen wir dabei nur drei Punkte einbeziehen.
![](simplex-grid-01.png)
Doch wie wird dieses vereinfachte Gitternetz aufgebaut? In einem weiteren brillanten und äußerst eleganten Schritt, werden die Zellen des viereckigen Gitternetzes jeweils in zwei gleichschenklige Dreiecke (mit jeweils zwei gleich langen Seiten) aufgeteilt. Anschließend wird das Netz so verzerrt, dass alle Dreiecke auch gleichseitig sind (also mit jeweils drei gleich langen Seiten). Denn damit lässt sich am einfachsten interpolieren.
![](simplex-grid-02.png)
Anschließend fahren wir fort, wie es [Stefan Gustavson in seinen Ausführungen beschreibt](http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf): "*... indem wir uns die ganzzahligen Anteile der transformierten Koordinaten (x,y) des zu berechnenden Punktes anschauen, denn darüber können wir leicht feststellen, zu welchen zwei Dreiecken der Punkt gehört. Indem wir die Werte von x und y vergleichen, erfahren wir, ob sich der Punkt in dem oberen oder in dem unteren Dreieck befindet. So können wir die drei korrekten Eckpunkte in die Berechnung einbeziehen.*“
Im folgenden Programmcode kannst Du die Kommentarzeichen aus der *Programmzeile 44* entfernen, um zu sehen, wie das Gitternetz gezerrt wird. Und sobald Du die Kommentierung von *Zeile 47* aufhebst, erkennst Du die Aufteilung der Fläche in gleichschenklige Dreiecke. Beachte, wie wir in *Zeile 22* das verzerrte Rechteck einfach in zwei gleichseitige Dreiecke aufteilen, indem wir testen, ob ```x > y``` ist („unteres“ Dreieck) oder ```y > x``` („oberes“ Dreieck).
<div class="codeAndCanvas" data="simplex-grid.frag"></div>
All diese Verbesserungen münden in das Meisterwerk, das als **Simplex Noise**-Algorithmus bekannt ist. Der folgende Programmcode ist eine Implementation dieses Algorithmus in GLSL, die von Ian McEwan und Stefan Gustavson entwickelt wurde ([hier nachzulesen](http://webstaff.itn.liu.se/~stegu/jgt2012/article.pdf)). Für unsere Lernzwecke ist diese theoretische Erklärung vielleicht etwas zu aufwändig. Allerdings wirst Du beim Anklicken der Grafik und einem Blick auf den dahinterstehenden Programmcode feststellen, dass dieser weniger kryptisch daherkommt, als Du vielleicht erwartet hast. Außerdem ist der Code vergleichsweise kompakt und kann schnell ausgeführt werden.
[ ![Ian McEwan von Ashima Arts - Simplex Noise](simplex-noise.png) ](../edit.php#11/2d-snoise-clear.frag)
Nun aber genug der technischen Spitzfindigkeiten. Es ist an der Zeit, dass Du den Simplex Noise-Algorithmus als eine wertvolle Ressource im Rahmen Deiner eigenen Projekte zum Einsatz bringst:
* Versuche das Besondere an den verschiedenen Implementationen von Noise zu erkennen. Stelle Sie Dir wie Rohmaterialien vor, aus denen ein Bildhauer seine Skulptur herausschält. Wie fühlen sich die unterschiedlichen Ergebnisse für Dich an? Verziehe beim Betrachten deine Augen, um der Vorstellungskraft Raum zu geben, so wie Du die Wolken nach Mustern absuchst. Was erkennst Du? Woran erinnert es Dich? Was könnte man wohl mit den verschiedenen Noise-Implementationen anstellen? Höre auf Deine innere Stimme und probiere es einfach aus!
* Entwickle einen Shader, der die Illusion einer Strömung von Flüssigkeiten erweckt. Etwa wie bei einer Lava-Lampe, Tintentropfen, Wasser etc.
<a href="../edit.php#11/lava-lamp.frag"><canvas id="custom" class="canvas" data-fragment-url="lava-lamp.frag" width="520px" height="200px"></canvas></a>
* Nutze den Simplex Noise-Algorithmus um Deinen bisherigen Arbeiten mehr Textur zu verleihen.
<a href="../edit.php#11/iching-03.frag"><canvas id="custom" class="canvas" data-fragment-url="iching-03.frag" width="520px" height="520px"></canvas></a>
In diesem Kapitel haben wir versucht, Kontrolle über das Chaos zu erlangen. Das war keine leichte Aufgabe. Es braucht seine Zeit, um ein Meister des Rauschens und der Raumkrümmung zu werden.
In den folgenden Kapiteln werden wir einige bekannte Techniken aufgreifen, mit Denen Du deine Fähigkeiten weiter verbessern kannst. Bis dahin genieße ein wenig Zeit draußen an der frischen Luft und lasse Dich von den Mustern und Strukturen der Natur inspirieren. Denn Deine Fähigkeiten zur Beobachtung müssen ähnlich gut entwickelt sein, wie Deine Programmierfähigkeiten. Vielleicht sogar noch besser. Genieße die wertvolle Zeit abseits des Computers!
<p style="text-align:center; font-style: italic;">"Sprich mit den Bäumen und werdet Freunde." Bob Ross
</p>

@ -0,0 +1,202 @@
![](dragonfly.jpg)
## Zelluläres Rauschen
Im Jahre 1996, 16 Jahre nach Veröffentlichung von Perlins ursprünglichem Noise-Algorithmus und fünf Jahre vor der Erfindung des Simplex Noise-Algorithmus, schrieb Steven Worley einen Artikel mit dem Titel [„Eine Basisfunktion für zelluläre Texturen“](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Darin beschreibt er eine Technik zur prozeduralen Texturierung von Flächen, die heute im Bereich der Computergrafik nicht mehr wegzudenken ist.
Um das Prinzip hinter diesem Verfahren zu verstehen, müssen wir die Abläufe aus dem Blickwinkel von **Iterationen** betrachten. Als Programmierer kannst Du Dir vielleicht denken, was das bedeutet: Ja, genau, es geht um Schleifen und um den Einsatz des ```for```-Befehls. Allerdings gibt es da einen wichtigen Aspekt in GLSL: Die Anzahl der Schleifendurchläufe muss durch eine Konstante (```const```) vorgegeben sein. Sie ist also nicht dynamisch, sondern steht grundsätzlich von vornherein fest.
Lass uns dazu am besten ein Beispiel anschauen.
### Punkte für ein Distanzfeld
Zelluläres Rauschen basiert auf Distanzfeldern, konkret auf der Berechnung der Entfernung zum nächstgelegenen Bezugspunkt aus einer gegebenen Menge von Punkten. Lass uns annehmen, wir wollten ein Distanzfeld aus vier Punkten erzeugen. Was benötigen wir dafür? Nun, **für jeden zu berechnenden Bildpunkt auf unserer Zeichenfläche wollen wir die Entfernung zum nächstgelegenen der vier Bezugspunkte berechnen **. Das bedeutet, dass wir alle vier Bezugspunkte durchlaufen, ihre Entfernung zum aktuell bearbeiteten Pixel berechnen und uns die kleinste dieser Entfernungen merken müssen.
```glsl
float min_dist = 100.; // speichert die kleineste Entf. zu einem der 4 Bezugspunkte
min_dist = min(min_dist, distance(st, point_a));
min_dist = min(min_dist, distance(st, point_b));
min_dist = min(min_dist, distance(st, point_c));
min_dist = min(min_dist, distance(st, point_d));
```
![](cell-00.png)
Diese Lösung ist natürlich nicht besonders elegant, aber sie erfüllt ihren Zweck. Lass uns das Ganze nun mit Hilfe eines Arrays und einer ```for```-Schleife realisieren.
```glsl
float m_dist = 100.; // speichert die minimale Entfernung
for (int i = 0; i < TOTAL_POINTS; i++) {
float dist = distance(st, points[i]);
m_dist = min(m_dist, dist);
}
```
Beachte, wie wir hier die ```for```-Schleife einsetzen, um ein Array mit Bezugspunkten zu durchlaufen, und die bislang kleinste Entfernung mit Hilfe der [```min()```](../glossary/?search=min)-Funktion festhalten. Hier folgt eine vollständige Umsetzung dieses Ansatzes in GLSL.
<div class="codeAndCanvas" data="cellnoise-00.frag"></div>
In dem obigen Shader wird einer der Bezugspunkte des Distanzfelds auf die Mausposition über der Zeichenfläche gesetzt. Fahre mit der Maus über die Fläche und spiele ein wenig damit herum. So bekommst Du am besten eine Vorstellung davon, wie der Code funktioniert. Probiere anschließend folgendes aus:
- Gelingt es Dir, die Position der anderen Bezugspunkte zu animieren?
- Nachdem Du [das Kapitel über Formen](../07/?lan=de) ja vermutlich bereits gelesen hast, stelle Dir einen interessanten Weg vor, was man mit dem vorliegenden Distanzfeld anstellen könnte.
- Was muss man tun, um das Distanzfeld um weitere Bezugspunkte zu erweitern? Wie können wir dynamisch einzelne Bezugspunkte hinzufügen oder entfernen?
### Kachelung und Wiederholung
Vielleicht ist Dir schon klargeworden, dass ```for``` Schleifen und *Arrays* nicht die besten Freunde von GLSL sind. Wie schon gesagt: Schleifen in GLSL akzeptieren keine variablen Limite für die Anzahl der Durchläufe. Außerdem verlangsamen vielfache Schleifendurchläufe die Ausführung Deiner Shader spürbar, da Schleifen nicht vorzeitig beendet werden können. Das hat zur Folge, dass dieser Ansatz für Distanzfelder mit einer Vielzahl von Bezugspunkten untauglich ist. Wir müssen einen anderen Weg wählen, einen, der einen Vorteil aus der Parallelverarbeitung der GPU zieht.
![](cell-01.png)
Ein Ansatz, um sich dieser Herausforderung zu stellen, ist die Unterteilung der Zeichenfläche in einzelne Kacheln bzw. Zellen. Nicht jeder Pixel muss die Entfernung zu allen Punkten des Distanzfeldes überprüfen. Manche sind auf jeden Fall zu weit entfernt, um ein Minima zu liefern. Dies gilt beispielsweise für alle Zellen, die nicht direkt an die aktuelle Zelle angrenzen.
Weil die Farbe für jeden Pixel in einem eigenen Thread berechnet wird, können wir die Zeichenfläche in einzelne Zellen unterteilen - jede mit einem Bezugspunkt.
Um Anomalien an den Schnittflächen zwischen den Zellen zu vermeiden, müssen wir jeweils die Entfernung zum Bezugspunkt der benachbarten Zellen überprüfen. Das ist im Wesentlichen die brillante Idee hinter dem [Ansatz von Steven Worley](http://www.rhythmiccanvas.com/research/papers/worley.pdf).
Letztendlich muss jeder Pixel nur die Entfernung zu neun Bezugspunkten berechnen: Dem seiner eigenen Zelle und jene der acht umliegenden Zellen. Alle anderen Zellen sind zu weit entfernt.
Wir haben bereits in den Kapiteln über [Muster](../09/?lan=de), [Generative Designs](../10/?lan=de) und [Rauschen](../11/?lan=de) gesehen, wie man die Zeichenfläche in einzelne Zellen unterteilt, von daher bist Du mit diesem Prinzip wahrscheinlich schon vertraut.
```glsl
// den Raum aufblaehen ...
st *= 3.;
// ... und in Zellen unterteilen
vec2 i_st = floor(st);
vec2 f_st = fract(st);
```
Also, wie lautet der Plan? Wir werden die Koordinate der Kachel/Zelle (die in dem Integer-Vektor ```i_st``` gespeichert ist) nutzen, um einen zufälligen Punkt zu erzeugen. Wir setzen dafür die ```random2f```-Funktion ein, die einen ```vec2``` als Parameter erhält und einen ```vec2``` mit einer Zufallsposition zurückliefert. So erhalten wir für jede Zelle einen Bezugspunkt mit einer zufälligen Position innerhalb der Zelle.
```glsl
vec2 point = random2(i_st);
```
Der jeweils zu zeichnende Bildpunkt innerhalb der Zelle (gespeichert in dem Fließkommavektor ```f_st```) wird seine Entfernung zu diesem zufällig gewählten Bezugspunkt berechnen.
```glsl
vec2 diff = point - f_st;
float dist = length(diff);
```
Das Ergebnis sieht dann wie folgt aus:
<a href="../edit.php#12/cellnoise-01.frag"><img src="cellnoise.png" width="520px" height="200px"></img></a>
Aber wir wollen ja zusätzlich noch die Entfernung zu den Bezugspunkten in den umliegenden Zellen einbeziehen. Dafür müssen wir diese Zellen **durchlaufen**. Aber nicht alle, sondern nur die unmittelbar angrenzenden. Das heißt die Zellen mit den Abständen von ```-1``` (links) bis ```1``` (rechts) entlang der ```x```-Achse, sowie die Zellen mit den Abständen von ```-1``` (unten) bis ```1``` (oben) entlang der ```y```-Achse. Dieser Bereich von 3x3 Zellen lässt sich leicht mit Hilfe einer doppelten ```for```-Schleife abarbeiten, so wie im Folgenden gezeigt:
```glsl
for (int y= -1; y <= 1; y++) {
for (int x= -1; x <= 1; x++) {
// benachbarte Zelle innerhalb des Rasters
vec2 neighbor = vec2(float(x),float(y));
...
}
}
```
![](cell-02.png)
Nun können wir die Bezugspunkte aus jeder der benachbarten Zellen in unserer doppelten ```for```-Schleife berechnen, indem wir den Versatz aus der Variablen ```neighbour``` zu den Koordinaten der aktuellen Zelle addieren.
```glsl
...
// Zufallsposition von der aktuellen + der benachbarten Zelle im Raster
vec2 point = random2(i_st + neighbor);
...
```
Dann bleibt nur noch, die Entfernung vom aktuell zu zeichnenden Punkt zu dem jeweiligen Bezugspunkt zu berechnen und die geringste Entfernung in der Variablen ```m_dist``` (für „minimale Distanz“) zu speichern.
```glsl
...
vec2 diff = neighbor + point - f_st;
// Entfernung zu diesem Punkt
float dist = length(diff);
// die kleinste Entfernung speichern
m_dist = min(m_dist, dist);
...
```
Der obige Programmcode wurde durch einen [Artikel von Inigo Quilez](http://www.iquilezles.org/www/articles/smoothvoronoi/smoothvoronoi.htm) inspiriert. Dort schreibt er:
„... es ist vielleicht interessant darauf hinzuweisen, dass in dem obigen Code ein netter Trick steckt. Die meisten Implementationen dieses Algorithmus leiden unter einer schlechten Präzision der Berechnungen, weil sie die zufälligen Bezugspunkte auf den gesamten Koordinatenraum beziehen, so dass die Koordinaten sehr weit vom Ursprung entfernt sind. Man kann dagegen ansteuern, indem man Variablentypen mit besonders hoher Genauigkeit verwendet, was sich jedoch negativ auf die Geschwindigkeit der Berechnungen auswirkt. Oder man macht es etwas cleverer, indem man die Koordinaten nicht auf den gesamten Koordinatenraum bezieht, sondern auf die Ebene der einzelnen Zellen: Sobald der ganzzahlige Teil und der Nachkommateil des zu zeichnenden Punktes berechnet sind und dadurch die Zelle feststeht, in der sich der Punkt befindet, beschäftigen wir uns nur noch damit, was um diese Zelle herum geschieht. Dadurch müssen wir uns nicht mehr um den ganzzahligen Teil der Koordinaten kümmern, wodurch man viele Bits bei den weiteren Berechnungen einspart. Tatsächlich steuern bei herkömmlichen Voronoi-Implementierungen die ganzzahligen Anteile der Punktkoordinaten ebenfalls dem Wert 0 entgegen, sobald die zufälligen Bezugspunkte der Zellen vom aktuell zu zeichnenden Punkt abgezogen werden. In der obigen Implementation lassen wir es gar nicht erst so weit kommen, weil wir alle Koordinatenberechnungen auf den Raum der Zellen beziehen. Mit diesem Trick kann man sogar einen ganzen Planeten mit derartig geformten Voronoi-Zellen überziehen, indem man die Punktkoordinaten einfach in doppelter Fließkommagenauigkeit darstellt, die Berechnungen von ```floor()``` und ```fract()``` durchführt, und dann mit einfacher Fließkommagenauigkeit fortfährt. So erspart man sich den (Zeit-) Aufwand, die gesamte Berechnung mit doppelter Fließkommagenauigkeit auszuführen. Natürlich kann man diesen Trick auch auf Perlins Noise-Algorithmus anwenden (allerdings habe ich noch nie ein solche Implementation gesehen). “
Um es noch einmal zusammenzufassen: Wir unterteilen den Raum in einzelne Zellen. Für jeden zu zeichnenden Punkt berechnen wir die kleinste Entfernung zum Bezugspunkt seiner Zelle bzw. zu den Bezugspunkten der acht umliegenden Zellen. Als Ergebnis erhalten wir ein Distanzfeld, so wie in dem folgenden Beispiel:
<div class="codeAndCanvas" data="cellnoise-02.frag"></div>
Experimentiere damit, indem Du:
- den Raum in mehr Zellen aufteilst.
- Dir andere Möglichkeiten ausdenkst, um die Bezugspunkte zu animieren.
- einen der Bezugspunkte durch die aktuelle Mausposition ersetzt.
- über andere Wege nachdenkst, um das Distanzfeld zu berechnen, abseits von ```m_dist = min(m_dist, dist);```.
- untersuchst, welche anderen interessanten Muster sich über dieses Distanzfeld erzeugen lassen.
Man kann diesen Algorithmus nicht nur aus der Perspektive der jeweils zu zeichnenden Pixel betrachten, sondern auch aus Sicht der Bezugspunkte. In diesem Fall lässt sich der Algorithmus so beschreiben: Jeder Bezugspunkt wächst aus seiner Mitte heraus, bis er an die Grenzen eines anderen wachsenden Bezugspunktes stößt. Das spiegelt das Wachstum biologischer Zellen in der Natur wieder. Lebendige Organismen werden von dieser Spannung zwischen dem inneren Antrieb zum Wachstum und äußeren Begrenzungen geformt. Der klassische Algorithmus, der dieses Verhalten nachahmt, ist nach [Georgi Feodosjewitsch Woronoi, engl „Georgy Voronoi“](https://de.wikipedia.org/wiki/Voronoi-Diagramm) benannt.
![](monokot_root.jpg)
### Der Voronoi-Algorithmus
Die Erzeugung von Voronoi-Diagrammen auf Basis von zellulärem Rauschen ist weniger kompliziert, als es vielleicht erscheint. Wir müssen nur zusätzliche Informationen über den Bezugspunkt *festhalten*, der dem zu zeichnenden Punkt am nächsten liegt. Dafür verwenden wir eine Variable vom Typ ```vec2``` mit dem Namen ```m_point```. Darin speichern wir den Vektor zum nächstgelegenen Bezugspunkt und nicht einfach nur dessen Entfernung. So behalten wir ein eindeutiges Identifikationsmerkmal für diesen Punkt.
```glsl
...
if( dist < m_dist ) {
m_dist = dist;
m_point = point;
}
...
```
Bitte beachte, dass wir in dem folgenden Programmcode die geringste Entfernung nicht mehr mit Hilfe der ```min```-Funktion berechnen, sondern einen herkömmlichen ```if```-Befehl einsetzen. Warum wir das tun? Weil wir diesmal etwas mehr unternehmen wollen, sobald ein neuer näherliegender Punkt auftaucht, nämlich seine Position speichern (*Programmzeilen 32 bis 37*).
<div class="codeAndCanvas" data="vorono-00.frag"></div>
Du wirst sehen, dass die Farbe der beweglichen Zelle (die dem Mauszeiger folgt) auf Basis ihrer Position wechselt. Die Ursache dafür ist, dass hier die Farbe aufgrund des Wertes (der Position) des nächstgelegenen Bezugspunktes zugewiesen wird.
Genau wie zuvor ist es nun an der Zeit, das Ganze zu erweitern, indem wir zu dem Algorithmus aus dem [Papier von Steven Worley](http://www.rhythmiccanvas.com/research/papers/worley.pdf) übergehen. Versuche doch einmal selbst, diesen Algorithmus zu implementieren. Du kannst dabei auf das folgende Beispiel zurückgreifen, indem Du darauf klickst.
Bitte beachte, dass der ursprüngliche Ansatz von Steven Worley eine variable Anzahl von Bezugspunkten für jede Zelle vorsieht. In seiner Implementation des Algorithmus in C nutzt er dies für einen zeitigen Abbruch der Schleife. Schleifen in GLSL erlauben jedoch keinen vorzeitigen Ausstieg oder eine variable Anzahl von Schleifendurchläufen, deshalb wirst Du vielleicht besser bei einem Bezugspunkt pro Zelle bleiben.
<a href="../edit.php#12/vorono-01.frag"><canvas id="custom" class="canvas" data-fragment-url="vorono-01.frag" width="520px" height="200px"></canvas></a>
Sobald Du die Funktionsweise dieses Algorithmus verstanden hast, kannst Du über interessante und kreative Einsatzmöglichkeiten nachdenken.
![Extended Voronoi - Leo Solaas (2011)](solas.png)
![Cloud Cities - Tomás Saraceno (2011)](saraceno.jpg)
![Accretion Disc Series - Clint Fulkerson](accretion.jpg)
![Vonoroi Puzzle - Reza Ali (2015)](reza.png)
### Verbesserung des Voronoi-Algorithmus
Im Jahre 2011 hat [Stefan Gustavson eine Optimierung von Steven Worleys Algorithmus für GPUs](http://webstaff.itn.liu.se/~stegu/GLSL-cellular/GLSL-cellular-notes.pdf) vorgeschlagen, bei der nur noch eine 2x2 Matrix benachbarter Zellen untersucht wird, an Stelle der bisherigen 3x3 Matrix. Das reduziert den Rechenaufwand für jeden Punkt deutlich, kann aber zur Artefakten durch unsaubere Übergänge an den Grenzen der Zellen führen. Schau Dir die folgenden Beispiele an.
<div class="glslGallery" data="12/2d-cnoise-2x2,12/2d-cnoise-2x2x2,12/2d-cnoise,12/3d-cnoise" data-properties="clickRun:editor,openFrameIcon:false"></div>
Im Jahre 2012 präsentierte [Inigo Quilez einen interessanten Artikel über die Erzeugung präziser Voronoi-Abgrenzungen](http://www.iquilezles.org/www/articles/voronoilines/voronoilines.htm).
<a href="../edit.php#12/2d-voronoi.frag"><img src="2d-voronoi.gif" width="520px" height="200px"></img></a>
Inigos Experimente zu diesem Thema hörten damit nicht auf. Im Jahr 2014 verfasste er einen schönen Beitrag über das, was er als [Voro-Noise, dt. „Voro-Rauschen“](http://www.iquilezles.org/www/articles/voronoise/voronoise.htm) bezeichnet - eine Funktion, die einen graduellen Übergang zwischen normalem Rauschen und Voronoi-Rauschen ermöglicht. Er schrieb:
„Abgesehen von ihrer Ähnlichkeit ist es entscheidend, dass das Raster aus Zellen in beiden Mustern unterschiedlich verwendet wird. Interpoliertes Rauschen mit Zufallswerten (wie bei Value-Noise) oder mit Gradienten (wie bei Gradient-Noise) unterscheidet sich von Voronoi, wo es auf die Entfernung zum nächstgelegenen Bezugspunkt ankommt. Schließlich sind die bilineare Interpolation und die Minima-Berechnung zwei ganz unterschiedliche Operationen, nicht wahr? Doch vielleicht kann man sie in einem größeren Rahmen vereinigen? Sollte das möglich sein, könnte man sowohl Rauschmuster als auch Voronoi-Muster als Spezialfälle eines allgemeineren rasterbasierten Mustergenerators betrachten.“
<a href="../edit.php#12/2d-voronoise.frag"><canvas id="custom" class="canvas" data-fragment-url="2d-voronoise.frag" width="520px" height="200px"></canvas></a>
Nun ist die Zeit gekommen, dass Du Dir die Dinge genau anschaust, Dich von der Natur inspirieren lässt und Deine eigene Nutzungsmöglichkeiten dieser Techniken entdeckst!
![Deyrolle glass film - 1831](DeyrolleFilm.png)
<div class="glslGallery" data="12/metaballs,12/stippling,12/cell,12/tissue,12/cracks,160504143842" data-properties="clickRun:editor,openFrameIcon:false"></div>

@ -0,0 +1,119 @@
![Due East over Shadequarter Mountain - Matthew Rangel (2005) ](rangel.jpg)
## Gebrochene Brownsche Bewegung
Rauschen kann für Menschen ganz unterschiedliche Dinge bedeuten, je nachdem, wen man danach fragt. Musiker denken bei diesem Stichwort an schlechte Klangqualität, Funkspezialisten an unerwünschte Überlagerungen und Astrophysiker an die kosmische Hintergrundstrahlung im Mikrowellenbereich. Diese Vorstellungen führen uns zurück zu den physikalischen Grundlagen des Zufälligen in unserer Welt.
Doch lass uns erst einmal mit etwas ganz Einfachem und Fundamentalem beginnen: Mit den Eigenschaften von Wellen. Eine Welle steht für die Schwankung einer bestimmten Eigenschaft im Verlauf der Zeit. Audiowellen sind Schwankungen des Luftdrucks, elektromagnetische Wellen sind Schwankungen elektrischer und magnetischer Felder. Zwei spezifische Merkmale von Wellen sind ihre Amplitude (die Intensität ihres Ausschlags) und ihre Frequenz (die Häufigkeit, mit der sich die Welle in einer bestimmten Zeit wiederholt). Die Formel für eine einfache lineare Welle (in einer Dimension) sieht so aus:
<div class="simpleFunction" data="
float amplitude = 1.;
float frequenz = 1.;
y = amplitude * sin(x * frequenz);
"></div>
* Verändere in der obigen Formel doch einfach mal die Werte für die Variablen ```amplitude``` und ```frequenz``` und beobachte, was dann geschieht.
* Versuche eine formgebende Funktion in die Formel einzubringen, so dass sich die Amplitude im Verlauf der Zeit ändert.
* Versuche das Gleiche, aber diesmal für eine Änderung der Frequenz im Laufe der Zeit.
Mit den letzten beiden Übungen modulierst Du die Sinuswelle. So erhältst Du einmal eine amplitudenmodulierte Welle (AM) und einmal eine frequenzmodulierte Welle (FM).
Ein weiteres interessantes Merkmal von Wellen kann man beobachten, wenn man mehrere Wellen addiert. Dabei entsteht ein Phänomen, das als „Überlagerung“ bekannt ist. Kommentiere in dem folgenden Beispiel einzelne Zeilen aus bzw. wieder ein und verändere die verschiedenen Faktoren für die Frequenz und die Amplitude. Verschaffe Dir einen Eindruck davon, wie sich das Gesamtbild auf diese Weise ändert.
<div class="simpleFunction" data="
float amplitude = 1.;
float frequenz = 1.;
y = sin(x * frequenz);
float t = 0.01*(-u_time*130.0);
y += sin(x*frequenz*2.1 + t)*4.5;
y += sin(x*frequenz*1.72 + t*1.121)*4.0;
y += sin(x*frequenz*2.221 + t*0.437)*5.0;
y += sin(x*frequenz*3.1122+ t*4.269)*2.5;
y *= amplitude*0.06;
"></div>
* Experimentiere mit Veränderungen der Amplitude und der Frequenz bei den hinzuaddierten Wellen.
* Gelingt es Dir, zwei Wellen zu erschaffen, die sich gegenseitig aufheben? Wie würde das aussehen?
* Ist es möglich, Wellen auf eine bestimmte Art und Weise zu addieren, so dass sie sich gegenseitig verstärken?
In der Musik steht jede Note für eine bestimmte Frequenz. Reiht man die Frequenzen der Noten einer Tonleiter aneinander, so ergibt sich ein charakteristisches Muster. Die Halbierung bzw. Verdoppelung der Frequenz entspricht dabei jeweils dem Sprung um eine Oktave nach unten bzw. oben.
Okay, lass uns die Sinuswelle nun durch Perlins Rauschfunktion ersetzen. Diese hat in ihrer einfachsten Form ein ähnliches Erscheinungsbild wie die Sinuswelle. Zwar sind die Frequenz und die Amplitude von Perlins Rauschfunktion nicht konstant, aber die Amplitude bleibt zumindest weitgehend gleich und die Frequenz schwankt nur in einem schmalen Bereich rund um die Basisfrequenz. Perlins Rauschfunktion ist dadurch nicht so gleichförmig wie eine Sinuswelle. So wird es einfacher, den Eindruck von Zufälligkeit zu erzielen, indem man mehrere dieser Funktionen erst skaliert und dann addiert. Zwar ist dies grundsätzlich auch mit Sinuswellen möglich. Doch benötigt man dann eine größere Anzahl einzelner Wellen, um den eigentlich so regelmäßigen und periodischen Charakter der zugrundeliegenden Sinuswelle zu verbergen.
Indem wir das Ergebnis mehrerer Rauschfunktionen (*oktaven*) addieren, wobei wir schrittweise die Frequenz durch Multiplikation um einen gleichbleibenden Faktor (*porositaet*) steigern und die Amplitude dieser Zuwächse verringern (*zuwachs* < 1.0), verleihen wir unserem Rauschen eine feinere Granularität mit mehr Details. Diese Technik ist als Gebrochene Brownsche Bewegung (engl.: fractal Brownian motion“), kurz *fBm*, oder auch einfach als frakturiertes Rauschen (engl.: fractal noise“) bekannt. In ihrer simpelsten Form kann man sie mit Hilfe des folgenden Codes erzeugen:
<div class="simpleFunction" data="// Properties
const int oktaven = 1;
float porositaet = 2.0;
float zuwachs = 0.5;
//
// Startwerte
float amplitude = 0.5;
float frequenz = 1.;
//
// die Oktaven durchlaufen
for (int i = 0; i < oktaven; i++) {
&#9;y += amplitude * noise(frequenz*x);
&#9;frequenz *= porositaet;
&#9;amplitude *= zuwachs;
}"></div>
* Erhöhe die Anzahl der Oktaven schrittweise von 1 auf 2, 4, 8 und 10 und beobachte, was dann geschieht.
* Sobald Du mehr als 4 Oktaven durchläufst, ändere den Wert für die Porosität.
* Ändere dann (bei *oktaven > 4*) auch den Wert für den Zuwachs, um die Auswirkungen zu beobachten.
Fällt Dir auf, dass der Funktionsgraph mit jeder zusätzlichen Oktave an Details gewinnt? Außerdem wächst die Selbstähnlichkeit: Der Kurvenverlauf in den einzelnen kleinen Abschnitten ähnelt immer mehr dem Verlauf im Großen. Dies ist ein wichtiges Merkmal mathematischer „Fraktale“ und wir simulieren dies hier durch die Oktaven-Schleife. Zwar erzeugen wir kein echtes Fraktal, weil wir die Aufsummierung nach einigen Schleifendurchläufen stoppen. Wenn wir die Schleife aber unendlich fortsetzen und immer weitere Rausch-Komponenten hinzufügen würden, erhielten wir tatsächlich ein vollständiges Fraktal.
Im Bereich der Computergrafik existieren immer Beschränkungen in der Hinsicht, wie fein wir einzelne Details auflösen können. Werden die Objekte beispielsweise kleiner als ein Pixel, macht es gar keinen Sinn mehr, weiterzurechnen. Manchmal bedarf es einer großen Anzahl an Schleifendurchläufen für hochauflösende Details, aber eine endlose Anzahl an Schleifendurchläufen und Details sind grundsätzlich nicht sinnvoll.
Der folgende Programmcode liefert ein Beispiel dafür, wie man eine fBm in zwei Dimensionen implementieren kann, um ein Muster ähnlich einem Fraktal zu erzeugen:
<div class='codeAndCanvas' data='2d-fbm.frag'></div>
* Reduziere die Anzahl der Oktaven, indem Du den Wert der Konstanten in *Zeile 37* änderst.
* Ändere die Porosität der fBm in *Zeile 47*.
* Untersuche die Auswirkungen, wenn Du die Verstärkung in *Zeile 48* veränderst.
Diese Technik wird in der Computergrafik häufig angewandt, um auf prozedurale Weise künstliche Landschaften zu erzeugen. Die Selbstähnlichkeit als Merkmal einer fBm ist perfekt für die Erzeugung von Bergen, Bergketten und ihren Tälern geeignet. Schließlich erzeugt die Erosion, die diese Strukturen in der Natur hervorbringt, ebenfalls eine Selbstähnlichkeit in mehreren unterschiedlichen Größenordnungen im Großen wie im Kleinen. Falls Dich das Thema interessiert, empfehle ich Dir diesen [hervorragenden Beitrag von Inigo Quiles über hochentwickeltes Rauschen](http://www.iquilezles.org/www/articles/morenoise/morenoise.htm).
![Blackout - Dan Holdsworth (2010)](holdsworth.jpg)
Mit mehr oder weniger derselben Technik lassen sich auch andere Effekte nachahmen, beispielsweise **Turbulenzen**. Dies geschieht mit einer fBm, wobei allerdings der Absolutwert einer vorzeichenbehafteten Rauschfunktion genutzt wird, um starke Täler zu erzeugen.
```glsl
for (int i = 0; i < OKTAVEN; i++) {
value += amplitude * abs(snoise(st));
st *= 2.;
amplitude *= .5;
}
```
<a href="../edit.php#13/turbulence.frag"><img src="turbulence-long.png" width="520px" height="200px"></img></a>
Ein weiteres Mitglied aus dieser Familie von Funktionen ist der **Bergrücken**, bei dem die tiefen Täler nach oben gekehrt werden, um scharfe Bergrücken bzw. Bergkämme zu erzeugen:
```glsl
n = abs(n); // erzeuge eine Falte
n = offset - n; // hole den Faltenboden nach oben
n = n * n; // intensiviere die Ausbuchtung
```
<a href="../edit.php#13/ridge.frag"><img src="ridge-long.png" width="520px" height="200px"></img></a>
Eine andere Variante dieses Verfahrens mit interessanten Ergebnissen besteht in der Multiplikation der einzelnen Rauschelemente anstelle der Addition. Man kann außerdem die Skalierung nicht gleichförmig mit jeder Detailebene (jedem Schleifendurchlauf) fortsetzen, sondern von den Ergebnissen vorheriger Schleifendurchläufe abhängig machen. Damit verlässt man allerdings die Welt klassischer Fraktale und dringt in das noch wenig erforschte Feld der „Multifraktale“ vor. Diese sind mathematisch nicht streng definiert, aber das macht sie für die Computergrafik nicht weniger nützlich. Tatsächlich werden Multifraktale bereits vielfältig in Software für die künstliche Erzeugung von Landschaftsstrukturen eingesetzt.
Falls Dich dieses Thema interessiert, kannst Du darüber z.B. in Kapitel 16 des Buches „Texturing and Modeling: a Procedural Approach“ (dritte Auflage) von Kenton Musgrave, mehr erfahren. Leider ist das Buch seit einigen Jahren vergriffen, aber man findet es noch in Bibliotheken und auf dem Gebrauchtmarkt. (Eine PDF-Version der ersten Auflage wird im Internet verkauft, aber die stammt von 1994 und enthält leider noch nicht die hier empfohlenen Kapitel.)
### Raumkrümmung
[Inigo Quiles hat einen weiteren faszinierenden Artikel](http://www.iquilezles.org/www/articles/warp/warp.htm) darüber verfasst, wie man ein fBm einsetzen kann, um einen Raum aus fBm zu verzerren. Abgefahren, nicht wahr? Das ist wie ein Traum über einen Traum, in dem es richtig rundgeht.
![ f(p) = fbm( p + fbm( p + fbm( p ) ) ) - Inigo Quiles (2002)](quiles.jpg)
Ein etwas weniger extremes Beispiel für diese Technik liefert der folgende Programmcode, wo mit Hilfe der Verzerrung wolkenartige Strukturen erzeugt werden. Auch hier spielt das Merkmal der Selbstähnlichkeit wiederum eine wichtige Rolle.
<div class='codeAndCanvas' data='clouds.frag'></div>
Die Texturkoordinaten mit Hilfe einer Rauschfunktion auf diese Weise zu verzerren, kann sehr nützlich sein und tolle Resultate liefern, es ist aber auch nicht ganz einfach zu beherrschen. Als hilfreiches Werkzeug erweist sich dabei der Ersatz der Koordinaten durch eine Ableitung (den Gradienten) der Rauschfunktion. [Ein berühmter Artikel von Ken Perlin und Fabrice Neyret mit dem Titel „flow noise“](http://evasion.imag.fr/Publications/2001/PN01/) erläutert diesen Ansatz.
Einige moderne Implementationen von Perlins Noise-Algorithmus berechnen sowohl den Funktionswert als auch den Verlauf. Wenn der konkrete Verlauf im Rahmen der prozeduralen Berechnung nicht verfügbar ist, kann man immer noch eine begrenzte Anzahl von Differenzen berechnen, um sich dem Verlauf anzunähern, auch wenn dies mehr Arbeit bedeutet und keine ganz exakten Ergebnisse liefert.

@ -0,0 +1,107 @@
<canvas id="custom" class="canvas" data-fragment-url="src/moon/moon.frag" data-textures="src/moon/moon.jpg" width="350px" height="350px"></canvas>
# The Book of Shaders
*von [Patricio Gonzalez Vivo](http://patriciogonzalezvivo.com/) und [Jen Lowe](http://jenlowe.net/)*
Dies ist eine behutsame Schritt-für-Schritt-Einführung in die komplexe und vielfach abstrakte Welt der Fragment Shader.
<div class="header">
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=B5FSVSHGEATCG" style="float: right;"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" alt=""></a>
</div>
## Inhalt
* [Über dieses Buch](00/?lan=de)
* Jetzt gehts los
* [Was ist ein Shader?](01/?lan=de)
* [“Hallo Welt!”](02/?lan=de)
* [Uniforms](03/?lan=de)
* [Ausführung Deiner Shader](04/?lan=de)
* Algorithmisches Zeichnen
* [Formgebende Funktionen](05/?lan=de)
* [Farben](06/?lan=de)
* [Formen](07/?lan=de)
* [Matrizen](08/?lan=de)
* [Muster](09/?lan=de)
* Generative Designs
* [Zufall](10/?lan=de)
* [Rauschen](11/?lan=de)
* [Zelluläres Rauschen](12/?lan=de)
* [Gebrochene Brownsche Bewegung](13/?lan=de)
* Fraktale
* Bildverarbeitung
* Texturen
* Bildbearbeitungsfunktionen
* Kernel Verwindungen
* Filter
* Weitere Effekte
* Simulationen
* Pingpong
* Conway
* Wellen
* Wasserfarben
* Reaktionsausbreitung
* 3D Grafiken
* Licht
* Normal Mapping
* Bump-Mapping
* Ray Marching
* Environmental-Maps (sphärisch und kubisch)
* Reflektionen und Ablenkungen
* [Anhang:](appendix/?lan=de) Weitere Wege zur Nutzung dieses Buches
* [Wie kann ich dieses Buch offline lesen?](appendix/00/?lan=de)
* [Wie lasse ich die Beispielprogramme auf einem Raspberry Pi ablaufen?](appendix/01/?lan=de)
* [Wie drucke ich dieses Buch aus?](appendix/02/?lan=de)
* [Wie kann ich zu diesem Buch beitragen?](appendix/03/?lan=de)
* [Eine Einführung für alle, die von JavaScript kommen](appendix/04/?lan=de) von [Nicolas Barradeau](http://www.barradeau.com/) (Englisch)
* [Beispielgalerien](examples/)
* [Glossar](glossary/) (Englisch)
## Über die Autoren
[Patricio Gonzalez Vivo](http://patriciogonzalezvivo.com/) (1982, Buenos Aires, Argentinien) ist ein Künstler und Entwickler, der in New York lebt. Er erforscht die Räume zwischen Organischem und Synthetischem, Analogem und Digitalem, Individuen und Kollektiven. In seinen Arbeiten nutzt er Programmcode als Ausdrucksform, um das Zusammenwirken von Menschen zu verbessern.
Patricio hat Psychologie studiert, außerdem kunstorientiertes Handeln, die sogenannte „Expressive Arts Therapy“. Er hat einen MFA-Abschluss in „Design & Technology“ von der „Parsons The New School“, wo er auch unterrichtet. Zur Zeit arbeitet Patricio als Grafikingenieur bei der Firma Mapzen und entwickelt dort Open Source Werkzeuge für die Computer-Kartographie.
<div class="header"> <a href="http://patriciogonzalezvivo.com/" target="_blank">Webseite</a> - <a href="https://twitter.com/patriciogv" target="_blank">Twitter</a> - <a href="https://github.com/patriciogonzalezvivo" target="_blank">GitHub</a> - <a href="https://vimeo.com/patriciogv" target="_blank">Vimeo</a> - <a href="https://www.flickr.com/photos/106950246@N06/" target="_blank"> Flickr</a></div>
[Jen Lowe](http://jenlowe.net/) ist eine unabhängige Datenwissenschaftlerin und Datenkommunikatorin bei der Firma Datatelling, wo sie Menschen, Zahlen und Sprache zusammenführt. Sie unterrichtet im Rahmen des „SVA Design for Social Innovation“-Programms, hat die Schule für „Poetic Computation“ mitbegründet, Mathematik für Künstler an der New Yorker ITP-Universität unterrichtet, Forschungen am „Spatial Information Design Lab“ der Columbia Universität durchgeführt und Beiträge für das „White House Office of Science and Technology“ geliefert, das den US-Präsidenten in Fragen des technischen Fortschritts berät. Als Sprecherin ist Jen auf Konferenzen wie der SXSW und der Eyeo aufgetreten. Von ihren Arbeiten hat unter anderem die New York Times, sowie das Magazin FastCompany berichtet. Ihre Forschungsarbeiten, Publikationen und Vorträge kreisen um die Versprechungen und Folgen von Daten und Technologien für die gesellschaftliche Entwicklung. Sie hat einen „Bachelor of Science“-Abschluss in angewandter Mathematik und einen Master-Abschluss in Informatik. Obwohl man angesichts dieser Biographie vielleicht etwas anderes vermuten könnte, schlägt sich Jen immer auf die Seite der Liebe.
<div class="header"> <a href="http://jenlowe.net/" target="_blank">Webseite</a> - <a href="https://twitter.com/datatelling" target="_blank">Twitter</a> - <a href="https://github.com/datatelling" target="_blank">GitHub</a></div>
## Danksagungen
Dank an [Scott Murray](http://alignedleft.com/) für die Inspirationen und Ratschläge.
Dank an [Kenichi Yoneda (Kynd)](https://twitter.com/kyndinfo), [Nicolas Barradeau](https://twitter.com/nicoptere) und [Karim Naaji](http://karim.naaji.fr/) für ihre Unterstützung, Anregungen und Programmcode.
Dank an [Kenichi Yoneda (Kynd)](https://twitter.com/kyndinfo) und [Sawako](https://twitter.com/sawakohome) für die [japanische Übersetzung des Textes (日本語訳)](?lan=jp)
Dank an [Tong Li](https://www.facebook.com/tong.lee.9484) und [Yi Zhang](https://www.facebook.com/archer.zetta?pnref=story) für die [chinesische Übersetzung des Textes (中文版)](?lan=ch)
Dank an [Jae Hyun Yoo](https://www.facebook.com/fkkcloud) für die [koreanische Übersetzung des Textes (한국어)](?lan=kr)
Dank an [Nahuel Coppero (Necsoft)](http://hinecsoft.com/) für die
[spanische Übersetzung des Textes (español)](?lan=es)
Dank an [Nicolas Barradeau](https://twitter.com/nicoptere) und [Karim Naaji](http://karim.naaji.fr/) für die [französische Übersetzung des Textes (français)](?lan=fr)
Dank an [Andrea Rovescalli](https://www.earove.info) für die [italienische Übersetzung des Textes (italiano)](?lan=it)
Dank an [Michael Tischer](http://www.mitinet.de) für die [deutsche Übersetzung des Textes](?lan=de)
Und natürlich Danke an alle, die an dieses Projekt geglaubt, dafür gespendet oder durch Hinweise und Korrekturen [daran mitgewirkt haben](https://github.com/patriciogonzalezvivo/thebookofshaders/graphs/contributors).
## Hol Dir die neuen Kapitel
Melde Dich für den Newsletter an oder [folge uns auf Twitter](https://twitter.com/bookofshaders)
<form style="border:1px solid #ccc;padding:3px;text-align:center;" action="https://tinyletter.com/thebookofshaders" method="post" target="popupwindow" onsubmit="window.open('https://tinyletter.com/thebookofshaders', 'popupwindow', 'scrollbars=yes,width=800,height=600');return true"><a href="https://tinyletter.com/thebookofshaders"><p><label for="tlemail">Deine Email-Adresse</label></p></a><p><input type="text" style="width:140px" name="email" id="tlemail" /></p><input type="hidden" value="1" name="embed"/><input type="submit" value="Subscribe" /><p><a href="https://tinyletter.com" target="_blank"></a></p></form>

@ -96,6 +96,8 @@ Thanks [Nicolas Barradeau](https://twitter.com/nicoptere) and [Karim Naaji](http
Thanks [Andrea Rovescalli](https://www.earove.info) for the Italian [translation (italiano)](?lan=it)
Thanks [Michael Tischer](http://www.mitinet.de) for the German [translation (deutsch)](?lan=de)
Thanks to everyone who has believed in this project and [contributed with fixes](https://github.com/patriciogonzalezvivo/thebookofshaders/graphs/contributors) or donations.
## Get new chapters

@ -0,0 +1,33 @@
## Wie kann ich dieses Buch offline lesen?
Nehmen wir einmal an, Du gehst auf eine längere Reise und möchtest Dich unterwegs in die Shader-Programmierung einarbeiten. In diesem Fall könntest Du eine Kopie dieses Buches auf Deinen Rechner laden und diese über einen lokalen Server anzeigen lassen.
Alles, was Du dafür benötigst, ist Python 2.6 und ein Client-Programm für GIT. Auf Computern mit MacOS und auf dem RaspberryPi ist Python standardmäßig bereits vorinstalliert. Dort musst Du lediglich den GIT-Client zusätzlich installieren.
Unter **MacOSX** benötigst Du dafür [homebrew](http://brew.sh/). Sobald das Paket installiert ist, kannst Du in einem Terminal-Fenster folgendes eingeben:
```bash
brew update
brew upgrade
brew install git
```
Auf einem **RaspberryPi** gibst Du folgendes ein:
```bash
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install git-core
```
Hast Du alles beisammen, musst Du lediglich folgende Befehle aufrufen, um das *Book of Shaders* per GIT auf Deinen Rechner zu laden und den Server zur Anzeige des Inhalts zu starten:
```bash
cd ~
git clone --recursive https://github.com/patriciogonzalezvivo/thebookofshaders.git
cd thebookofshaders
git submodule foreach git pull
php -S localhost:8000
```
Nutze dann den vorinstallierten Internet-Browser auf Deinem Rechner zur Anzeige des Buches durch Eingabe folgender URL [```http://localhost:8000/```](http://localhost:8000/)

@ -0,0 +1,25 @@
## Wie kann ich die Beispielprogramme auf einem RaspberryPi ausführen?
Vor wenigen Jahren konnte man noch nicht davon ausgehen, dass jedermann über einen Computer mit einer GPU verfügt. Heutzutage gilt das nicht mehr. Doch im Bereich von Schulen, Universitäten und anderen Weiterbildungseichrichtungen ist dies immer noch eine hohe Anforderung.
Durch das [Raspberry Projekt](http://www.raspberrypi.org/) hat mittlerweile eine neue Generation kleiner und billiger Computer (das Stück ab ca. 40 Euro) ihren Weg in viele Klassenzimmer gefunden. Vor allem verfügt der [RaspberryPi](http://www.raspberrypi.org/) über einen ansehnlichen Grafikchip mit GPU, der direkt aus der Kommandozeile angesprochen werden kann.
Ich habe ein flexibles Werkzeug für die Programmierung von GLSL-Shadern entwickelt, den [**glslViewer**](https://github.com/patriciogonzalezvivo/glslViewer). Damit können alle Beispiele aus diesem Buch ausgeführt werden. Sobald man Veränderungen am aktuellen Shader-Programmcode abspeichert, kompiliert das Programm den Shader erneut und bringt ihn zur Ausführung. Auf dem Bildschirm erscheint daraufhin die aktualisierte Anzeige des Shaders.
Indem Du eine lokale Kopie dieses Buches und seiner Beispielprogramme auf Deinem Rechner anlegst (mehr dazu im vorhergehenden Kapitel) und den [```glslViewer```] (https://github.com/patriciogonzalezvivo/glslViewer) installierst, kannst Du die Beispielprogramme mit dem ```glslviewer``` ausführen. Wenn Du beim Start dieses Programms den Kommandozeilenschalter ```-l``` angibst, erscheint die erzeugte Grafik in einer Ecke des Bildschirms, während Du gleichzeitig den Shader-Programmcode mit einem beliebigen Text-Editor (etwa ```nano```, ```pico```, ```vi```, ```vim``` oder ```emacs```) bearbeitest. Das funktioniert auch, wenn Du mit dem Terminal des RaspberryPi über ssh/sftp verbunden bist.
Um die angesprochenen Tools auf einem RaspberryPi zu installieren, rufe nach dem Start des Betriebssystems und dem Einloggen folgende Befehle über die Kommandozeile auf:
```bash
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install git-core
cd ~
git clone http://github.com/patriciogonzalezvivo/glslViewer.git
cd glslViewer
make
make install
cd ~
git clone https://github.com/patriciogonzalezvivo/thebookofshaders.git
cd thebookofshaders
```

@ -0,0 +1,69 @@
## Wie kann ich dieses Buch ausdrucken?
Nehmen wir einmal an, Du willst gar nicht mit den Beispielprogrammen in diesem Buch interagieren, sondern den Text wie ein gutes altes Buch im Urlaub oder auf dem täglichen Weg zur Arbeit lesen. In diesem Fall kannst Du Dir den Text einfach ausdrucken.
#### Installation des glslViewer
Um den Text auszudrucken, müssen die verschiedenen Bestandteile des Buches zunächst aufbereitet werden. Dafür benötigst Du den [```glslViewer```](https://github.com/patriciogonzalezvivo/glslViewer), ein Werkzeug für die Kommandozeile, mit dem Du aus den verschiedenen Beispielprogrammen die daraus resultierenden Bilder generieren kannst.
Unter **MacOSX** benötigst Du zunächst [homebrew](http://brew.sh/). Nach dessen Installation kannst Du in einem Terminalfenster folgendes eingeben:
```bash
brew update
brew upgrade
brew tap homebrew/versions
brew install glfw3
cd ~
git clone http://github.com/patriciogonzalezvivo/glslViewer.git
cd glslViewer
make
make install
```
Auf einem **RaspberryPi** gibst Du folgende Befehle ein:
```bash
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install git-core
cd ~
git clone http://github.com/patriciogonzalezvivo/glslViewer.git
cd glslViewer
make
make install
```
#### Installation von Latex und Pandoc
Für den Ausdruck müssen die einzelnen Kapitel zunächst aus dem vorliegenden Textformat (*Markdown*) zunächst nach Latex und anschließend nach PDF konvertiert werden.
Unter **MacOSX**:
Lade und installiere zunächst [basictex inkl. der MacTeX-Erweiterungen](http://www.tug.org/mactex/morepackages.html) und installiere anschließend [Pandoc](http://johnmacfarlane.net/pandoc/), indem Du folgende Kommandos eingibst:
```bash
brew install pandoc
```
Auf einem **RaspberryPi** gibst Du bitte folgende Kommandos ein:
```bash
sudo apt-get install texlive-xetex pandoc
```
#### Das Buch nach PDF umwandeln und ausdrucken
Jetzt, wo Du alle Werkzeuge beisammenhast, ist es an der Zeit, eine Kopie des Buches aus der [Ablage im Internet](https://github.com/patriciogonzalezvivo/thebookofshaders) herunterzuladen und daraus eine PDF-Datei zu erstellen.
Öffne dafür erneut ein Terminalfenster und gib die folgenden Befehle ein:
```bash
cd ~
git clone https://github.com/patriciogonzalezvivo/thebookofshaders.git
cd thebookofshaders
make
```
Wenn alles funktioniert hat, findest Du anschließend die Datei ```book.pdf``` vor, die Du auf Deinem bevorzugten Gerät lesen oder ausdrucken kannst.

@ -0,0 +1,65 @@
## Wie kann ich zu diesem Buch beitragen?
Schön, dass Du Interesse hast, an diesem Buch mitzuwirken. Zahlreiche Möglichkeiten bieten sich dafür an. Du kannst ...
- Inhalte übersetzen
- Das [```Glossar```](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/glossary) verbessern
- Fehler bereinigen
- Deine eigenen GLSL-Shader über den [Online Editor](http://editor.thebookofshaders.com/) mit anderen teilen
### Inhalte übersetzen
Der Quelltext dieses Buches wurde in [Markdown](https://daringfireball.net/projects/markdown/syntax) verfasst. Dadurch ist es sehr einfach, den Text zu bearbeiten und zu erweitern.
1. Besuche zunächst die Internet-Ablage dieses Buches bei [Github unter ```github.com/patriciogonzalezvivo/thebookofshaders```](https://github.com/patriciogonzalezvivo/thebookofshaders). Verschaffe Dir einen Überblick über die verschiedenen Verzeichnisse und die darin enthaltenen Dateien. Du wirst feststellen, dass die eigentlichen Textinhalte des Buches jeweils in der Datei ```README.md``` und in anderen Dateien enthalten sind, die Großbuchstaben im Namen tragen. Beispiele dafür sind etwa ```TITLE.md```, ```SUMMARY.md``` usw. Die Übersetzungen dieser Texte stecken in Dateien, die am Ende des Namens ein Kürzel für die jeweilige Sprache tragen, also z.B. ```README-jp.md```, ```README-es.md``` usw.
2. Lege einen Fork der Ablage an und klone den Fork auf Deinen Computer.
3. Lege jeweils eine Kopie der Datei an, die Du übersetzen möchtest, und vergiss dabei nicht, das Sprachkürzel im Dateinamen zu ergänzen.
4. Übersetze den Inhalt des Dokuments Zeile für Zeile (siehe dazu auch die **Übersetzungshinweise** unten).
5. Überprüfe den Inhalt hinsichtlich der Rechtschreibung und der korrekten Anzeige im Browser (siehe unten unter **Testen**).
6. Lade die veränderten Dateien in Deinen Fork hoch und setze einen [Pull Request](https://help.github.com/articles/using-pull-requests/) ab.
#### Übersetzungshinweise
Lösche und verändere nichts an der Einbindung der Beispielprogramme innerhalb des Quelltextes. Dieses sehen wie folgt aus:
```html
<div class="codeAndCanvas" data="grid-making.frag"></div>
```
oder
```html
<div class="simpleFunction" data="y = mod(x,2.0);"></div>
```
#### Testen
Starte auf Deinem lokalen Rechner einen PHP-Server innerhalb des Verzeichnisses, in das Du das Buch geklont hast:
```bash
php -S localhost:8000
```
Rufe dann in Deinem Internet-Browser die URL ```localhost:8000``` auf. Klicke Dich bis zu dem Kapitel durch, an dem Du gerade arbeitest. Füge der angezeigten URL in der Adresszeile des Browsers den Zusatz ```?lan=``` hinzu, gefolgt von dem Sprachenkürzel, das Du bei der Benennung der jeweiligen Datei verwendet hast.
Um ein Beispiel zu nennen: Wenn Du gerade das Kapitel ```03``` ins Französische übersetzt und dabei mit der Datei ```03/README-fr.md``` arbeitest, kannst Du diese Datei anzeigen, indem Du folgende URL eingibst: ```http://localhost:8000/03/?lan=fr```
### Verbesserungen am Glossar
Das Glossar befindet sich noch in Arbeit. Wir freuen uns über Vorschläge, wie man das Glossar zu einem wertvollen Bestandteil des Buches ausbauen kann. Schick uns einfach eine Nachricht an [@bookofshaders](https://twitter.com/bookofshaders).
### Fehler bereinigen
Irren ist menschlich! Wenn Dir ein Fehler auffällt, bereinige die Stelle und setze einfach einen entsprechenden Pull Request auf Github ab, oder eröffnete dort eine Diskussion zu dem Thema. Vielen Dank!
### Teile Deine Shader mit Anderen
Du wirst im Quelltext des Buches bei den Beispielen viele Verweise auf den [Online-Editor](http://editor.thebookofshaders.com/) sehen.
Sobald Du einen Shader entwickelt hast, auf den Du stolz bist, klicke auf die „Export“-Schaltfläche (bzw. das ```⇪```-Symbol) und kopiere anschließend die im Editor angezeigte „URL to code...“. Sende diese URL an [@bookofshaders](https://twitter.com/bookofshaders) oder an [@kyndinfo](https://twitter.com/kyndinfo). Wir freuen uns auf tolle Shader und werden diese gerne unserer [Galerie mit Beispielen](https://thebookofshaders.com/examples/) hinzufügen.

@ -0,0 +1,15 @@
# Appendix
1. [Wie kann ich dieses Buch offline lesen?](00/?lan=de)
2. [Wie kann ich die Beispielprogramme auf einem Raspberry Pi ausführen?](01/?lan=de)
3. [Wie kann ich dieses Buch ausdrucken?](02/?lan=de)
4. [Wie kann ich zu diesem Buch beitragen?](03/?lan=de)
5. [An introduction for those coming from JS](04/) by [Nicolas Barradeau](http://www.barradeau.com/)
6. [An introduction for vectors](05/) by ...
7. [An introduction to interpolation](06) by ...

@ -1,6 +1,6 @@
<div class="header">
<p class="subtitle"><a href="https://thebookofshaders.com/">The Book of Shaders</a> by <a href="http://patriciogonzalezvivo.com">Patricio Gonzalez Vivo</a> & <a href="http://jenlowe.net">Jen Lowe</a> </p>
<p> <a href="?lan=jp">日本</a> - <a href="?lan=ch">中文版</a> - <a href="?lan=kr">한국어</a> - <a href="?lan=es">Español</a> - <a href="?lan=fr">Français</a> - <a href="?lan=it">Italiano</a> - <a href=".">English</a></p>
<p> <a href="?lan=jp">日本</a> - <a href="?lan=ch">中文版</a> - <a href="?lan=kr">한국어</a> - <a href="?lan=es">Español</a> - <a href="?lan=fr">Français</a> - <a href="?lan=it">Italiano</a> - <a href="?lan=de">Deutsch</a> - <a href=".">English</a></p>
</div>
<hr>

@ -0,0 +1,2 @@
## Ausgewählte Beispiel Shader

@ -0,0 +1,9 @@
# Galerie mit ausgewählten Shader Beispielen
<p class="gallery_author">Kuratiert von <a href="https://www.kynd.info">kynd</a>(<a href="https://twitter.com/kyndinfo">@kyndinfo</a>) und Patricio Gonzalez Vivo(<a href="https://twitter.com/patriciogv">@patriciogv</a>)</p>
Dies ist eine Sammlung von Shader Beispielen aus den verschiedenen Kapiteln dieses Buches. Sie wird ergänzt durch weitere Shader, die von Lesern über den [Online-Editor](http://editor.thebookofshaders.com/) zur Verfügung gestellt wurden.
Du bist herzlich eingeladen, die verschiedenen Shader auszuprobieren, zu erweitern und zu verändern. Und natürlich kannst Du auch ganz neue Shader enwickeln.
Wenn Du Deine Arbeiten anderen Lesern zur Verfügung stellen möchtest, klicke auf die „Export“-Schaltfläche im Editor und kopiere anschließend den Inhalt des Feldes „URL to code...“. Sende diese URL an [@bookofshaders](https://twitter.com/bookofshaders) oder an [@kyndinfo](https://twitter.com/kyndinfo). Wir freuen uns auf Deine Ergebnisse.

@ -1 +1 @@
Subproject commit 22050b571c923a702761844c91d26dfbbd841750
Subproject commit 5d41f8a8920815b0ea3f5f9185e4e7deeeafefde

@ -1,3 +1,3 @@
<div class="toc-header">
<p> <a href="?lan=jp">日本</a> - <a href="?lan=ch">中文版</a> - <a href="?lan=kr">한국어</a> - <a href="?lan=es">Español</a> - <a href="?lan=fr">Français</a> - <a href="?lan=it">Italiano</a> - <a href=".">English</a></p>
<p> <a href="?lan=jp">日本</a> - <a href="?lan=ch">中文版</a> - <a href="?lan=kr">한국어</a> - <a href="?lan=es">Español</a> - <a href="?lan=fr">Français</a> - <a href="?lan=it">Italiano</a> - <a href="?lan=de">Deutsch</a> - <a href=".">English</a></p>
</div>

Loading…
Cancel
Save