Merge pull request #157 from yvan-sraka/master

Remove trailing whitespaces & dos2unix all files
pull/163/head
Patricio Gonzalez Vivo 7 years ago committed by GitHub
commit f3a4ed14f2

@ -48,4 +48,4 @@ Fragment shaders片段着色器可以让你控制像素在屏幕上的快
* [做一个PDF版的书用于打印](https://thebookofshaders.com/appendix/)
* 用[github仓库](https://github.com/patriciogonzalezvivo/thebookofshaders)来帮助解决问题和分享代码
* 用[github仓库](https://github.com/patriciogonzalezvivo/thebookofshaders)来帮助解决问题和分享代码

@ -1,50 +1,49 @@
# 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.
# 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.

@ -1,4 +1,4 @@
# Introduction
# Introduction
<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas>
@ -42,7 +42,7 @@ ce que ce livre n'est pas:
* ce *n'est pas* livre sur l'openGL ou le webGL. OpenGL/webGL dépasse de loin le GLSL ou les shaders. si vous voulez en savoir plus, les liens suivants vous aideront [OpenGL Introduction](https://open.gl/introduction), [the 8th edition of the OpenGL Programming Guide](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) (alias "the red book") ou [WebGL: Up and Running](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)
* ce *n'est pas* un livre de maths. Même si le livre contient un certain nombre de notions et d'algorithmes nécessitant des connaissances en algèbre et en trigonométrie, nous ne rentrerons pas dans le détail. Pour toute question relative aux maths, vous pouvez choisir un de ces livres et le garder près de vous : [3rd Edition of Mathematics for 3D Game Programming and computer Graphics](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) ou [2nd Edition of Essential Mathematics for Games and Interactive Applications](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).
## bien démarrer
@ -57,4 +57,3 @@ Cela étant et selon ce que vous voulez faire de ce livre, vous pouvez :
- [créer un PDF du livre pour l'imprimer](https://thebookofshaders.com/appendix/)
- vous servir du [repo online](https://github.com/patriciogonzalezvivo/thebookofshaders) pour contribuer ou nous aider à débugger.

@ -47,4 +47,3 @@ In alternativa, in base a ciò di cui avete bisogno, è possibile:
- [Fare un PDF del libro da stampare](https://thebookofshaders.com/appendix/)
- Utilizzare la [repository on-line](https://github.com/patriciogonzalezvivo/thebookofshaders) per aiutare a risolvere i problemi e per condividere il codice.

@ -1,48 +1,47 @@
# Introduction
<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas>
위에 두 이미지는 다른 방법을 통해 만들어졌다. 첫번째것은 반 고흐가 직접 레이어 위에 레이어를 쌓는 방식으로 만들어졌다. 제법 시간이 걸렸을것이다. 두번째것은 몇초 안되는 시간안에 픽셀들의 행렬연산 4개를 통해 만들어 졌다: 한개는 cyan색, 다른 한개는 magenta색, 또 다른 한개는 yellow, 그리고 마지막것은 black. 중요한점은 두번째 이미지는 그림을 부분마다 따로 그려나가게 아니라 그림의 다른 모든 부분이 한번에 그려졌다는 것이다.
이 책은, *fragment shaders*, 라는 디지털 그림 제작과정을 다음 레벨로 이끌어낼 혁신적인 컴퓨팅 기술에 대한 것이다. 바로 그래픽 인더스트리의 구텐베르크 인쇄술인것이다.
![Gutenberg's press](gutenpress.jpg)
Fragment shader는 매우 빠른 속도로 스크린에 렌더되는 픽셀들을 완전히 컨트롤 할수 있는 능력을 준다. 핸드폰의 비디오 필터나, AAA 3D 비디오 같은 미디어에서 쓰이는 이유도 이것때문이다.
![Journey by That Game Company](journey.jpg)
앞으로 맞이할 챕터들은 독자가 이 강력하고 바른 기술을 스스로 습득하고, 자신의 작업에 적용할수 있는 길을 보여줄것이다.
## 누구를 위한 책인가?
이 책은 삼각함수와 선형대수학에 대한 기본이해가 있고 작업에 있어 그래픽 요소를 극대화 시키려는 creative coder, 게임 개발자, 그래픽 엔지니어들을 위한 책이다. (만약 본인이 코딩입문자라면 이 링크를 보고, [Processing](https://processing.org/) 코딩이 익숙해졌을때쯤 다시 돌아와 이책을 보길 권한다.)
이책은 독자들에게 쉐이더를 프로젝트에 어떻게 쓰는지와, 이를 통한 퍼포먼스 향상과 퀄리티를 높이는 방법들을 보여줄것이다. GLSL (OpenGL Shading Language) 쉐이더들은 OpenGL, OpenGL ES 혹은 WebGL을 가진 환경에서 컴파일되고 실행될것이다. 한마디로, 이것에 대한 기술을 [Processing](https://processing.org/) 스켓치파일들, [openFrameworks](http://openframeworks.cc/) 어플들, [Cinder](http://libcinder.org/) 설치미술들, [Three.js](http://threejs.org/) 웹사이트들 또는 iOS/Android 게임들에 적용할수 있다는 것이다.
## 어떤 내용들을 다루나?
이책은 GLSL pixel shader를 메인으로 다룬다. 먼저, 쉐이더가 무엇인지 알아보고, 절차적(procedural) 모양, 패턴, 텍스쳐, 애니메이션등에 응용해볼것이다. 쉐이딩 랭기지의 기본에 대해 다지게 되고, 여러 분야에 적용해볼수 있도록 유도하는데 예를들면: 이미지 처리(이미지 여산, 메트릭스 회선, blurs, color filters, 룩업테이블과 기타 효과들)와 시뮬레이션 (Conway's game of life, Gray-Scott's reaction-diffusion, water ripples, 물감 효과, Voronoi cells등등)이 그 좋은 예이다. 책의 막바지에는 Ray Marching과 같은 고급기술도 소개를 한다.
*각 챕터는 인터엑티브한 예제들로 구성되어 있다.* 예제들의 코드를 변경하면, 바로 그에 대한 결과를 볼수 있다. 컨셉자체가 추상적이거나 난해할수도 있기에, 이런 인터엑티브 예제가 이해하는데 큰 도움이 될거라고 믿는다. 컨셉에 대한 예제를 많이 가지고 놀아볼수록 그에 대한 이해역시 빨리 될거라고 생각한다.
이책이 다루지 않는 부분:
* 이책은 openGL이나 webGL서적이 아니다. openGL/webGL은 GLSL이나 fragment shader보다 훨씬 더 큰 주제이다. 그런것들에 대해 좀더 싶히 공부하고 싶다면: [OpenGL Introduction](https://open.gl/introduction), [the 8th edition of the OpenGL Programming Guide](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) (빨간책이라고도 알려진) 이나 [WebGL: Up and Running](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) 등을 추천한다.
* 이책은 수학색이 아니라. 물론 여러 종류의 알고리즘과 대수학과, 삼각함수에 기댄 수학수식이 많이 이용되지만, 그런것들에 대해 자세히 설명하지는 않을 것이다. 수학에 대한 질문은 : [3rd Edition of Mathematics for 3D Game Programming and computer Graphics](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) 를 보거나, [2nd Edition of Essential Mathematics for Games and Interactive Applications](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) 등을 참고하기 바란다.
## 시작하기 위해 무엇을 해야하나?
필요한것은 따로 없다! 근대 브라우져를 이용하고 있다면, WebGL이 서포트 될것이고 (구글 크롬이나 파이어폭스, 사파리), 인터넷만 있으면 된다! (지금 보고 있지만) 페이지 최하단에 있는 "Next"버튼을 눌러 다음챕터로 가면 시작이다.
아니면 , 다음과 같은 방법으로도 이 책을 접할수 있다:
- [이책의 오프라인 버젼](https://thebookofshaders.com/appendix/)
- [Raspberry Pi에서 브라우져 없이 예제들 돌리기](https://thebookofshaders.com/appendix/)
- [이책의 PDF버젼 만들기](https://thebookofshaders.com/appendix/)
- 또는 [온라인 리포](https://github.com/patriciogonzalezvivo/thebookofshaders) 이슈들을 답하거나, 올려주세요.
# Introduction
<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas>
위에 두 이미지는 다른 방법을 통해 만들어졌다. 첫번째것은 반 고흐가 직접 레이어 위에 레이어를 쌓는 방식으로 만들어졌다. 제법 시간이 걸렸을것이다. 두번째것은 몇초 안되는 시간안에 픽셀들의 행렬연산 4개를 통해 만들어 졌다: 한개는 cyan색, 다른 한개는 magenta색, 또 다른 한개는 yellow, 그리고 마지막것은 black. 중요한점은 두번째 이미지는 그림을 부분마다 따로 그려나가게 아니라 그림의 다른 모든 부분이 한번에 그려졌다는 것이다.
이 책은, *fragment shaders*, 라는 디지털 그림 제작과정을 다음 레벨로 이끌어낼 혁신적인 컴퓨팅 기술에 대한 것이다. 바로 그래픽 인더스트리의 구텐베르크 인쇄술인것이다.
![Gutenberg's press](gutenpress.jpg)
Fragment shader는 매우 빠른 속도로 스크린에 렌더되는 픽셀들을 완전히 컨트롤 할수 있는 능력을 준다. 핸드폰의 비디오 필터나, AAA 3D 비디오 같은 미디어에서 쓰이는 이유도 이것때문이다.
![Journey by That Game Company](journey.jpg)
앞으로 맞이할 챕터들은 독자가 이 강력하고 바른 기술을 스스로 습득하고, 자신의 작업에 적용할수 있는 길을 보여줄것이다.
## 누구를 위한 책인가?
이 책은 삼각함수와 선형대수학에 대한 기본이해가 있고 작업에 있어 그래픽 요소를 극대화 시키려는 creative coder, 게임 개발자, 그래픽 엔지니어들을 위한 책이다. (만약 본인이 코딩입문자라면 이 링크를 보고, [Processing](https://processing.org/) 코딩이 익숙해졌을때쯤 다시 돌아와 이책을 보길 권한다.)
이책은 독자들에게 쉐이더를 프로젝트에 어떻게 쓰는지와, 이를 통한 퍼포먼스 향상과 퀄리티를 높이는 방법들을 보여줄것이다. GLSL (OpenGL Shading Language) 쉐이더들은 OpenGL, OpenGL ES 혹은 WebGL을 가진 환경에서 컴파일되고 실행될것이다. 한마디로, 이것에 대한 기술을 [Processing](https://processing.org/) 스켓치파일들, [openFrameworks](http://openframeworks.cc/) 어플들, [Cinder](http://libcinder.org/) 설치미술들, [Three.js](http://threejs.org/) 웹사이트들 또는 iOS/Android 게임들에 적용할수 있다는 것이다.
## 어떤 내용들을 다루나?
이책은 GLSL pixel shader를 메인으로 다룬다. 먼저, 쉐이더가 무엇인지 알아보고, 절차적(procedural) 모양, 패턴, 텍스쳐, 애니메이션등에 응용해볼것이다. 쉐이딩 랭기지의 기본에 대해 다지게 되고, 여러 분야에 적용해볼수 있도록 유도하는데 예를들면: 이미지 처리(이미지 여산, 메트릭스 회선, blurs, color filters, 룩업테이블과 기타 효과들)와 시뮬레이션 (Conway's game of life, Gray-Scott's reaction-diffusion, water ripples, 물감 효과, Voronoi cells등등)이 그 좋은 예이다. 책의 막바지에는 Ray Marching과 같은 고급기술도 소개를 한다.
*각 챕터는 인터엑티브한 예제들로 구성되어 있다.* 예제들의 코드를 변경하면, 바로 그에 대한 결과를 볼수 있다. 컨셉자체가 추상적이거나 난해할수도 있기에, 이런 인터엑티브 예제가 이해하는데 큰 도움이 될거라고 믿는다. 컨셉에 대한 예제를 많이 가지고 놀아볼수록 그에 대한 이해역시 빨리 될거라고 생각한다.
이책이 다루지 않는 부분:
* 이책은 openGL이나 webGL서적이 아니다. openGL/webGL은 GLSL이나 fragment shader보다 훨씬 더 큰 주제이다. 그런것들에 대해 좀더 싶히 공부하고 싶다면: [OpenGL Introduction](https://open.gl/introduction), [the 8th edition of the OpenGL Programming Guide](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) (빨간책이라고도 알려진) 이나 [WebGL: Up and Running](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) 등을 추천한다.
* 이책은 수학색이 아니라. 물론 여러 종류의 알고리즘과 대수학과, 삼각함수에 기댄 수학수식이 많이 이용되지만, 그런것들에 대해 자세히 설명하지는 않을 것이다. 수학에 대한 질문은 : [3rd Edition of Mathematics for 3D Game Programming and computer Graphics](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) 를 보거나, [2nd Edition of Essential Mathematics for Games and Interactive Applications](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) 등을 참고하기 바란다.
## 시작하기 위해 무엇을 해야하나?
필요한것은 따로 없다! 근대 브라우져를 이용하고 있다면, WebGL이 서포트 될것이고 (구글 크롬이나 파이어폭스, 사파리), 인터넷만 있으면 된다! (지금 보고 있지만) 페이지 최하단에 있는 "Next"버튼을 눌러 다음챕터로 가면 시작이다.
아니면 , 다음과 같은 방법으로도 이 책을 접할수 있다:
- [이책의 오프라인 버젼](https://thebookofshaders.com/appendix/)
- [Raspberry Pi에서 브라우져 없이 예제들 돌리기](https://thebookofshaders.com/appendix/)
- [이책의 PDF버젼 만들기](https://thebookofshaders.com/appendix/)
- 또는 [온라인 리포](https://github.com/patriciogonzalezvivo/thebookofshaders) 이슈들을 답하거나, 올려주세요.

@ -2,7 +2,7 @@
<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas>
The images above were made in different ways. The first one was made by Van Gogh's hand applying layer over layer of paint. It took him hours. The second was produced in seconds by the combination of four matrices of pixels: one for cyan, one for magenta, one for yellow and one for black. The key difference is that the second image is produced in a non-serial way (that means not step-by-step, but all at the same time).
The images above were made in different ways. The first one was made by Van Gogh's hand applying layer over layer of paint. It took him hours. The second was produced in seconds by the combination of four matrices of pixels: one for cyan, one for magenta, one for yellow and one for black. The key difference is that the second image is produced in a non-serial way (that means not step-by-step, but all at the same time).
This book is about the revolutionary computational technique, *fragment shaders*, that is taking digitally generated images to the next level. You can think of it as the equivalent of Gutenberg's press for graphics.
@ -45,4 +45,3 @@ Alternatively, based on what you have or what you need from this book you can:
- [Make a PDF of the book to print](https://thebookofshaders.com/appendix/)
- Use the [on-line repository](https://github.com/patriciogonzalezvivo/thebookofshaders) to help resolve issues and share code.

@ -14,7 +14,7 @@ precision mediump float;
#define SST 0.888
#define SSQ 0.288
uniform sampler2D u_tex0;
uniform sampler2D u_tex0;
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
@ -72,7 +72,7 @@ void main() {
mat2 mm = rotm(R+D2R(75.0));
mat2 my = rotm(R);
mat2 mk = rotm(R+D2R(45.0));
float k = halftone(fc,mk).a;
vec4 c = cmyki2rgb(ss(vec4(
halftone(fc,mc).r,
@ -86,6 +86,6 @@ void main() {
st = vec2(st.x,st.y*0.5)*2.0;
gl_FragColor = texture2D(u_tex0,st);
}
}
}

@ -2,7 +2,7 @@
precision mediump float;
#endif
uniform sampler2D u_tex0;
uniform sampler2D u_tex0;
uniform vec2 u_resolution;
uniform vec2 u_mouse;
@ -30,7 +30,7 @@ void main () {
if (st.x > 0.5) {
// Halftone dot matrix shader
// @author Tomek Augustyn 2010
// Ported from my old PixelBender experiment
// https://github.com/og2t/HiSlope/blob/master/src/hislope/pbk/fx/halftone/Halftone.pbk
float ratio = u_resolution.y / u_resolution.x;
@ -39,25 +39,25 @@ void main () {
vec2 srcCoord = vec2(st.x-0.5, st.y*0.5)*2.0;
vec2 rotationCenter = vec2(0.5);
vec2 shift = dstCoord - rotationCenter;
float dotSize = 5.0;
float angle = 45.0;
float rasterPattern = added(shift, sind(angle), cosd(angle), rotationCenter, PI / dotSize * 680.0);
vec4 srcPixel = texture2D(u_tex0, srcCoord);
float avg = 0.2125 * srcPixel.r + 0.7154 * srcPixel.g + 0.0721 * srcPixel.b;
float gray = (rasterPattern * threshold + avg - threshold) / (1.0 - threshold);
// uncomment to see how the raster pattern looks
// uncomment to see how the raster pattern looks
// gray = rasterPattern;
gl_FragColor = vec4(gray, gray, gray, 1.0);
} else {
st = vec2(st.x,st.y*0.5)*2.0;
gl_FragColor = texture2D(u_tex0, st);
}
}

@ -1,4 +1,4 @@
<?php
<?php
$path = "..";
$subtitle = ": about this book";
@ -28,5 +28,5 @@
<li class="navigationBar" onclick="nextPage()">Next &gt; &gt;</li>
</ul>';
include($path."/footer.php");
include($path."/footer.php");
?>

@ -29,7 +29,7 @@ Shaders 也是一系列的指令,但是这些指令会对屏幕上的每个像
![GPU](04.jpeg)
设想一堆小型微处理器排成一个平面的画面假设每个像素的数据是乒乓球。14400000个乒乓球可以在一秒内阻塞几乎任何管道。但是一面800x600的管道墙每秒接收30波480000个像素的信息就可以流畅完成。这在更高的分辨率下也是成立的 —— 并行的处理器越多,可以处理的数据流就越大。
设想一堆小型微处理器排成一个平面的画面假设每个像素的数据是乒乓球。14400000个乒乓球可以在一秒内阻塞几乎任何管道。但是一面800x600的管道墙每秒接收30波480000个像素的信息就可以流畅完成。这在更高的分辨率下也是成立的 —— 并行的处理器越多,可以处理的数据流就越大。
另一个 GPU 的魔法是特殊数学函数可通过硬件加速。非常复杂的数学操作可以直接被微芯片解决,而无须通过软件。这就表示可以有更快的三角和矩阵运算 —— 和电流一样快。
@ -45,4 +45,4 @@ GLSL 代表 openGL Shading LanguageopenGL 着色语言,这是你在接下
并且 GPU 会让所有并行的微处理器(管道们)一直处在忙碌状态;只要它们一有空闲就会接到新的信息。一个线程不可能知道它前一刻在做什么。它可能是在画操作系统界面上的一个按钮,然后渲染了游戏中的一部分天空,然后显示了一封 email 中的一些文字。每个线程不仅是“盲视”的,而且还是“无记忆”的。同时,它要求编写一个通用的规则,依据像素的不同位置依次输出不同的结果。这种抽象性,和盲视、无记忆的限制使得 shaders 在程序员新手中不是很受欢迎。
但是不要担心!在接下来的章节中,我们会一步一步地,由浅入深地学习着色语言。如果你是在用一个靠谱的浏览器阅读这个教程,你会喜欢边读边玩书中的示例的。好了,不要再浪费时间了,赶快去玩起来吧! 点击 **Next >>** 开启 shader 之旅!
但是不要担心!在接下来的章节中,我们会一步一步地,由浅入深地学习着色语言。如果你是在用一个靠谱的浏览器阅读这个教程,你会喜欢边读边玩书中的示例的。好了,不要再浪费时间了,赶快去玩起来吧! 点击 **Next >>** 开启 shader 之旅!

@ -1,48 +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.
# 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.

@ -45,4 +45,4 @@ Affinché ogni tubo, o thread, venga eseguito in parallelo, è necessario che si
Anche la GPU mantiene costantemente occupati i micro-processore paralleli (i tubi); non appena sono liberi ricevono nuove informazioni da elaborare. E' quindi impossibile per un thread sapere che cosa stava facendo nel momento precedente. Potrebbe disegnare un bottone dell'UI del sistema operativo, subito dopo rendere una porzione di cielo in un videogioco e poi visualizzare il testo di una e-mail. Ogni thread non è solo **cieco ** ma anche **senza memoria**. Oltre all'astrazione necessaria per programmare una funzione generica che cambia il risultato pixel per pixel, a seconda della sua posizione, i vincoli ciechi e senza memoria non rendono gli shaders molto popolari tra i programmatori debuttanti.
Non preoccuparti! Nei capitoli seguenti, impareremo passo-passo a partire dai semplici shaders fino a quelli avanzati. Se stai leggendo questo libro con un navigatore moderno, potrai giocare con gli esempi interattivi. Quindi non aspettare altro tempo e clicca su *Next >>* per iniziare il divertimento!
Non preoccuparti! Nei capitoli seguenti, impareremo passo-passo a partire dai semplici shaders fino a quelli avanzati. Se stai leggendo questo libro con un navigatore moderno, potrai giocare con gli esempi interattivi. Quindi non aspettare altro tempo e clicca su *Next >>* per iniziare il divertimento!

@ -33,16 +33,16 @@ CPU가 하나의 큰 공장같은 파이프라고 가정하자. 파이프로 들
GPU의 또다른 슈퍼파워중 하나는, 하드웨어지원으로 가속된 수학 함수 연산이다. 즉, 소프트웨어상에서가 아닌, 마이크로칩상에서 바로 연산이 진행된다는 이야기다. 이말은 더 많은 삼각함수연산, 매트릭스연산이 가능하다는 말이다 - 전기가 얼마나 빠르게 흐르냐에 따라.
## GLSL은 무엇인가?
## GLSL은 무엇인가?
GLSL은 openGL Shading Language의 줄임말로, 앞으로의 챕터들에서 쓰게될 쉐이더 프로그램 랭기지이다. 하드웨어나 운영체제에 따라 이 언어는 달라지기도 한다. 이 책에서는 크로노스그룹에서 규정된 openGL 규격을 따른다. [Khronos Group](https://www.khronos.org/opengl/). OpenGL의 역사를 이해하는것 또한 앞으로 보게될 전문용어들에 크게 도움이 될것이며, 아래 링크를 추천한다: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html)
GLSL은 openGL Shading Language의 줄임말로, 앞으로의 챕터들에서 쓰게될 쉐이더 프로그램 랭기지이다. 하드웨어나 운영체제에 따라 이 언어는 달라지기도 한다. 이 책에서는 크로노스그룹에서 규정된 openGL 규격을 따른다. [Khronos Group](https://www.khronos.org/opengl/). OpenGL의 역사를 이해하는것 또한 앞으로 보게될 전문용어들에 크게 도움이 될것이며, 아래 링크를 추천한다: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html)
## 왜 쉐이더를 사람들이 어렵다고 할까?
2차 세계대전에서 쌀공급으로 유명한 미국의 벤삼촌이 이르길, "큰 힘에는 큰 책임이 따른다"고 했다. 병렬연산또한 이 법칙을 따른다; GPU의 강력한 컴퓨테이션 능력은 이것을 쓰기위해 따라야할 제약과 제한이 있다.
2차 세계대전에서 쌀공급으로 유명한 미국의 벤삼촌이 이르길, "큰 힘에는 큰 책임이 따른다"고 했다. 병렬연산또한 이 법칙을 따른다; GPU의 강력한 컴퓨테이션 능력은 이것을 쓰기위해 따라야할 제약과 제한이 있다.
파이프상에서 병렬처리를 하기위해서는, 각 쓰레드마다, 서로에 대해 철저히 개별적이여야 한다. 쓰레드는 다른 쓰레드에 대해 "실명" 되어 있다고 미국에서는 표현하는데, 서로의 데이터에 대해 엑세스가 없다는 말이다. 그래서 각각의 프로세스들은 서로 데이터를 주고 받고 처리하는것이 불가능하다. 쓰레드끼리 소통하게 하는것은 데이터를 더럽힐수 있다.
또한, GPU는 모든 병렬 마이크로 프로세서들 (파이프들) 을 항시 바쁘게 하고 있다; 이 파이프들은 해당작업이 끝나는 대로 다른 작업을 받아 수행하도록 설계되어 있다. 또한, 각 쓰레드는 이미 수행한 작업에 대한 어떠한 정보도 가질수 없다. 보통 이런 작업들은 운영체제의 UI요소를 그리고 있는것이거나, 게임의 배경화면을 그리거나, 브라우져의 이메일 텍스트를 그리는 것들이다. 각 쓰레드는 서로에게 **실명**되있다고 표현할뿐아니라, **기억이없음** 이라고도 표현하는데, 이것은 이미 수행한 작업에 대한 어떠한 정보도 가지고 있지 않다는 말이다. 바로 이런 점들이 일반적인 프로그래밍 요소와 크게 다른부분이라고 할수 있어서 프로그래밍을 막 접한 이들에게는 어려운 컨셉일수도 있는것이다.
하지만 걱정하지 마시라! 앞으로의 챕터들에서 우리는 간단한 것부터 복잡한 쉐이딩 연산들에 대해 하나씩 짚고 넘어갈 것이다. 만약 당신이 이 책을 근대 브라우져에서 읽오 있다면, 인터엑티브한 예제들로 인해 공부에 도움을 받을것이다. 더이상 지겨운 서론은 짚어 치우고, *Next >>*를 누르고 코드로 넘어가보자!
하지만 걱정하지 마시라! 앞으로의 챕터들에서 우리는 간단한 것부터 복잡한 쉐이딩 연산들에 대해 하나씩 짚고 넘어갈 것이다. 만약 당신이 이 책을 근대 브라우져에서 읽오 있다면, 인터엑티브한 예제들로 인해 공부에 도움을 받을것이다. 더이상 지겨운 서론은 짚어 치우고, *Next >>*를 누르고 코드로 넘어가보자!

@ -1,7 +1,7 @@
# Getting started
## What is a fragment shader?
In the previous chapter we described shaders as the equivalent of the Gutenberg press for graphics. Why? And more importantly: what's a shader?
In the previous chapter we described shaders as the equivalent of the Gutenberg press for graphics. Why? And more importantly: what's a shader?
![From Letter-by-Letter, Right: William Blades (1891). To Page-by-page, Left: Rolt-Wheeler (1920).](print.png)
@ -33,13 +33,13 @@ Picture the tiny microprocessors as a table of pipes, and the data of each pixel
Another “super power” of the GPU is special math functions accelerated via hardware, so complicated math operations are resolved directly by the microchips instead of by software. That means extra fast trigonometrical and matrix operations - as fast as electricity can go.
## What is GLSL?
## What is GLSL?
GLSL stands for openGL Shading Language, which is the specific standard of shader programs you'll see in the following chapters. There are other types of shaders depending on hardware and Operating Systems. Here we will work with the openGL specs regulated by [Khronos Group](https://www.khronos.org/opengl/). Understanding the history of OpenGL can be helpful for understanding most of its weird conventions, for that I recommend taking a look at: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html)
GLSL stands for openGL Shading Language, which is the specific standard of shader programs you'll see in the following chapters. There are other types of shaders depending on hardware and Operating Systems. Here we will work with the openGL specs regulated by [Khronos Group](https://www.khronos.org/opengl/). Understanding the history of OpenGL can be helpful for understanding most of its weird conventions, for that I recommend taking a look at: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html)
## Why are Shaders famously painful?
As Uncle Ben said “with great power comes great responsibility,” and parallel computation follows this rule; the powerful architectural design of the GPU comes with its own constraints and restrictions.
As Uncle Ben said “with great power comes great responsibility,” and parallel computation follows this rule; the powerful architectural design of the GPU comes with its own constraints and restrictions.
In order to run in parallel every pipe, or thread, has to be independent from every other thread. We say the threads are *blind* to what the rest of the threads are doing. This restriction implies that all data must flow in the same direction. So its impossible to check the result of another thread, modify the input data, or pass the outcome of a thread into another thread. Allowing thread-to-thread communications puts the integrity of the data at risk.

@ -1,4 +1,4 @@
<?php
<?php
$path = "..";
$subtitle = ": What is a shader?";
@ -29,5 +29,5 @@
<li class="navigationBar" onclick="nextPage()">Next &gt; &gt;</li>
</ul>';
include($path."/footer.php");
include($path."/footer.php");
?>

@ -5,4 +5,4 @@
### Nicolas B
* clearly answer the "what is a fragment shader?" question in some sort of recap paragraph.
* beef up explanations around the compilation step (a brief overview will do).
* beef up explanations around the compilation step (a brief overview will do).

@ -5,7 +5,7 @@
然而在 GPU 的世界里,第一步就渲染一行文字太难了,所以我们改为选择一个鲜艳的欢迎色,来吧躁起来!
<div class="codeAndCanvas" data="hello_world.frag"></div>
如果你是在线阅读这本书的话,上面的代码都是可以交互的。你可以点击或者改动代码中任何一部分,尽情探索。多亏 GPU 的架构shader 会**飞速**地编译和更新这使得你的改动都会立刻出现在你眼前。试试改动第6行的值看会发生什么。
尽管这几行简单的代码看起来不像有很多内容,我们还是可以据此推测出一些知识点:

@ -1,53 +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).
## 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).

@ -5,7 +5,7 @@ Di solito l'esempio "Ciao Mondo!" è il primo passo per imparare un nuovo lingua
Nel mondo GPU rendere un testo è un esercizio troppo complicato per un primo passo, perciò sceglieremo un colore brillante di benvenuto per mostrare il nostro entusiasmo!
<div class="codeAndCanvas" data="hello_world.frag"></div>
Se stai leggendo questo libro in un navigatore, noterai che il precedente blocco di codice è interattivo. Ciò significa che è possibile fare click e modificare qualsiasi parte del codice per capire come funziona. Le modifiche verranno aggiornate immediatamente grazie all'architettura GPU che compila e sostituisce gli shaders *al volo*. Prova per esempio a cambiare i valori della linea 6.
Anche se queste semplici righe di codice non sembrano essere molto importanti, possiamo trarre molte informazioni:

@ -1,53 +1,53 @@
## Hello World
보통 "Hello world!" 예제들은 모든 컴퓨터 언어의 시작챕터의 제목이다. 라인하나를 출력하는 명령어로 보통 시작되며, 이 언어가 어떤 것들을 할수 있는지에 대한 첫번째 발걸음을 시작한다.
GPU-세상에서는 이런 문자열을 출력하는것은 첫번째 발걸음으로 다소 복잡한 경향이 있다. 하여, 우리는 밝은 색하나를 출력하는 것으로 대신해 발걸음을 떼어본다!
<div class="codeAndCanvas" data="hello_world.frag"></div>
이첵을 브라우져에서 읽고 있다면, 위에 구간이 상호작용이 가능하다는것을 알수 있다. 클릭하거나, 코드를 수정하여 결과를 바로 볼수 있다는 것이다. 이런 변화 인풋은 바로 GPU파이프라인으로 주입되어 컴파일되고, *실시간으로* 결과를 바꿔준다. 6번째 줄의 코드를 수정하여 이를 체험해보시라.
매우 간단한 코드지만, 상당히 중요한 내용을 우리는 엿볼수 있는데:
1. 쉐이더 언어는 color값을 리턴하는 ```main``` 함수이고, 이는 C와 형태가 유사하다.
2. 마지막으로 리턴되는 픽셀 색 값은, ```gl_FragColor```라는 전역변수에 대입된다.
3. 이 C-유형의 언어는, 미리 선언된, *변수*들 (```gl_FragColor```같은), *함수**타입*를 가진다. 이 예제의 경우, 실수로 이루어진 4차원 벡터 타입인, ```vec4```. 더 나아가면서, ```vec3``` 나 ```vec2```, ```float```, ```int```, 또한 ```bool```같은 것들이 보이게 될것이다.
4. '''vec4''' 타입을 자세히 살펴보면, 각 인수는 RED, GREEN, BLUE and ALPHA 채널이다. 이 값들은 *노멀라이즈된* 값이 ```0.0``` 에서 ```1.0``` 으로 맵핑된것이다. 나중에 나아가면서 노멀라이징을 어떻게 하는지, *map* 을 어떻게 하는지 살펴보게 될것이다.
5. 예제에서 볼수 있는 또 다른 중요한 *C 요소*는 전처리기 마크로들에 대한 사용이다. 마크로들은 컴파일되기 전에 일어나는 스텝이다. ```#define```을 이용해, 전역변수를 선언하거나, 기본적인 논리구현이 가능하다 (```#ifdef```나 ```#endif```를 통해). 모든 마크로는 해쉬태그 마크 (```#```) 로 시작한다. 이런 Pre-compilation은 컴파일이 실제로 일어나기 바로 전에 각 해쉬태그의 해당값을 이 코드로 카피한다. 위에 예제 'hello world!'를 보면, 우리는 ```GL_ES```를 선언하였는데, 이는 모바일 기기나, 브라우져에서 컴파일될때 전처리되는 부분들인 것이다.
6. 실수 타입들은 쉐이더에서 신경써야할 부분중 하나인데, *precision(실수정확도)*의 정도가 퍼포먼스에 영향을 미치기 때문이다. 낮은 정도의 precision을 가질수록 빠른 렌더 속도를 가지지만, 렌더 퀄리티가 그만큼 떨어진다는 것을 의미한다. 첫번째 라인을 보면, (```precision mediump float;```) 라는 내용이 보이는데, 실수정확도를 중간정도로 맞춘것이다. 높게는 (```precision lowp float;```) 낮게는 (```precision lowp float;```)이다.
7. 마지막으로, 그리고 제일 중요할지도 모르지만, GLSL에서는 데이터 타입의 casting이 확보되지 않는다. 무슨말인가하면, 제조업체들은 그래픽카드의 연산을 가속화 하기위해 각각 다른 시도들을 하였는데, 결국은 이것은 최소사양을 저격하고 있다. 자동 casting같은 경우는 여기에 포함되지 않고 있다. 우리의 "hello world!" 예제의 ```vec4``` 또한, ```floats```라는 데이터타입을 예상하게 되는것이다. 앞으로 쉐이더 프로그램을 하면서 실수의 경우에는 항상 점 (```.```) 을 포함하여 이 변수가, 값이 실수임을 명시하자. 예를들어 아래와 같은 코드는 작동이 안될것이다:
```glsl
void main() {
gl_FragColor = vec4(1,0,0,1); // ERROR
}
```
자, 이제 우리의 첫 예제인 "hello world!"프로그램에 대한 설명을 마친다. 예제의 코드를 수정하면서 이 단원에서 배운 내용을 곱씹어보는 시간을 갖길 바란다. 만약 코드에 에러가 있다면 컴파일 에러가 나면서 화면이 하얗게 될것이다. 아래와 같은 재밌는 시도들도 해볼수 있을것이다.:
* 실수값들을 정수값들로 바꿔보고, 본인의 그래픽 카드가 이값을 인식하고 아웃풋하는 결과를 보라.
* 6번째 라인을 코멘트아웃하고, 함수의 픽셀값에 아무런 값도 넣어보지 말라.
* ```main()```안에, 새로운 함수를 만들고 새로운 값을 리턴하게 해보라, 힌트로는 아래는 빨간색을 리턴하는 함수다 :
```glsl
vec4 red(){
return vec4(1.0,0.0,0.0,1.0);
}
```
* ```vec4```값을 만드는 방법을 여러가지가 있다. 아래역시 그중하나이다:
```glsl
vec4 color = vec4(vec3(1.0,0.0,1.0),1.0);
```
이 예제 자체가 그리 흥미롭지는 않지만 매우 중요한 기본 예제중 하나이다 - 캔바스의 모든 색을 같은색으로 바꿔보는 작업. 다음에 오는 챕터에서는 픽셀 색들을 2개의 인풋을 사용하여 바꿔보는 예제를 해볼것이다. (스크린위에 픽셀들의 위치를 이용한) 그리고 시간을 이용해 이들을 바꾸는 작업도 해볼것이다. (페이지가 로드완료된 후로 몇초가 지났는지를 이용한)
## Hello World
보통 "Hello world!" 예제들은 모든 컴퓨터 언어의 시작챕터의 제목이다. 라인하나를 출력하는 명령어로 보통 시작되며, 이 언어가 어떤 것들을 할수 있는지에 대한 첫번째 발걸음을 시작한다.
GPU-세상에서는 이런 문자열을 출력하는것은 첫번째 발걸음으로 다소 복잡한 경향이 있다. 하여, 우리는 밝은 색하나를 출력하는 것으로 대신해 발걸음을 떼어본다!
<div class="codeAndCanvas" data="hello_world.frag"></div>
이첵을 브라우져에서 읽고 있다면, 위에 구간이 상호작용이 가능하다는것을 알수 있다. 클릭하거나, 코드를 수정하여 결과를 바로 볼수 있다는 것이다. 이런 변화 인풋은 바로 GPU파이프라인으로 주입되어 컴파일되고, *실시간으로* 결과를 바꿔준다. 6번째 줄의 코드를 수정하여 이를 체험해보시라.
매우 간단한 코드지만, 상당히 중요한 내용을 우리는 엿볼수 있는데:
1. 쉐이더 언어는 color값을 리턴하는 ```main``` 함수이고, 이는 C와 형태가 유사하다.
2. 마지막으로 리턴되는 픽셀 색 값은, ```gl_FragColor```라는 전역변수에 대입된다.
3. 이 C-유형의 언어는, 미리 선언된, *변수*들 (```gl_FragColor```같은), *함수**타입*를 가진다. 이 예제의 경우, 실수로 이루어진 4차원 벡터 타입인, ```vec4```. 더 나아가면서, ```vec3``` 나 ```vec2```, ```float```, ```int```, 또한 ```bool```같은 것들이 보이게 될것이다.
4. '''vec4''' 타입을 자세히 살펴보면, 각 인수는 RED, GREEN, BLUE and ALPHA 채널이다. 이 값들은 *노멀라이즈된* 값이 ```0.0``` 에서 ```1.0``` 으로 맵핑된것이다. 나중에 나아가면서 노멀라이징을 어떻게 하는지, *map* 을 어떻게 하는지 살펴보게 될것이다.
5. 예제에서 볼수 있는 또 다른 중요한 *C 요소*는 전처리기 마크로들에 대한 사용이다. 마크로들은 컴파일되기 전에 일어나는 스텝이다. ```#define```을 이용해, 전역변수를 선언하거나, 기본적인 논리구현이 가능하다 (```#ifdef```나 ```#endif```를 통해). 모든 마크로는 해쉬태그 마크 (```#```) 로 시작한다. 이런 Pre-compilation은 컴파일이 실제로 일어나기 바로 전에 각 해쉬태그의 해당값을 이 코드로 카피한다. 위에 예제 'hello world!'를 보면, 우리는 ```GL_ES```를 선언하였는데, 이는 모바일 기기나, 브라우져에서 컴파일될때 전처리되는 부분들인 것이다.
6. 실수 타입들은 쉐이더에서 신경써야할 부분중 하나인데, *precision(실수정확도)*의 정도가 퍼포먼스에 영향을 미치기 때문이다. 낮은 정도의 precision을 가질수록 빠른 렌더 속도를 가지지만, 렌더 퀄리티가 그만큼 떨어진다는 것을 의미한다. 첫번째 라인을 보면, (```precision mediump float;```) 라는 내용이 보이는데, 실수정확도를 중간정도로 맞춘것이다. 높게는 (```precision lowp float;```) 낮게는 (```precision lowp float;```)이다.
7. 마지막으로, 그리고 제일 중요할지도 모르지만, GLSL에서는 데이터 타입의 casting이 확보되지 않는다. 무슨말인가하면, 제조업체들은 그래픽카드의 연산을 가속화 하기위해 각각 다른 시도들을 하였는데, 결국은 이것은 최소사양을 저격하고 있다. 자동 casting같은 경우는 여기에 포함되지 않고 있다. 우리의 "hello world!" 예제의 ```vec4``` 또한, ```floats```라는 데이터타입을 예상하게 되는것이다. 앞으로 쉐이더 프로그램을 하면서 실수의 경우에는 항상 점 (```.```) 을 포함하여 이 변수가, 값이 실수임을 명시하자. 예를들어 아래와 같은 코드는 작동이 안될것이다:
```glsl
void main() {
gl_FragColor = vec4(1,0,0,1); // ERROR
}
```
자, 이제 우리의 첫 예제인 "hello world!"프로그램에 대한 설명을 마친다. 예제의 코드를 수정하면서 이 단원에서 배운 내용을 곱씹어보는 시간을 갖길 바란다. 만약 코드에 에러가 있다면 컴파일 에러가 나면서 화면이 하얗게 될것이다. 아래와 같은 재밌는 시도들도 해볼수 있을것이다.:
* 실수값들을 정수값들로 바꿔보고, 본인의 그래픽 카드가 이값을 인식하고 아웃풋하는 결과를 보라.
* 6번째 라인을 코멘트아웃하고, 함수의 픽셀값에 아무런 값도 넣어보지 말라.
* ```main()```안에, 새로운 함수를 만들고 새로운 값을 리턴하게 해보라, 힌트로는 아래는 빨간색을 리턴하는 함수다 :
```glsl
vec4 red(){
return vec4(1.0,0.0,0.0,1.0);
}
```
* ```vec4```값을 만드는 방법을 여러가지가 있다. 아래역시 그중하나이다:
```glsl
vec4 color = vec4(vec3(1.0,0.0,1.0),1.0);
```
이 예제 자체가 그리 흥미롭지는 않지만 매우 중요한 기본 예제중 하나이다 - 캔바스의 모든 색을 같은색으로 바꿔보는 작업. 다음에 오는 챕터에서는 픽셀 색들을 2개의 인풋을 사용하여 바꿔보는 예제를 해볼것이다. (스크린위에 픽셀들의 위치를 이용한) 그리고 시간을 이용해 이들을 바꾸는 작업도 해볼것이다. (페이지가 로드완료된 후로 몇초가 지났는지를 이용한)

@ -1,11 +1,11 @@
## Hello World
Usually the "Hello world!" example is the first step to learning a new language. It's a simple one-line program that outputs an enthusiastic welcoming message and declares opportunities ahead.
Usually the "Hello world!" example is the first step to learning a new language. It's a simple one-line program that outputs an enthusiastic welcoming message and declares opportunities ahead.
In GPU-land rendering text is an overcomplicated task for a first step, instead we'll choose a bright welcoming color to shout our enthusiasm!
<div class="codeAndCanvas" data="hello_world.frag"></div>
If you are reading this book in a browser the previous block of code is interactive. That means you can click and change any part of the code you want to explore. Changes will be updated immediately thanks to the GPU architecture that compiles and replaces shaders *on the fly*. Give it a try by changing the values on line 6.
Although these simple lines of code don't look like a lot, we can infer substantial knowledge from them:
@ -16,7 +16,7 @@ Although these simple lines of code don't look like a lot, we can infer substant
3. This C-flavored language has built in *variables* (like ```gl_FragColor```), *functions* and *types*. In this case we've just been introduced to ```vec4``` that stands for a four dimensional vector of floating point precision. Later we will see more types like ```vec3``` and ```vec2``` together with the popular: ```float```, ```int``` and ```bool```.
4. If we look closely to the ```vec4``` type we can infer that the four arguments respond to the RED, GREEN, BLUE and ALPHA channels. Also we can see that these values are *normalized*, which means they go from ```0.0``` to ```1.0```. Later, we will learn how normalizing values makes it easier to *map* values between variables.
4. If we look closely to the ```vec4``` type we can infer that the four arguments respond to the RED, GREEN, BLUE and ALPHA channels. Also we can see that these values are *normalized*, which means they go from ```0.0``` to ```1.0```. Later, we will learn how normalizing values makes it easier to *map* values between variables.
5. Another important *C feature* we can see in this example is the presence of preprocessor macros. Macros are part of a pre-compilation step. With them it is possible to ```#define``` global variables and do some basic conditional operation ( with ```#ifdef``` and ```#endif```). All the macro comands begin with a hashtag (```#```). Pre-compilation happens right before compiling and copies all the calls to ```#defines``` and check ```#ifdef``` (is defined) and ```#ifndef``` (is not defined) conditionals. In our "hello world!" example above, we only insert the line 2 if ```GL_ES``` is defined, which mostly happens when the code is compiled on mobile devices and browsers.
@ -50,4 +50,4 @@ vec4 red(){
vec4 color = vec4(vec3(1.0,0.0,1.0),1.0);
```
Although this example isn't very exciting, it is the most basic example - we are changing all the pixels inside the canvas to the same exact color. In the following chapter we will see how to change the pixel colors by using two types of input: space (the place of the pixel on the screen) and time (the number of seconds since the page was loaded).
Although this example isn't very exciting, it is the most basic example - we are changing all the pixels inside the canvas to the same exact color. In the following chapter we will see how to change the pixel colors by using two types of input: space (the place of the pixel on the screen) and time (the number of seconds since the page was loaded).

@ -1 +1 @@
Usually the "Hello world!" example is the first step to learning a new language. In GPU-land rendering text is an overcomplicated task for a first step, instead we'll choose a bright welcoming color to shout our enthusiasm!
Usually the "Hello world!" example is the first step to learning a new language. In GPU-land rendering text is an overcomplicated task for a first step, instead we'll choose a bright welcoming color to shout our enthusiasm!

@ -5,7 +5,3 @@ precision mediump float;
void main() {
gl_FragColor = vec4(1.0,0.0,1.0,1.0);
}

@ -11,4 +11,4 @@
(float) 1 == 1.0
```
* I figured out that vec4() is a vector with 4 values, but perhaps you could make that explicit somewhere.
* I figured out that vec4() is a vector with 4 values, but perhaps you could make that explicit somewhere.

@ -11,7 +11,7 @@ precision mediump float;
uniform vec2 u_resolution; // 画布尺寸(宽,高)
uniform vec2 u_mouse; // 鼠标位置(在屏幕上哪个像素)
uniform float u_time; // 时间(加载后的秒数)
uniform float u_time; // 时间(加载后的秒数)
```
你可以把 uniforms 想象成连通 GPU 和 CPU 的许多小的桥梁。虽然这些 uniforms 的名字千奇百怪,但是在这一系列的例子中我一直有用到:```u_time``` (时间), ```u_resolution``` (画布尺寸)和 ```u_mouse``` (鼠标位置)。按业界传统应在 uniform 值的名字前加 ```u_``` ,这样一看即知是 uniform。尽管如此你也还会见到各种各样的名字。比如[ShaderToy.com](https://www.shadertoy.com/)就用了如下的名字:
@ -58,4 +58,4 @@ GLSL 还有更多惊喜。GPU 的硬件加速支持我们使用角度,三角
* 你可以用 ```u_time``` 和 ```u_mouse``` 来改变颜色的图案吗?不妨琢磨一些有趣的途径。
经过这些小练习后,你可能会好奇还能用强大的 shader 做什么。接下来的章节你会知道如何把你的 shader 和 three.jsProcessing和 openFrameworks 结合起来。
经过这些小练习后,你可能会好奇还能用强大的 shader 做什么。接下来的章节你会知道如何把你的 shader 和 three.jsProcessing和 openFrameworks 结合起来。

@ -1,61 +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.
## 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.

@ -1,61 +1,61 @@
## Uniforms
Finora abbiamo visto come la GPU gestisce un gran numero di thread paralleli, ciascuno responsabile nell'assegnazione d'un colore ad una frazione dell'immagine totale. Sebbene ogni thread parallelo è cieco nei confronti degli altri, dobbiamo essere in grado d'inviare alcuni input dalla CPU a tutti i thread. A causa dell'architettura della scheda grafica tali input saranno uguali (*uniform*) per tutti i thread e necessariamente impostati come di *sola lettura*. In altre parole, ogni thread riceve gli stessi dati che possono essere letti ma non possono essere cambiati.
Questi input sono chiamati ```uniform``` e sono disponibili nella maggior parte di tipi supportati: ```float```, ```vec2```, ```vec3```, ```vec4```, ```mat2```, ```mat3```, ```mat4```, ```sampler2D``` e ```samplerCube```. Gli Uniforms sono definiti con i rispettivi tipi, all'inizio del codice, dopo aver definito la precisione della virgola mobile.
```glsl
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution; // dimensione del Canvas (larghezza, altezza)
uniform vec2 u_mouse; // posizione del mouse (x,y) in pixels
uniform float u_time; // tempo in secondi da quando lo shader è iniziato
```
È possibile immaginare gli uniforms come piccoli ponti tra la CPU e la GPU. I nomi variano da applicazione ad applicazione, ma in questa serie di esempi userò: ```u_time``` (tempo in secondi da quando lo shader è iniziato), ```u_resolution``` (la dimensione della finestra in cui lo shader è in corso d'elaborazione) e ```u_mouse``` (la posizione in pixel del mouse all'interno della finestra). Seguirò la convenzione di mettere ```u_``` prima del nome degli uniforms per essere espliciti sulla natura di questa variabile, ma incontrerete varie nomenclature per gli uniforms. Per esempio [ShaderToy.com](https://www.shadertoy.com/) utilizza gli stessi uniforms, ma con i seguenti nomi:
```glsl
uniform vec3 iResolution; // dimensione del Canvas (in pixels)
uniform vec4 iMouse; // posizione del mouse in pixels. xy: corrente, zw: click
uniform float iGlobalTime; // tempo (in secondi) da quando lo shader è iniziato
```
Ma ora basta chiacchiere, vediamo gli uniforms in azione. Nel seguente codice utilizziamo ```u_time``` - il numero di secondi da quando lo shader è iniziato - insieme ad una funzione seno per animare con una transizione la quantità di rosso sullo schermo.
<div class="codeAndCanvas" data="time.frag"></div>
Come potete vedere GLSL ha molte sorprese. La GPU ha funzioni trigonometriche ed esponenziali, che sono accelerate dall'hardware. Alcune di queste funzioni sono: [```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) and [```clamp()```](../glossary/?search=clamp).
Ora è il momento di giocare con il codice qui sopra.
* Rallentate la frequenza fino a quando il cambiamento di colore diventa quasi impercettibile.
* Aumentate la frequenza fino a vedere un solo colore, senza sfarfallio.
* Date tre frequenze differenti ai tre canali (RGB) per ottenere motivi e comportamenti interessanti.
## gl_FragCoord
Allo stesso modo GLSL ci dà un output di default, ```vec4 gl_FragColor```, ma anche un input di default, ```vec4 gl_FragCoord```, che contiene le coordinate sullo schermo del *pixel* o del *screen fragment* del thread attivo. Con ```vec4 gl_FragCoord```, sappiamo dove un thread sta lavorando all'interno dello schermo. In questo caso la variabile non è un ```uniform``` perché sarà diversa da thread a thread. Le variabili che cambiano in ogni thread, come ```gl_FragCoord```, sono chiamate *varying*.
<div class="codeAndCanvas" data="space.frag"></div>
Nel codice qui sopra *normalizziamo* le coordinate del fragment dividendole per la risoluzione totale dello schermo. In questo modo i valori andranno tra ```0.0``` e ```1.0```, una tecnica che rende facile mappare i valori X e Y per i canali ROSSO e VERDE.
Nel mondo degli shaders non abbiamo troppe risorse per il debug a parte l'assegnazione di colori intensi alle variabili e cercare di trovargli un senso. Scoprirete che a volte programmando in GLSL è come mettere una nave all'interno di una bottiglia: un processo difficile, bello e gratificante.
![](08.png)
Ora è il momento di mettere in pratica gli insegnamenti che abbiamo imparato.
* Sapreste dire dove è la coordinata ```(0.0,0.0)``` sul nostro schermo?
* E dove sono ```(1.0,0.0)```, ```(0.0,1.0)```, ```(0.5,0.5)``` e ```(1.0,1.0)```?
* Riuscite ad immaginare come usare ```u_mouse``` sapendo che i valori sono espressi in pixel e NON in valori normalizzati? Sapresti usare ```u_mouse``` per muovere i colori?
* Sapreste trovare un modo interessante per cambiare questo pattern grafico utilizzando ```u_time``` e le coordinate ```u_mouse```?
Dopo aver fatto questi esercizi, ci si potrebbe chiedere dove si potrebbero provare i nuovi super poteri che gli shader ci hanno dato. Nel prossimo capitolo vedremo come creare i vostri shader in Three.js, Processing e openFrameworks.
## Uniforms
Finora abbiamo visto come la GPU gestisce un gran numero di thread paralleli, ciascuno responsabile nell'assegnazione d'un colore ad una frazione dell'immagine totale. Sebbene ogni thread parallelo è cieco nei confronti degli altri, dobbiamo essere in grado d'inviare alcuni input dalla CPU a tutti i thread. A causa dell'architettura della scheda grafica tali input saranno uguali (*uniform*) per tutti i thread e necessariamente impostati come di *sola lettura*. In altre parole, ogni thread riceve gli stessi dati che possono essere letti ma non possono essere cambiati.
Questi input sono chiamati ```uniform``` e sono disponibili nella maggior parte di tipi supportati: ```float```, ```vec2```, ```vec3```, ```vec4```, ```mat2```, ```mat3```, ```mat4```, ```sampler2D``` e ```samplerCube```. Gli Uniforms sono definiti con i rispettivi tipi, all'inizio del codice, dopo aver definito la precisione della virgola mobile.
```glsl
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution; // dimensione del Canvas (larghezza, altezza)
uniform vec2 u_mouse; // posizione del mouse (x,y) in pixels
uniform float u_time; // tempo in secondi da quando lo shader è iniziato
```
È possibile immaginare gli uniforms come piccoli ponti tra la CPU e la GPU. I nomi variano da applicazione ad applicazione, ma in questa serie di esempi userò: ```u_time``` (tempo in secondi da quando lo shader è iniziato), ```u_resolution``` (la dimensione della finestra in cui lo shader è in corso d'elaborazione) e ```u_mouse``` (la posizione in pixel del mouse all'interno della finestra). Seguirò la convenzione di mettere ```u_``` prima del nome degli uniforms per essere espliciti sulla natura di questa variabile, ma incontrerete varie nomenclature per gli uniforms. Per esempio [ShaderToy.com](https://www.shadertoy.com/) utilizza gli stessi uniforms, ma con i seguenti nomi:
```glsl
uniform vec3 iResolution; // dimensione del Canvas (in pixels)
uniform vec4 iMouse; // posizione del mouse in pixels. xy: corrente, zw: click
uniform float iGlobalTime; // tempo (in secondi) da quando lo shader è iniziato
```
Ma ora basta chiacchiere, vediamo gli uniforms in azione. Nel seguente codice utilizziamo ```u_time``` - il numero di secondi da quando lo shader è iniziato - insieme ad una funzione seno per animare con una transizione la quantità di rosso sullo schermo.
<div class="codeAndCanvas" data="time.frag"></div>
Come potete vedere GLSL ha molte sorprese. La GPU ha funzioni trigonometriche ed esponenziali, che sono accelerate dall'hardware. Alcune di queste funzioni sono: [```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) and [```clamp()```](../glossary/?search=clamp).
Ora è il momento di giocare con il codice qui sopra.
* Rallentate la frequenza fino a quando il cambiamento di colore diventa quasi impercettibile.
* Aumentate la frequenza fino a vedere un solo colore, senza sfarfallio.
* Date tre frequenze differenti ai tre canali (RGB) per ottenere motivi e comportamenti interessanti.
## gl_FragCoord
Allo stesso modo GLSL ci dà un output di default, ```vec4 gl_FragColor```, ma anche un input di default, ```vec4 gl_FragCoord```, che contiene le coordinate sullo schermo del *pixel* o del *screen fragment* del thread attivo. Con ```vec4 gl_FragCoord```, sappiamo dove un thread sta lavorando all'interno dello schermo. In questo caso la variabile non è un ```uniform``` perché sarà diversa da thread a thread. Le variabili che cambiano in ogni thread, come ```gl_FragCoord```, sono chiamate *varying*.
<div class="codeAndCanvas" data="space.frag"></div>
Nel codice qui sopra *normalizziamo* le coordinate del fragment dividendole per la risoluzione totale dello schermo. In questo modo i valori andranno tra ```0.0``` e ```1.0```, una tecnica che rende facile mappare i valori X e Y per i canali ROSSO e VERDE.
Nel mondo degli shaders non abbiamo troppe risorse per il debug a parte l'assegnazione di colori intensi alle variabili e cercare di trovargli un senso. Scoprirete che a volte programmando in GLSL è come mettere una nave all'interno di una bottiglia: un processo difficile, bello e gratificante.
![](08.png)
Ora è il momento di mettere in pratica gli insegnamenti che abbiamo imparato.
* Sapreste dire dove è la coordinata ```(0.0,0.0)``` sul nostro schermo?
* E dove sono ```(1.0,0.0)```, ```(0.0,1.0)```, ```(0.5,0.5)``` e ```(1.0,1.0)```?
* Riuscite ad immaginare come usare ```u_mouse``` sapendo che i valori sono espressi in pixel e NON in valori normalizzati? Sapresti usare ```u_mouse``` per muovere i colori?
* Sapreste trovare un modo interessante per cambiare questo pattern grafico utilizzando ```u_time``` e le coordinate ```u_mouse```?
Dopo aver fatto questi esercizi, ci si potrebbe chiedere dove si potrebbero provare i nuovi super poteri che gli shader ci hanno dato. Nel prossimo capitolo vedremo come creare i vostri shader in Three.js, Processing e openFrameworks.

@ -1,6 +1,6 @@
## Uniforms
우리는 여태것 GPU가 병렬처리에 왜 유리한지, 또 GPU의 각 Thread가 한 이미지의 각 부분을 어떻게 다루는지 또한 살펴보았다. 병렬처리 Thread들이 서로에 대해 데이터를 공유할수 없더라도, CPU에서 인풋을 받을수 있다. 그리고 이 인풋들은 모든 Thread들에 있어서 일정(*uniform*)하고 *read only*이다. 즉, 읽을순 있어도 변경할수 없다는 뜻이다.
우리는 여태것 GPU가 병렬처리에 왜 유리한지, 또 GPU의 각 Thread가 한 이미지의 각 부분을 어떻게 다루는지 또한 살펴보았다. 병렬처리 Thread들이 서로에 대해 데이터를 공유할수 없더라도, CPU에서 인풋을 받을수 있다. 그리고 이 인풋들은 모든 Thread들에 있어서 일정(*uniform*)하고 *read only*이다. 즉, 읽을순 있어도 변경할수 없다는 뜻이다.
이런 인풋들을 ```uniform```이라고 하고, ```float```, ```vec2```, ```vec3```, ```vec4```, ```mat2```, ```mat3```, ```mat4```, ```sampler2D```, ```samplerCube``` 등의 데이터 타입을 지원한다. 유니폼 값들은 보통 floating pont precision설정이 끝난후 선언된다.
@ -11,7 +11,7 @@ precision mediump float;
uniform vec2 u_resolution; // Canvas size (width,height)
uniform vec2 u_mouse; // mouse position in screen pixels
uniform float u_time; // Time in seconds since load
uniform float u_time; // Time in seconds since load
```
유니폼은 CPU와 GPU사이에 다리라고 봐도 좋을것이다. 유니폼 값들의 이름은 구현마다 다 다르지만 여기서는: ```u_time``` (쉐이더 연산이 시작된후부터의 초), ```u_resolution``` (쉐이더가 그려지고 있는 빌보드의 사이즈) and ```u_mouse``` (그려지는 빌보드내에서 마우스의 현재 픽셀 위치값) 등으로 나타내겠다. ```u_``` 를 변수앞에 붙혀서, 유니폼이라고 명시한다는 점도 유의하기 바란다. 더 많은 예제는 [ShaderToy.com](https://www.shadertoy.com/) 에서 찾아볼수 있지만, 변수이름이 약간 다르니 살펴보기 바란다:
@ -39,7 +39,7 @@ GLSL의 재미를 약간 맛볼수 있었다. GPU는 전에도 설명했듯이,
## gl_FragCoord
비슷한 원리로, GLSL은 내장 아웃풋 값들을 가진다. ```vec4 gl_FragColor```, 또한 내장 인풋 값도 있다, *screen fragment*상에서 *pixel*의 위치를 가지고 있는 ```vec4 gl_FragCoord```. ```vec4 gl_FragCoord```로 각 쓰레드가 빌보드의 어느 부분을 작업하고 있는지 알수 있다. 그래서 이값은 ```uniform```값과는 조금다르다. 각 쓰레드마다 값이 다른 *varying*타입이기 때문이다.
비슷한 원리로, GLSL은 내장 아웃풋 값들을 가진다. ```vec4 gl_FragColor```, 또한 내장 인풋 값도 있다, *screen fragment*상에서 *pixel*의 위치를 가지고 있는 ```vec4 gl_FragCoord```. ```vec4 gl_FragCoord```로 각 쓰레드가 빌보드의 어느 부분을 작업하고 있는지 알수 있다. 그래서 이값은 ```uniform```값과는 조금다르다. 각 쓰레드마다 값이 다른 *varying*타입이기 때문이다.
In the same way GLSL gives us a default output, ```vec4 gl_FragColor```, it also gives us a default input, ```vec4 gl_FragCoord```, which holds the screen coordinates of the *pixel* or *screen fragment* that the active thread is working on. With ```vec4 gl_FragCoord```, we know where a thread is working inside the billboard. In this case we don't call it ```uniform``` because it will be different from thread to thread, instead ```gl_FragCoord``` is called a *varying*.
<div class="codeAndCanvas" data="space.frag"></div>
@ -60,4 +60,4 @@ In the same way GLSL gives us a default output, ```vec4 gl_FragColor```, it also
* ```u_time```과, ```u_mouse```를 이용해, 색의 패턴을 재밌게 바꾸는 시도도 해보자.
몇번 해보다 보면, 이런 쉐이딩 기술을 어디에 적용할지 의문이 갈것이다. 다음챕터에서, 쉐이딩 기술을 이용하는 라이브러리들에 대해 알아볼것이다. three.js, Processing, openFrameworks와 같은 툴을 이용하여.
몇번 해보다 보면, 이런 쉐이딩 기술을 어디에 적용할지 의문이 갈것이다. 다음챕터에서, 쉐이딩 기술을 이용하는 라이브러리들에 대해 알아볼것이다. three.js, Processing, openFrameworks와 같은 툴을 이용하여.

@ -1,6 +1,6 @@
## Uniforms
So far we have seen how the GPU manages large numbers of parallel threads, each one responsible for assigning the color to a fraction of the total image. Although each parallel thread is blind to the others, we need to be able to send some inputs from the CPU to all the threads. Because of the architecture of the graphics card those inputs are going to be equal (*uniform*) to all the threads and necessarily set as *read only*. In other words, each thread receives the same data which it can read but cannot change.
So far we have seen how the GPU manages large numbers of parallel threads, each one responsible for assigning the color to a fraction of the total image. Although each parallel thread is blind to the others, we need to be able to send some inputs from the CPU to all the threads. Because of the architecture of the graphics card those inputs are going to be equal (*uniform*) to all the threads and necessarily set as *read only*. In other words, each thread receives the same data which it can read but cannot change.
These inputs are called ```uniform``` and come in most of the supported types: ```float```, ```vec2```, ```vec3```, ```vec4```, ```mat2```, ```mat3```, ```mat4```, ```sampler2D``` and ```samplerCube```. Uniforms are defined with the corresponding type at the top of the shader right after assigning the default floating point precision.
@ -11,7 +11,7 @@ precision mediump float;
uniform vec2 u_resolution; // Canvas size (width,height)
uniform vec2 u_mouse; // mouse position in screen pixels
uniform float u_time; // Time in seconds since load
uniform float u_time; // Time in seconds since load
```
You can picture the uniforms like little bridges between the CPU and the GPU. The names will vary from implementation to implementation but in this series of examples Im always passing: ```u_time``` (time in seconds since the shader started), ```u_resolution``` (billboard size where the shader is being drawn) and ```u_mouse``` (mouse position inside the billboard in pixels). Im following the convention of putting ```u_``` before the uniform name to be explicit about the nature of this variable but you will find all kinds of names for uniforms. For example [ShaderToy.com](https://www.shadertoy.com/) uses the same uniforms but with the following names:
@ -42,7 +42,7 @@ In the same way GLSL gives us a default output, ```vec4 gl_FragColor```, it also
<div class="codeAndCanvas" data="space.frag"></div>
In the above code we *normalize* the coordinate of the fragment by dividing it by the total resolution of the billboard. By doing this the values will go between ```0.0``` and ```1.0```, which makes it easy to map the X and Y values to the RED and GREEN channel.
In the above code we *normalize* the coordinate of the fragment by dividing it by the total resolution of the billboard. By doing this the values will go between ```0.0``` and ```1.0```, which makes it easy to map the X and Y values to the RED and GREEN channel.
In shader-land we dont have too many resources for debugging besides assigning strong colors to variables and trying to make sense of them. You will discover that sometimes coding in GLSL is very similar to putting ships inside bottles. Is equally hard, beautiful and gratifying.
@ -54,7 +54,7 @@ Now it is time to try and challenge our understanding of this code.
* What about ```(1.0,0.0)```, ```(0.0,1.0)```, ```(0.5,0.5)``` and ```(1.0,1.0)```?
* Can you figure out how to use ```u_mouse``` knowing that the values are in pixels and NOT normalized values? Can you use it to move colors around?
* Can you figure out how to use ```u_mouse``` knowing that the values are in pixels and NOT normalized values? Can you use it to move colors around?
* Can you imagine an interesting way of changing this color pattern using ```u_time``` and ```u_mouse``` coordinates?

@ -1,4 +1,4 @@
<?php
<?php
$path = "..";
$subtitle = ": uniforms";
@ -29,5 +29,5 @@
<li class="navigationBar" onclick="nextPage()">Next &gt; &gt;</li>
</ul>';
include($path."/footer.php");
include($path."/footer.php");
?>

@ -41,11 +41,11 @@ void main() {
// gl_FragCoord.xy = vec2(0.0,0.0);
// / /
// vec2(500.0,500.0);
vec2 st = gl_FragCoord.xy/u_resolution;
// ST -> vec2(0.0,0.0) to vec2(1.0,1.0)
// RED GREEN BLUE ALPHA
gl_FragColor = vec4(st.x, st.y, 0.0, 1.0);
}
@ -64,4 +64,3 @@ which holds the screen coordinates of the *pixel* or *screen fragment* that the
* I've stressed the fact that gl_FragCoord is implicitly declared so that people don't panic when they don't find it in the new code sample :)
also those are reserved names, so I stressed the fact that you can't use them as var names in your custom code.

@ -7,5 +7,3 @@ uniform float u_time;
void main() {
gl_FragColor = vec4(abs(sin(u_time)),0.0,0.0,1.0);
}

@ -42,7 +42,7 @@
function init() {
container = document.getElementById( 'container' );
camera = new THREE.Camera();
camera.position.z = 1;
@ -66,7 +66,7 @@
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
container.appendChild( renderer.domElement );
onWindowResize();
@ -102,7 +102,7 @@ PShader shader;
void setup() {
size(640, 360, P2D);
noStroke();
shader = loadShader("shader.frag");
}
@ -139,12 +139,12 @@ void main() {
### **openFrameworks**
每个人都有自己的舒适区,我的则是[openFrameworks community](http://openframeworks.cc/)。这个 C++ 框架打包了 OpenGL 和其他开源 C++ 库。在很多方面它和 Processing 非常像,但是明显和 C++ 编译器打交道一定比较麻烦。和 Processing 很像地openFrameworks 会在你的 data 文件夹里寻找 shader 文件,所以不要忘记把你的后缀 ```.frag``` 的文件拷进去,加载的时候记得改名。
```cpp
void ofApp::draw(){
ofShader shader;
shader.load("","shader.frag");
shader.begin();
shader.setUniform1f("u_time", ofGetElapsedTimef());
shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight());

@ -1,190 +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.
## 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.

@ -91,7 +91,7 @@ Notez bien la balise de script appelée ```id="fragmentShader"```, c'est là qu'
function init() {
container = document.getElementById( 'container' );
camera = new THREE.Camera();
camera.position.z = 1;
@ -116,12 +116,12 @@ Notez bien la balise de script appelée ```id="fragmentShader"```, c'est là qu'
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
@ -162,7 +162,7 @@ PShader shader;
void setup() {
size(640, 360, P2D);
noStroke();
shader = loadShader("shader.frag");
}
@ -203,12 +203,12 @@ Chacun a sa zone de confort, pour moi, ça reste [la communité openFrameworks](
Ce framework C++ intègre OpenGL et d'autres librairies C++ open source.
C'est très proche de Processing à ceci près que c'est un langage compilé et qu'il vaut donc mieux être habitué aux compilateurs C++.
Comme Processing, openFrameworks va chercher le fichier du shader dans la dossier data, donc n'oubliez pas de créer un fichier ```.frag```, d'y coller le contenu du shader et de spécifier le nom de ce fichier dans votre programme OF.
```cpp
void ofApp::draw(){
ofShader shader;
shader.load("","shader.frag");
shader.begin();
shader.setUniform1f("u_time", ofGetElapsedTimef());
shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight());

@ -70,7 +70,7 @@ Di seguito è riportato un esempio di codice HTML e JS per iniziare con gli shad
function init() {
container = document.getElementById( 'container' );
camera = new THREE.Camera();
camera.position.z = 1;
@ -95,12 +95,12 @@ Di seguito è riportato un esempio di codice HTML e JS per iniziare con gli shad
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
@ -136,7 +136,7 @@ PShader shader;
void setup() {
size(640, 360, P2D);
noStroke();
shader = loadShader("shader.frag");
}
@ -173,12 +173,12 @@ Per ulteriori informazioni sugli shader in Processing controllate questo [tutori
### In **openFrameworks**
Ognuno ha un luogo in cui sentirsi a proprio agio e, nel mio caso, è ancora la [comunità di openFrameworks](http://openframeworks.cc/). Questo framework C++ integra OpenGL e altre librerie C++ open source. Per molti aspetti è molto simile a Processing, ma con le ovvie complicazioni dovute ai compilatori C++. Allo stesso modo di Processing, openFrameworks cercherà i tuoi file shader nella cartella dati, quindi non dimenticate di copiare i file ```.frag``` che si desiderano utilizzare e modificate il nome quando li si carica.
```cpp
void ofApp::draw(){
ofShader shader;
shader.load("","shader.frag");
shader.begin();
shader.setUniform1f("u_time", ofGetElapsedTimef());
shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight());
@ -187,4 +187,4 @@ void ofApp::draw(){
}
```
Per ulteriori informazioni sugli shader in openFrameworks consultate questo [ottimo tutorial](http://openframeworks.cc/ofBook/chapters/shaders.html) fatto da [Joshua Noble](http://thefactoryfactory.com/).
Per ulteriori informazioni sugli shader in openFrameworks consultate questo [ottimo tutorial](http://openframeworks.cc/ofBook/chapters/shaders.html) fatto da [Joshua Noble](http://thefactoryfactory.com/).

@ -7,7 +7,7 @@
**Note 2**: 만약 WebGL에서 쉐이더를 구동하고, 다른 프레임워크를 따로 쓰고 싶지 않다면, [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas)를 이용해서 할수 있다. 이 웹 툴은 이 책에 최적화 되어 있고, 실제로 저자가 프로젝트마다 사용하는 툴이기도 하다.
### **Three.js** 에서
Ricardo Cabello (aka [MrDoob](https://twitter.com/mrdoob) ) 가 다른 참여자[참여자](https://github.com/mrdoob/three.js/graphs/contributors)들과 개발한 WebGL을 이용한 프레임 워크인 [Three.js](http://threejs.org/). 많은 예제와, 튜토리얼, 책들이 존재하고, 이를 이용해 여러 3D graphics데모를 만들어 볼수 있다.
아래는 HTML과 JS를 이용해 three.js를 구동하는 예제이다. ```id="fragmentShader"```부분을 보면, 쉐이더가 어디에서 적용되는지 볼수 있다.
@ -40,7 +40,7 @@ Ricardo Cabello (aka [MrDoob](https://twitter.com/mrdoob) ) 가 다른 참여자
function init() {
container = document.getElementById( 'container' );
camera = new THREE.Camera();
camera.position.z = 1;
@ -64,7 +64,7 @@ Ricardo Cabello (aka [MrDoob](https://twitter.com/mrdoob) ) 가 다른 참여자
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
container.appendChild( renderer.domElement );
onWindowResize();
@ -100,7 +100,7 @@ PShader shader;
void setup() {
size(640, 360, P2D);
noStroke();
shader = loadShader("shader.frag");
}
@ -141,7 +141,7 @@ void main() {
void ofApp::draw(){
ofShader shader;
shader.load("","shader.frag");
shader.begin();
shader.setUniform1f("u_time", ofGetElapsedTimef());
shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight());

@ -2,7 +2,7 @@
As part of the construction of this book and my art practice I made an ecosystem of tools to create, display, share and curate shaders. This tools works consistently across Linux Desktops, MacOS, [Raspberry Pi](https://www.raspberrypi.org/) and browsers without the need of changing your code.
**Display**: all live examples in this book are displayed using [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas) which makes the process of running standalone shader incredible easy.
**Display**: all live examples in this book are displayed using [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas) which makes the process of running standalone shader incredible easy.
```html
<canvas class="glslCanvas" data-fragment-url=“yourShader.frag" data-textures=“yourInputImage.png” width="500" height="500"></canvas>
@ -37,8 +37,8 @@ If you prefer to work offline using [SublimeText](https://www.sublimetext.com/)
In case you already have experience programming in a framework like: [Processing](https://processing.org/), [Three.js](http://threejs.org/) or [OpenFrameworks](http://openframeworks.cc/), you're probably excited to try shaders on this platforms you feel comfortable with. The following are examples of how to set shaders in some popular frameworks with the same uniforms that we are going to use throughout this book. (In the [GitHub repository for this chapter](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), you'll find the full source code for these three frameworks.)
### In **Three.js**
The brilliant and very humble Ricardo Cabello (aka [MrDoob](https://twitter.com/mrdoob) ) has been developing along with other [contributors](https://github.com/mrdoob/three.js/graphs/contributors) probably one of the most famous frameworks for WebGL, called [Three.js](http://threejs.org/). You will find a lot of examples, tutorials and books that teach you how to use this JavaScript library to make cool 3D graphics.
The brilliant and very humble Ricardo Cabello (aka [MrDoob](https://twitter.com/mrdoob) ) has been developing along with other [contributors](https://github.com/mrdoob/three.js/graphs/contributors) probably one of the most famous frameworks for WebGL, called [Three.js](http://threejs.org/). You will find a lot of examples, tutorials and books that teach you how to use this JavaScript library to make cool 3D graphics.
Below is an example of the HTML and JS you need to get started with shaders in three.js. Pay attention to the ```id="fragmentShader"``` script, here is where you can copy the shaders you find in this book.
@ -70,7 +70,7 @@ Below is an example of the HTML and JS you need to get started with shaders in t
function init() {
container = document.getElementById( 'container' );
camera = new THREE.Camera();
camera.position.z = 1;
@ -95,12 +95,12 @@ Below is an example of the HTML and JS you need to get started with shaders in t
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
@ -136,7 +136,7 @@ PShader shader;
void setup() {
size(640, 360, P2D);
noStroke();
shader = loadShader("shader.frag");
}
@ -173,12 +173,12 @@ For more information about shaders in Processing check out this [tutorial](https
### In **openFrameworks**
Everybody has a place where they feel comfortable, in my case, thats still the [openFrameworks community](http://openframeworks.cc/). This C++ framework wraps around OpenGL and other open source C++ libraries. In many ways it's very similar to Processing, but with the obvious complications of dealing with C++ compilers. In the same way as Processing, openFrameworks will search for your shader files in the data folder, so dont forget to copy the ```.frag``` files you want to use and change the name when you load them.
```cpp
void ofApp::draw(){
ofShader shader;
shader.load("","shader.frag");
shader.begin();
shader.setUniform1f("u_time", ofGetElapsedTimef());
shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight());

@ -1,4 +1,4 @@
<?php
<?php
$path = "..";
$subtitle = ": Running your shader";
@ -29,5 +29,5 @@
<li class="navigationBar" onclick="nextPage()">Next &gt; &gt;</li>
</ul>';
include($path."/footer.php");
include($path."/footer.php");
?>

@ -12,4 +12,4 @@ uniform float u_time;
void main() {
vec2 st = gl_FragCoord.st/u_resolution;
gl_FragColor = vec4(st.x,st.y,0.0,1.0);
}
}

@ -4,7 +4,7 @@
//--------------------------------------------------------------
void ofApp::setup(){
// Load and compile the shader
//
shader.load("","shader.frag");
@ -12,30 +12,30 @@ void ofApp::setup(){
//--------------------------------------------------------------
void ofApp::update(){
}
//--------------------------------------------------------------
void ofApp::draw(){
// Replace the pipeline with our shader
shader.begin();
// Send uniforms
shader.setUniform1f("u_time", ofGetElapsedTimef());
shader.setUniform2f("u_mouse", mouseX, mouseY);
shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight());
// make a billboard
ofRect(0,0,ofGetWidth(), ofGetHeight());
// Default shader pipeline
shader.end();
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key){
// Reload everytime you press a key
//
shader.load("","shader.frag");
@ -77,6 +77,6 @@ void ofApp::gotMessage(ofMessage msg){
}
//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){
void ofApp::dragEvent(ofDragInfo dragInfo){
}

@ -19,6 +19,6 @@ public:
void windowResized(int w, int h);
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);
ofShader shader;
};

@ -14,4 +14,4 @@ uniform float u_time;
void main() {
vec2 st = gl_FragCoord.st/u_resolution;
gl_FragColor = vec4(st.x,st.y,0.0,1.0);
}
}

@ -5,7 +5,7 @@ PShader shader;
void setup() {
size(640, 360, P2D);
noStroke();
// Load and compile shader
shader = loadShader("shader.frag");
}
@ -15,10 +15,10 @@ 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);
// Replace the default pipeline programs with our shader
shader(shader);
// Draw a billboard
rect(0,0,width,height);
}

@ -38,7 +38,7 @@
function init() {
container = document.getElementById( 'container' );
camera = new THREE.Camera();
camera.position.z = 1;
@ -63,7 +63,7 @@
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
container.appendChild( renderer.domElement );
onWindowResize();
@ -88,4 +88,4 @@
renderer.render( scene, camera );
}
</script>
</body>
</body>

@ -22,7 +22,7 @@
[```pow()```](../glossary/?search=pow) 求x的y次幂是 GLSL 的一个原生函数GLSL 有很多原生函数。大多数原生函数都是硬件加速的,也就是说如果你正确使用这些函数,你的代码就会跑得更快。
换掉第 19 行的幂函数,试试看[```exp()```](../glossary/?search=exp)以自然常数e为底的指数函数[```log()```](../glossary/?search=log)(对数函数) 和 [```sqrt()```](../glossary/?search=sqrt)(平方根函数)。当你用 Pi 来玩的时候有些方程会变得更有趣。在第 5 行我定义了一个宏,使得每当程序调用 ```PI``` 的时候就用 ```3.14159265359``` 来替换它。
### Step 和 Smoothstep
GLSL 还有一些独特的原生插值函数可以被硬件加速。

@ -1,152 +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)
# 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)

@ -9,7 +9,7 @@ La seguente struttura di codice sarà la nostra recinzione. In questa visualizzi
<div class="codeAndCanvas" data="linear.frag"></div>
**Nota veloce**: il costruttore di tipo ```vec3``` "capisce" che vuoi assegnare i tre canali di colori allo stesso valore, mentre ```vec4``` capisce che vuoi costruire un vettore a quattro dimensioni con tre unidimensionali più un quarto valore (in questo caso il valore che controlla lalfa o lopacità). Guarda, ad esempio, le righe 20 e 26 qui sopra.
**Nota veloce**: il costruttore di tipo ```vec3``` "capisce" che vuoi assegnare i tre canali di colori allo stesso valore, mentre ```vec4``` capisce che vuoi costruire un vettore a quattro dimensioni con tre unidimensionali più un quarto valore (in questo caso il valore che controlla lalfa o lopacità). Guarda, ad esempio, le righe 20 e 26 qui sopra.
Questo codice è il tuo recinto; è importante osservarlo e capirlo. Tornerai spesso in questo spazio tra *0.0* e *1.0*. Imparerai larte di combinare e modellare questa linea.
@ -22,7 +22,7 @@ Interessante, vero? Alla riga 22 prova esponenti diversi, per esempio: 20.0, 2.0
[```pow()```](../glossary/?search=pow) è una funzione nativa il GLSL e ce ne sono molte altre. La maggior parte di queste sono accelerate al livello dellhardware; ciò significa che se esse sono usate in modo appropriato e con discrezione, renderanno il tuo codice molto più veloce.
Sostituisci la funzione alla riga 22. Provane altre, come: [```exp()```](../glossary/?search=exp), [```log()```](../glossary/?search=log) e [```sqrt()```](../glossary/?search=sqrt). Alcune di queste funzioni sono più interessanti quando le si utilizza con PI. Puoi vedere alla riga 8, che ho definito un macro che sostituisce qualsiasi chiamata a ```PI``` con valore ```3.14159265359```.
### Step e Smoothstep
GLSL ha anche alcune funzioni interpolanti native uniche che sono accelerate dallhardware.
@ -84,7 +84,7 @@ AAl termine dellultimo esercizio abbiamo presentato alcune nuove funzioni. È
<div class="simpleFunction" data="y = mod(x,0.5); // restituisce il modulo di 0.5
//y = fract(x); // restituisce solo la parte frazionale di un numero
//y = ceil(x); // il numero intero più vicino che sia più grande o uguale a x
//y = floor(x); // il numero intero più vicino che sia più piccolo o uguale a x
//y = floor(x); // il numero intero più vicino che sia più piccolo o uguale a x
//y = sign(x); // estrae il segno di x
//y = abs(x); // restituisce il valore assoluto di x
//y = clamp(x,0.0,1.0); // costringe x a restare fra 0.0 e 1.0
@ -93,7 +93,7 @@ AAl termine dellultimo esercizio abbiamo presentato alcune nuove funzioni. È
### Funzioni di forma avanzate
[Golan Levin](http://www.flong.com/) possiede unampia documentazione molto utile sulle funzioni di forma complesse. Trasportare queste funzioni in GLSL è un ottimo modo per incominciare a costruire la propria cassetta degli attrezzi per creare codici.
[Golan Levin](http://www.flong.com/) possiede unampia documentazione molto utile sulle funzioni di forma complesse. Trasportare queste funzioni in GLSL è un ottimo modo per incominciare a costruire la propria cassetta degli attrezzi per creare codici.
* [Polynomial Shaping Functions: www.flong.com/texts/code/shapers_poly](http://www.flong.com/texts/code/shapers_poly/)

@ -1,8 +1,8 @@
# Algorithmic drawing
## Shaping functions
이번 챕터는 "미야기씨의 울타리 수업"이라고 표현할수 있겠다. 전에는, 노멀라이즈된 ,*x*와 *y**red**green*채널들에 적용해 보았다.
원래는 2차원 벡터(x and y)를 받아, 4차원 벡터(r, g, b and a)를 리턴하는 함수가 좀더 자연스럽니다. 하지만 지금 이런문제를 해결하기 전에, 간단한것부터 시작해보자... 훨씬더 간단한것부터. 이말은 1차원 함수에 대한 정의에서부터 시작한다. 시간과 에너지를 많이 투자하고 배우고 마스터하려고 하다보면, 우리는 더욱더 강한 쉐이더 카라테를 배울수 있을것이다.
이번 챕터는 "미야기씨의 울타리 수업"이라고 표현할수 있겠다. 전에는, 노멀라이즈된 ,*x*와 *y**red**green*채널들에 적용해 보았다.
원래는 2차원 벡터(x and y)를 받아, 4차원 벡터(r, g, b and a)를 리턴하는 함수가 좀더 자연스럽니다. 하지만 지금 이런문제를 해결하기 전에, 간단한것부터 시작해보자... 훨씬더 간단한것부터. 이말은 1차원 함수에 대한 정의에서부터 시작한다. 시간과 에너지를 많이 투자하고 배우고 마스터하려고 하다보면, 우리는 더욱더 강한 쉐이더 카라테를 배울수 있을것이다.
![베스트 키드 (1985)](mr_miyagi.jpg)
@ -23,7 +23,7 @@
[```pow()```](../glossary/?search=pow) 는 GLSL의 내장형 함수이고 GLSL은 이런 수학함수를 많이 제공한다. 거의 모든 함수들은 하드웨어 레벨에서 구동되도록 '가속화' 되어 있다. 다시말해, 이런 이점을 잘 활용하면 굉장히 빠른 코드를 쓸수 있게 된다.
라인 19의 power 함수를 다른 함수로 교체해보자.: [```exp()```](../glossary/?search=exp), [```log()```](../glossary/?search=log), [```sqrt()```](../glossary/?search=sqrt). 어떤함수들은 인자로 PI값을 넣었을때 재밌는 결과를 내기도 한다. 라인 5에 ```PI```값을 ```3.14159265359```로 define해 둔것을 알수 있다.
### Step and Smoothstep
GLSL에는 하드웨어 가속화된 내장 보간법 함수들이 존재한다.
@ -34,7 +34,7 @@ GLSL에는 하드웨어 가속화된 내장 보간법 함수들이 존재한다.
<div class="codeAndCanvas" data="step.frag"></div>
또 하나의 잘 알려진 함수중 하나는 [```smoothstep()```](../glossary/?search=smoothstep)이다. 두값의 레인지를 주고, 그 사이의 값으로 보간시켜주는 방법이다. 처음 두개의 인자는 레인지의 시작점과 끝점이고, 세번째 인자는 두 점사이에서 보간되고 리턴되는 값이다.
또 하나의 잘 알려진 함수중 하나는 [```smoothstep()```](../glossary/?search=smoothstep)이다. 두값의 레인지를 주고, 그 사이의 값으로 보간시켜주는 방법이다. 처음 두개의 인자는 레인지의 시작점과 끝점이고, 세번째 인자는 두 점사이에서 보간되고 리턴되는 값이다.
<div class="codeAndCanvas" data="smoothstep.frag"></div>
@ -94,7 +94,7 @@ GLSL에는 하드웨어 가속화된 내장 보간법 함수들이 존재한다.
### 고급 쉐이핑 함수들
[Golan Levin](http://www.flong.com/) 는 제법 복잡하지만 굉장히 유용한 쉐이핑 함수들을 잘 정리해 두었다. 이들을 GLSL로 포팅하는것또한 굉장히 유용한 공부방법일 것이다. 자신만의 쉐이핑 펑션 라이브러리를 개설해보자.
[Golan Levin](http://www.flong.com/) 는 제법 복잡하지만 굉장히 유용한 쉐이핑 함수들을 잘 정리해 두었다. 이들을 GLSL로 포팅하는것또한 굉장히 유용한 공부방법일 것이다. 자신만의 쉐이핑 펑션 라이브러리를 개설해보자.
* [Polynomial Shaping Functions: www.flong.com/texts/code/shapers_poly](http://www.flong.com/texts/code/shapers_poly/)
@ -106,7 +106,7 @@ GLSL에는 하드웨어 가속화된 내장 보간법 함수들이 존재한다.
요리사가 자신만의 요리재료와 소스 노하우를 모으듯, digital artist들이나, creative coder들 역시 그들만의 쉐이핑 펑션을 만드는 버릇을 가져야 할것이다.
[Iñigo Quiles](http://www .iquilezles.org/)가 가지고 있는 [useful functions](http://www.iquilezles.org/www/articles/functions/functions.htm)정리는 매우 유용하다. [이 글](http://www.iquilezles.org/www/articles/functions/functions.htm)을 읽고, GLSL로 번역해보는 작업도 해볼수 있다. 조심해야 될 점들은, "."(점)을 실수 뒤에 꼭 넣어야 한다는 점이다. 함수의 이름이 ```powf()``` 에서 ```pow()```등으로 바뀌어 구현되는 점등이다.
[Iñigo Quiles](http://www .iquilezles.org/)가 가지고 있는 [useful functions](http://www.iquilezles.org/www/articles/functions/functions.htm)정리는 매우 유용하다. [이 글](http://www.iquilezles.org/www/articles/functions/functions.htm)을 읽고, GLSL로 번역해보는 작업도 해볼수 있다. 조심해야 될 점들은, "."(점)을 실수 뒤에 꼭 넣어야 한다는 점이다. 함수의 이름이 ```powf()``` 에서 ```pow()```등으로 바뀌어 구현되는 점등이다.
* [Impulse](../edit.php#05/impulse.frag)
* [Cubic Pulse](../edit.php#05/cubicpulse.frag)

@ -1,7 +1,7 @@
# Algorithmic drawing
## Shaping functions
This chapter could be named "Mr. Miyagi's fence lesson." Previously, we mapped the normalized position of *x* and *y* to the *red* and *green* channels. Essentially we made a function that takes a two dimensional vector (x and y) and returns a four dimensional vector (r, g, b and a). But before we go further transforming data between dimensions we need to start simpler... much simpler. That means understanding how to make one dimensional functions. The more energy and time you spend learning and mastering this, the stronger your shader karate will be.
This chapter could be named "Mr. Miyagi's fence lesson." Previously, we mapped the normalized position of *x* and *y* to the *red* and *green* channels. Essentially we made a function that takes a two dimensional vector (x and y) and returns a four dimensional vector (r, g, b and a). But before we go further transforming data between dimensions we need to start simpler... much simpler. That means understanding how to make one dimensional functions. The more energy and time you spend learning and mastering this, the stronger your shader karate will be.
![The Karate Kid (1984)](mr_miyagi.jpg)
@ -19,17 +19,17 @@ This one-to-one relationship between *x* and *y* (or the brightness) is know as
Interesting, right? On line 22 try different exponents: 20.0, 2.0, 1.0, 0.0, 0.2 and 0.02 for example. Understanding this relationship between the value and the exponent will be very helpful. Using these types of mathematical functions here and there will give you expressive control over your code, a sort of data acupuncture that let you control the flow of values.
[```pow()```](../glossary/?search=pow) is a native function in GLSL and there are many others. Most of them are accelerated at the level of the hardware, which means if they are used in the right way and with discretion they will make your code faster.
[```pow()```](../glossary/?search=pow) is a native function in GLSL and there are many others. Most of them are accelerated at the level of the hardware, which means if they are used in the right way and with discretion they will make your code faster.
Replace the power function on line 22. Try other ones like: [```exp()```](../glossary/?search=exp), [```log()```](../glossary/?search=log) and [```sqrt()```](../glossary/?search=sqrt). Some of these functions are more interesting when you play with them using PI. You can see on line 8 that I have defined a macro that will replace any call to ```PI``` with the value ```3.14159265359```.
### Step and Smoothstep
GLSL also has some unique native interpolation functions that are hardware accelerated.
GLSL also has some unique native interpolation functions that are hardware accelerated.
The [```step()```](../glossary/?search=step) interpolation receives two parameters. The first one is the limit or threshold, while the second one is the value we want to check or pass. Any value under the limit will return ```0.0``` while everything above the limit will return ```1.0```.
The [```step()```](../glossary/?search=step) interpolation receives two parameters. The first one is the limit or threshold, while the second one is the value we want to check or pass. Any value under the limit will return ```0.0``` while everything above the limit will return ```1.0```.
Try changing this threshold value on line 20 of the following code.
Try changing this threshold value on line 20 of the following code.
<div class="codeAndCanvas" data="step.frag"></div>
@ -65,7 +65,7 @@ Try the following exercises and notice what happens:
* Multiply time (```u_time```) by *x* before computing the ```sin```. See how the **frequency** between phases becomes more and more compressed. Note that u_time may have already become very large, making the graph hard to read.
* Add 1.0 to [```sin(x)```](../glossary/?search=sin). See how all the wave is **displaced** up and now all values are between 0.0 and 2.0.
* Add 1.0 to [```sin(x)```](../glossary/?search=sin). See how all the wave is **displaced** up and now all values are between 0.0 and 2.0.
* Multiply [```sin(x)```](../glossary/?search=sin) by 2.0. See how the **amplitude** doubles in size.
@ -93,7 +93,7 @@ At the end of the last exercise we introduced some new functions. Now its tim
### Advance shaping functions
[Golan Levin](http://www.flong.com/) has great documentation of more complex shaping functions that are extraordinarily helpful. Porting them to GLSL is a really smart move, to start builidng your own resource of snippets of code.
[Golan Levin](http://www.flong.com/) has great documentation of more complex shaping functions that are extraordinarily helpful. Porting them to GLSL is a really smart move, to start builidng your own resource of snippets of code.
* [Polynomial Shaping Functions: www.flong.com/texts/code/shapers_poly](http://www.flong.com/texts/code/shapers_poly/)
@ -105,7 +105,7 @@ At the end of the last exercise we introduced some new functions. Now its tim
<div class="glslGallery" data="160414041542,160414041933,160414041756" data-properties="clickRun:editor,hoverPreview:false"></div>
Like chefs that collect spices and exotic ingredients, digital artists and creative coders have a particular love of working on their own shaping functions.
Like chefs that collect spices and exotic ingredients, digital artists and creative coders have a particular love of working on their own shaping functions.
[Iñigo Quiles](http://www.iquilezles.org/) has a great collection of [useful functions](http://www.iquilezles.org/www/articles/functions/functions.htm). After reading [this article](http://www.iquilezles.org/www/articles/functions/functions.htm) take a look at the following translation of these functions to GLSL. Pay attention to the small changes required, like putting the "." (dot) on floating point numbers and using the GLSL name for *C functions*; for example instead of ```powf()``` use ```pow()```:

@ -9,7 +9,7 @@ uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
// Function from Iñigo Quiles
// Function from Iñigo Quiles
// www.iquilezles.org/www/articles/functions/functions.htm
float cubicPulse( float c, float w, float x ){
x = abs(x - c);
@ -19,7 +19,7 @@ float cubicPulse( float c, float w, float x ){
}
float plot(vec2 st, float pct){
return smoothstep( pct-0.02, pct, st.y) -
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
@ -29,9 +29,9 @@ void main() {
float y = cubicPulse(0.5,0.2,st.x);
vec3 color = vec3(y);
float pct = plot(st,y);
color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);
gl_FragColor = vec4(color,1.0);
}
}

@ -179,7 +179,7 @@ float backInOut(float t) {
}
float plot(vec2 st, float pct){
return smoothstep( pct-0.02, pct, st.y) -
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
@ -230,4 +230,4 @@ void main() {
float pct = plot(st,y);
color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);
gl_FragColor = vec4(color,1.0);
}
}

@ -12,7 +12,7 @@ uniform vec2 u_mouse;
uniform float u_time;
float plot(vec2 st, float pct){
return smoothstep( pct-0.02, pct, st.y) -
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
@ -25,6 +25,6 @@ void main() {
float pct = plot(st,y);
color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);
gl_FragColor = vec4(color,1.0);
}
}

@ -9,14 +9,14 @@ uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
// Function from Iñigo Quiles
// Function from Iñigo Quiles
// www.iquilezles.org/www/articles/functions/functions.htm
float expStep( float x, float k, float n ){
return exp( -k*pow(x,n) );
}
float plot(vec2 st, float pct){
return smoothstep( pct-0.02, pct, st.y) -
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
@ -26,9 +26,9 @@ void main() {
float y = expStep(st.x,10.,1.0);
vec3 color = vec3(y);
float pct = plot(st,y);
color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);
gl_FragColor = vec4(color,1.0);
}
}

@ -1 +1 @@
<div class="glslGallery" data="160414041542,160414041933,160414041756" data-properties="clickRun:editor,hoverPreview:false"></div>
<div class="glslGallery" data="160414041542,160414041933,160414041756" data-properties="clickRun:editor,hoverPreview:false"></div>

@ -9,7 +9,7 @@ uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
// Function from Iñigo Quiles
// Function from Iñigo Quiles
// www.iquilezles.org/www/articles/functions/functions.htm
float impulse( float k, float x ){
float h = k*x;
@ -17,7 +17,7 @@ float impulse( float k, float x ){
}
float plot(vec2 st, float pct){
return smoothstep( pct-0.02, pct, st.y) -
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
@ -27,9 +27,9 @@ void main() {
float y = impulse(12.,st.x);
vec3 color = vec3(y);
float pct = plot(st,y);
color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);
gl_FragColor = vec4(color,1.0);
}
}

@ -1,4 +1,4 @@
<?php
<?php
$path = "..";
$subtitle = ": Shaping functions";
@ -19,7 +19,7 @@
include($path."/src/parsedown/Parsedown.php");
$Parsedown = new Parsedown();
echo $Parsedown->text(file_get_contents($README.'.md'));
echo '
</div>
<hr>
@ -29,5 +29,5 @@
<li class="navigationBar" onclick="nextPage()">Next &gt; &gt;</li>
</ul>';
include($path."/footer.php");
include($path."/footer.php");
?>

@ -8,7 +8,7 @@ uniform float u_time;
// Plot a line on Y using a value between 0.0-1.0
float plot(vec2 st, float pct){
return smoothstep( pct-0.02, pct, st.y) -
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
@ -18,10 +18,10 @@ void main() {
float y = st.x;
vec3 color = vec3(y);
// Plot a line
float pct = plot(st,y);
color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);
gl_FragColor = vec4(color,1.0);
}
}

@ -7,4 +7,4 @@
* Actually, this is the point where you lose me. I want it to be more gradual. It feels like there are 100 new concepts on this one page.
### Nicolas
* took the freedom to explain more indepth what interpolation is and why it rocks :)
* took the freedom to explain more indepth what interpolation is and why it rocks :)

@ -8,14 +8,14 @@ precision mediump float;
uniform vec2 u_resolution;
uniform float u_time;
// Function from Iñigo Quiles
// Function from Iñigo Quiles
// www.iquilezles.org/www/articles/functions/functions.htm
float parabola( float x, float k ){
return pow( 4.0*x*(1.0-x), k );
}
float plot(vec2 st, float pct){
return smoothstep( pct-0.02, pct, st.y) -
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
@ -25,9 +25,9 @@ void main() {
float y = parabola(st.x,1.0);
vec3 color = vec3(y);
float pct = plot(st,y);
color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);
gl_FragColor = vec4(color,1.0);
}
}

@ -9,7 +9,7 @@ uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
// Function from Iñigo Quiles
// Function from Iñigo Quiles
// www.iquilezles.org/www/articles/functions/functions.htm
float pcurve( float x, float a, float b ){
float k = pow(a+b,a+b) / (pow(a,a)*pow(b,b));
@ -17,7 +17,7 @@ float pcurve( float x, float a, float b ){
}
float plot(vec2 st, float pct){
return smoothstep( pct-0.02, pct, st.y) -
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
@ -27,9 +27,9 @@ void main() {
float y = pcurve(st.x,3.0,1.0);
vec3 color = vec3(y);
float pct = plot(st,y);
color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);
gl_FragColor = vec4(color,1.0);
}
}

@ -9,7 +9,7 @@ uniform vec2 u_mouse;
uniform float u_time;
float plot(vec2 st, float pct){
return smoothstep( pct-0.02, pct, st.y) -
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
@ -20,9 +20,9 @@ void main() {
float y = smoothstep(0.1,0.9,st.x);
vec3 color = vec3(y);
float pct = plot(st,y);
color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);
gl_FragColor = vec4(color,1.0);
}
}

@ -8,7 +8,7 @@ uniform vec2 u_resolution;
uniform float u_time;
float plot(vec2 st, float pct){
return smoothstep( pct-0.02, pct, st.y) -
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
@ -23,6 +23,6 @@ void main() {
float pct = plot(st,y);
color = (1.0-pct)*color+pct*vec3(0.0,1.0,0.0);
gl_FragColor = vec4(color,1.0);
}
}

@ -11,7 +11,7 @@
vec3 red = vec3(1.0,0.0,0.0);
red.x = 1.0;
red.y = 0.0;
red.z = 0.0;
red.z = 0.0;
```
以x,y,z定义颜色是不是有些奇怪正因如此我们有其他方法访问这些变量——以不同的名字。```.x```, ```.y```, ```.z```也可以被写作```.r```, ```.g```, ```.b``` 和 ```.s```, ```.t```, ```.p```。(```.s```, ```.t```, ```.p```通常被用做后面章节提到的贴图空间坐标)你也可以通过使用索引位置```[0]```, ```[1]``` 和 ```[2]```来访问向量.
@ -34,7 +34,7 @@ GLSL中向量类型的另一大特点是可以用你需要的任意顺序简单
```glsl
vec3 yellow, magenta, green;
// Making Yellow
// Making Yellow
yellow.rg = vec2(1.0); // Assigning 1. to red and green channels
yellow[2] = 0.0; // Assigning 0. to blue channel
@ -42,7 +42,7 @@ yellow[2] = 0.0; // Assigning 0. to blue channel
magenta = yellow.rbg; // Assign the channels with green and blue swapped
// Making Green
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
```
#### 个人工具箱
@ -97,9 +97,9 @@ green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue
* 用 ```step``` 函数在做一个五彩的旗子。
### HSB
我们不能脱离色彩空间来谈论颜色。正如你所知除了rgb值有其他不同的方法去描述定义颜色。
[HSB](http://en.wikipedia.org/wiki/HSL_and_HSV) 代表色相,饱和度和亮度(或称为值)。这更符合直觉也更有利于组织颜色。稍微花些时间阅读下面的 ```rgb2hsv()``` 和 ```hsv2rgb()``` 函数。
将x坐标位置映射到Hue值并将y坐标映射到明度我们就得到了五彩的可见光光谱。这样的色彩空间分布实现起来非常方便比起RGB用HSB来拾取颜色更直观。
@ -137,12 +137,10 @@ HSB原本是在极坐标下产生的以半径和角度定义而并非在
在进入下一章之前让我们停下脚步回顾下。复习下之前例子的函数。你会注意到变量类型之前有个限定符 ```in```,在这个 [*qualifier*](http://www.shaderific.com/glsl-qualifiers/#inputqualifier) (限定符)例子中它特指这个变量是只读的。在之后的例子中我们会看到可以定义一个 ```out``` 或者 ```inout```变量。最后这个 ```inout```,再概念上类似于参照输入一个变量,这意味着我们有可能修改一个传入的变量。
```glsl
int newFunction(in vec4 aVec4, // read-only
int newFunction(in vec4 aVec4, // read-only
out vec3 aVec3, // write-only
inout int aInt); // read-write
```
```
或许你还不相信我们可以用所有这些元素来画一些炫酷的东西。下一章我们会学习如何结合所有这些技巧通过融合 (*blending*) 空间来创造几何形状。没错。。。融合(*blending*) 空间。

@ -1,147 +1,145 @@
![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=faceforward), [```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.
![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=faceforward), [```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.

@ -14,7 +14,7 @@ Si vous connaissez la Programmation Orientée Objet, vous aurez remarqué que no
vec3 red = vec3(1.0,0.0,0.0);
red.x = 1.0;
red.y = 0.0;
red.z = 0.0;
red.z = 0.0;
```
Dans l'exemple ci dessus, *x*, *y* et *z* permettent d'**accéder** aux 3 valeurs contenues dans l'objet ```red``` de type ```vec3```, ce sont les **accesseurs** aux propriétés de ```red```.
@ -259,10 +259,7 @@ Cette dernière, ```inout```, est équivalente à passer un argument *par réfé
int newFunction(in vec4 aVec4, // lecture seule
out vec3 aVec3, // écriture seule
inout int aInt); // lecture / écriture
```
```
Vous ne le savez pas encore et vous pourriez ne pas le croire mais nous avons à présent tout ce qu'il nous faut pour dessiner à peu près n'importe quoi.
Au prochain chapitre, nous verrons comment combiner ces techniques pour *mélanger* l'espace. Oui... *mélanger* l'espace.

@ -10,7 +10,7 @@ Se siete pratici con i paradigmi di programmazione orientata agli oggetti, proba
vec3 red = vec3(1.0,0.0,0.0);
red.x = 1.0;
red.y = 0.0;
red.z = 0.0;
red.z = 0.0;
```
Definire il colore usando una notazione *x*, *y* e *z* può essere fuorviante e creare confusione, vero? Per questo esistono altri modi di accedere alle stesse informazioni, con nomi diversi. I valori di ```.x```, ```.y``` e ```.z``` possono anche essere chiamati ```.r```, ```.g``` e ```.b```, e ```.s```, ```.t``` e ```.p```. (```.s```, ```.t``` e ```.p``` solitamente sono usati per le coordinate spaziali di una texture, che vedremo nel prossimo capitolo). Puoi anche accedere ai valori in un vettore usando gli indici di posizione ```[0]```, ```[1]``` e ```[2]```.
@ -44,7 +44,7 @@ magenta = yellow.rbg; // Invertite il canale del verde con quello del blu
green.rgb = yellow.bgb; // Assegnare il canale blu del giallo (0) ai canali rosso e blu
```
#### Per la vostra cassetta degli attrezzi
#### Per la vostra cassetta degli attrezzi
Potreste non essere abituati a selezionare i colori attraverso numeri - di sicuro questo processo potrebbe risultare controintuitivo. Per vostra fortuna esistono tanti programmi che semplificano questo lavoro. Trovatene uno che vada incontro ai vostri bisogni e usatelo per ottenere colori in formato ```vec3``` 0 ```vec4``` format. Per esempio, qui trovate i templates che io uso su [Spectrum](http://www.eigenlogik.com/spectrum/mac):
@ -75,7 +75,7 @@ La funzione [```mix()```](../glossary/?search=mix) ha molto da offrire. Invece d
Guardate l'esempio seguente. Così come negli esempi nel capitolo precedente, stiamo collegando la transizione alla *x* normalizzata e la visualizziamo con una linea. In questo momento tutti e tre i canali seguono la medesima linea.
Ora, togliete il commento alla riga 25 e guardate cosa succede. Poi provate a togliere il commento alle righe 26 e 27. Ricordate che le linee visualizzano la quantità di ```colorA``` e ```colorB``` da mescolare per ogni canale.
Ora, togliete il commento alla riga 25 e guardate cosa succede. Poi provate a togliere il commento alle righe 26 e 27. Ricordate che le linee visualizzano la quantità di ```colorA``` e ```colorB``` da mescolare per ogni canale.
<div class="codeAndCanvas" data="gradient.frag"></div>
@ -103,7 +103,7 @@ Mappando la posizione sull'asse x con la tonalità e la posizione sull'asse y co
### HSB nelle coordinate polari
Originariamente HSB è stato creato per essere rappresentato in coordinate polari (basate su angoli e raggio) e non in coordinate cartesiane (basate su x e y). Per unire la nostra funzione HSB alle coordinate polari, dobbiamo ottenere l'angolo e la distanza dal centro del canvas per ogni coordinata pixel. Per far questo usiamo la funzione [```length()```](../glossary/?search=length) e [```atan(y,x)```](../glossary/?search=atan) (che è la versione GLSL della più comune ```atan2(y,x)```).
Originariamente HSB è stato creato per essere rappresentato in coordinate polari (basate su angoli e raggio) e non in coordinate cartesiane (basate su x e y). Per unire la nostra funzione HSB alle coordinate polari, dobbiamo ottenere l'angolo e la distanza dal centro del canvas per ogni coordinata pixel. Per far questo usiamo la funzione [```length()```](../glossary/?search=length) e [```atan(y,x)```](../glossary/?search=atan) (che è la versione GLSL della più comune ```atan2(y,x)```).
Quando si usano vettori e funzioni trigonometriche, ```vec2```, ```vec3``` e ```vec4``` sono considerati come vettori anche quando rappresentano i colori. Inizieremo a considerare in modo simile i colori e i vettori, e in realtà troverete che questa flessibilità concettuale è molto potente.
@ -141,4 +141,4 @@ int newFunction(in vec4 aVec4, // solo lettura
inout int aInt); // lettura e scrittura
```
Potreste non crederci ma ora abbiamo tutti gli elementi per creare dei fantastici disegni. Nel prossimo capitolo impareremo come si possono combinare tutte queste tecniche per creare forme geometriche *fondendo* lo spazio. Sì, avete capito bene, *fondendo* lo spazio.
Potreste non crederci ma ora abbiamo tutti gli elementi per creare dei fantastici disegni. Nel prossimo capitolo impareremo come si possono combinare tutte queste tecniche per creare forme geometriche *fondendo* lo spazio. Sì, avete capito bene, *fondendo* lo spazio.

@ -2,7 +2,7 @@
## Colors
We haven't much of a chance to talk about GLSL vector types. Before going further it's important to learn more about these variables and the subject of colors is a great way to find out more about them.
We haven't much of a chance to talk about GLSL vector types. Before going further it's important to learn more about these variables and the subject of colors is a great way to find out more about them.
If you are familiar with object oriented programming paradigms you've probably noticed that we have been accessing the data inside the vectors like any regular C-like ```struct```.
@ -10,7 +10,7 @@ If you are familiar with object oriented programming paradigms you've probably n
vec3 red = vec3(1.0,0.0,0.0);
red.x = 1.0;
red.y = 0.0;
red.z = 0.0;
red.z = 0.0;
```
Defining color using an *x*, *y* and *z* notation can be confusing and misleading, right? That's why there are other ways to access this same information, but with different names. The values of ```.x```, ```.y``` and ```.z``` can also be called ```.r```, ```.g``` and ```.b```, and ```.s```, ```.t``` and ```.p```. (```.s```, ```.t``` and ```.p``` are usually used for spatial coordinates of a texture, which we'll see in a later chapter.) You can also access the data in a vector by using the index position, ```[0]```, ```[1]``` and ```[2]```.
@ -25,14 +25,14 @@ vector[2] = vector.b = vector.z = vector.p;
vector[3] = vector.a = vector.w = vector.q;
```
These different ways of pointing to the variables inside a vector are just nomenclatures designed to help you write clear code. This flexibility embedded in shading language is a door for you to start thinking interchangably about color and space coordinates.
These different ways of pointing to the variables inside a vector are just nomenclatures designed to help you write clear code. This flexibility embedded in shading language is a door for you to start thinking interchangably about color and space coordinates.
Another great feature of vector types in GLSL is that the properties can be combined in any order you want, which makes it easy to cast and mix values. This ability is called *swizzle*.
```glsl
vec3 yellow, magenta, green;
// Making Yellow
// Making Yellow
yellow.rg = vec2(1.0); // Assigning 1. to red and green channels
yellow[2] = 0.0; // Assigning 0. to blue channel
@ -40,7 +40,7 @@ yellow[2] = 0.0; // Assigning 0. to blue channel
magenta = yellow.rbg; // Assign the channels with green and blue swapped
// Making Green
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
```
#### For your toolbox
@ -58,7 +58,7 @@ Now that you know how colors are defined, it's time to integrate this with our p
![](mix-f.jpg)
Check the following code at line 18 and see how we are using the absolute values of a sin wave over time to mix ```colorA``` and ```colorB```.
Check the following code at line 18 and see how we are using the absolute values of a sin wave over time to mix ```colorA``` and ```colorB```.
<div class="codeAndCanvas" data="mix.frag"></div>
@ -66,13 +66,13 @@ Show off your skills by:
* Make an expressive transition between colors. Think of a particular emotion. What color seems most representative of it? How does it appear? How does it fade away? Think of another emotion and the matching color for it. Change the beginning and ending color of the above code to match those emotions. Then animate the transition using shaping functions. Robert Penner developed a series of popular shaping functions for computer animation known as [easing functions](http://easings.net/), you can use [this example](../edit.php#06/easing.frag) as research and inspiration but the best result will come from making your own transitions.
### Playing with gradients
### Playing with gradients
The [```mix()```](../glossary/?search=mix) function has more to offer. Instead of a single ```float```, we can pass a variable type that matches the two first arguments, in our case a ```vec3```. By doing that we gain control over the mixing percentages of each individual color channel, ```r```, ```g``` and ```b```.
![](mix-vec.jpg)
Take a look at the following example. Like the examples in the previous chapter, we are hooking the transition to the normalized *x* coordinate and visualizing it with a line. Right now all the channels go along the same line.
Take a look at the following example. Like the examples in the previous chapter, we are hooking the transition to the normalized *x* coordinate and visualizing it with a line. Right now all the channels go along the same line.
Now, uncomment line number 25 and watch what happens. Then try uncommenting lines 26 and 27. Remember that the lines visualize the amount of ```colorA``` and ```colorB``` to mix per channel.
@ -92,9 +92,9 @@ You probably recognize the three shaping functions we are using on lines 25 to 2
### HSB
We can't talk about color without speaking about color space. As you probably know there are different ways to organize color besides by red, green and blue channels.
We can't talk about color without speaking about color space. As you probably know there are different ways to organize color besides by red, green and blue channels.
[HSB](http://en.wikipedia.org/wiki/HSL_and_HSV) stands for Hue, Saturation and Brightness (or Value) and is a more intuitive and useful organization of colors. Take a moment to read the ```rgb2hsv()``` and ```hsv2rgb()``` functions in the following code.
[HSB](http://en.wikipedia.org/wiki/HSL_and_HSV) stands for Hue, Saturation and Brightness (or Value) and is a more intuitive and useful organization of colors. Take a moment to read the ```rgb2hsv()``` and ```hsv2rgb()``` functions in the following code.
By mapping the position on the x axis to the Hue and the position on the y axis to the Brightness, we obtain a nice spectrum of visible colors. This spatial distribution of color can be very handy; it's more intuitive to pick a color with HSB than with RGB.
@ -104,7 +104,7 @@ By mapping the position on the x axis to the Hue and the position on the y axis
HSB was originally designed to be represented in polar coordinates (based on the angle and radius) instead of cartesian coordinates (based on x and y). To map our HSB function to polar coordinates we need to obtain the angle and distance from the center of the billboard to the pixel coordinate. For that we will use the [```length()```](../glossary/?search=length) function and [```atan(y,x)```](../glossary/?search=atan) (which is the GLSL version of the commonly used ```atan2(y,x)```).
When using vector and trigonometric functions, ```vec2```, ```vec3``` and ```vec4``` are treated as vectors even when they represent colors. We will start treating colors and vectors similarly, in fact you will come to find this conceptual flexibility very empowering.
When using vector and trigonometric functions, ```vec2```, ```vec3``` and ```vec4``` are treated as vectors even when they represent colors. We will start treating colors and vectors similarly, in fact you will come to find this conceptual flexibility very empowering.
**Note:** If you were wondering, there are more geometric functions besides [```length```](../glossary/?search=length) like: [```distance()```](../glossary/?search=distance), [```dot()```](../glossary/?search=dot), [```cross```](../glossary/?search=cross), [```normalize()```](../glossary/?search=normalize), [```faceforward()```](../glossary/?search=faceforward), [```reflect()```](../glossary/?search=reflect) and [```refract()```](../glossary/?search=refract). Also GLSL has special vector relational functions such as: [```lessThan()```](../glossary/?search=lessThan), [```lessThanEqual()```](../glossary/?search=lessThanEqual), [```greaterThan()```](../glossary/?search=greaterThan), [```greaterThanEqual()```](../glossary/?search=greaterThanEqual), [```equal()```](../glossary/?search=equal) and [```notEqual()```](../glossary/?search=notEqual).
@ -135,11 +135,9 @@ Try the following exercises:
Before jumping to the next chapter lets stop and rewind. Go back and take look at the functions in previous examples. You will notice ```in``` before the type of the arguments. This is a [*qualifier*](http://www.shaderific.com/glsl-qualifiers/#inputqualifier) and in this case it specifies that the variable is read only. In future examples we will see that it is also possible to define arguments as ```out``` or ```inout```. This last one, ```inout```, is conceptually similar to passing an argument by reference which will give us the possibility to modify a passed variable.
```glsl
int newFunction(in vec4 aVec4, // read-only
int newFunction(in vec4 aVec4, // read-only
out vec3 aVec3, // write-only
inout int aInt); // read-write
```
You may not believe it but now we have all the elements to make cool drawings. In the next chapter we will learn how to combine all our tricks to make geometric forms by *blending* the space. Yep... *blending* the space.

@ -186,4 +186,4 @@ void main() {
float pct = cubicInOut( abs(fract(t)*2.0-1.) );
gl_FragColor = vec4(vec3(mix(colorA, colorB, pct)),1.0);
}
}

@ -12,7 +12,7 @@ vec3 colorA = vec3(0.149,0.141,0.912);
vec3 colorB = vec3(1.000,0.833,0.224);
float plot (vec2 st, float pct){
return smoothstep( pct-0.01, pct, st.y) -
return smoothstep( pct-0.01, pct, st.y) -
smoothstep( pct, pct+0.01, st.y);
}
@ -21,7 +21,7 @@ void main() {
vec3 color = vec3(0.0);
vec3 pct = vec3(st.x);
// pct.r = smoothstep(0.0,1.0, st.x);
// pct.g = sin(st.x*PI);
// pct.b = pow(st.x,0.5);
@ -34,4 +34,4 @@ void main() {
color = mix(color,vec3(0.0,0.0,1.0),plot(st,pct.b));
gl_FragColor = vec4(color,1.0);
}
}

@ -7,12 +7,12 @@ precision mediump float;
uniform vec2 u_resolution;
uniform float u_time;
// Function from Iñigo Quiles
// Function from Iñigo Quiles
// https://www.shadertoy.com/view/MsS3Wc
vec3 hsb2rgb( in vec3 c ){
vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
6.0)-3.0)-1.0,
0.0,
6.0)-3.0)-1.0,
0.0,
1.0 );
rgb = rgb*rgb*(3.0-2.0*rgb);
return c.z * mix( vec3(1.0), rgb, c.y);
@ -26,10 +26,10 @@ void main(){
vec2 toCenter = vec2(0.5)-st;
float angle = atan(toCenter.y,toCenter.x);
float radius = length(toCenter)*2.0;
// Map the angle (-PI to PI) to the Hue (from 0 to 1)
// and the Saturation to the radius
color = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0));
gl_FragColor = vec4(color,1.0);
}
}

@ -7,25 +7,25 @@ uniform float u_time;
vec3 rgb2hsb( in vec3 c ){
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz),
vec4(c.gb, K.xy),
vec4 p = mix(vec4(c.bg, K.wz),
vec4(c.gb, K.xy),
step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r),
vec4(c.r, p.yzx),
vec4 q = mix(vec4(p.xyw, c.r),
vec4(c.r, p.yzx),
step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),
d / (q.x + e),
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),
d / (q.x + e),
q.x);
}
// Function from Iñigo Quiles
// Function from Iñigo Quiles
// https://www.shadertoy.com/view/MsS3Wc
vec3 hsb2rgb( in vec3 c ){
vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
6.0)-3.0)-1.0,
0.0,
6.0)-3.0)-1.0,
0.0,
1.0 );
rgb = rgb*rgb*(3.0-2.0*rgb);
return c.z * mix(vec3(1.0), rgb, c.y);
@ -40,4 +40,4 @@ void main(){
color = hsb2rgb(vec3(st.x,1.0,st.y));
gl_FragColor = vec4(color,1.0);
}
}

@ -1,4 +1,4 @@
<?php
<?php
$path = "..";
$subtitle = ": color";
@ -29,5 +29,5 @@
<li class="navigationBar" onclick="nextPage()">Next &gt; &gt;</li>
</ul>';
include($path."/footer.php");
include($path."/footer.php");
?>

@ -13,9 +13,9 @@ void main() {
float pct = abs(sin(u_time));
// Mix uses pct (a value from 0-1) to
// Mix uses pct (a value from 0-1) to
// mix the two colors
color = mix(colorA, colorB, pct);
color = mix(colorA, colorB, pct);
gl_FragColor = vec4(color,1.0);
}
}

@ -94,7 +94,7 @@ or you can instead, use a single ```vec4``` which ```.xy``` **accessor** will re
[/NICO]
These different ways of pointing to the variables inside a vector are just nomenclatures designed to help you write clear code. This flexibility embedded in shading language is a door for you to start thinking interchangably about color and space coordinates.
These different ways of pointing to the variables inside a vector are just nomenclatures designed to help you write clear code. This flexibility embedded in shading language is a door for you to start thinking interchangably about color and space coordinates.
[NICO]
@ -104,4 +104,4 @@ Another great feature of vector types in GLSL is that the properties can be comb
to:
Concatenation or *swizzle* gets really interesting when we need to cast and mix values. The following example show you how to *swizzle* properties between vectors.
[/NICO]
[/NICO]

@ -8,4 +8,4 @@
* L 113 the longest distance between a pixel and the center in a normalised space is: SQRT( 2 ) * 0.5 = ~0.7071..., not 0.5 (also present ion chapter 6)
* L 123 'a bigger or smaller circular surface' a circular surface is called a 'disc' :)
* L 175 a word about Quadrants and its relation to the bi-unit square maybe? or just explaining why we use a bi-unit square instead of the regular 0-1 normalized space...
* L 217 'how use' missing 'to'
* L 217 'how use' missing 'to'

@ -1,5 +1,5 @@
## 形状
![Alice Hubbard, Providence, United States, ca. 1892. Photo: Zindman/Freemont.](froebel.jpg)
@ -20,7 +20,7 @@
```glsl
if ( (X GREATER THAN 1) AND (Y GREATER THAN 1) )
paint white
else
else
paint black
```
@ -32,13 +32,13 @@ uniform vec2 u_resolution;
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
// Each result will return 1.0 (white) or 0.0 (black).
float left = step(0.1,st.x); // Similar to ( X greater than 0.1 )
float bottom = step(0.1,st.y); // Similar to ( Y greater than 0.1 )
// The multiplication of left*bottom will be similar to the logical AND.
color = vec3( left * bottom );
color = vec3( left * bottom );
gl_FragColor = vec4(color,1.0);
}
@ -51,7 +51,7 @@ step函数会让没每一个小于0.1的像素变成黑色vec30.0
在前一例代码中我们重复每个像素的结构左边和底边。我们可以把原来的一个值换成两个值直接给step来精减代码。就像这样
```glsl
vec2 borders = step(vec2(0.1),st);
vec2 borders = step(vec2(0.1),st);
float pct = borders.x * borders.y;
```
@ -131,7 +131,7 @@ There are several ways to calculate that distance. The easiest one uses the [```
其实我们是通过“空间距离”来重新解释什么是图形。这种技巧被称之为“距离场”从字体轮廓到3D图形被广泛应用。
来小试下牛刀:
* 用[```step()```](../glossary/?search=step)函数把所有大于0.5的像素点变成白色并把小于的变成黑色0.0)。
* 反转前景色和背景色。
@ -229,10 +229,10 @@ pct = pow(distance(st,vec2(0.4)),distance(st,vec2(0.6)));
* 用这个例子,改造一个输入位置,指定图形(形状)的顶点数来返回一个距离场(的值)。
* 结合使用 [```min()```](../glossary/?search=min) 和 [```max()```](../glossary/?search=max) 函数混合距离场。
* 结合使用 [```min()```](../glossary/?search=min) 和 [```max()```](../glossary/?search=max) 函数混合距离场。
* 用距离场画个自己感兴趣的logo。
恭喜!你完成了最艰难的部分!休息下让这些概念沉淀一下吧 —— 用Processing 来画简单的形状很容易,但却不到火候。在 shader 的世界里,画形状是很纠结,而且适应这种新的编程范式会有些累人。
既然现在你知道了如何画形状,我十分肯定你脑袋里已经充满了新的点子。在接下来的章节里你会学习到怎么移动,旋转以及缩放图形。这将使你的创作如虎添翼!
既然现在你知道了如何画形状,我十分肯定你脑袋里已经充满了新的点子。在接下来的章节里你会学习到怎么移动,旋转以及缩放图形。这将使你的创作如虎添翼!

@ -1,234 +1,233 @@
![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.
![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.

@ -1,230 +1,230 @@
![Alice Hubbard, Providence, United States, ca. 1892. Photo: Zindman/Freemont.](froebel.jpg)
## Figure
Finalmente! Abbiamo costruito e allenato le nostre abilità per questo momento! Avete imparato la maggior parte delle basi, dei tipi e delle funzioni in GLSL. Vi siete esercitati continuamente sulle equazioni di forma. Ora è arrivato il momento di collegare tutti gli elementi. Siete allaltezza di questa sfida! In questo capitolo imparerete a disegnare forme semplici con una procedura in parallelo.
### Rettangolo
Immaginate di avere una carta millimetrata, come quelle che si usano per le lezioni di matematica, e che il nostro compito sia quello di disegnare un quadrato. Le dimensioni del foglio sono 10x10 e il quadrato dovrebbe essere 8x8. Cosa fareste?
![](grid_paper.jpg)
Colorereste tutto tranne la prima e lultima riga e la prima e lultima colonna, giusto?
Come si collega ciò agli shaders? Ogni piccolo quadrato della vostra carta millimetrata è un thread (un pixel). Ogni piccolo quadretto conosce la propria posizione, come per le coordinate di una scacchiera. Nei capitoli precedenti abbiamo associato *x* e *y* ai canali di colore *rosso* e *verde*, e abbiamo imparato come usare il limitato spazio bidimensionale tra 0.0 e 1.0. Come possiamo utilizzare tutto questo per disegnare un quadrato centrato nel mezzo del nostro canvas?
Iniziamo facendo uno pseudocodice che usi la dichiarazione ```if``` sul campo dello spazio. I principi per fare ciò sono straordinariamente simili a come immaginiamo lo scenario della carta millimetrata.
```glsl
if ( (X più grande di 1) AND (Y più grande di 1) )
colora di bianco
else
colora di nero
```
Ora che abbiamo unidea più chiara di come funziona, sostituiamo la dichiarazione ```if``` con [```step()```](../glossary/?search=step), e invece di usare 10x10, usiamo i valori normalizzati tra 0.0 e 1.0.
```glsl
uniform vec2 u_resolution;
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
// per ogni valore restituirà 1.0 (bianco) o 0.0 (nero).
float left = step(0.1,st.x); // Simile a ( X più grande di 0.1 )
float bottom = step(0.1,st.y); // Simile a ( Y più grande di 0.1 )
// La moltiplicazione di left*bottom sarà simile alla porta logica AND.
color = vec3( left * bottom );
gl_FragColor = vec4(color,1.0);
}
```
La funzione [```step()```](../glossary/?search=step) trasformerà ogni pixel al di sotto di 0.1 in nero (```vec3(0.0)```) e il resto in bianco (```vec3(1.0)```). La moltiplicazione tra left e bottom funziona come loperazione logica AND, dove entrambi devono essere tra 1.0 per tornare a 1.0. Questo traccia due linee nere, una alla base e laltra sul lato sinistro del canvas.
![](rect-01.jpg)
Nel codice precedente abbiamo ripetuto la struttura per ciascun asse (sinistra e base). Possiamo risparmiare alcune linee di codice passando due valori, invece di uno, direttamente a [```step()```](../glossary/?search=step) Ecco comè:
```glsl
vec2 borders = step(vec2(0.1),st);
float pct = borders.x * borders.y;
```
Fino ad ora abbiamo disegnato solamente due bordi (base-sinistra) del nostro rettangolo. Facciamo gli altri due (alto-destra). Osserva il seguente codice:
<div class="codeAndCanvas" data="rect-making.frag"></div>
Togliete il commento alle righe 21-22 e osservate come invertiamo le coordinate ```st``` e ripetiamo la stessa funzione [```step()```](../glossary/?search=step). In questo modo il ```vec2(0.0,0.0)``` sarà nellangolo in alto a destra. Questo è lequivalente digitale del capovolgimento della pagina e della ripetizione della procedura precedente.
![](rect-02.jpg)
Osservate che alla *riga 18 e alla riga 22* ogni lato è stato moltiplicato insieme. Questo equivale a scrivere:
```glsl
vec2 bl = step(vec2(0.1),st); // sotto-sinistra
vec2 tr = step(vec2(0.1),1.0-st); // sopra-destra
color = vec3(bl.x * bl.y * tr.x * tr.y);
```
Interessante, vero? Questa tecnica si basa tutta sulluso di [```step()```](../glossary/?search=step), della moltiplicazione per le operazioni logiche e il capovolgimento delle coordinate.
Prima di proseguire, provate i seguenti esercizi:
* Cambiate le misure e le proporzioni del rettangolo.
* Provate con lo stesso codice ma usando [```smoothstep()```](../glossary/?search=smoothstep) al posto di [```step()```](../glossary/?search=step). Notate che cambiando valori, potete passare da margini indistinti a lati eleganti e lisci.
* Fate unaltra implementazione che usi [```floor()```](../glossary/?search=floor).
* Scegliete limplementazione che preferite e create una sua funzione che potrete riusare in futuro. Rendete la vostra funzione flessibile ed efficiente.
* Create unaltra funzione che semplicemente tracci il contorno di un rettangolo.
* Come pensate di poter importare e spostare diversi rettangoli sullo stesso canvas? Se immaginate come, dimostrate le vostre capacità costruendo una composizione di rettangoli e colori che ricordi il dipinto di [Piet Mondrian](https://it.wikipedia.org/wiki/Piet_Mondrian).
![Piet Mondrian - Tableau (1921)](mondrian.jpg)
### Circonferenze
Disegnare quadrati e rettangoli su carta millimetrata con coordinate cartesiane è semplice, ma le circonferenze richiedono un approccio diverso, specialmente per il fatto che abbiamo bisogno di un algoritmo “per-pixel”. Una soluzione è riassegnare le coordinate spaziali, in modo tale da poter usare la funzione [```step()```](../glossary/?search=step) per disegnare una circonferenza.
Come? Iniziamo tornando indietro alla lezione di matematica e al foglio a quadretti, sul quale abbiamo aperto il compasso con il raggio della circonferenza, abbiamo premuto lago del compasso al centro della circonferenza e tracciato il perimetro della circonferenza con una semplice rotazione.
![](compass.jpg)
Tradurre ciò in un shader, dove ogni quadrato sul foglio a quadretti è un pixel, implica *chiedere* ad ogni pixel (o thread) se si trova allinterno dellarea della circonferenza. Lo facciamo calcolando la distanza tra il pixel e il centro della circonferenza.
![](circle.jpg)
Esistono diversi modi per calcolare questa distanza. Il più semplice utilizza la funzione [```distance()```](../glossary/?search=distance), che al suo interno calcola la funzione [```length()```](../glossary/?search=length) della differenza tra due punti ( nel nostro caso le coordinate del pixel e il centro del canvas). La funzione ```length()``` non è altro che una scorciatoia dell[equazione dellipotenusa](https://it.wikipedia.org/wiki/Ipotenusa), che usa al suo interno la radice quadrata (([```sqrt()```](../glossary/?search=sqrt))).
![](hypotenuse.png)
Potete usare [```distance()```](../glossary/?search=distance), [```length()```](../glossary/?search=length) o [```sqrt()```](../glossary/?search=sqrt) per calcolare la distanza dal centro del canvas. Il codice seguente contiene queste tre funzioni e il fatto non sorprendente è che ciascuna restituisce esattamente lo stesso risultato.
* Commentate e togliete il commento alle righe per provare i diversi modi di ottenere il medesimo risultato.
<div class="codeAndCanvas" data="circle-making.frag"></div>
Nellesempio precedente abbiamo mappato la distanza dal centro del canvas con la luminosità del colore del pixel. Più un pixel è vicino al centro, minore ( più scuro) è il suo valore. Notate che i valori non diventano troppo alti perché la massima distanza dal centro ( ```vec2(0.5, 0.5)``` ) va a malapena oltre 0.5. Osservate attentamente questa mappa e pensate:
* Cosa potete dedurre da essa?
* Come possiamo usarla per tracciare una circonferenza?
* Modificate il codice qui sopra per far sì che lintero gradiente circolare sia contenuto nel canvas.
### Campo di distanza
Possiamo anche immaginare lesempio soprastante come una carta delle altitudini, dove più scuro implica più alto. Il gradiente ci mostra qualcosa di simile al modello creato da un cono. Immaginate di trovarvi sulla cima di un cono. La distanza orizzontale dal bordo del cono è 0.5. Questa sarà costante in ogni direzione. Scegliendo dove “tagliare” il cono, otterrete una superficie circolare più grande o più piccola.
![](distance-field.jpg)
In sostanza, per creare delle forme, stiamo utilizzando una reinterpretazione dello spazio basata sulla distanza dal centro. Questa tecnica è conosciuta come “campo di distanza” (distance field) ed è usata in modi diversi, dai profili dei caratteri (font) alla grafica 3D.
Esercitatevi con i seguenti esercizi:
* Usate [```step()```](../glossary/?search=step) per trasformare in bianco tutto ciò che è al di sopra di 0.5 e al di sotto di 0.0.
* Invertite i colori dello sfondo e del primo piano.
* Usate [```smoothstep()```](../glossary/?search=smoothstep), provate con valori diversi per ottenere dei margini lisci sulla vostra circonferenza.
* Una volta che siete soddisfatti con unimplementazione, createne una funzione, che potrete riutilizzare in futuro.
* Aggiungete il colore alla circonferenza.
* Riuscite a creare animazioni sulla circonferenza per farla crescere e rimpicciolire, simulando il battito del cuore? (Potete trarre ispirazione dalle animazioni nel capitolo precedente).
* Che ne dite di spostare questa circonferenza? Riuscite a spostarla e a mettere altre circonferenze su uno stesso canvas?
* Cosa succede se combinate i campi di distanza con diverse operazioni e funzioni?
```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)));
```
* Create tre composizioni usando questa tecnica. Se poi riuscite ad animarle, ancora meglio!
#### Per la vostra cassetta degli attrezzi
In termini di potenza computazionale, la funzione [```sqrt()```](../glossary/?search=sqrt), e le altre funzioni che dipendono da essa, possono essere dispendiose. Ecco un altro modo per creare un campo di distanza circolare, basato sulla funzione [```dot()```](../glossary/?search=dot).
<div class="codeAndCanvas" data="circle.frag"></div>
### Proprietà utili dei campi di distanza
![Zen garden](zen-garden.jpg)
I campi di distanza possono essere usati per disegnare quasi qualsiasi cosa. Ovviamente, più una forma è complessa, più sarà complicata la sua equazione, ma una volta che avete la formula per creare un campo di distanza di una certa forma è molto facile combinare e/o applicare degli effetti ad essa, come lati lisci e profili multipli. Per questo motivo, i campi di distanza hanno molto successo nella rappresentazione dei caratteri (font), come [Mapbox GL Labels](https://www.mapbox.com/blog/text-signed-distance-fields/), [Matt DesLauriers](https://twitter.com/mattdesl) [Material Design Fonts](http://mattdesl.svbtle.com/material-design-on-the-gpu) e come è descritto nel [Capitolo 7 del libro "iPhone 3D Programming", OReilly](http://chimera.labs.oreilly.com/books/1234000001814/ch07.html#ch07_id36000921)
Osservate il codice seguente.
<div class="codeAndCanvas" data="rect-df.frag"></div>
Iniziamo spostando il sistema di coordinate al centro e riducendolo a metà per riassegnare i valori di posizione tra -1 e 1. Alla *riga 24* stiamo vedendo i valori del campo di distanza usando una funzione [```fract()```](../glossary/?search=fract), semplificando la visualizzazione dei motivi che essi creano. Il motivo del campo di distanza si continua a ripetere come i cerchi in un giardino zen.
Osserviamo la formula del campo di distanza alla *riga 19*. Lì stiamo calcolando la distanza dalla posizione su ```(.3,.3)``` o ```vec3(.3)``` in tutti e quattro i quadranti ( questo è ciò che fa [```abs()```](../glossary/?search=abs) qui) .
Se togliete il commento alla *riga 20*, noterete che stiamo collegando le distanze a questi quattro punti usando il [```min()```](../glossary/?search=min) a zero. Il risultato produce un nuovo motivo interessante.
Ora provate a togliere il commento alla *riga 21*; stiamo facendo la stessa cosa ma usando la funzione [```max()```](../glossary/?search=max). Il risultato è un rettangolo con gli angoli arrotondati. Notate come gli anelli del campo di distanza diventano più lisci mano a mano che si allontanano dal centro.
Terminate togliendo il commento una ad una alle *righe da 27 a 29*, per capire i diversi usi dei motivi di un campo di distanza.
### Forme polari
![Robert Mangold - Untitled (2008)](mangold.jpg)
Nel capitolo sul colore, abbiamo assegnato alle coordinate cartesiane le coordinate polari, calcolando il *raggio* e gli *angoli* di ciascun pixel con la seguente formula:
```glsl
vec2 pos = vec2(0.5)-st;
float r = length(pos)*2.0;
float a = atan(pos.y,pos.x);
```
Usiamo parte di questa formula allinizio del capitolo per tracciare una circonferenza. Abbiamo calcolato la distanza dal centro usando [```length()```](../glossary/?search=length). Ora che conosciamo i campi di distanza, possiamo imparare un altro modo per disegnare le forme usando le coordinate polari.
Questa tecnica è un po restrittiva ma molto semplice. Consiste nel cambiare il raggio di una circonferenza in funzione dellangolo per realizzare forme diverse. Come funziona la modulazione? Esatto, usando le funzioni di forma!
Qui sotto troverete le medesime funzioni sul diagramma cartesiano e in un esempio shader nelle coordinate polari ( tra le *righe 21 e 25*). Togliete il commento alle funzioni una alla volta, facendo attenzione alla relazione tra un sistema di coordinate e laltro.
<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>
Provate a:
* Animare queste forme.
* Combinare diverse funzioni di forma per fare dei *buchi* nella forma e creare fiori, fiocchi di neve e degli ingranaggi.
* Usare la funzione ```plot()``` che abbiamo usato nel capitolo sulle *funzioni di forma*, per disegnare solamente la sagoma.
### Unire i poteri
Ora che abbiamo imparato come modulare il raggio di una circonferenza in relazione allangolo, usando la funzione [```atan()```](../glossary/?search=atan) per disegnare diverse forme, possiamo imparare come usare ```atan()``` con i campi di distanza e applicare tutti i trucchi e gli effetti possibili con i campi di distanza.
Il nostro trucco userà il numero di lati di un poligono per costruire il campo di distanza, usando le coordinate polari. Controllate [il seguente codice](http://thndl.com/square-shaped-shaders.html) di [Andrew Baldwin](https://twitter.com/baldand).
<div class="codeAndCanvas" data="shapes.frag"></div>
* Usando questesempio, create una funzione che inserisca la posizione e il numero degli angoli di una forma desiderata e restituisca il valore di un campo di distanza.
* Mescolate i campi di distanza usando [```min()```](../glossary/?search=min) e [```max()```](../glossary/?search=max).
* Scegliete un logo geometrico da riprodurre usando i campi di distanza.
Congratulazioni! Avete affrontato la parte più complicata! Fate una pausa per poter assimilare questi concetti: disegnare delle semplici forme con Processing è facile, ma qui no. Nella “terra degli Shader”, disegnare le forme è contorto e può essere faticoso adattarsi al nuovo paradigma di codificazione.
Ora che sapete come disegnare le forme, sono sicuro che vi verranno in mente nuove idee. Nel capitolo successivo imparerete a spostare, ruotare e ridimensionare le forme. Questo vi permetterà di fare delle composizioni!
![Alice Hubbard, Providence, United States, ca. 1892. Photo: Zindman/Freemont.](froebel.jpg)
## Figure
Finalmente! Abbiamo costruito e allenato le nostre abilità per questo momento! Avete imparato la maggior parte delle basi, dei tipi e delle funzioni in GLSL. Vi siete esercitati continuamente sulle equazioni di forma. Ora è arrivato il momento di collegare tutti gli elementi. Siete allaltezza di questa sfida! In questo capitolo imparerete a disegnare forme semplici con una procedura in parallelo.
### Rettangolo
Immaginate di avere una carta millimetrata, come quelle che si usano per le lezioni di matematica, e che il nostro compito sia quello di disegnare un quadrato. Le dimensioni del foglio sono 10x10 e il quadrato dovrebbe essere 8x8. Cosa fareste?
![](grid_paper.jpg)
Colorereste tutto tranne la prima e lultima riga e la prima e lultima colonna, giusto?
Come si collega ciò agli shaders? Ogni piccolo quadrato della vostra carta millimetrata è un thread (un pixel). Ogni piccolo quadretto conosce la propria posizione, come per le coordinate di una scacchiera. Nei capitoli precedenti abbiamo associato *x* e *y* ai canali di colore *rosso* e *verde*, e abbiamo imparato come usare il limitato spazio bidimensionale tra 0.0 e 1.0. Come possiamo utilizzare tutto questo per disegnare un quadrato centrato nel mezzo del nostro canvas?
Iniziamo facendo uno pseudocodice che usi la dichiarazione ```if``` sul campo dello spazio. I principi per fare ciò sono straordinariamente simili a come immaginiamo lo scenario della carta millimetrata.
```glsl
if ( (X più grande di 1) AND (Y più grande di 1) )
colora di bianco
else
colora di nero
```
Ora che abbiamo unidea più chiara di come funziona, sostituiamo la dichiarazione ```if``` con [```step()```](../glossary/?search=step), e invece di usare 10x10, usiamo i valori normalizzati tra 0.0 e 1.0.
```glsl
uniform vec2 u_resolution;
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
// per ogni valore restituirà 1.0 (bianco) o 0.0 (nero).
float left = step(0.1,st.x); // Simile a ( X più grande di 0.1 )
float bottom = step(0.1,st.y); // Simile a ( Y più grande di 0.1 )
// La moltiplicazione di left*bottom sarà simile alla porta logica AND.
color = vec3( left * bottom );
gl_FragColor = vec4(color,1.0);
}
```
La funzione [```step()```](../glossary/?search=step) trasformerà ogni pixel al di sotto di 0.1 in nero (```vec3(0.0)```) e il resto in bianco (```vec3(1.0)```). La moltiplicazione tra left e bottom funziona come loperazione logica AND, dove entrambi devono essere tra 1.0 per tornare a 1.0. Questo traccia due linee nere, una alla base e laltra sul lato sinistro del canvas.
![](rect-01.jpg)
Nel codice precedente abbiamo ripetuto la struttura per ciascun asse (sinistra e base). Possiamo risparmiare alcune linee di codice passando due valori, invece di uno, direttamente a [```step()```](../glossary/?search=step) Ecco comè:
```glsl
vec2 borders = step(vec2(0.1),st);
float pct = borders.x * borders.y;
```
Fino ad ora abbiamo disegnato solamente due bordi (base-sinistra) del nostro rettangolo. Facciamo gli altri due (alto-destra). Osserva il seguente codice:
<div class="codeAndCanvas" data="rect-making.frag"></div>
Togliete il commento alle righe 21-22 e osservate come invertiamo le coordinate ```st``` e ripetiamo la stessa funzione [```step()```](../glossary/?search=step). In questo modo il ```vec2(0.0,0.0)``` sarà nellangolo in alto a destra. Questo è lequivalente digitale del capovolgimento della pagina e della ripetizione della procedura precedente.
![](rect-02.jpg)
Osservate che alla *riga 18 e alla riga 22* ogni lato è stato moltiplicato insieme. Questo equivale a scrivere:
```glsl
vec2 bl = step(vec2(0.1),st); // sotto-sinistra
vec2 tr = step(vec2(0.1),1.0-st); // sopra-destra
color = vec3(bl.x * bl.y * tr.x * tr.y);
```
Interessante, vero? Questa tecnica si basa tutta sulluso di [```step()```](../glossary/?search=step), della moltiplicazione per le operazioni logiche e il capovolgimento delle coordinate.
Prima di proseguire, provate i seguenti esercizi:
* Cambiate le misure e le proporzioni del rettangolo.
* Provate con lo stesso codice ma usando [```smoothstep()```](../glossary/?search=smoothstep) al posto di [```step()```](../glossary/?search=step). Notate che cambiando valori, potete passare da margini indistinti a lati eleganti e lisci.
* Fate unaltra implementazione che usi [```floor()```](../glossary/?search=floor).
* Scegliete limplementazione che preferite e create una sua funzione che potrete riusare in futuro. Rendete la vostra funzione flessibile ed efficiente.
* Create unaltra funzione che semplicemente tracci il contorno di un rettangolo.
* Come pensate di poter importare e spostare diversi rettangoli sullo stesso canvas? Se immaginate come, dimostrate le vostre capacità costruendo una composizione di rettangoli e colori che ricordi il dipinto di [Piet Mondrian](https://it.wikipedia.org/wiki/Piet_Mondrian).
![Piet Mondrian - Tableau (1921)](mondrian.jpg)
### Circonferenze
Disegnare quadrati e rettangoli su carta millimetrata con coordinate cartesiane è semplice, ma le circonferenze richiedono un approccio diverso, specialmente per il fatto che abbiamo bisogno di un algoritmo “per-pixel”. Una soluzione è riassegnare le coordinate spaziali, in modo tale da poter usare la funzione [```step()```](../glossary/?search=step) per disegnare una circonferenza.
Come? Iniziamo tornando indietro alla lezione di matematica e al foglio a quadretti, sul quale abbiamo aperto il compasso con il raggio della circonferenza, abbiamo premuto lago del compasso al centro della circonferenza e tracciato il perimetro della circonferenza con una semplice rotazione.
![](compass.jpg)
Tradurre ciò in un shader, dove ogni quadrato sul foglio a quadretti è un pixel, implica *chiedere* ad ogni pixel (o thread) se si trova allinterno dellarea della circonferenza. Lo facciamo calcolando la distanza tra il pixel e il centro della circonferenza.
![](circle.jpg)
Esistono diversi modi per calcolare questa distanza. Il più semplice utilizza la funzione [```distance()```](../glossary/?search=distance), che al suo interno calcola la funzione [```length()```](../glossary/?search=length) della differenza tra due punti ( nel nostro caso le coordinate del pixel e il centro del canvas). La funzione ```length()``` non è altro che una scorciatoia dell[equazione dellipotenusa](https://it.wikipedia.org/wiki/Ipotenusa), che usa al suo interno la radice quadrata (([```sqrt()```](../glossary/?search=sqrt))).
![](hypotenuse.png)
Potete usare [```distance()```](../glossary/?search=distance), [```length()```](../glossary/?search=length) o [```sqrt()```](../glossary/?search=sqrt) per calcolare la distanza dal centro del canvas. Il codice seguente contiene queste tre funzioni e il fatto non sorprendente è che ciascuna restituisce esattamente lo stesso risultato.
* Commentate e togliete il commento alle righe per provare i diversi modi di ottenere il medesimo risultato.
<div class="codeAndCanvas" data="circle-making.frag"></div>
Nellesempio precedente abbiamo mappato la distanza dal centro del canvas con la luminosità del colore del pixel. Più un pixel è vicino al centro, minore ( più scuro) è il suo valore. Notate che i valori non diventano troppo alti perché la massima distanza dal centro ( ```vec2(0.5, 0.5)``` ) va a malapena oltre 0.5. Osservate attentamente questa mappa e pensate:
* Cosa potete dedurre da essa?
* Come possiamo usarla per tracciare una circonferenza?
* Modificate il codice qui sopra per far sì che lintero gradiente circolare sia contenuto nel canvas.
### Campo di distanza
Possiamo anche immaginare lesempio soprastante come una carta delle altitudini, dove più scuro implica più alto. Il gradiente ci mostra qualcosa di simile al modello creato da un cono. Immaginate di trovarvi sulla cima di un cono. La distanza orizzontale dal bordo del cono è 0.5. Questa sarà costante in ogni direzione. Scegliendo dove “tagliare” il cono, otterrete una superficie circolare più grande o più piccola.
![](distance-field.jpg)
In sostanza, per creare delle forme, stiamo utilizzando una reinterpretazione dello spazio basata sulla distanza dal centro. Questa tecnica è conosciuta come “campo di distanza” (distance field) ed è usata in modi diversi, dai profili dei caratteri (font) alla grafica 3D.
Esercitatevi con i seguenti esercizi:
* Usate [```step()```](../glossary/?search=step) per trasformare in bianco tutto ciò che è al di sopra di 0.5 e al di sotto di 0.0.
* Invertite i colori dello sfondo e del primo piano.
* Usate [```smoothstep()```](../glossary/?search=smoothstep), provate con valori diversi per ottenere dei margini lisci sulla vostra circonferenza.
* Una volta che siete soddisfatti con unimplementazione, createne una funzione, che potrete riutilizzare in futuro.
* Aggiungete il colore alla circonferenza.
* Riuscite a creare animazioni sulla circonferenza per farla crescere e rimpicciolire, simulando il battito del cuore? (Potete trarre ispirazione dalle animazioni nel capitolo precedente).
* Che ne dite di spostare questa circonferenza? Riuscite a spostarla e a mettere altre circonferenze su uno stesso canvas?
* Cosa succede se combinate i campi di distanza con diverse operazioni e funzioni?
```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)));
```
* Create tre composizioni usando questa tecnica. Se poi riuscite ad animarle, ancora meglio!
#### Per la vostra cassetta degli attrezzi
In termini di potenza computazionale, la funzione [```sqrt()```](../glossary/?search=sqrt), e le altre funzioni che dipendono da essa, possono essere dispendiose. Ecco un altro modo per creare un campo di distanza circolare, basato sulla funzione [```dot()```](../glossary/?search=dot).
<div class="codeAndCanvas" data="circle.frag"></div>
### Proprietà utili dei campi di distanza
![Zen garden](zen-garden.jpg)
I campi di distanza possono essere usati per disegnare quasi qualsiasi cosa. Ovviamente, più una forma è complessa, più sarà complicata la sua equazione, ma una volta che avete la formula per creare un campo di distanza di una certa forma è molto facile combinare e/o applicare degli effetti ad essa, come lati lisci e profili multipli. Per questo motivo, i campi di distanza hanno molto successo nella rappresentazione dei caratteri (font), come [Mapbox GL Labels](https://www.mapbox.com/blog/text-signed-distance-fields/), [Matt DesLauriers](https://twitter.com/mattdesl) [Material Design Fonts](http://mattdesl.svbtle.com/material-design-on-the-gpu) e come è descritto nel [Capitolo 7 del libro "iPhone 3D Programming", OReilly](http://chimera.labs.oreilly.com/books/1234000001814/ch07.html#ch07_id36000921)
Osservate il codice seguente.
<div class="codeAndCanvas" data="rect-df.frag"></div>
Iniziamo spostando il sistema di coordinate al centro e riducendolo a metà per riassegnare i valori di posizione tra -1 e 1. Alla *riga 24* stiamo vedendo i valori del campo di distanza usando una funzione [```fract()```](../glossary/?search=fract), semplificando la visualizzazione dei motivi che essi creano. Il motivo del campo di distanza si continua a ripetere come i cerchi in un giardino zen.
Osserviamo la formula del campo di distanza alla *riga 19*. Lì stiamo calcolando la distanza dalla posizione su ```(.3,.3)``` o ```vec3(.3)``` in tutti e quattro i quadranti ( questo è ciò che fa [```abs()```](../glossary/?search=abs) qui) .
Se togliete il commento alla *riga 20*, noterete che stiamo collegando le distanze a questi quattro punti usando il [```min()```](../glossary/?search=min) a zero. Il risultato produce un nuovo motivo interessante.
Ora provate a togliere il commento alla *riga 21*; stiamo facendo la stessa cosa ma usando la funzione [```max()```](../glossary/?search=max). Il risultato è un rettangolo con gli angoli arrotondati. Notate come gli anelli del campo di distanza diventano più lisci mano a mano che si allontanano dal centro.
Terminate togliendo il commento una ad una alle *righe da 27 a 29*, per capire i diversi usi dei motivi di un campo di distanza.
### Forme polari
![Robert Mangold - Untitled (2008)](mangold.jpg)
Nel capitolo sul colore, abbiamo assegnato alle coordinate cartesiane le coordinate polari, calcolando il *raggio* e gli *angoli* di ciascun pixel con la seguente formula:
```glsl
vec2 pos = vec2(0.5)-st;
float r = length(pos)*2.0;
float a = atan(pos.y,pos.x);
```
Usiamo parte di questa formula allinizio del capitolo per tracciare una circonferenza. Abbiamo calcolato la distanza dal centro usando [```length()```](../glossary/?search=length). Ora che conosciamo i campi di distanza, possiamo imparare un altro modo per disegnare le forme usando le coordinate polari.
Questa tecnica è un po restrittiva ma molto semplice. Consiste nel cambiare il raggio di una circonferenza in funzione dellangolo per realizzare forme diverse. Come funziona la modulazione? Esatto, usando le funzioni di forma!
Qui sotto troverete le medesime funzioni sul diagramma cartesiano e in un esempio shader nelle coordinate polari ( tra le *righe 21 e 25*). Togliete il commento alle funzioni una alla volta, facendo attenzione alla relazione tra un sistema di coordinate e laltro.
<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>
Provate a:
* Animare queste forme.
* Combinare diverse funzioni di forma per fare dei *buchi* nella forma e creare fiori, fiocchi di neve e degli ingranaggi.
* Usare la funzione ```plot()``` che abbiamo usato nel capitolo sulle *funzioni di forma*, per disegnare solamente la sagoma.
### Unire i poteri
Ora che abbiamo imparato come modulare il raggio di una circonferenza in relazione allangolo, usando la funzione [```atan()```](../glossary/?search=atan) per disegnare diverse forme, possiamo imparare come usare ```atan()``` con i campi di distanza e applicare tutti i trucchi e gli effetti possibili con i campi di distanza.
Il nostro trucco userà il numero di lati di un poligono per costruire il campo di distanza, usando le coordinate polari. Controllate [il seguente codice](http://thndl.com/square-shaped-shaders.html) di [Andrew Baldwin](https://twitter.com/baldand).
<div class="codeAndCanvas" data="shapes.frag"></div>
* Usando questesempio, create una funzione che inserisca la posizione e il numero degli angoli di una forma desiderata e restituisca il valore di un campo di distanza.
* Mescolate i campi di distanza usando [```min()```](../glossary/?search=min) e [```max()```](../glossary/?search=max).
* Scegliete un logo geometrico da riprodurre usando i campi di distanza.
Congratulazioni! Avete affrontato la parte più complicata! Fate una pausa per poter assimilare questi concetti: disegnare delle semplici forme con Processing è facile, ma qui no. Nella “terra degli Shader”, disegnare le forme è contorto e può essere faticoso adattarsi al nuovo paradigma di codificazione.
Ora che sapete come disegnare le forme, sono sicuro che vi verranno in mente nuove idee. Nel capitolo successivo imparerete a spostare, ruotare e ridimensionare le forme. Questo vi permetterà di fare delle composizioni!

@ -2,7 +2,7 @@
## Shapes
Finally! We have been building skills for this moment! You have learned most of the GLSL foundations, types and functions. You have practiced your shaping equations over and over. Now is the time to put it all together. You are up for this challenge! In this chapter you'll learn how to draw simple shapes in a parallel procedural way.
Finally! We have been building skills for this moment! You have learned most of the GLSL foundations, types and functions. You have practiced your shaping equations over and over. Now is the time to put it all together. You are up for this challenge! In this chapter you'll learn how to draw simple shapes in a parallel procedural way.
### Rectangle
@ -10,7 +10,7 @@ Imagine we have grid paper like we used in math classes and our homework is to d
![](grid_paper.jpg)
You'd paint everything except the first and last rows and the first and last column, right?
You'd paint everything except the first and last rows and the first and last column, right?
How does this relate to shaders? Each little square of our grid paper is a thread (a pixel). Each little square knows its position, like the coordinates of a chess board. In previous chapters we mapped *x* and *y* to the *red* and *green* color channels, and we learned how to use the narrow two dimensional territory between 0.0 and 1.0. How can we use this to draw a centered square in the middle of our billboard?
@ -19,7 +19,7 @@ Let's start by sketching pseudocode that uses ```if``` statements over the spati
```glsl
if ( (X GREATER THAN 1) AND (Y GREATER THAN 1) )
paint white
else
else
paint black
```
@ -31,13 +31,13 @@ uniform vec2 u_resolution;
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
// Each result will return 1.0 (white) or 0.0 (black).
float left = step(0.1,st.x); // Similar to ( X greater than 0.1 )
float bottom = step(0.1,st.y); // Similar to ( Y greater than 0.1 )
// The multiplication of left*bottom will be similar to the logical AND.
color = vec3( left * bottom );
color = vec3( left * bottom );
gl_FragColor = vec4(color,1.0);
}
@ -50,7 +50,7 @@ The [```step()```](../glossary/?search=step) function will turn every pixel belo
In the previous code we repeat the structure for each axis (left and bottom). We can save some lines of code by passing two values directly to [```step()```](../glossary/?search=step) instead of one. That looks like this:
```glsl
vec2 borders = step(vec2(0.1),st);
vec2 borders = step(vec2(0.1),st);
float pct = borders.x * borders.y;
```
@ -58,7 +58,7 @@ So far, weve only drawn two borders (bottom-left) of our rectangle. Let's do
<div class="codeAndCanvas" data="rect-making.frag"></div>
Uncomment *lines 21-22* and see how we invert the ```st``` coordinates and repeat the same [```step()```](../glossary/?search=step) function. That way the ```vec2(0.0,0.0)``` will be in the top right corner. This is the digital equivalent of flipping the page and repeating the previous procedure.
Uncomment *lines 21-22* and see how we invert the ```st``` coordinates and repeat the same [```step()```](../glossary/?search=step) function. That way the ```vec2(0.0,0.0)``` will be in the top right corner. This is the digital equivalent of flipping the page and repeating the previous procedure.
![](rect-02.jpg)
@ -90,13 +90,13 @@ Before going forward, try the following exercises:
### Circles
It's easy to draw squares on grid paper and rectangles on cartesian coordinates, but circles require another approach, especially since we need a "per-pixel" algorithm. One solution is to *re-map* the spatial coordinates so that we can use a [```step()```](../glossary/?search=step) function to draw a circle.
It's easy to draw squares on grid paper and rectangles on cartesian coordinates, but circles require another approach, especially since we need a "per-pixel" algorithm. One solution is to *re-map* the spatial coordinates so that we can use a [```step()```](../glossary/?search=step) function to draw a circle.
How? Let's start by going back to math class and the grid paper, where we opened a compass to the radius of a circle, pressed one of the compass points at the center of the circle and then traced the edge of the circle with a simple spin.
![](compass.jpg)
Translating this to a shader where each square on the grid paper is a pixel implies *asking* each pixel (or thread) if it is inside the area of the circle. We do this by computing the distance from the pixel to the center of the circle.
Translating this to a shader where each square on the grid paper is a pixel implies *asking* each pixel (or thread) if it is inside the area of the circle. We do this by computing the distance from the pixel to the center of the circle.
![](circle.jpg)
@ -112,7 +112,7 @@ You can use [```distance()```](../glossary/?search=distance), [```length()```](.
In the previous example we map the distance to the center of the billboard to the color brightness of the pixel. The closer a pixel is to the center, the lower (darker) value it has. Notice that the values don't get too high because from the center ( ```vec2(0.5, 0.5)``` ) the maximum distance barely goes over 0.5. Contemplate this map and think:
* What you can infer from it?
* What you can infer from it?
* How we can use this to draw a circle?
@ -127,14 +127,14 @@ We can also think of the above example as an altitude map, where darker implies
Basically we are using a re-interpretation of the space (based on the distance to the center) to make shapes. This technique is known as a “distance field” and is used in different ways from font outlines to 3D graphics.
Try the following exercises:
* Use [```step()```](../glossary/?search=step) to turn everything above 0.5 to white and everything below to 0.0.
* Inverse the colors of the background and foreground.
* Using [```smoothstep()```](../glossary/?search=smoothstep), experiment with different values to get nice smooth borders on your circle.
* Once you are happy with an implementation, make a function of it that you can reuse in the future.
* Once you are happy with an implementation, make a function of it that you can reuse in the future.
* Add color to the circle.
@ -172,7 +172,7 @@ Take a look at the following code.
We start by moving the coordinate system to the center and shrinking it in half in order to remap the position values between -1 and 1. Also on *line 24* we are visualizing the distance field values using a [```fract()```](../glossary/?search=fract) function making it easy to see the pattern they create. The distance field pattern repeats over and over like rings in a Zen garden.
Lets take a look at the distance field formula on *line 19*. There we are calculating the distance to the position on ```(.3,.3)``` or ```vec3(.3)``` in all four quadrants (thats what [```abs()```](../glossary/?search=abs) is doing there).
Lets take a look at the distance field formula on *line 19*. There we are calculating the distance to the position on ```(.3,.3)``` or ```vec3(.3)``` in all four quadrants (thats what [```abs()```](../glossary/?search=abs) is doing there).
If you uncomment *line 20*, you will note that we are combining the distances to these four points using the [```min()```](../glossary/?search=min) to zero. The result produces an interesting new pattern.
@ -192,7 +192,7 @@ In the chapter about color we map the cartesian coordinates to polar coordinates
float a = atan(pos.y,pos.x);
```
We use part of this formula at the beginning of the chapter to draw a circle. We calculated the distance to the center using [```length()```](../glossary/?search=length). Now that we know about distance fields we can learn another way of drawing shapes using polar coordinates.
We use part of this formula at the beginning of the chapter to draw a circle. We calculated the distance to the center using [```length()```](../glossary/?search=length). Now that we know about distance fields we can learn another way of drawing shapes using polar coordinates.
This technique is a little restrictive but very simple. It consists of changing the radius of a circle depending on the angle to achieve different shapes. How does the modulation work? Yes, using shaping functions!
@ -216,7 +216,7 @@ Try to:
Now that we've learned how to modulate the radius of a circle according to the angle using the [```atan()```](../glossary/?search=atan) to draw different shapes, we can learn how use ```atan()``` with distance fields and apply all the tricks and effects possible with distance fields.
The trick will use the number of edges of a polygon to construct the distance field using polar coordinates. Check out [the following code](http://thndl.com/square-shaped-shaders.html) from [Andrew Baldwin](https://twitter.com/baldand).
The trick will use the number of edges of a polygon to construct the distance field using polar coordinates. Check out [the following code](http://thndl.com/square-shaped-shaders.html) from [Andrew Baldwin](https://twitter.com/baldand).
<div class="codeAndCanvas" data="shapes.frag"></div>

@ -39,8 +39,8 @@ void main(){
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
float d = 0.0;
d = min(shape(st,3),shape(st+vec2(0.,0.19),4));
gl_FragColor = vec4(vec3(1.0-aastep(.2,d)),1.0);
}
}

@ -10,7 +10,7 @@ uniform vec2 u_mouse;
uniform float u_time;
float plot (float y, float pct){
return smoothstep( pct-0.01, pct, y) -
return smoothstep( pct-0.01, pct, y) -
smoothstep( pct, pct+0.01, y);
}
@ -35,4 +35,4 @@ void main(){
gl_FragColor = vec4( color, 1.0 );
}
}

@ -16,17 +16,17 @@ void main(){
// a. The DISTANCE from the pixel to the center
pct = distance(st,vec2(0.5));
// b. The LENGTH of the vector
// from the pixel to the center
// b. The LENGTH of the vector
// from the pixel to the center
// vec2 toCenter = vec2(0.5)-st;
// pct = length(toCenter);
// c. The SQUARE ROOT of the vector
// from the pixel to the center
// c. The SQUARE ROOT of the vector
// from the pixel to the center
// vec2 tC = vec2(0.5)-st;
// pct = sqrt(tC.x*tC.x+tC.y*tC.y);
vec3 color = vec3(pct);
gl_FragColor = vec4( color, 1.0 );
}
}

@ -18,8 +18,8 @@ float circle(in vec2 _st, in float _radius){
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(circle(st,0.9));
gl_FragColor = vec4( color, 1.0 );
}
}

@ -21,7 +21,7 @@ float box(in vec2 st, in vec2 size){
}
float cross(in vec2 st, float size){
return box(st, vec2(size,size/4.)) +
return box(st, vec2(size,size/4.)) +
box(st, vec2(size/4.,size));
}
@ -29,4 +29,4 @@ void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
gl_FragColor = vec4( vec3( cross(st,0.4) ) ,1.0);
}
}

@ -1,4 +1,4 @@
<?php
<?php
$path = "..";
$subtitle = ": Shapes";
@ -29,5 +29,5 @@
<li class="navigationBar" onclick="nextPage()">Next &gt; &gt;</li>
</ul>';
include($path."/footer.php");
include($path."/footer.php");
?>

@ -6,10 +6,10 @@ uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float line( vec2 _st,
vec2 _p1, vec2 _p2,
float line( vec2 _st,
vec2 _p1, vec2 _p2,
float _width, float _spread){
_width = 1.0 / _width;
vec2 p2p1 = _p1 - _p2;
vec2 p1p2 = -(p2p1);
@ -22,8 +22,8 @@ float line( vec2 _st,
float pr2 = dot(p1p2, p1p);
if(pr1 > 0.0 && pr2 > 0.0) {
return pow(1.0 / abs(proj * _width), _spread);
} else {
return pow(1.0 / abs(proj * _width), _spread);
} else {
return 0.0;
}
}
@ -37,4 +37,4 @@ void main(){
0.005, 3.0) );
gl_FragColor = vec4(color,1.0);
}
}

@ -27,4 +27,4 @@ void main(){
color = vec3( 1.-smoothstep(f,f+0.02,r) );
gl_FragColor = vec4(color, 1.0);
}
}

@ -27,4 +27,4 @@ void main(){
// gl_FragColor = vec4(vec3( step(.3,d) ),1.0);
// gl_FragColor = vec4(vec3( step(.3,d) * step(d,.4)),1.0);
// gl_FragColor = vec4(vec3( smoothstep(.3,.4,d)* smoothstep(.6,.5,d)) ,1.0);
}
}

@ -12,16 +12,16 @@ uniform float u_time;
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
// bottom-left
vec2 bl = step(vec2(0.1),st);
vec2 bl = step(vec2(0.1),st);
float pct = bl.x * bl.y;
// top-right
// top-right
// vec2 tr = step(vec2(0.1),1.0-st);
// pct *= tr.x * tr.y;
color = vec3(pct);
gl_FragColor = vec4(color,1.0);
}
}

@ -21,4 +21,4 @@ void main(){
vec3 color = vec3( rect(st, vec2(0.9) ) );
gl_FragColor = vec4(color,1.0);
}
}

@ -27,7 +27,7 @@ void main(){
// Angle and radius from the current pixel
float a = atan(st.x,st.y)+PI;
float r = TWO_PI/float(N);
// Shaping function that modulate the distance
d = cos(floor(.5+a/r)*r-a)*length(st);
@ -35,4 +35,4 @@ void main(){
// color = vec3(d);
gl_FragColor = vec4(color,1.0);
}
}

@ -63,4 +63,4 @@ void main(){
color += shapeBorder(st+offset+vec2(0.,0.05), 3, .05, .03);
gl_FragColor = vec4(color,1.0);
}
}

@ -36,4 +36,4 @@ void main(){
d = step(.4,d);
gl_FragColor = vec4(vec3(1.0-d),1.0);
}
}

@ -10,7 +10,7 @@ uniform vec2 u_mouse;
uniform float u_time;
// Based on https://www.shadertoy.com/view/4sSSzG
float triangleDF(vec2 st,
float triangleDF(vec2 st,
vec2 p0, vec2 p1, vec2 p2){
vec3 e0, e1, e2;
@ -34,9 +34,9 @@ void main(){
vec3 color = vec3(0.0);
// Distance Field in 3 channels
float df = triangleDF(st,
vec2(0.40,0.45),
vec2(0.60,0.45),
float df = triangleDF(st,
vec2(0.40,0.45),
vec2(0.60,0.45),
vec2(0.5,0.60));
color = vec3(df);
@ -47,4 +47,4 @@ void main(){
smoothstep(size+0.001,size+1e-7,df);
gl_FragColor = vec4(color,1.0);
}
}

@ -10,8 +10,8 @@ uniform vec2 u_mouse;
uniform float u_time;
// Based on https://www.shadertoy.com/view/4sSSzG
float triangle (vec2 st,
vec2 p0, vec2 p1, vec2 p2,
float triangle (vec2 st,
vec2 p0, vec2 p1, vec2 p2,
float smoothness){
vec3 e0, e1, e2;
@ -27,19 +27,19 @@ float triangle (vec2 st,
float b = max(0.0, dot(e1.xy, st) - e1.z);
float c = max(0.0, dot(e2.xy, st) - e2.z);
return smoothstep(smoothness * 2.0,
1e-7,
return smoothstep(smoothness * 2.0,
1e-7,
length(vec3(a, b, c)));
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3( triangle(st,
vec2(0.0,0.15),
vec2(1.0,0.15),
vec2(0.5,0.88),
vec3 color = vec3( triangle(st,
vec2(0.0,0.15),
vec2(1.0,0.15),
vec2(0.5,0.88),
0.001) );
gl_FragColor = vec4(color,1.0);
}
}

@ -75,7 +75,7 @@ mat2 scale(vec2 _scale){
}
```
<div class="codeAndCanvas" data="cross-scale.frag"></div>
<div class="codeAndCanvas" data="cross-scale.frag"></div>
试试下面的练习,尝试深入理解矩阵的工作机制:

@ -1,101 +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.
## 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.

@ -1,101 +1,101 @@
## Matrici 2D
<canvas id="custom" class="canvas" data-fragment-url="matrix.frag" width="700px" height="200px"></canvas>
### Traslare
Nel capitolo precedente abbiamo imparato a fare alcune figure - il trucco per spostare quelle figure è stato di spostare il sistema di coordinate stesso. Siamo in grado d'ottenere questa trasformazione aggiungendo un vettore alla variabile ```st``` che contiene la posizione di ogni frammento. Ciò causa uno spostamento complessivo del sistema di coordinate.
![](translate.jpg)
Di sicuro è più facile da vedere che da spiegare:
* Rimuovete il commento alla linea 35 del codice sottostante e osservate come il sistema di coordinate si muove.
<div class="codeAndCanvas" data="cross-translate.frag"></div>
Ora provate il seguente esercizio:
* Utilizzate ```u_time``` insieme alle funzioni di forma per spostare la piccola croce in un modo interessante. Pensate a un tipo di movimento e tentate di applicarlo alla croce. Prendete degli esempi dal "mondo reale", potrebbero esservi utili - per esempio l'andirivieni delle onde, un movimento a pendolo, una palla che rimbalza, una macchina che accelera, una bicicletta che si ferma.
### Rotazioni
Anche per ruotare degli oggetti abbiamo bisogno di spostare l'intero sistema spaziale. Per questo utilizzeremo una [matrice](https://it.wikipedia.org/wiki/Matrice). Una matrice è un insieme di numeri organizzato in colonne e righe. Quando si moltiplica un vettore per una matrice, la matrice esegue una serie di operazioni e trasforma il vettore in funzione dei valori che questa contiene.
[![Wikipedia entry for Matrix (mathematics) ](matrixes.png)](https://it.wikipedia.org/wiki/Matrice)
GLSL ha un supporto nativo per le matrici a due, tre e quattro dimensioni: [```mat2```](../glossary/?search=mat2) (2x2), [```mat3```](../glossary/?search=mat3) (3x3) e [```mat4```](../glossary/?search=mat4) (4x4). GLSL supporta anche la moltiplicazione di matrici (```*```) e una funzione specifica chiamata ([```matrixCompMult()```](../glossary/?search=matrixCompMult)).
Le matrici possono essere usate per produrre dei comportamenti specifici. Per esempio per traslare un vettore:
![](3dtransmat.png)
Ancora più interessante è la possibilità di utilizzare una matrice per ruotare il sistema di coordinate:
![](rotmat.png)
Il seguente codice mostra come costruire una matrice di rotazione 2D. Questa funzione segue la [formula](http://en.wikipedia.org/wiki/Rotation_matrix) per vettori a due dimensioni e fa ruotare le coordinate intorno al punto ```vec2(0.0)```.
```glsl
mat2 rotate2d(float _angle){
return mat2(cos(_angle),-sin(_angle),
sin(_angle),cos(_angle));
}
```
Questa maniera d'effettuare una rotazione (intorno all'origine) non funziona con l'approccio che abbiamo utilizzato finora per disegnare le figure. La nostra croce viene disegnata al centro della tela, che corrisponde alla posizione ```vec2(0.5)```. Quindi, prima di ruotare lo spazio, abbiamo bisogno di spostare la figura dal `centro` alla coordinata ```vec2(0.0)```, poi di ruotare lo spazio, e infine di spostarla di nuovo nella posizione originale.
![](rotate.jpg)
Date un'occhiata al codice:
<div class="codeAndCanvas" data="cross-rotate.frag"></div>
Provate i seguenti esercizi:
* Rimuovete il commento alla linea 45 del codice qui sopra e prestate attenzione a ciò che accade.
* Commentate le traslazioni, prima e dopo la rotazione, alle linee 37 e 39, e osservate le conseguenze.
* Utilizzate delle rotazioni per migliorare l'animazione che avete simulato nell'esercizio sulla traslazione.
### Scalare
Abbiamo visto come le matrici sono usate per traslare e ruotare gli oggetti nello spazio. (O più precisamente come trasformare il sistema di coordinate per ruotare e spostare gli oggetti.) Se avete utilizzato un software di modellazione 3D o le funzioni push e pop delle matrici in Processing, si sa che le matrici possono essere utilizzati anche per scalare la dimensione di un oggetto.
![](scale.png)
Usando la formula precedente, siamo in grado di scrivere una matrice a due dimensioni per scalare una figura:
```glsl
mat2 scale(vec2 _scale){
return mat2(_scale.x,0.0,
0.0,_scale.y);
}
```
<div class="codeAndCanvas" data="cross-scale.frag"></div>
Provate i seguenti esercizi per capirne il funzionamento.
* Rimuovete il commento alla linea 42 del codice per vedere come funziona la messa in scala attraverso l'uso di colori.
* Osservate cosa succede quando si commentano le traslazioni, prima e dopo il ridimensionamento alle linee 37 e 39.
* Provate a combinare una matrice di rotazione insieme con una matrice di scala. Attenzione, l'ordine delle operazioni è importante: per prima cosa moltiplicate le matrici fra di loro e poi moltiplicate la matrice finale per i vettori.
* Ora che sapete come disegnare, spostare, ruotare, scalare molteplici forme, è il momento di fare una bella composizione. Progettate e realizzate una [falsa UI o HUD (heads up display)](https://www.pinterest.com/patriciogonzv/huds/). Utilizzate il seguente esempio su ShaderToy di [Ndel](https://www.shadertoy.com/user/ndel) per avere un riferimento.
<iframe width="800" height="450" frameborder="0" src="https://www.shadertoy.com/embed/4s2SRt?gui=true&t=10&paused=true" allowfullscreen></iframe>
### Altri usi delle matrici: il colore YUV
Lo [YUV](https://it.wikipedia.org/wiki/YUV) è uno spazio colore utilizzato per la codifica analogica di foto e video che tenga conto della gamma di percezione umana per ridurre la larghezza di banda dei componenti della crominanza.
Nel seguente codice utilizzeremo delle operazioni di matrice in GLSL per trasformare i colori da uno spazio colore all'altro.
<div class="codeAndCanvas" data="yuv.frag"></div>
Come si può vedere, stiamo trattando i colori come dei vettori che vengono moltiplicati con delle matrici. Abbiamo "spostato" i valori di colore come se avessimo spostato un vettore di posizione nello spazio.
In questo capitolo abbiamo imparato come usare le trasformazioni di matrice per spostare, ruotare e ridimensionare i vettori. Queste trasformazioni saranno essenziali per creare delle composizioni con le figure che abbiamo visto nel capitolo precedente. Nel prossimo capitolo provvederemo ad applicare tutto quello che abbiamo imparato per fare dei bei pattern procedurali. Vedrete come la ripetizione e la variazione del codice possano diventare delle pratiche gratificanti.
## Matrici 2D
<canvas id="custom" class="canvas" data-fragment-url="matrix.frag" width="700px" height="200px"></canvas>
### Traslare
Nel capitolo precedente abbiamo imparato a fare alcune figure - il trucco per spostare quelle figure è stato di spostare il sistema di coordinate stesso. Siamo in grado d'ottenere questa trasformazione aggiungendo un vettore alla variabile ```st``` che contiene la posizione di ogni frammento. Ciò causa uno spostamento complessivo del sistema di coordinate.
![](translate.jpg)
Di sicuro è più facile da vedere che da spiegare:
* Rimuovete il commento alla linea 35 del codice sottostante e osservate come il sistema di coordinate si muove.
<div class="codeAndCanvas" data="cross-translate.frag"></div>
Ora provate il seguente esercizio:
* Utilizzate ```u_time``` insieme alle funzioni di forma per spostare la piccola croce in un modo interessante. Pensate a un tipo di movimento e tentate di applicarlo alla croce. Prendete degli esempi dal "mondo reale", potrebbero esservi utili - per esempio l'andirivieni delle onde, un movimento a pendolo, una palla che rimbalza, una macchina che accelera, una bicicletta che si ferma.
### Rotazioni
Anche per ruotare degli oggetti abbiamo bisogno di spostare l'intero sistema spaziale. Per questo utilizzeremo una [matrice](https://it.wikipedia.org/wiki/Matrice). Una matrice è un insieme di numeri organizzato in colonne e righe. Quando si moltiplica un vettore per una matrice, la matrice esegue una serie di operazioni e trasforma il vettore in funzione dei valori che questa contiene.
[![Wikipedia entry for Matrix (mathematics) ](matrixes.png)](https://it.wikipedia.org/wiki/Matrice)
GLSL ha un supporto nativo per le matrici a due, tre e quattro dimensioni: [```mat2```](../glossary/?search=mat2) (2x2), [```mat3```](../glossary/?search=mat3) (3x3) e [```mat4```](../glossary/?search=mat4) (4x4). GLSL supporta anche la moltiplicazione di matrici (```*```) e una funzione specifica chiamata ([```matrixCompMult()```](../glossary/?search=matrixCompMult)).
Le matrici possono essere usate per produrre dei comportamenti specifici. Per esempio per traslare un vettore:
![](3dtransmat.png)
Ancora più interessante è la possibilità di utilizzare una matrice per ruotare il sistema di coordinate:
![](rotmat.png)
Il seguente codice mostra come costruire una matrice di rotazione 2D. Questa funzione segue la [formula](http://en.wikipedia.org/wiki/Rotation_matrix) per vettori a due dimensioni e fa ruotare le coordinate intorno al punto ```vec2(0.0)```.
```glsl
mat2 rotate2d(float _angle){
return mat2(cos(_angle),-sin(_angle),
sin(_angle),cos(_angle));
}
```
Questa maniera d'effettuare una rotazione (intorno all'origine) non funziona con l'approccio che abbiamo utilizzato finora per disegnare le figure. La nostra croce viene disegnata al centro della tela, che corrisponde alla posizione ```vec2(0.5)```. Quindi, prima di ruotare lo spazio, abbiamo bisogno di spostare la figura dal `centro` alla coordinata ```vec2(0.0)```, poi di ruotare lo spazio, e infine di spostarla di nuovo nella posizione originale.
![](rotate.jpg)
Date un'occhiata al codice:
<div class="codeAndCanvas" data="cross-rotate.frag"></div>
Provate i seguenti esercizi:
* Rimuovete il commento alla linea 45 del codice qui sopra e prestate attenzione a ciò che accade.
* Commentate le traslazioni, prima e dopo la rotazione, alle linee 37 e 39, e osservate le conseguenze.
* Utilizzate delle rotazioni per migliorare l'animazione che avete simulato nell'esercizio sulla traslazione.
### Scalare
Abbiamo visto come le matrici sono usate per traslare e ruotare gli oggetti nello spazio. (O più precisamente come trasformare il sistema di coordinate per ruotare e spostare gli oggetti.) Se avete utilizzato un software di modellazione 3D o le funzioni push e pop delle matrici in Processing, si sa che le matrici possono essere utilizzati anche per scalare la dimensione di un oggetto.
![](scale.png)
Usando la formula precedente, siamo in grado di scrivere una matrice a due dimensioni per scalare una figura:
```glsl
mat2 scale(vec2 _scale){
return mat2(_scale.x,0.0,
0.0,_scale.y);
}
```
<div class="codeAndCanvas" data="cross-scale.frag"></div>
Provate i seguenti esercizi per capirne il funzionamento.
* Rimuovete il commento alla linea 42 del codice per vedere come funziona la messa in scala attraverso l'uso di colori.
* Osservate cosa succede quando si commentano le traslazioni, prima e dopo il ridimensionamento alle linee 37 e 39.
* Provate a combinare una matrice di rotazione insieme con una matrice di scala. Attenzione, l'ordine delle operazioni è importante: per prima cosa moltiplicate le matrici fra di loro e poi moltiplicate la matrice finale per i vettori.
* Ora che sapete come disegnare, spostare, ruotare, scalare molteplici forme, è il momento di fare una bella composizione. Progettate e realizzate una [falsa UI o HUD (heads up display)](https://www.pinterest.com/patriciogonzv/huds/). Utilizzate il seguente esempio su ShaderToy di [Ndel](https://www.shadertoy.com/user/ndel) per avere un riferimento.
<iframe width="800" height="450" frameborder="0" src="https://www.shadertoy.com/embed/4s2SRt?gui=true&t=10&paused=true" allowfullscreen></iframe>
### Altri usi delle matrici: il colore YUV
Lo [YUV](https://it.wikipedia.org/wiki/YUV) è uno spazio colore utilizzato per la codifica analogica di foto e video che tenga conto della gamma di percezione umana per ridurre la larghezza di banda dei componenti della crominanza.
Nel seguente codice utilizzeremo delle operazioni di matrice in GLSL per trasformare i colori da uno spazio colore all'altro.
<div class="codeAndCanvas" data="yuv.frag"></div>
Come si può vedere, stiamo trattando i colori come dei vettori che vengono moltiplicati con delle matrici. Abbiamo "spostato" i valori di colore come se avessimo spostato un vettore di posizione nello spazio.
In questo capitolo abbiamo imparato come usare le trasformazioni di matrice per spostare, ruotare e ridimensionare i vettori. Queste trasformazioni saranno essenziali per creare delle composizioni con le figure che abbiamo visto nel capitolo precedente. Nel prossimo capitolo provvederemo ad applicare tutto quello che abbiamo imparato per fare dei bei pattern procedurali. Vedrete come la ripetizione e la variazione del codice possano diventare delle pratiche gratificanti.

@ -100,4 +100,3 @@ mat2 scale(vec2 _scale){
見てのとおり色をベクトルとして扱い行列を掛け合わせています。このようにして色の値を「動かす」ことができるのです。
この章では行列を使ってベクトルを移動、回転、拡大・縮小する方法を学びました。これらの変形は、前章で学んだ図形を組み合わせてより複雑な図を作成するのに欠かせない技術です。次の章ではこれまで学んだことを全て活かして、規則に基づいた美しいパターンを作成します。コードによる反復と変化の楽しさを発見しましょう。

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save